Skip to content

Add DNSZone controller for Designate DNS zone support - #956

Open
zunken1337 wants to merge 1 commit into
k-orc:mainfrom
zunken1337:new-controller-dnszone
Open

zunken1337 wants to merge 1 commit into
k-orc:mainfrom
zunken1337:new-controller-dnszone

Conversation

@zunken1337

@zunken1337 zunken1337 commented Oct 2, 2026 •

Copy link
Copy Markdown

Summary

Closes #954. First of three Designate controllers split out of #955 at @mandre's request
(#955 (comment)) -
+16k LOC in one PR was too large to review. This one adds DNSZone (zone CRUD). RecordSet
(#957) and DNSZoneShare (#958) follow as separate PRs, both stacked on this one since they
extend the same shared DNSClient this PR introduces.

Credit

This supersedes @eshulman2's stalled #825, which has been without activity since late June and
has accumulated merge conflicts against the current generic-controller framework. Per @mandre's
own suggestion on #825, this is a fresh implementation built from the current scaffolding rather
than a rebase of #825 - but #825's work is gratefully acknowledged: reviewing it first is what
surfaced two real gaps fixed here (a projectID status field missing entirely, and masters
typed as an unvalidated []string rather than a real IP type), and its own review thread
(#825 (comment)) has the
full writeup. @eshulman2, if you'd rather finish #825 yourself instead, just say so - happy to
close this in favor of that.

Architecture notes

  • Introduces osclients.DNSClient, a single shared client for all Designate resources (the "one
    service, one client" convention NetworkClient already established for Neutron), rather than
    a dedicated client per kind. Zone-only for now; RecordSet and DNSZoneShare each extend this
    same interface with their own methods in their own PRs.
  • DNSZone.spec.resource.name must be explicit and end with a period - Designate rejects
    anything else, and unlike most other resources there's no sensible object-name fallback (the
    ORC object's own Kubernetes name won't have a trailing period).
  • Type (PRIMARY/SECONDARY) and Masters/TransferredAt model Designate's own DNS-protocol
    zone transfer (AXFR master/slave replication) - a different thing from Designate's
    project-ownership zone transfer (transfer_requests/transfer_accepts), which this PR does
    not implement. That's intentional scope control, not an oversight: project-ownership transfer
    needs two different projects' credentials in one flow (see Enhancement: Glance image member sharing (grant + accept) #948's Image sharing for the same
    shape), while DNSZoneShare (next PR in this series) covers the single-credential alternative
    we chose to support first.

Testing

  • Unit test for the one mutable-field update path (description/ttl/masters, masters compared as
    a set, not positionally, since Designate doesn't guarantee return order).
  • Full test/apivalidations suite extended with immutability, required-field, and PRIMARY/
    SECONDARY cross-field CEL validation tests.
  • All 5 required KUTTL e2e scenarios.
  • Caught and fixed a real bug via the full go test ./... run (not just the package under active
    work): a curly/smart quote had snuck into one CEL rule's string literal, which would have made
    the CRD uninstallable on any real Kubernetes API server (controller-gen doesn't validate CEL
    syntax, it just transcribes the rule string - the breakage only surfaced when envtest tried to
    actually install the CRD). Fixed by using has(self.email) instead of comparing against an
    empty string literal, which also matches the convention every other CEL rule in this codebase
    already uses.
  • This is the first K-ORC controller to need Designate, so the e2e workflow's devstack deployment
    never had it enabled - added enable_plugin designate ... + DESIGNATE_BACKEND_DRIVER=bind9
    to .github/workflows/e2e.yaml, same pattern already used for neutron/manila.

Test plan

  • go build ./..., go vet ./..., gofmt -l . clean
  • go test ./... passes (only unrelated test/e2e, which needs a live kind cluster, fails in
    this environment)
  • make generate output committed (CRDs, deepcopy, adapters/controllers,
    applyconfiguration/clientset/lister/informer, mocks, API reference docs)
  • make lint clean (0 issues)
  • KUTTL e2e suite run against a real OpenStack cloud in CI

🤖 Generated with Claude Code

First of three Designate controllers split out of a single oversized
PR (zone, then DNSZoneShare and RecordSet as separate follow-up PRs)
at mandre's request - ~16k LOC in one PR was too large to review.

DNSZone covers zone CRUD (PRIMARY/SECONDARY, AXFR masters, serial,
transferredAt) against a new shared osclients.DNSClient, following
the same "one OpenStack service, one client" convention NetworkClient
already established for Neutron. DNSZoneShare and RecordSet will each
add their own methods to this same client in their own PRs, since all
three are Designate resources on one ServiceClient.

Credit: this picks up the gap left by @eshulman2's stalled k-orc#825 (zone
CRUD only, no project-ownership transfer, no RecordSet) with a fresh
implementation built via the current scaffolding, rather than
rebasing k-orc#825 through months of generic-controller-framework changes
- the path mandre suggested. k-orc#825 gets closed/superseded by this
series; eshulman2's original design exploration there is gratefully
acknowledged and is what first surfaced several of the real gaps this
PR fixes (a projectID-in-status field that was missing entirely, and
Masters typed as unvalidated []string rather than a real IP type).

Full test coverage: unit test for the one mutable-field update path
(description/ttl/masters, masters compared as a set not positionally),
the full test/apivalidations envtest/CEL suite, and all 5 required
KUTTL e2e scenarios. Verified via `make generate`, `make lint` (0
issues), and `make test` (full suite, zero regressions) on real
hardware before pushing - gofmt specifically checked byte-for-byte
after a prior session found it can corrupt an empty-string CEL
comparison into a smart quote; avoided here by using has() instead,
which also matches every other CEL rule already in this codebase.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Signed-off-by: Joakim Johansson <joakimjohansson@cleura.nu>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

semver:major Breaking change

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Designate DNS zone + record support (DNSZone, DNSZoneShare, RecordSet)

1 participant