From 242bcd98d9f78b76a5b9acba8897c2d93d076e82 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mats=20T=C3=B6rnberg?= Date: Fri, 16 Oct 2026 10:34:31 +0200 Subject: [PATCH] migrate: read the live address overrides from the zones ConfigMap, not the seed The old console kept the zone files and the live address-overrides.rpz in the same fancy-dns-zones ConfigMap; fancy-dns-rpz was only the static seed the overrides started from. Reading the live cluster showed the two had diverged (6 entries against 5, the missing one being stackship.k6n.net), so the default would have silently dropped a redirect. The default is now fancy-dns-zones, and the test puts a different stale seed in fancy-dns-rpz so reading the wrong one fails. Co-Authored-By: Claude Sonnet 5.5 --- cmd/fancy-dns-console/migrate.go | 2 +- cmd/fancy-dns-console/migrate_test.go | 17 +++++++++++++---- deploy/MIGRATION.md | 9 +++++---- 3 files changed, 19 insertions(+), 9 deletions(-) diff --git a/cmd/fancy-dns-console/migrate.go b/cmd/fancy-dns-console/migrate.go index 26177f1..fad45de 100644 --- a/cmd/fancy-dns-console/migrate.go +++ b/cmd/fancy-dns-console/migrate.go @@ -41,7 +41,7 @@ func migrateMain(args []string, stdout, stderr io.Writer) error { kubeconfig = fs.String("kubeconfig", os.Getenv("FANCYDNS_KUBECONFIG"), "kubeconfig (default: in-cluster, then $KUBECONFIG, then ~/.kube/config)") kubeContext = fs.String("kube-context", os.Getenv("FANCYDNS_KUBE_CONTEXT"), "kubeconfig context") zonesCM = fs.String("zones-configmap", "fancy-dns-zones", "ConfigMap holding the zone--.zone files (\"\" to skip)") - rpzCM = fs.String("rpz-configmap", "fancy-dns-rpz", "ConfigMap holding the address-overrides RPZ (\"\" to skip)") + rpzCM = fs.String("rpz-configmap", "fancy-dns-zones", "ConfigMap holding the address-overrides RPZ (\"\" to skip). The old console kept it in the same ConfigMap as the zone files; fancy-dns-rpz was only the seed it started from") rpzKey = fs.String("rpz-key", "address-overrides.rpz", "key of the RPZ in that ConfigMap") zonesDir = fs.String("zones-dir", "", "read zone files from this directory (.zone) instead of the ConfigMap") rpzFile = fs.String("rpz-file", "", "read the address-overrides RPZ from this file instead of the ConfigMap") diff --git a/cmd/fancy-dns-console/migrate_test.go b/cmd/fancy-dns-console/migrate_test.go index 3eae394..d56d9d8 100644 --- a/cmd/fancy-dns-console/migrate_test.go +++ b/cmd/fancy-dns-console/migrate_test.go @@ -58,8 +58,11 @@ func useClient(t *testing.T, c dynamic.Interface) { // wrote, prints manifests without touching anything, and then applies them. func TestMigrateFromTheClusterThenApply(t *testing.T) { c := fakeCluster( - configMap("dns", "fancy-dns-zones", map[string]any{"zone--home.example.com.zone": zone, "unrelated": "x"}), - configMap("dns", "fancy-dns-rpz", map[string]any{"address-overrides.rpz": rpz}), + // The old console kept the zone files and the live overrides in one + // ConfigMap; fancy-dns-rpz was only the seed it started from, and is + // deliberately different here so reading the wrong one fails. + configMap("dns", "fancy-dns-zones", map[string]any{"zone--home.example.com.zone": zone, "address-overrides.rpz": rpz, "unrelated": "x"}), + configMap("dns", "fancy-dns-rpz", map[string]any{"address-overrides.rpz": "$TTL 60\nstale-seed.example A 10.0.0.1\n"}), ) useClient(t, c) @@ -81,9 +84,15 @@ func TestMigrateFromTheClusterThenApply(t *testing.T) { if err := migrateMain([]string{"-kube-namespace", "dns", "-apply"}, &out, &errb); err != nil { t.Fatalf("apply: %v\n%s", err, errb.String()) } - if l, _ := c.Resource(kubesource.OverrideGVR).Namespace("dns").List(context.Background(), metav1.ListOptions{}); len(l.Items) != 2 { + l, _ := c.Resource(kubesource.OverrideGVR).Namespace("dns").List(context.Background(), metav1.ListOptions{}) + if len(l.Items) != 2 { t.Fatalf("%d overrides applied, want 2", len(l.Items)) } + for _, it := range l.Items { + if strings.Contains(it.GetName(), "stale-seed") { + t.Fatal("the stale seed ConfigMap was read instead of the live one") + } + } if l, _ := c.Resource(kubesource.ZoneGVR).Namespace("dns").List(context.Background(), metav1.ListOptions{}); len(l.Items) != 1 { t.Fatalf("%d zones applied, want 1", len(l.Items)) } @@ -91,7 +100,7 @@ func TestMigrateFromTheClusterThenApply(t *testing.T) { t.Errorf("no reassurance in the report:\n%s", errb.String()) } // The ConfigMaps are exactly as they were. - cm, err := c.Resource(configMaps).Namespace("dns").Get(context.Background(), "fancy-dns-rpz", metav1.GetOptions{}) + cm, err := c.Resource(configMaps).Namespace("dns").Get(context.Background(), "fancy-dns-zones", metav1.GetOptions{}) if err != nil || cm.Object["data"].(map[string]any)["address-overrides.rpz"] != rpz { t.Fatalf("the source ConfigMap changed: %v %v", cm, err) } diff --git a/deploy/MIGRATION.md b/deploy/MIGRATION.md index d6dc1a5..f25795e 100644 --- a/deploy/MIGRATION.md +++ b/deploy/MIGRATION.md @@ -1,14 +1,15 @@ # Moving a ConfigMap deployment to cluster objects Until now the console edited zones and address redirects by writing two -ConfigMaps (`fancy-dns-zones`, `fancy-dns-rpz`) through the resolver's service -account, and the domains page rewrote the config file. Those mechanisms are gone. +ConfigMap (`fancy-dns-zones`: zone files and the live address overrides) through +the resolver's service account (`fancy-dns-rpz` was only the seed the overrides +started from), and the domains page rewrote the config file. Those mechanisms are gone. Everything the console edits is now an object: | Was | Is | |---|---| | `zone--.zone` keys in the `fancy-dns-zones` ConfigMap | `DNSZone` | -| `address-overrides.rpz` in the `fancy-dns-rpz` ConfigMap | `AddressOverride` (one per name) | +| the `address-overrides.rpz` key in the **same** `fancy-dns-zones` ConfigMap | `AddressOverride` (one per name) | | `blocklist.allow_entries` / `block_entries` | `DomainRule` (`inline-allow`, `inline-block`) | | `blocklist.lists` with a URL | `BlockList` | | `acl.groups` | `ClientGroup` | @@ -29,7 +30,7 @@ kubectl apply -f deploy/k8s/console/console.yaml # the console, which writes t ## 2. Convert what you have -The command reads the two ConfigMaps from the cluster and, if you give it the +The command reads the ConfigMap from the cluster and, if you give it the resolver's `config.yaml`, its URL lists, inline entries and ACL groups. By default it only **prints** manifests.