diff --git a/api/v1alpha1/bindzone_types.go b/api/v1alpha1/bindzone_types.go index e7925b3..a90c64a 100644 --- a/api/v1alpha1/bindzone_types.go +++ b/api/v1alpha1/bindzone_types.go @@ -103,7 +103,7 @@ type BindZoneSpec struct { // +optional DNSSECPolicyRef string `json:"dnssecPolicyRef,omitempty"` - // Forwarders lists upstreams for a forward-type zone. + // Forwarders lists upstreams for a forward-type zone; an empty list disables forwarding for the zone. // +optional Forwarders []string `json:"forwarders,omitempty"` diff --git a/config/crd/bases/bind.unkin.net_bindzones.yaml b/config/crd/bases/bind.unkin.net_bindzones.yaml index 11e193c..ad3cf24 100644 --- a/config/crd/bases/bind.unkin.net_bindzones.yaml +++ b/config/crd/bases/bind.unkin.net_bindzones.yaml @@ -90,7 +90,8 @@ spec: When true, UpdateKeyRef must reference a BindTSIGKey. type: boolean forwarders: - description: Forwarders lists upstreams for a forward-type zone. + description: Forwarders lists upstreams for a forward-type zone; an + empty list disables forwarding for the zone. items: type: string type: array diff --git a/config/crd/install.yaml b/config/crd/install.yaml index 29a9f1d..9e8d89a 100644 --- a/config/crd/install.yaml +++ b/config/crd/install.yaml @@ -2763,7 +2763,8 @@ spec: When true, UpdateKeyRef must reference a BindTSIGKey. type: boolean forwarders: - description: Forwarders lists upstreams for a forward-type zone. + description: Forwarders lists upstreams for a forward-type zone; an + empty list disables forwarding for the zone. items: type: string type: array diff --git a/internal/bind/render.go b/internal/bind/render.go index b00c680..190d882 100644 --- a/internal/bind/render.go +++ b/internal/bind/render.go @@ -154,8 +154,10 @@ func renderForwardZone(z bindv1alpha1.BindZone, indent string) string { b.WriteString(fmt.Sprintf("%szone \"%s\" {\n", indent, z.Spec.ZoneName)) b.WriteString(indent + " type forward;\n") b.WriteString(indent + " forward only;\n") - if len(z.Spec.Forwarders) > 0 { - b.WriteString(fmt.Sprintf("%s forwarders { %s };\n", indent, terminate(z.Spec.Forwarders))) + if list := terminate(z.Spec.Forwarders); list != "" { + b.WriteString(fmt.Sprintf("%s forwarders { %s };\n", indent, list)) + } else { + b.WriteString(indent + " forwarders { };\n") } b.WriteString(indent + "};\n") return b.String() diff --git a/internal/bind/render_test.go b/internal/bind/render_test.go index 78808ba..210fcc3 100644 --- a/internal/bind/render_test.go +++ b/internal/bind/render_test.go @@ -261,3 +261,19 @@ func TestRenderDeterministicWithShuffledForwards(t *testing.T) { t.Fatalf("render must be independent of forward-zone input order:\n--- A ---\n%s\n--- B ---\n%s", pa, pb) } } + +func TestRenderForwardZoneForwarders(t *testing.T) { + for _, tc := range []struct { + fwd []string + want string + }{ + {nil, " forwarders { };\n"}, + {[]string{"198.18.19.15", "198.18.19.16;"}, " forwarders { 198.18.19.15; 198.18.19.16; };\n"}, + } { + z := bindv1alpha1.BindZone{Spec: bindv1alpha1.BindZoneSpec{ZoneName: "spamhaus.org", Type: bindv1alpha1.ZoneForward, Forwarders: tc.fwd}} + want := "zone \"spamhaus.org\" {\n type forward;\n forward only;\n" + tc.want + "};\n" + if got := renderForwardZone(z, ""); got != want { + t.Errorf("forwarders %v:\ngot %q\nwant %q", tc.fwd, got, want) + } + } +}