# Issue
* New record type: "RP" (supported by BIND and GANDI_V5)
* Cloudflare: CF_REDIRECT/CF_TEMP_REDIRECT now generate
CF_SINGLE_REDIRECT records. All PAGE_RULE-based code is removed.
PAGE_RULEs are deprecated at Cloudflare. (be careful when upgrading!)
* New "v2" RecordConfig: RP and CF_SINGLE_REDIRECT are the only record
types that use this method. It shifts most of the work out of JavaScript
and into the Go code, making new record types easier to make, easier to
test, and easier to use by providers. This opens the door to new things
like a potential code-generator for rtypes. Converting existing rtypes
will happen over the next year.
* When only the TTL changes (MODIFY-TTL), the output lists the TTL
change first, not at the end of the line where it is visually lost.
* CF_REDIRECT/CF_TEMP_REDIRECT generate different rule "names". They
will be updated the first time you "push" with this release. The order
of the rules may also change. If you rules depend on a particular order,
be very careful with this upgrade!
Refactoring:
* New "v2" RecordConfig: Record types using this new method simply
package the parameters from dnsconfig.js statements like
CF_REDIRECT(foo,bar) and send them (raw) to the Go code. The Go code
does all processing, validation, etc. and turns them into RecordConfig
that store all the rdata in `RecordConfig.F`. No more adding fields to
RecordConfig for each new record type!
* RecordConfig.IsModernType() returns true if the record uses the new v2
record mechanism.
* PostProcess is now a method on DnsConfig and DomainConfig.
* DOC: How to create new rtypes using the v2 method (incomplete)
Other things:
* Integration tests for CF "full proxy" are removed. This feature
doesn't exist any more.
* DEV: Debugger tips now includes VSCode advice
* TESTING: The names of testgroup's can now have extra spaces to make
data align better
* CF_TEMP_REDIRECT/CF_REDIRECT is now a "builder" that generates
CLOUDFLAREAPI_SINGLE_REDIRECT records.
* And more!
# Resolution
---------
Co-authored-by: Jakob Ackermann <das7pad@outlook.com>
<!--
## Before submiting a pull request
Please make sure you've run the following commands from the root
directory.
bin/generate-all.sh
(this runs commands like "go generate", fixes formatting, and so on)
## Release changelog section
Help keep the release changelog clear by pre-naming the proper section
in the GitHub pull request title.
Some examples:
* CICD: Add required GHA permissions for goreleaser
* DOCS: Fixed providers with "contributor support" table
* ROUTE53: Allow R53_ALIAS records to enable target health evaluation
More examples/context can be found in the file .goreleaser.yml under the
'build' > 'changelog' key.
!-->
https://github.com/StackExchange/dnscontrol/issues/420
Please create the GitHub label 'provider-ALIDNS'
---------
Co-authored-by: Tom Limoncelli <6293917+tlimoncelli@users.noreply.github.com>
The PR follows https://github.com/StackExchange/dnscontrol/pull/3542
Found some bugs when running intergration tests locally again, and the
PR is an attempt to fix them:
- When updating/creating HTTPS/SRV records, Vercel API only reads from
the corresponding struct (either `srv` or `https`). If we provide a
`value`, the Vercel API will reject with an error.
- The PR makes `Value` "nil-able", and sets `Value` to nil when dealing
with `SRV` or `HTTPS` records.
- When updating a record, currently, we treat the empty SVC param as
omitting the field. But with Vercel's API, omitting a field means not
updating the field. We need to explicitly make the field an empty string
to create/update an empty SVC param, and the PR does that.
- Vercel implements an unknown `ech=` parameter validation process for
HTTPS records. The validation process is unknown, undocumented, thus I
can't implement a `rejectif` for `AuditRecord`.
- Let's make this a known caveat, describe it in the provider docs, skip
these intergration tests, and move on.
Please tag this PR w/ `provider-VERCEL`.
# Issue
The previous fix had backwards compatibility issues and treated
uppercase Unicode incorrectly.
# Resolution
* Don't call strings.ToUpper() on Unicode strings. Only call it on the
output of ToASCII.
* Fix BIND's "filenameformat" to be more compatible (only breaks if you
had uppercase unicode in a domain name... which you probably didn't)
* Change IDN to ASCII in most places (Thanks for the suggestion,
@KaiSchwarz-cnic!)
* Update BIND documentation
Hi @D3luxee!
While reviewing all the `ZoneCreator` implementations, I noticed that
the DESEC provider has an incomplete caching implementation for zones.
The provider is populating the cache once on first access. Any zones
that are created will not be readable in the same life-cycle of
dnscontrol. This PR is populating the zone cache after creating a zone.
Would you mind giving this a try and let me know how it goes? Thanks!
Part of https://github.com/StackExchange/dnscontrol/issues/3007
Hi @pragmaton!
While reviewing all the `ZoneCreator` implementations, I noticed that
the CLOUDNS provider has an incomplete caching implementation for zones.
The provider is populating the cache once on first access. Any zones
that are created will not be readable in the same life-cycle of
dnscontrol. This PR is populating the zone cache after creating a zone.
Would you mind giving this a try and let me know how it goes? Thanks!
Part of https://github.com/StackExchange/dnscontrol/issues/3007
Hi @tresni!
While reviewing all the `ZoneCreator` implementations, I noticed that
the ROUTE53 provider has an unsafe caching implementation for zones and
`EnsureZoneExists` has a race-condition bug. `EnsureZoneExists` resets
the cache before making the API call for creating a given zone. This
might run concurrently to the processing of other zones and in turn
could result in unexpected behavior: the cache could get re-populated
before the creation of the zone completes and the new zone could be
missing from the newly populated cache. This PR is making all access to
the zone cache thread-safe and fixing the aforementioned race-condition.
Would you mind giving this a try and let me know how it goes? Thanks!
Bonus: The zone cache is no longer reset when creating zones. Instead,
the cache is populated with the zone that is included in the API
response from creating the zone.
Part of https://github.com/StackExchange/dnscontrol/issues/3007
- Closes https://github.com/StackExchange/dnscontrol/issues/3853
This PR is gracefully handling FQDN labels when listing records from the
Hetzner DNS Control api.
These records can be created via other tools or the browser UI.
Testing:
```diff
diff --git a/providers/hetzner/types.go b/providers/hetzner/types.go
index 964f1b7b..3429acc2 100644
--- a/providers/hetzner/types.go
+++ b/providers/hetzner/types.go
@@ -3,2 +3,3 @@ package hetzner
import (
+ "fmt"
"strings"
@@ -63,3 +64,3 @@ func fromRecordConfig(in *models.RecordConfig, zone zone) record {
r := record{
- Name: in.GetLabel(),
+ Name: in.GetLabelFQDN() + ".",
Type: in.Type,
@@ -69,2 +70,3 @@ func fromRecordConfig(in *models.RecordConfig, zone zone) record {
}
+ fmt.Printf("CREATE: %q\n", r.Name)
@@ -93,2 +95,3 @@ func toRecordConfig(domain string, r *record) (*models.RecordConfig, error) {
}
+ fmt.Printf("LISTING: %q\n", r.Name)
if strings.HasSuffix(r.Name, "."+domain+".") {
```
Config:
```js
var REG_NONE = NewRegistrar('none')
var DSP = NewDnsProvider("HETZNER")
D('testing1.dev', REG_NONE, DnsProvider(DSP),
A('@', '127.0.0.1'),
A('foo', '127.0.0.1')
)
```
First push:
```
Waiting for concurrent gathering(s) to complete...LISTING: "@"
LISTING: "@"
LISTING: "@"
LISTING: "@"
CREATE: "foo.testing1.dev."
DONE
******************** Domain: testing1.dev
1 correction (HETZNER)
#1: Batch creation of records:
+ CREATE A foo.testing1.dev 127.0.0.1 ttl=300
SUCCESS!
Done. 1 corrections.
```
Second push (no-op):
```
Waiting for concurrent gathering(s) to complete...LISTING: "@"
LISTING: "@"
LISTING: "@"
LISTING: "@"
LISTING: "foo.testing1.dev."
DONE
******************** Domain: testing1.dev
Done. 0 corrections.
```
DNS query:
```
$ dig foo.testing1.dev. @helium.ns.hetzner.de.
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 53563
foo.testing1.dev. 300 IN A 127.0.0.1
```
Additional testing:
- update/delete `foo` when record `foo.testing1.dev.` exists, works
- creating `foo.testing1.dev` is treated as
`foo.testing1.dev.testing1.dev.` in the API, hence the specific suffix
check for `<dot>DOMAIN<dot>`
- Test with HETZNER_V2, rejects records with FQDN
```
FAILURE! has dot (.) suffix (invalid_input, 50f9cf872ed8f1f808fd33c25cf88a81)
```
<!--
## Before submiting a pull request
Please make sure you've run the following commands from the root
directory.
bin/generate-all.sh
(this runs commands like "go generate", fixes formatting, and so on)
## Release changelog section
Help keep the release changelog clear by pre-naming the proper section
in the GitHub pull request title.
Some examples:
* CICD: Add required GHA permissions for goreleaser
* DOCS: Fixed providers with "contributor support" table
* ROUTE53: Allow R53_ALIAS records to enable target health evaluation
More examples/context can be found in the file .goreleaser.yml under the
'build' > 'changelog' key.
!-->
Closes https://github.com/StackExchange/dnscontrol/issues/3787
This PR is adding a `HETZNER_V2` provider for the "new" Hetzner DNS API.
Testing:
- The integration tests are passing.
- Manual testing:
- `preview` (see diff for existing zone)
- `preview --populate-on-preview` (see full diff for newly created zone)
- `push` (see full diff; no diff after push)
- `push` (see full diff; no diff after push to newly created zone --
i.e. single pass and done)
```js
var REG_NONE = NewRegistrar('none')
var DSP = NewDnsProvider('HETZNER_V2')
D('testing-2025-11-14-7.dev', REG_NONE, DnsProvider(DSP),
A('@', '127.0.0.1')
)
```
<details>
```
# push for newly created zone
CONCURRENTLY checking for 1 zone(s)
SERIALLY checking for 0 zone(s)
Waiting for concurrent checking(s) to complete...DONE
******************** Domain: testing-2025-11-14-7.dev
1 correction (HETZNER_V2)
#1: Ensuring zone "testing-2025-11-14-7.dev" exists in "HETZNER_V2"
SUCCESS!
CONCURRENTLY gathering records of 1 zone(s)
SERIALLY gathering records of 0 zone(s)
Waiting for concurrent gathering(s) to complete...DONE
******************** Domain: testing-2025-11-14-7.dev
4 corrections (HETZNER_V2)
#1: ± MODIFY-TTL testing-2025-11-14-7.dev NS helium.ns.hetzner.de. ttl=(3600->300)
± MODIFY-TTL testing-2025-11-14-7.dev NS hydrogen.ns.hetzner.com. ttl=(3600->300)
± MODIFY-TTL testing-2025-11-14-7.dev NS oxygen.ns.hetzner.com. ttl=(3600->300)
SUCCESS!
#2: + CREATE testing-2025-11-14-7.dev A 127.0.0.1 ttl=300
SUCCESS!
Done. 5 corrections.
```
</details>
Feedback for @jooola and @LKaemmerling:
- The SDK was very useful in getting 80% there! Nice! 🎉
- Footgun:
- The `result` values are not "up-to-date" after waiting for an
`Action`, e.g. `Zone.AuthoritativeNameservers.Assigned` is not set when
`Client.Zone.Create()` returns and the following "wait" will not update
it.
- Taking a step back here: Waiting for an `Action` with a separate SDK
call does not seem very natural to me. Does the SDK-user need to know
that you are processing operations asynchronous? (Which seems like an
implementation detail to me, something that the SDK could abstrct over.)
Can `Client.Zone.Create()` return the final `Zone` instead of the
intermediate result?
- Features missing compared to the DNS Console, in priority order:
- It is no longer possible to remove your provided name servers from the
root/apex. Use-case: dual-home/multi-home zone with fewer than three
servers from Hetzner. I'm operating one of these and cannot migrate over
until this is fixed.
- Performance regression due to lack of bulk create/modify. E.g. [one of
the test
suites](a71b89e5a2/integrationTest/integration_test.go (L619))
spends about 4.5 minutes on making creating 100 record-sets and then
another 4 minutes for deleting them in sequence again. With your async
API, these are `create 2*100 + delete 2*100 = 400` API calls.
Previously, these were `create 1 + delete 100 = 101` API calls. Are you
planning on adding batch processing again?
- Usability nits
- Compared to other record-set based APIs, upserts for record-sets are
missing. This applies to records of a record-set and the ttl of the
record-set (see separate SDK calls for the cases `diff2.CREATE` vs
`diff2.CHANGE` and two calls in `diff2.CHANGE` for updating the TTL vs
records).
- Some SDK methods return an `Action` (e.g. `Zone.ChangeRRSetTTL()`),
others wrap the `Action` in a struct (`Client.Zone.CreateRRSet()`) --
even when the struct has a single field (`ZoneRRSetDeleteResult`).
---------
Co-authored-by: "Jonas L." <jooola@users.noreply.github.com>
Co-authored-by: "Lukas Kämmerling" <LKaemmerling@users.noreply.github.com>
Co-authored-by: Tom Limoncelli <6293917+tlimoncelli@users.noreply.github.com>
# Issue
Fixes https://github.com/StackExchange/dnscontrol/issues/3842
CC @das7pad
# Resolution
Convert domain.Name to IDN earlier in the pipeline. Hack the --domains
processing to convert everything to IDN.
* Domain names are now stored 3 ways: The original input from
dnsconfig.js, canonical IDN format (`xn--...`), and Unicode format. All
are downcased. Providers that haven't been updated will receive the IDN
format instead of the original input format. This might break some
providers but only for users with unicode in their D("domain.tld").
PLEASE TEST YOUR PROVIDER.
* BIND filename formatting options have been added to access the new
formats.
# Breaking changes
* BIND zonefiles may change. The default used the name input in the D()
statement. It now defaults to the IDN name + "!tag" if there is a tag.
* Providers that are not IDN-aware may break (hopefully only if they
weren't processing IDN already)
---------
Co-authored-by: Jakob Ackermann <das7pad@outlook.com>
# Issue
The maintainers of OPENSRC and DIGITALOCEAN have indicated they would
like to step down.
@chicks-net has stepped up to take over maintenance of DIGITALOCEAN.
# Resolution
* Update the `OWNERS` file.
* Update the `providerMaintainer` value for the providers.
* Update the README file.
CC @Deraen @philhug @chicks-net
---------
Co-authored-by: Jeffrey Cafferata <jeffrey@jcid.nl>
<!--
## Before submiting a pull request
Please make sure you've run the following commands from the root
directory.
bin/generate-all.sh
(this runs commands like "go generate", fixes formatting, and so on)
## Release changelog section
Help keep the release changelog clear by pre-naming the proper section
in the GitHub pull request title.
Some examples:
* CICD: Add required GHA permissions for goreleaser
* DOCS: Fixed providers with "contributor support" table
* ROUTE53: Allow R53_ALIAS records to enable target health evaluation
More examples/context can be found in the file .goreleaser.yml under the
'build' > 'changelog' key.
!-->
The PR fixes#3850.