Repository navigation
feat(p/CONSTELLIX): add Constellix DNS provider - #5029
Merged
Merged
Conversation
Add a DNS provider for Constellix (CONSTELLIX) using the DNS v4 API. - Record sets are diffed with diff2.ByRecordSet and applied with one POST, PUT or DELETE per set, addressed by record ID. - Supports Basic8, ALIAS (as ANAME with skipLookup) and PTR in reverse zones; SOA is declared unimplemented. - Lists and creates zones through pkg/zonecache. - Drops configured apex NS records that point at the zone's own Constellix nameservers; other apex NS records are managed, so dual hosting works. - Refuses on read any record that uses a feature DNSControl does not model (failover, pools, GTD regions, IP filters, GeoProximity, disabled records or values, other types, template-linked zones). - Honours the account-wide rate limit: on 429 or X-RateLimit-Remaining 0 all requests wait until X-RateLimit-Reset, and a 429 is resent. - Writes TXT strings back to back and reads them back from the joined text, because the API re-splits long values itself. Refs DNSControl#842
TomOnTime
approved these changes
Oct 21, 2026
Collaborator
|
Thank you for contributing to this new provider, @ZeroClover ! An action item before we can merge this PR:
When I receive the email, I’ll merge this PR. Thanks again! |
Contributor
Author
|
Hi @TomOnTime I've sent the email. Thanks. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a DNS provider for Constellix (
CONSTELLIX), using their DNS v4 API. Closes #842 ("Constellix" on the requested-providers list).Please create the GitHub label 'provider-CONSTELLIX'
What it does
diff2.ByRecordSet: a Constellix record object is one name + type with a list of values, so each change is onePOST(create),PUT(complete value list + TTL; the API's PUT is partial) orDELETE, addressed by the record's ID.Basic8,ALIAS(ConstellixANAME, sent withskipLookupso a target created in the same push is accepted),PTRin reverse zones only (Constellix refuses PTR names in forward zones:The name is not valid).SOAis declared unimplemented.get-zones/ListZonesandcreate-domains/ auto-create onpush(EnsureZoneExists), withpkg/zonecachelike CLOUDFLAREAPI. A zone whose creation or first read fails is remembered with the error, so the same run cannot compute a delegation without Constellix.NSrecords that point at them are dropped (like CLOUDFLAREAPI'scheckNSModifications, but matched against the zone's actual nameserver list); any other apexNSrecord is managed normally, so dual hosting works (TestDualProviderspasses).HTTPredirects,NAPTR, ...), and template-linked zones."..."".."), the form the API stores; read back from the joined text, because the API re-splits long values by their escaped length.AuditRecords: empty TXT, null MX, null SRV target, CAA tags other thanissue/issuewild/iodef, and NS records whose target is the zone apex (the API answers those with HTTP 500). TTLs above 2147483647 are lowered before the diff.Rate limit
The API allows 180 units per 60 seconds for the whole account (one request can use several units) and answers
429withoutRetry-After;X-RateLimit-Resetsays when the window resets. The client has one gate per provider instance: after a429, or a response withX-RateLimit-Remaining: 0, every request of that instance waits until the reset (+1 s; 60 s if the header is missing), and the rejected request is sent again with a fresh token (POST included: a POST applied after all would answer "already exists", never create a duplicate). A single request gives up after 5 minutes of waiting in total. No other status or transport error is retried.Testing
Integration tests
go test -timeout 120m -v -args -verbose -record -profile CONSTELLIXagainst the made-up test zonednscontrol-constellix-test.com: PASS in 789 s (13 min 15 s wall time), 0 failures.PTR→not("CONSTELLIX")(the group creates a PTR in a forward zone; Constellix:The name is not valid). PTR in reverse zones was verified by hand, below.NullMX,NullMXApex,a 0-byte TXT, andNS Record pointing to @(foo NS <zone>.answered HTTP 500 reproducibly, even with the apex A in place).pager101passes; all other skipped groups are capability-gated oronly(...)groups for other providers.Full output: https://gist.github.com/ZeroClover/217e5b72d4ac21604d31c37159339d4b
TXT procedure (
testing-txt-records.md)t0–t3 were created in the Constellix portal with the values
test0,test1,"test2","test3". The portal's TXT field is read like zone-file text (the same as the API), so"test2"is stored as the stringtest2: the API returned"test0","test1","test2","test3"and the authoritative server answered the same.preview(withDefaultTTL(1800), the portal's default) therefore reported changes for t1 and t3, not t1 and t2. Afterpush,previewis clean and the authoritative answers (dig @ns11.constellix.comand@ns41.constellix.net) equal the strings indnsconfig.js:"test0""\"test1\"""test2""\"test3\""PTR in reverse zones
2.0.192.in-addr.arpaand8.b.d.0.1.0.0.2.ip6.arpa: push created single- and multi-value PTR sets (including a 24-nibble IPv6 name and a relative target), changed a target and deleted sets;dig @ns11.constellix.comshowed each state (IPv6 answers lag a few seconds after a write), andpreviewwas clean after every push.Concurrency
go build -race, thendnscontrol preview --cmode allover four test zones, twice: no race report, soCanConcurstaysCan(). A unit test also reads six zones concurrently with a429on one of them undergo test -race.Other checks
go generate ./...: generated files up to date.golangci-lint run ./...: 0 issues.staticcheck ./...: clean.modernize -fix ./...: no changes.go vet ./...: clean.go test ./...: passes (except twopkg/spflibtests that look upspf.mtasv.net, which does not resolve from my machine; unrelated).Notes