Skip to content

Commit 01ea5ce

Browse files
Jakob3xDclaude
andcommitted
fix(instances): skip IPv6 ExternalIP for Robot servers without a subnet
Robot servers do not necessarily have an IPv6 subnet assigned. In that case the Robot API reports an empty `server_ipv6_net`, and appending "1" to it added the literal address "1" as an ExternalIP to the Node object. Guard the concatenation with an emptiness check and validate the result before using it, emitting a warning event when the reported subnet does not yield a valid address. Co-authored-by: Claude <noreply@anthropic.com>
1 parent 49026c3 commit 01ea5ce

2 files changed

Lines changed: 51 additions & 2 deletions

File tree

hcloud/instances.go

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ import (
4141
const (
4242
ProvidedBy = "instance.hetzner.cloud/provided-by"
4343
MisconfiguredInternalIP = "MisconfiguredInternalIP"
44+
InvalidIPv6Net = "InvalidIPv6Net"
4445
instancesV2Subsystem = "instances_v2"
4546
)
4647

@@ -281,10 +282,23 @@ func robotNodeAddresses(
281282
ipv4 := cfg.Instance.AddressFamily == config.AddressFamilyIPv4 || dualStack
282283
ipv6 := cfg.Instance.AddressFamily == config.AddressFamilyIPv6 || dualStack
283284

284-
if ipv6 {
285+
// Robot servers do not necessarily have an IPv6 subnet assigned, in which case the field is empty.
286+
if ipv6 && server.ServerIPv6Net != "" {
285287
// For a given IPv6 network of 2a01:f48:111:4221::, the instance address is 2a01:f48:111:4221::1
286288
hostAddress := server.ServerIPv6Net + "1"
287-
addresses = append(addresses, corev1.NodeAddress{Type: corev1.NodeExternalIP, Address: hostAddress})
289+
290+
if net.ParseIP(hostAddress) == nil {
291+
utils.WarnEventLogf(
292+
recorder,
293+
node,
294+
InvalidIPv6Net,
295+
"Robot server %q reports the IPv6 subnet %q, which does not yield a valid address. As a result, no IPv6 ExternalIP is added",
296+
server.Name,
297+
server.ServerIPv6Net,
298+
)
299+
} else {
300+
addresses = append(addresses, corev1.NodeAddress{Type: corev1.NodeExternalIP, Address: hostAddress})
301+
}
288302
}
289303

290304
if ipv4 {

hcloud/instances_test.go

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -712,6 +712,41 @@ func TestNodeAddressesRobotServer(t *testing.T) {
712712
{Type: corev1.NodeExternalIP, Address: "203.0.113.7"},
713713
},
714714
},
715+
{
716+
name: "public ipv6 without IPv6 subnet",
717+
addressFamily: config.AddressFamilyIPv6,
718+
server: &hrobotmodels.Server{
719+
Name: "foobar",
720+
ServerIP: "203.0.113.7",
721+
},
722+
expected: []corev1.NodeAddress{
723+
{Type: corev1.NodeHostName, Address: "foobar"},
724+
},
725+
},
726+
{
727+
name: "public dual stack without IPv6 subnet",
728+
addressFamily: config.AddressFamilyDualStack,
729+
server: &hrobotmodels.Server{
730+
Name: "foobar",
731+
ServerIP: "203.0.113.7",
732+
},
733+
expected: []corev1.NodeAddress{
734+
{Type: corev1.NodeHostName, Address: "foobar"},
735+
{Type: corev1.NodeExternalIP, Address: "203.0.113.7"},
736+
},
737+
},
738+
{
739+
name: "public ipv6 with malformed IPv6 subnet",
740+
addressFamily: config.AddressFamilyIPv6,
741+
server: &hrobotmodels.Server{
742+
Name: "foobar",
743+
ServerIP: "203.0.113.7",
744+
ServerIPv6Net: "2001:db8:1234::/64",
745+
},
746+
expected: []corev1.NodeAddress{
747+
{Type: corev1.NodeHostName, Address: "foobar"},
748+
},
749+
},
715750
}
716751

717752
for _, test := range tests {

0 commit comments

Comments
 (0)