Repository navigation
fix: match ip_type case-insensitively in IONOS and Hetzner providers - #316
Merged
TimothyYe merged 1 commit intoSep 12, 2026
Merged
Conversation
Both providers compared the configured ip_type against a fixed spelling
instead of normalising the case first, so each one picked the A record
when the user asked for IPv6.
ionos_handler.go:158 compared ip_type against utils.IPV6 ("IPV6"). The
README documents the value as "IPv4" or "IPv6" and every sample config
writes "IPv4", so a hand written IPv6 config fell through to the A
record: godns looked up recordType=A and then PUT the IPv6 address into
the A record on every cycle, because an IPv6 address never equals the A
record's content.
hetzner_handler.go:159 compared ip_type against the literal "IPv6". That
matches the documented spelling but not the one the web UI saves. The IP
mode toggle in web/components/ip-mode.tsx sends "IPV6", and
UpdateNetworkSettings in internal/server/controllers/network.go writes
that string straight into ip_type, so switching to IPv6 in the UI left
Hetzner updating the A record.
Every other provider already normalises with strings.ToUpper before
comparing against utils.IPV6, so both call sites now do the same.
Adds a mock API server test for each provider, in the style of
cloudflare_verify_test.go, covering a dual stack host and the "IPv6",
"IPV6" and "ipv6" spellings. To make the base address injectable the two
providers gained an API field set from BaseURL in Init, matching the API
field the Cloudflare provider already uses for the same purpose.
Owner
|
Thanks for your contribution! |
TimothyYe
added a commit
that referenced
this pull request
Sep 12, 2026
Follow-up to #316. The two providers were merged with their own strings.ToUpper comparisons because the shared helpers landed on master at the same time. Route them through utils.RecordType like every other provider; IONOS keeps accepting the legacy "AAAA" spelling via strings.EqualFold. The tests added in #316 cover both providers. Co-Authored-By: Claude Fable 5.1 <[email protected]>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The IONOS and Hetzner providers each compare the configured
ip_typeagainst one fixed spelling instead of normalising the case first, so both of them go on updating the A record when the user asked for IPv6.IONOS,
internal/provider/ionos/ionos_handler.go:158, comparesprovider.configuration.IPTypeagainstutils.IPV6, which is the string"IPV6". The README documents the value asIPv4orIPv6, and every sample underconfigs/writesIPv4, so a config written from the docs never matches andgetRecordqueriesrecordType=A. An IPv6 address never equals the A record's content, so the early return inUpdateIPnever fires and the provider PUTs the IPv6 address into the A record on every cycle.Hetzner,
internal/provider/hetzner/hetzner_handler.go:159, compares against the literal"IPv6". That matches the documented spelling but not the one the web UI stores. The toggle inweb/components/ip-mode.tsxsendsIPV6, andUpdateNetworkSettingsatinternal/server/controllers/network.go:53writes that string straight intoip_typeand saves the config, so switching to IPv6 mode in the UI leaves Hetzner picking the A record.Every other provider that reads
ip_typealready normalises withstrings.ToUpperbefore comparing againstutils.IPV6, so these two call sites now do the same. IONOS still acceptsAAAAas it did before.Each provider gets a mock API server test in the style of
internal/provider/cloudflare/cloudflare_verify_test.go. The mock zone holds both an A and an AAAA record for the same host, and the test asserts which recordUpdateIPlooks up and writes forIPv6,IPV6,ipv6,IPv4and an unsetip_type. To point the providers at the mock they gained anAPIfield set fromBaseURLinInit, the same field the Cloudflare provider already carries for this.Verified on macOS 15 with Go 1.26.4 and golangci-lint v1.64.8, the version the Lint job pins.
Restoring just the two comparisons and keeping the new tests reproduces the bug, which is what the tests are there to catch:
One thing I left alone:
UpdateNetworkSettingscompares the incomingip_modeagainstutils.IPV4andutils.IPV6whileGetNetworkSettingshands outc.config.IPTypeunchanged, so a config holdingIPv6fails both of those checks on the way back in. That is a separate fix in the server and the frontend, happy to send it as its own PR if you want it.