dnscontrol/providers/hetzner
Jakob Ackermann c073f2e654
HETZNER: gracefully handle FQDN labels when listing records (#3859)
- 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.
!-->
2025-12-01 09:08:43 -05:00
..
api.go
auditrecords.go
hetznerProvider.go
types.go HETZNER: gracefully handle FQDN labels when listing records (#3859) 2025-12-01 09:08:43 -05:00