commit 18ec6f48f722a41504be0fc693cf4ab9cdbe790b
Author: tr <tr@immerda.ch>
Date:   Thu Nov 5 22:19:28 2020 +0100

    Fix rulenames which includes an index
    
    The rulename has a regex pattern `[/^[a-zA-Z0-9_]+-[a-zA-Z0-9_]+(-\d+)?$/]`
    which allows an index at the end of the rulename (with a delimiter).
    This is split later with `$data = split($rulename, '-')` but the content
    of the index part is never used as a fragment. Therefor the fragment was
    defined twice.
    This fix will add the index to the fragment name.

diff --git a/manifests/rule.pp b/manifests/rule.pp
index d7471a6..d9aeadc 100644
--- a/manifests/rule.pp
+++ b/manifests/rule.pp
@@ -19,18 +19,24 @@ define nftables::rule(
   if $ensure == 'present' {
     $data = split($rulename, '-')
 
+    if $data[2] {
+      $fragment = "nftables-${table}-chain-${data[0]}-rule-${data[1]}-${data[2]}"
+    } else {
+      $fragment = "nftables-${table}-chain-${data[0]}-rule-${data[1]}"
+    }
+
     concat::fragment{
-      "nftables-${table}-chain-${data[0]}-rule-${data[1]}":
+      $fragment:
         order  => $order,
         target => "nftables-${table}-chain-${data[0]}",
     }
 
     if $content {
-      Concat::Fragment["nftables-${table}-chain-${data[0]}-rule-${data[1]}"]{
+      Concat::Fragment[$fragment]{
         content => "  ${content}",
       }
     } else {
-      Concat::Fragment["nftables-${table}-chain-${data[0]}-rule-${data[1]}"]{
+      Concat::Fragment[$fragment]{
         source => $source,
       }
     }
diff --git a/spec/classes/rules_out_dns_spec.rb b/spec/classes/rules_out_dns_spec.rb
new file mode 100644
index 0000000..9e60148
--- /dev/null
+++ b/spec/classes/rules_out_dns_spec.rb
@@ -0,0 +1,76 @@
+require 'spec_helper'
+
+describe 'nftables' do
+  let(:pre_condition) { 'Exec{path => "/bin"}' }
+
+  on_supported_os.each do |os, os_facts|
+    context "on #{os}" do
+      let(:facts) { os_facts }
+
+      context 'with standard dns' do
+        let(:pre_condition) do
+          '
+          include nftables::rules::out::dns
+          '
+        end
+
+        it {
+          is_expected.to contain_concat__fragment('nftables-inet-filter-chain-default_out-rule-dnsudp').with(
+            target:  'nftables-inet-filter-chain-default_out',
+            content: %r{^  udp dport 53 accept$},
+            order:   '50',
+          )
+        }
+        it {
+          is_expected.to contain_concat__fragment('nftables-inet-filter-chain-default_out-rule-dnstcp').with(
+            target:  'nftables-inet-filter-chain-default_out',
+            content: %r{^  tcp dport 53 accept$},
+            order:   '50',
+          )
+        }
+      end
+
+      context 'with custom dns servers' do
+        let(:pre_condition) do
+          "
+          class{'nftables::rules::out::dns':
+            dns_server => ['192.0.2.1', '2001:db8::1'],
+          }
+          "
+        end
+
+        it { is_expected.to compile }
+
+        it {
+          is_expected.to contain_concat__fragment('nftables-inet-filter-chain-default_out-rule-dnsudp-0').with(
+            target:  'nftables-inet-filter-chain-default_out',
+            content: %r{^  ip daddr 192.0.2.1 udp dport 53 accept$},
+            order:   '50',
+          )
+        }
+        it {
+          is_expected.to contain_concat__fragment('nftables-inet-filter-chain-default_out-rule-dnstcp-0').with(
+            target:  'nftables-inet-filter-chain-default_out',
+            content: %r{^  ip daddr 192.0.2.1 tcp dport 53 accept$},
+            order:   '50',
+          )
+        }
+
+        it {
+          is_expected.to contain_concat__fragment('nftables-inet-filter-chain-default_out-rule-dnsudp-1').with(
+            target:  'nftables-inet-filter-chain-default_out',
+            content: %r{^  ip6 daddr 2001:db8::1 udp dport 53 accept$},
+            order:   '50',
+          )
+        }
+        it {
+          is_expected.to contain_concat__fragment('nftables-inet-filter-chain-default_out-rule-dnstcp-1').with(
+            target:  'nftables-inet-filter-chain-default_out',
+            content: %r{^  ip6 daddr 2001:db8::1 tcp dport 53 accept$},
+            order:   '50',
+          )
+        }
+      end
+    end
+  end
+end
