diff --git a/cloud/linode/instances.go b/cloud/linode/instances.go index 7c89f7d2..f2f467c3 100644 --- a/cloud/linode/instances.go +++ b/cloud/linode/instances.go @@ -6,6 +6,7 @@ import ( "os" "slices" "strconv" + "strings" "sync" "time" @@ -36,8 +37,8 @@ type nodeCache struct { ttl time.Duration } -// getInstanceIPv4Addresses returns all ipv4 addresses configured on a linode. -func (nc *nodeCache) getInstanceIPv4Addresses(instance linodego.Instance, vpcips []string) []nodeIP { +// getInstanceAddresses returns all addresses configured on a linode. +func (nc *nodeCache) getInstanceAddresses(instance linodego.Instance, vpcips []string) []nodeIP { ips := []nodeIP{} // If vpc ips are present, list them first @@ -54,6 +55,10 @@ func (nc *nodeCache) getInstanceIPv4Addresses(instance linodego.Instance, vpcips ips = append(ips, nodeIP{ip: ip.String(), ipType: ipType}) } + if instance.IPv6 != "" { + ips = append(ips, nodeIP{ip: strings.TrimSuffix(instance.IPv6, "/128"), ipType: v1.NodeExternalIP}) + } + return ips } @@ -97,7 +102,7 @@ func (nc *nodeCache) refreshInstances(ctx context.Context, client client.Client) } node := linodeInstance{ instance: &instances[i], - ips: nc.getInstanceIPv4Addresses(instance, vpcNodes[instance.ID]), + ips: nc.getInstanceAddresses(instance, vpcNodes[instance.ID]), } newNodes[instance.ID] = node } @@ -141,7 +146,7 @@ func (i *instances) linodeByIP(kNode *v1.Node) (*linodego.Instance, error) { defer i.nodeCache.RUnlock() var kNodeAddresses []string for _, address := range kNode.Status.Addresses { - if address.Type == "ExternalIP" || address.Type == "InternalIP" { + if address.Type == v1.NodeExternalIP || address.Type == v1.NodeInternalIP { kNodeAddresses = append(kNodeAddresses, address.Address) } } @@ -262,7 +267,7 @@ func (i *instances) InstanceMetadata(ctx context.Context, node *v1.Node) (*cloud return nil, err } - ips, err := i.getLinodeIPv4Addresses(ctx, node) + ips, err := i.getLinodeAddresses(ctx, node) if err != nil { sentry.CaptureError(ctx, err) return nil, err @@ -291,7 +296,7 @@ func (i *instances) InstanceMetadata(ctx context.Context, node *v1.Node) (*cloud return meta, nil } -func (i *instances) getLinodeIPv4Addresses(ctx context.Context, node *v1.Node) ([]nodeIP, error) { +func (i *instances) getLinodeAddresses(ctx context.Context, node *v1.Node) ([]nodeIP, error) { ctx = sentry.SetHubOnContext(ctx) instance, err := i.lookupLinode(ctx, node) if err != nil { diff --git a/cloud/linode/instances_test.go b/cloud/linode/instances_test.go index 89e1cfe6..57d5eec5 100644 --- a/cloud/linode/instances_test.go +++ b/cloud/linode/instances_test.go @@ -144,38 +144,51 @@ func TestMetadataRetrieval(t *testing.T) { ipTests := []struct { name string - inputIPs []string + inputIPv4s []string + inputIPv6 string outputAddresses []v1.NodeAddress expectedErr error }{ - {"no IPs", nil, nil, instanceNoIPAddressesError{192910}}, + {"no IPs", nil, "", nil, instanceNoIPAddressesError{192910}}, { "one public, one private", []string{"32.74.121.25", "192.168.121.42"}, + "", []v1.NodeAddress{{Type: v1.NodeExternalIP, Address: "32.74.121.25"}, {Type: v1.NodeInternalIP, Address: "192.168.121.42"}}, nil, }, + { + "one public ipv4, one public ipv6", + []string{"32.74.121.25"}, + "2600:3c06::f03c:94ff:fe1e:e072", + []v1.NodeAddress{{Type: v1.NodeExternalIP, Address: "32.74.121.25"}, {Type: v1.NodeExternalIP, Address: "2600:3c06::f03c:94ff:fe1e:e072"}}, + nil, + }, { "one public, no private", []string{"32.74.121.25"}, + "", []v1.NodeAddress{{Type: v1.NodeExternalIP, Address: "32.74.121.25"}}, nil, }, { "one private, no public", []string{"192.168.121.42"}, + "", []v1.NodeAddress{{Type: v1.NodeInternalIP, Address: "192.168.121.42"}}, nil, }, { "two public addresses", []string{"32.74.121.25", "32.74.121.22"}, + "", []v1.NodeAddress{{Type: v1.NodeExternalIP, Address: "32.74.121.25"}, {Type: v1.NodeExternalIP, Address: "32.74.121.22"}}, nil, }, { "two private addresses", []string{"192.168.121.42", "10.0.2.15"}, + "", []v1.NodeAddress{{Type: v1.NodeInternalIP, Address: "192.168.121.42"}, {Type: v1.NodeInternalIP, Address: "10.0.2.15"}}, nil, }, @@ -189,8 +202,8 @@ func TestMetadataRetrieval(t *testing.T) { providerID := providerIDPrefix + strconv.Itoa(id) node := nodeWithProviderID(providerID) - ips := make([]*net.IP, 0, len(test.inputIPs)) - for _, ip := range test.inputIPs { + ips := make([]*net.IP, 0, len(test.inputIPv4s)) + for _, ip := range test.inputIPv4s { parsed := net.ParseIP(ip) if parsed == nil { t.Fatalf("cannot parse %v as an ipv4", ip) @@ -201,7 +214,7 @@ func TestMetadataRetrieval(t *testing.T) { linodeType := "g6-standard-1" region := "us-east" client.EXPECT().ListInstances(gomock.Any(), nil).Times(1).Return([]linodego.Instance{ - {ID: id, Label: name, Type: linodeType, Region: region, IPv4: ips}, + {ID: id, Label: name, Type: linodeType, Region: region, IPv4: ips, IPv6: test.inputIPv6}, }, nil) meta, err := instances.InstanceMetadata(ctx, node)