commit c94658e1720b5632d3280ff14dbaa56b5fbe2bc8
Author: Nacho Barrientos <nacho.barrientos@cern.ch>
Date:   Tue Jul 6 16:48:47 2021 +0200

    Allow declaring the same set in several tables
    
    Closes #100

diff --git a/REFERENCE.md b/REFERENCE.md
index 9f2366e..ba960d9 100644
--- a/REFERENCE.md
+++ b/REFERENCE.md
@@ -1554,9 +1554,9 @@ Default value: ``undef``
 
 ##### <a name="table"></a>`table`
 
-Data type: `String`
+Data type: `Variant[String, Array[String, 1]]`
 
-table to add set to.
+table or array of tables to add the set to.
 
 Default value: `'inet-filter'`
 
diff --git a/manifests/set.pp b/manifests/set.pp
index 5b6b416..06678f0 100644
--- a/manifests/set.pp
+++ b/manifests/set.pp
@@ -12,7 +12,7 @@
 # @param setname name of set, equal to to title.
 # @param order concat ordering.
 # @param type type of set.
-# @param table table to add set to.
+# @param table table or array of tables to add the set to.
 # @param flags specify flags for set
 # @param timeout timeout in seconds
 # @param gc_interval garbage collection interval.
@@ -27,7 +27,7 @@ define nftables::set (
   Pattern[/^[-a-zA-Z0-9_]+$/] $setname = $title,
   Pattern[/^\d\d$/] $order = '10',
   Optional[Enum['ipv4_addr', 'ipv6_addr', 'ether_addr', 'inet_proto', 'inet_service', 'mark']] $type = undef,
-  String $table = 'inet-filter',
+  Variant[String, Array[String, 1]] $table = 'inet-filter',
   Array[Enum['constant', 'dynamic', 'interval', 'timeout'], 0, 4] $flags = [],
   Optional[Integer] $timeout = undef,
   Optional[Integer] $gc_interval = undef,
@@ -44,39 +44,43 @@ define nftables::set (
     }
   }
 
-  if $ensure == 'present' {
-    concat::fragment {
-      "nftables-${table}-set-${setname}":
-        order  => $order,
-        target => "nftables-${table}",
-    }
+  $_tables = Array($table, true)
 
-    if $content {
-      Concat::Fragment["nftables-${table}-set-${setname}"] {
-        content => "  ${content}",
-      }
-    } elsif $source {
-      Concat::Fragment["nftables-${table}-set-${setname}"] {
-        source => $source,
-      }
-    } else {
-      if $type == undef {
-        fail('The way the resource is configured must have a type set')
+  if $ensure == 'present' {
+    $_tables.each |Integer $index, String $_table| {
+      concat::fragment {
+        "nftables-${_table}-set-${setname}":
+          order  => $order,
+          target => "nftables-${_table}",
       }
-      Concat::Fragment["nftables-${table}-set-${setname}"] {
-        content => epp('nftables/set.epp',
-          {
-            'name'        => $setname,
-            'type'        => $type,
-            'flags'       => $flags,
-            'timeout'     => $timeout,
-            'gc_interval' => $gc_interval,
-            'elements'    => $elements,
-            'size'        => $size,
-            'policy'      => $policy,
-            'auto_merge'  => $auto_merge,
-          }
-        )
+
+      if $content {
+        Concat::Fragment["nftables-${_table}-set-${setname}"] {
+          content => "  ${content}",
+        }
+      } elsif $source {
+        Concat::Fragment["nftables-${_table}-set-${setname}"] {
+          source => $source,
+        }
+      } else {
+        if $type == undef {
+          fail('The way the resource is configured must have a type set')
+        }
+        Concat::Fragment["nftables-${_table}-set-${setname}"] {
+          content => epp('nftables/set.epp',
+            {
+              'name'        => $setname,
+              'type'        => $type,
+              'flags'       => $flags,
+              'timeout'     => $timeout,
+              'gc_interval' => $gc_interval,
+              'elements'    => $elements,
+              'size'        => $size,
+              'policy'      => $policy,
+              'auto_merge'  => $auto_merge,
+            }
+          )
+        }
       }
     }
   }
diff --git a/spec/acceptance/all_rules_spec.rb b/spec/acceptance/all_rules_spec.rb
index 602b44b..45f6880 100644
--- a/spec/acceptance/all_rules_spec.rb
+++ b/spec/acceptance/all_rules_spec.rb
@@ -71,6 +71,11 @@ describe 'nftables class' do
       include nftables::rules::wireguard
       include nftables::services::dhcpv6_client
       include nftables::services::openafs_client
+      nftables::set{'my_test_set':
+        type       => 'ipv4_addr',
+        elements   => ['192.168.0.1', '10.0.0.2'],
+        table      => ['inet-filter', 'ip-nat'],
+      }
       # nftables cannot be started in docker so replace service with a validation only.
       systemd::dropin_file{"zzz_docker_nft.conf":
         ensure  => present,
diff --git a/spec/defines/set_spec.rb b/spec/defines/set_spec.rb
index 0a5ce4c..4c28671 100644
--- a/spec/defines/set_spec.rb
+++ b/spec/defines/set_spec.rb
@@ -154,6 +154,61 @@ describe 'nftables::set' do
           )
         }
       end
+
+      describe 'default table can be changed' do
+        let(:params) do
+          {
+            type: 'ipv6_addr',
+            elements: ['2001:1458::1', '2001:1458:1::2'],
+            table: 'ip-nat'
+          }
+        end
+
+        it { is_expected.to compile }
+        it {
+          is_expected.to contain_concat__fragment('nftables-ip-nat-set-my_set').with(
+            target:  'nftables-ip-nat',
+            content: %r{^  set my_set \{\n    type ipv6_addr\n    elements = \{ 2001:1458::1, 2001:1458:1::2 \}\n  \}$}m,
+            order:   '10',
+          )
+        }
+      end
+
+      describe 'multiple tables no tables' do
+        let(:params) do
+          {
+            type: 'ipv6_addr',
+            elements: ['2001:1458::1', '2001:1458:1::2'],
+            table: []
+          }
+        end
+
+        it { is_expected.not_to compile }
+      end
+
+      describe 'multiple tables' do
+        let(:params) do
+          {
+            type: 'ipv6_addr',
+            elements: ['2001:1458::1', '2001:1458:1::2'],
+            table: ['inet-filter', 'ip-nat']
+          }
+        end
+
+        it { is_expected.to compile }
+        it {
+          is_expected.to contain_concat__fragment('nftables-inet-filter-set-my_set').with(
+            target:  'nftables-inet-filter',
+            content: %r{^  set my_set \{\n    type ipv6_addr\n    elements = \{ 2001:1458::1, 2001:1458:1::2 \}\n  \}$}m,
+            order:   '10',
+          )
+          is_expected.to contain_concat__fragment('nftables-ip-nat-set-my_set').with(
+            target:  'nftables-ip-nat',
+            content: %r{^  set my_set \{\n    type ipv6_addr\n    elements = \{ 2001:1458::1, 2001:1458:1::2 \}\n  \}$}m,
+            order:   '10',
+          )
+        }
+      end
     end
   end
 end
