From f9a114b29ab2131a33b45d6b417e5c25e8eaefe6 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Rapha=C3=ABl=20Pinson?= <raphael.pinson@camptocamp.com>
Date: Thu, 18 Oct 2018 14:50:55 +0200
Subject: [PATCH] Support multiple destinations in postfix::virtual (Fix #164)

---
 manifests/virtual.pp                 | 28 +++++++++++++-----------
 spec/defines/postfix_virtual_spec.rb | 32 +++++++++++++++++++++++-----
 2 files changed, 43 insertions(+), 17 deletions(-)

diff --git a/manifests/virtual.pp b/manifests/virtual.pp
index 6b43e0c..8e08537 100644
--- a/manifests/virtual.pp
+++ b/manifests/virtual.pp
@@ -5,9 +5,9 @@
 # === Parameters
 #
 # [*name*]        - name of address postfix will lookup. See virtual(8).
-# [*destination*] - where the emails will be delivered to. See virtual(8).
+# [*destination*] - a list of destinations where the emails will be delivered to. See virtual(8).
 # [*ensure*]      - present/absent, defaults to present.
-# [*file*]        - A string defining the location of the pre-hash map.
+# [*file*]        - a string defining the location of the pre-hash map.
 #
 # === Requires
 #
@@ -21,8 +21,7 @@
 #   node "toto.example.com" {
 #
 #     include postfix
-#
-#     postfix::hash { "/etc/postfix/virtual":
+# #     postfix::hash { "/etc/postfix/virtual":
 #       ensure => present,
 #     }
 #     postfix::config { "virtual_alias_maps":
@@ -30,24 +29,29 @@
 #     }
 #     postfix::virtual { "user@example.com":
 #       ensure      => present,
-#       destination => "root",
+#       destination => ['root', 'postmaster'],
 #     }
 #   }
 #
 define postfix::virtual (
-  String                    $destination,
-  Stdlib::Absolutepath      $file='/etc/postfix/virtual',
-  Enum['present', 'absent'] $ensure='present'
+  Variant[String, Array[String]] $destination,
+  Stdlib::Absolutepath           $file='/etc/postfix/virtual',
+  Enum['present', 'absent']      $ensure='present'
 ) {
   include ::postfix::augeas
 
+  $dest_sets = [$destination].flatten.map |$i, $d| {
+    $idx = $i+1
+    "set \$entry/destination[${idx}] '${d}'"
+  }
+
   case $ensure {
     'present': {
       $changes = [
-        "set pattern[. = '${name}'] '${name}'",
-        # TODO: support more than one destination
-        "set pattern[. = '${name}']/destination '${destination}'",
-      ]
+        "defnode entry pattern[. = '${name}'] '${name}'",
+        'rm $entry/destination',
+        $dest_sets,
+      ].flatten
     }
 
     'absent': {
diff --git a/spec/defines/postfix_virtual_spec.rb b/spec/defines/postfix_virtual_spec.rb
index cd6dcfa..216a2d2 100644
--- a/spec/defines/postfix_virtual_spec.rb
+++ b/spec/defines/postfix_virtual_spec.rb
@@ -26,7 +26,7 @@ describe 'postfix::virtual' do
 
       context 'when sending wrong type for destination' do
         let (:params) { {
-          :destination => ['bar'],
+          :destination => true,
         } }
 
         it 'should fail' do
@@ -98,8 +98,9 @@ describe 'postfix::virtual' do
           :incl    => '/etc/postfix/virtual',
           :lens    => 'Postfix_Virtual.lns',
           :changes => [
-            "set pattern[. = 'foo'] 'foo'",
-            "set pattern[. = 'foo']/destination 'bar'",
+            "defnode entry pattern[. = 'foo'] 'foo'",
+            "rm $entry/destination",
+            "set $entry/destination[1] 'bar'",
           ])
         }
       end
@@ -116,8 +117,29 @@ describe 'postfix::virtual' do
           :incl    => '/tmp/virtual',
           :lens    => 'Postfix_Virtual.lns',
           :changes => [
-            "set pattern[. = 'foo'] 'foo'",
-            "set pattern[. = 'foo']/destination 'bar'",
+            "defnode entry pattern[. = 'foo'] 'foo'",
+            "rm $entry/destination",
+            "set $entry/destination[1] 'bar'",
+          ])
+        }
+      end
+
+      context 'when passing destination as array' do
+        let (:params) { {
+          :destination => ['bar', 'baz'],
+          :file        => '/tmp/virtual',
+          :ensure      => 'present',
+        } }
+
+        it { is_expected.to contain_class('postfix::augeas') }
+        it { is_expected.to contain_augeas('Postfix virtual - foo').with(
+          :incl    => '/tmp/virtual',
+          :lens    => 'Postfix_Virtual.lns',
+          :changes => [
+            "defnode entry pattern[. = 'foo'] 'foo'",
+            "rm $entry/destination",
+            "set $entry/destination[1] 'bar'",
+            "set $entry/destination[2] 'baz'",
           ])
         }
       end
-- 
GitLab