-
-
Notifications
You must be signed in to change notification settings - Fork 252
add hetznernetworking provider #1046
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
|
Can someone merge this? |
|
I'd be interested in this as well. Out of curiosity (I don't know much about Go):
Am I doing something wrong? |
|
@suntorytimed How did you solve the issues I described? If you didn't see those, how did you build the container? Thanks in advance! |
|
Does this work fine with wildcard? Because with this image every 5 minutes ddns-updater says it updated the wildcard dns entry but there was no change. The normal dns entry dont show this behavour. |
|
Sorry for the massive delay everyone, life got in the way; |
| func (p *Provider) BuildDomainName() string { | ||
| // Override to preserve wildcard characters for Hetzner Cloud API |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that will cause issues; BuildDomainName() is used in a few places to resolve the domain name and compare it with the current public ip address. *.domain.com is not something that can be resolved, unlike any.domain.com
| "zone_identifier": "example.com", | ||
| "domain": "example.com", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can we extract zone_identifier from domain instead? i.e. x.y.com -> y.com - it looks like extractRRName does it?
| - One of the following ([how to find API keys](https://docs.hetzner.cloud/api/getting-started/generating-api-token)): | ||
| - API Token `"token"`, configured with DNS write permissions for your DNS zone |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| - One of the following ([how to find API keys](https://docs.hetzner.cloud/api/getting-started/generating-api-token)): | |
| - API Token `"token"`, configured with DNS write permissions for your DNS zone | |
| - `"token"` is your API token configured with DNS write permissions for your DNS zone, see [how to find API keys](https://docs.hetzner.cloud/api/getting-started/generating-api-token) |
| return nil, err | ||
| } | ||
|
|
||
| ttl := uint32(1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this ok for the default ttl? Shouldn't it be i.e. 5 minutes?
| } | ||
|
|
||
| // Check if action status indicates success or is still running | ||
| if actionResp.Action.Status != "running" && actionResp.Action.Status != "success" { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if the action is still running, we might want to run this in a loop with a fixed amount of retries and sleeps between each request, to make sure it completes successfully
for example if the hetzner api is malfunctioning, and stalls, we would indicate as "success" although it would not update the record.
| } | ||
|
|
||
| // rrSetResponse represents the response from Hetzner Networking API RRSet GET requests | ||
| type rrSetResponse struct { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit since this is used only in getRecordID, let's inline the type definition in there. For example
var rrSetResponse struct {
RRSet struct {
ID string `json:"id"`
Records []struct {
Value string `json:"value"`
} `json:"records"`
} `json:"rrset"`
}and remove it from types.go
| recordType = constants.AAAA | ||
| } | ||
|
|
||
| // Extract RR name from domain relative to zone |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit unneeded comment
| // Extract RR name from domain relative to zone |
| // For example: domain="example.com", zone="example.com" -> "@" | ||
| // For example: domain="*.sub.example.com", zone="example.com" -> "*.sub" | ||
| func (p *Provider) extractRRName() (string, error) { | ||
| domain := p.BuildDomainName() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I suggest you use https://pkg.go.dev/golang.org/x/net/publicsuffix#EffectiveTLDPlusOne instead. A unit test for this function wouldn't hurt either 😉
This is how the owners (rr names) are extracted from the domain string in the settings parsing:
ddns-updater/internal/params/json.go
Line 237 in 40f8009
| newDomainRegistered, err := publicsuffix.EffectiveTLDPlusOne(domain) |
| @@ -0,0 +1,145 @@ | |||
| package hetznercloud | |||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please remove, not sure why this is here
| headers.SetUserAgent(request) | ||
| headers.SetContentType(request, "application/json") | ||
| headers.SetAccept(request, "application/json") | ||
| request.Header.Set("Authorization", "Bearer "+p.token) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| request.Header.Set("Authorization", "Bearer "+p.token) | |
| headers.SetAuthBearer(p.token) |
DNS management was previously in a separate DNS console and got now added to the Hetzner console (both having their own API). At the moment there's a timeframe where both still exist to allow a smooth transition. So at the moment both the old and new API exist but you can only have your DNS zone in either the old or the current panel and you can also only use the respective API for the old or current panel. That means supporting both in ddns-updater until the old panel and API get shut down will allow users to choose when to migrate their zones. If the current implementation would just be replaced, users would be forced to migrate their zones to the new panel as soon as they update ddns-updater. |
Add Hetzner Networking DNS Provider
Overview
Adds support for the new Hetzner Cloud DNS API with the
hetznernetworkingprovider. This is a separate provider from the existinghetznerprovider, offering modern RRSet-based operations and wildcard domain support.Features
*.example.com)Configuration
{ "settings": [ { "provider": "hetznernetworking", "zone_identifier": "example.com", "domain": "sub.example.com", "token": "your-api-token", "ttl": 600, "ip_version": "ipv4" } ] }API Endpoints
GET /v1/zones/{zone}/rrsets/{name}/{type}- Get recordsPOST /v1/zones/{zone}/rrsets/{name}/{type}/actions/add_records- Create recordsPOST /v1/zones/{zone}/rrsets/{name}/{type}/actions/set_records- Update recordsTesting
Breaking Changes
None - purely additive change. Legacy
hetznerprovider remains unchanged.Documentation
docs/hetznernetworking.md