NEW PROVIDER: NexDNS - #4685
Conversation
TomOnTime
left a comment
There was a problem hiding this comment.
Hi there!
Thank you for submitting this new provider! We love to get new submissions!
I'd really like to add NexDNS to the automated testing we do on GHA. Is there a free tier or some way I can get an API key to do the testing? It doesn't have to be a real domain (sandbox or unregistered zone is fine). Since this is an all-volunteer project, we look for any free way to do this testing.
Thanks!
Tom
|
Hi Tom, happy to. There is now a free account for the project, with no expiry and nothing to pay.
The Where would you like the token sent? Happy to use whatever you normally do for this. |
|
Fantastic! I normally use SendSafely.com. Please send to my email address (tal at whatexit dot org). I'm also open to any other mechanism (1password, etc). SendSafely has a free tier. Tom |
|
Sent via SendSafely to your address. |
|
I received the creds. Thanks! I'll try to get to this in the next few days. |
|
Code looks good. I'll merge this and then move it to the v5 branch. There's a lot of unit tests for things that don't normally need testing. I suspect an LLM was used? I don't mind, that's allowed. However the code does need to be cleaned up a bit. |
|
Thank you for contributing this new provider, @morozov-alexey ! A few action items before we can merge this PR:
Thanks again! |
| "customer-number": "$NETCUP_CUSTOMER_NUMBER", | ||
| "domain": "$NETCUP_DOMAIN" | ||
| }, | ||
| "NEXDNS": { |
There was a problem hiding this comment.
Please put this in alphabetical order. If you run bin/generate-all.sh it will do that for you.
| // rejectif has a helper for the trailing case but not for this one, because the | ||
| // integration suite leaves leading whitespace untested - it is nonetheless | ||
| // trimmed the same way here. | ||
| func rejectTxtLeadingSpace(rc *models.RecordConfig) error { |
There was a problem hiding this comment.
This seems useful to others. Pleave move it to pkg/rejectif/txt.go
| // rejectCaaTag rejects CAA records whose property tag the API does not accept. | ||
| func rejectCaaTag(rc *models.RecordConfig) error { | ||
| if !slices.Contains(caaTags, rc.CaaTag) { | ||
| return fmt.Errorf("caa tag %q is not supported", rc.CaaTag) | ||
| } | ||
| return nil | ||
| } |
There was a problem hiding this comment.
This seems useful to others. Please move it to pkg/rejectif/caa.go
| "github.com/DNSControl/dnscontrol/v4/models" | ||
| ) | ||
|
|
||
| func TestAuditRecords(t *testing.T) { |
There was a problem hiding this comment.
Move these to pkg/rejectif/*_test.go as appropriate.
|
|
||
| switch rc.Type { | ||
| case "MX": | ||
| req.Content = rc.GetTargetField() |
There was a problem hiding this comment.
Please move "Content" to the end of each case. I know this sounds weird, but i try to keep these in the same order as they appear in the struct defined in https://codeberg.org/miekg/dns/src/branch/main/rdata/rdata.go
| tc("Create some records", | ||
| a("foo", "1.1.1.1"), | ||
| a("foo", "10.10.10.10"), | ||
| a("foo", "9.9.9.9"), |
There was a problem hiding this comment.
| a("foo", "9.9.9.9"), | |
| a("foo", "9.9.9.9"), // Use a non-RFC1918 address since some DSP reject internal IPs |
| func TestNewNexdns(t *testing.T) { | ||
| if _, err := newNexdns(map[string]string{}, json.RawMessage{}); err == nil { | ||
| t.Error("expected an error when api_token is missing") | ||
| } | ||
|
|
||
| p, err := newNexdns(map[string]string{"api_token": "nxd_notarealtoken"}, json.RawMessage{}) | ||
| if err != nil { | ||
| t.Fatalf("newNexdns() error = %v", err) | ||
| } | ||
| if got := p.(*nexdnsProvider).client.baseURL; got != defaultAPIURL { | ||
| t.Errorf("baseURL = %q, want %q", got, defaultAPIURL) | ||
| } | ||
|
|
||
| p, err = newNexdns(map[string]string{"api_token": "nxd_notarealtoken", "api_url": "https://api.example.com/v1"}, json.RawMessage{}) | ||
| if err != nil { | ||
| t.Fatalf("newNexdns() error = %v", err) | ||
| } | ||
| if got := p.(*nexdnsProvider).client.baseURL; got != "https://api.example.com/v1" { | ||
| t.Errorf("baseURL = %q, want the configured one", got) | ||
| } | ||
| } |
There was a problem hiding this comment.
Delete. Seems superfluous
| func TestNewNexdns(t *testing.T) { | |
| if _, err := newNexdns(map[string]string{}, json.RawMessage{}); err == nil { | |
| t.Error("expected an error when api_token is missing") | |
| } | |
| p, err := newNexdns(map[string]string{"api_token": "nxd_notarealtoken"}, json.RawMessage{}) | |
| if err != nil { | |
| t.Fatalf("newNexdns() error = %v", err) | |
| } | |
| if got := p.(*nexdnsProvider).client.baseURL; got != defaultAPIURL { | |
| t.Errorf("baseURL = %q, want %q", got, defaultAPIURL) | |
| } | |
| p, err = newNexdns(map[string]string{"api_token": "nxd_notarealtoken", "api_url": "https://api.example.com/v1"}, json.RawMessage{}) | |
| if err != nil { | |
| t.Fatalf("newNexdns() error = %v", err) | |
| } | |
| if got := p.(*nexdnsProvider).client.baseURL; got != "https://api.example.com/v1" { | |
| t.Errorf("baseURL = %q, want the configured one", got) | |
| } | |
| } |
|
Trimmed the tests down to the round trip, the apex NS filter and the audit rules. Left the retry in Invite accepted, and emailed Faisal. |
Adds a DNS provider for NexDNS. I run the service and will maintain the provider.
The API addresses one record value at a time, so the provider uses diff2.ByRecord(). A record's id is derived from its name, type and content, so an id stops resolving as soon as the record it names changes; each correction therefore uses only the id it read from the zone it is about to modify.
Supported: A, AAAA, ALIAS, CAA, CNAME, DNAME, DS, MX, NS, PTR, SRV, TLSA, TXT. The SOA record and the apex NS records are maintained by the platform and rejected by the API, so both are left out of the zone contents and the desired state, and DocDualHost is Cannot.
The integration suite passes: 249 cases, 0 failures. It needed two changes in integrationTest/integration_test.go, and I would rather flag them than have you find them.
NEXDNS is added to the not(...) list of the apex-NS group: the apex NS records follow the zone's nameserver group and the API rejects an edit, which is what NAMEDOTCOM and NETCUP are excluded for.
In "IGNORE with modify", one address changes from 10.10.10.10 to 9.9.9.9. That value is only the "before" of the change the following cases make (10 -> 11 -> 12 -> 13), so the range looks incidental to what the test checks, while an RFC 1918 address is refused outright by any provider serving public zones only; 9.9.9.9 is already used elsewhere in the same file. Happy to exclude NEXDNS from the group instead if you prefer, but that would drop the whole of the IGNORE semantics from this provider's coverage over one value the test does not depend on.
Please create the GitHub label 'provider-NEXDNS'.