<!--
## 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>
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
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>
* Added basic structure for domain name shop
* Finished proof of concept for domainnameshop
* Fixed handeling of IDNA for CNAME records
* Updated documentation notes
* Added docs
* Ran linter and vet
* Removed proxy config used for debugging
* Ran go generate
* Fixed issue with TTLs being restricted to a multiple of 60
* Ran tests, vet and linting and fixed flaws
* Fixed typo in docs
* Improved code based on feedback
* Fixed issues with TXT records not working properly
* Refactored according to new file layout proposed
* Updated documentation matrix
* Suggestions and corrections
* Corrected according to suggestions
Co-authored-by: Simen Bai <git@simenbai.no>
Co-authored-by: Tom Limoncelli <tlimoncelli@stackoverflow.com>
Anthony delegates all tasks relating to our DNSControl DNSimple integration to me. It would be more efficient to set me as the code owner.
I am an employee of DNSimple and use DNSControl's DNSimple integration in my other projects as well.
CC @aeden in case he needs to sign off.
* Update maintainers for Route53 and Cloudflare
I'm happy to take these two over in addition to EasyName.
* Missed a volunteer request reference
Co-authored-by: Tom Limoncelli <tlimoncelli@stackoverflow.com>
* Initial support for easyname as registrar
* DRY
Moving a bunch of the HTTP stuff into a single function for cleanliness and ease of future maintianence.
* Seperate API and Provider logic
* Updating error messages and sorting found nameservers
* Adding provider info to OWNERS and README
This also moves a few of the not-actually-DNS Providers to their own section.
* Update README.md
Co-authored-by: Tom Limoncelli <tlimoncelli@stackoverflow.com>
* implement DNS Made Easy provider
* fix sandbox instructions in DNS Made Easy provider docs
* remove unnecessary blank lines and fix golint warnings
* remove unused deleteRecord method from DNSME api
* remove trailing comma in providers.json
* implement check for TXT records with double quotes for DNSME provider
* implement changing apex NS records
* rename DNSME to DNSMADEEASY
Co-authored-by: Tom Limoncelli <tlimoncelli@stackoverflow.com>
* Add http.net provider
* Rename httpnetProvider
* Add SSHFP capability
* Add paging for records
* Sort documentation notes alphabetically
* Add custom base URL
* Extend documentation for custom base URL
* - renamed to hosting.de
- Fix EnsureDomainExists
- GetNameservers read from NS Records
* Replaced http.net with hosting.de
Contributor Support from hosting.de
* baseURL for hosting.de in documentation
replaced %v with %w for errors
special handling for txt records using .TxtStrings
* removed last references to rc.Target
fixed Trim of last dot
* Re-engineer TXT records for simplicity and better compliance (#1063)
Co-authored-by: Tom Limoncelli <tlimoncelli@stackoverflow.com>
Co-authored-by: Oliver Dick <o.dick@hosting.de>
Co-authored-by: Oliver Dick <31733320+membero@users.noreply.github.com>
* HETZNER: implement the provider for Hetzner DNS Console
Signed-off-by: Jakob Ackermann <das7pad@outlook.com>
* HETZNER: apply review feedback
- add domain into error messages
- insert sub-strings using `%q`
- insert sub-errors using `%w`
- change api.getZone() signature to return a (potentially `nil`) Zone
pointer instead of a (potentially empty) Zone value
- sort imports and confirm with `$ goimports -w providers/hetzner/`
- use exact 'api_key' term in error message of settings validation
- add blank line for logic separation
- drop internal record id from correction messages
Co-Authored-By: Tom Limoncelli <tlimoncelli@stackoverflow.com>
Signed-off-by: Jakob Ackermann <das7pad@outlook.com>
* HETZNER: add request rate-limiting handling
There are a limited number of data-points on how their rate-limiting
works at this time. I deduce from my account to others and use a fixed/
constant backoff of 1s as the initial delay. Thereafter exponential
increase with factor 2 (not needed at this time).
Hetzner has not made any official statements on rate-limiting, so this
is guesswork only.
Signed-off-by: Jakob Ackermann <das7pad@outlook.com>
* HETZNER: address golint complaints
- baseUrl -> baseURL
- mark Record as private -> record
- mark Zone as private -> zone
- mark RequestRateLimiter as private -> requestRateLimiter
- capitalize Id fields as ID
- keep delay logic on same level, move return out of branch
Signed-off-by: Jakob Ackermann <das7pad@outlook.com>
* HETZNER: rate_limited: init the response timestamp on requestRateLimiter
Signed-off-by: Jakob Ackermann <das7pad@outlook.com>
* HETZNER: requestRateLimiter: align local variable with struct name
Signed-off-by: Jakob Ackermann <das7pad@outlook.com>
Co-authored-by: Tom Limoncelli <tlimoncelli@stackoverflow.com>