Skip to content
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

Get IP addresses type from Linode #233

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 15 additions & 13 deletions cloud/linode/instances.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
"os"
"slices"
"strconv"
"strings"
"sync"
"time"

Expand Down Expand Up @@ -38,25 +37,24 @@
}

// getInstanceAddresses returns all addresses configured on a linode.
func (nc *nodeCache) getInstanceAddresses(instance linodego.Instance, vpcips []string) []nodeIP {
func (nc *nodeCache) getInstanceAddresses(instanceips *linodego.InstanceIPAddressResponse, vpcips []string) []nodeIP {
ips := []nodeIP{}

// If vpc ips are present, list them first
for _, ip := range vpcips {
ipType := v1.NodeInternalIP
ips = append(ips, nodeIP{ip: ip, ipType: ipType})
ips = append(ips, nodeIP{ip: ip, ipType: v1.NodeInternalIP})
}

for _, ip := range instance.IPv4 {
ipType := v1.NodeExternalIP
if ip.IsPrivate() {
ipType = v1.NodeInternalIP
}
ips = append(ips, nodeIP{ip: ip.String(), ipType: ipType})
for _, ip := range instanceips.IPv4.Public {
ips = append(ips, nodeIP{ip: ip.Address, ipType: v1.NodeExternalIP})
}

for _, ip := range instanceips.IPv4.Private {
ips = append(ips, nodeIP{ip: ip.Address, ipType: v1.NodeInternalIP})
}

if instance.IPv6 != "" {
ips = append(ips, nodeIP{ip: strings.TrimSuffix(instance.IPv6, "/128"), ipType: v1.NodeExternalIP})
if instanceips.IPv6.SLAAC.Address != "" {
ips = append(ips, nodeIP{ip: instanceips.IPv6.SLAAC.Address, ipType: v1.NodeExternalIP})
}

return ips
Expand Down Expand Up @@ -100,9 +98,13 @@
if vpcID != 0 && len(vpcNodes[instance.ID]) == 0 {
continue
}
ips, err := client.GetInstanceIPAddresses(ctx, instance.ID)
if err != nil {
return err

Check warning on line 103 in cloud/linode/instances.go

View check run for this annotation

Codecov / codecov/patch

cloud/linode/instances.go#L103

Added line #L103 was not covered by tests
}
node := linodeInstance{
instance: &instances[i],
ips: nc.getInstanceAddresses(instance, vpcNodes[instance.ID]),
ips: nc.getInstanceAddresses(ips, vpcNodes[instance.ID]),
}
newNodes[instance.ID] = node
}
Expand Down
78 changes: 68 additions & 10 deletions cloud/linode/instances_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,28 @@ func nodeWithName(name string) *v1.Node {
return &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: name}}
}

func ipsResponse(privateIPs, publicIPs []*net.IP, ipv6SLAAC string) *linodego.InstanceIPAddressResponse {
privateInstanceIPs := []*linodego.InstanceIP{}
publicInstanceIPs := []*linodego.InstanceIP{}

for _, ip := range privateIPs {
privateInstanceIPs = append(privateInstanceIPs, &linodego.InstanceIP{Address: ip.String()})
}
for _, ip := range publicIPs {
publicInstanceIPs = append(publicInstanceIPs, &linodego.InstanceIP{Address: ip.String()})
}

return &linodego.InstanceIPAddressResponse{
IPv4: &linodego.InstanceIPv4Response{
Public: publicInstanceIPs,
Private: privateInstanceIPs,
},
IPv6: &linodego.InstanceIPv6Response{
SLAAC: &linodego.InstanceIP{Address: ipv6SLAAC},
},
}
}

func TestInstanceExists(t *testing.T) {
ctx := context.TODO()
ctrl := gomock.NewController(t)
Expand Down Expand Up @@ -54,6 +76,7 @@ func TestInstanceExists(t *testing.T) {
Type: "g6-standard-2",
},
}, nil)
client.EXPECT().GetInstanceIPAddresses(gomock.Any(), gomock.Any()).Times(1).Return(ipsResponse(nil, nil, ""), nil)

exists, err := instances.InstanceExists(ctx, node)
assert.NoError(t, err)
Expand All @@ -68,6 +91,7 @@ func TestInstanceExists(t *testing.T) {
client.EXPECT().ListInstances(gomock.Any(), nil).Times(1).Return([]linodego.Instance{
{ID: 123, Label: name},
}, nil)
client.EXPECT().GetInstanceIPAddresses(gomock.Any(), gomock.Any()).Times(1).Return(ipsResponse(nil, nil, ""), nil)

exists, err := instances.InstanceExists(ctx, node)
assert.NoError(t, err)
Expand All @@ -88,6 +112,8 @@ func TestMetadataRetrieval(t *testing.T) {
privateIP := net.ParseIP("192.168.159.135")
expectedInstance := linodego.Instance{Label: "expected-instance", ID: 12345, IPv4: []*net.IP{&publicIP, &privateIP}}
client.EXPECT().ListInstances(gomock.Any(), nil).Times(1).Return([]linodego.Instance{{Label: "wrong-instance", ID: 3456, IPv4: []*net.IP{&publicIP, &privateIP}}, expectedInstance}, nil)
client.EXPECT().GetInstanceIPAddresses(gomock.Any(), gomock.Any()).Times(2).Return(ipsResponse([]*net.IP{&privateIP}, []*net.IP{&publicIP}, ""), nil)

name := "expected-instance"
node := nodeWithName(name)

Expand Down Expand Up @@ -120,6 +146,7 @@ func TestMetadataRetrieval(t *testing.T) {
client.EXPECT().ListInstances(gomock.Any(), nil).Times(1).Return([]linodego.Instance{
{ID: id, Label: name, Type: linodeType, Region: region, IPv4: []*net.IP{&publicIPv4, &privateIPv4}},
}, nil)
client.EXPECT().GetInstanceIPAddresses(gomock.Any(), gomock.Any()).Times(1).Return(ipsResponse([]*net.IP{&privateIPv4}, []*net.IP{&publicIPv4}, ""), nil)

meta, err := instances.InstanceMetadata(ctx, node)
assert.NoError(t, err)
Expand All @@ -143,36 +170,41 @@ func TestMetadataRetrieval(t *testing.T) {
})

ipTests := []struct {
name string
inputIPv4s []string
inputIPv6 string
outputAddresses []v1.NodeAddress
expectedErr error
name string
inputPublicIPv4s []string
inputPrivateIPv4s []string
inputIPv6 string
outputAddresses []v1.NodeAddress
expectedErr error
}{
{"no IPs", nil, "", nil, instanceNoIPAddressesError{192910}},
{"no IPs", nil, nil, "", nil, instanceNoIPAddressesError{192910}},
{
"one public, one private",
[]string{"32.74.121.25", "192.168.121.42"},
[]string{"32.74.121.25"},
[]string{"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"},
[]string{},
"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"},
[]string{},
"",
[]v1.NodeAddress{{Type: v1.NodeExternalIP, Address: "32.74.121.25"}},
nil,
},
{
"one private, no public",
[]string{},
[]string{"192.168.121.42"},
"",
[]v1.NodeAddress{{Type: v1.NodeInternalIP, Address: "192.168.121.42"}},
Expand All @@ -181,17 +213,27 @@ func TestMetadataRetrieval(t *testing.T) {
{
"two public addresses",
[]string{"32.74.121.25", "32.74.121.22"},
[]string{},
"",
[]v1.NodeAddress{{Type: v1.NodeExternalIP, Address: "32.74.121.25"}, {Type: v1.NodeExternalIP, Address: "32.74.121.22"}},
nil,
},
{
"two private addresses",
[]string{},
[]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,
},
{
"private address as external IP address",
[]string{"192.168.121.42"},
[]string{},
"",
[]v1.NodeAddress{{Type: v1.NodeExternalIP, Address: "192.168.121.42"}},
nil,
},
}

for _, test := range ipTests {
Expand All @@ -202,12 +244,23 @@ func TestMetadataRetrieval(t *testing.T) {
providerID := providerIDPrefix + strconv.Itoa(id)
node := nodeWithProviderID(providerID)

ips := make([]*net.IP, 0, len(test.inputIPv4s))
for _, ip := range test.inputIPv4s {
ips := make([]*net.IP, 0, len(test.inputPrivateIPv4s)+len(test.inputPublicIPv4s))
privateIps := make([]*net.IP, 0, len(test.inputPrivateIPv4s))
for _, ip := range test.inputPrivateIPv4s {
parsed := net.ParseIP(ip)
if parsed == nil {
t.Fatalf("cannot parse %v as an ipv4", ip)
}
privateIps = append(privateIps, &parsed)
ips = append(ips, &parsed)
}
publicIps := make([]*net.IP, 0, len(test.inputPublicIPv4s))
for _, ip := range test.inputPublicIPv4s {
parsed := net.ParseIP(ip)
if parsed == nil {
t.Fatalf("cannot parse %v as an ipv4", ip)
}
publicIps = append(publicIps, &parsed)
ips = append(ips, &parsed)
}

Expand All @@ -216,6 +269,7 @@ func TestMetadataRetrieval(t *testing.T) {
client.EXPECT().ListInstances(gomock.Any(), nil).Times(1).Return([]linodego.Instance{
{ID: id, Label: name, Type: linodeType, Region: region, IPv4: ips, IPv6: test.inputIPv6},
}, nil)
client.EXPECT().GetInstanceIPAddresses(gomock.Any(), gomock.Any()).Times(1).Return(ipsResponse(privateIps, publicIps, test.inputIPv6), nil)

meta, err := instances.InstanceMetadata(ctx, node)

Expand Down Expand Up @@ -274,9 +328,10 @@ func TestMetadataRetrieval(t *testing.T) {
expectedInstance := linodego.Instance{Label: "expected-instance", ID: 12345, IPv4: []*net.IP{&publicIP, &privateIP}}

for _, test := range getByIPTests {
t.Run(fmt.Sprintf("gets lindoe by IP - %s", test.name), func(t *testing.T) {
t.Run(fmt.Sprintf("gets linode by IP - %s", test.name), func(t *testing.T) {
instances := newInstances(client)
client.EXPECT().ListInstances(gomock.Any(), nil).Times(1).Return([]linodego.Instance{{ID: 3456, IPv4: []*net.IP{&wrongIP}}, expectedInstance}, nil)
client.EXPECT().GetInstanceIPAddresses(gomock.Any(), gomock.Any()).Times(2).Return(ipsResponse(nil, []*net.IP{&wrongIP}, ""), nil)
node := v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "test-node-1"}, Status: v1.NodeStatus{Addresses: test.nodeAddresses}}
meta, err := instances.InstanceMetadata(ctx, &node)
if test.expectedErr != nil {
Expand Down Expand Up @@ -346,6 +401,7 @@ func TestInstanceShutdown(t *testing.T) {
client.EXPECT().ListInstances(gomock.Any(), nil).Times(1).Return([]linodego.Instance{
{ID: id, Label: "offline-linode", Status: linodego.InstanceOffline},
}, nil)
client.EXPECT().GetInstanceIPAddresses(gomock.Any(), gomock.Any()).Times(1).Return(ipsResponse(nil, nil, ""), nil)
shutdown, err := instances.InstanceShutdown(ctx, node)

assert.NoError(t, err)
Expand All @@ -359,6 +415,7 @@ func TestInstanceShutdown(t *testing.T) {
client.EXPECT().ListInstances(gomock.Any(), nil).Times(1).Return([]linodego.Instance{
{ID: id, Label: "shutting-down-linode", Status: linodego.InstanceShuttingDown},
}, nil)
client.EXPECT().GetInstanceIPAddresses(gomock.Any(), gomock.Any()).Times(1).Return(ipsResponse(nil, nil, ""), nil)
shutdown, err := instances.InstanceShutdown(ctx, node)

assert.NoError(t, err)
Expand All @@ -372,6 +429,7 @@ func TestInstanceShutdown(t *testing.T) {
client.EXPECT().ListInstances(gomock.Any(), nil).Times(1).Return([]linodego.Instance{
{ID: id, Label: "running-linode", Status: linodego.InstanceRunning},
}, nil)
client.EXPECT().GetInstanceIPAddresses(gomock.Any(), gomock.Any()).Times(1).Return(ipsResponse(nil, nil, ""), nil)
shutdown, err := instances.InstanceShutdown(ctx, node)

assert.NoError(t, err)
Expand Down
7 changes: 7 additions & 0 deletions cloud/linode/route_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ func TestListRoutes(t *testing.T) {
assert.NoError(t, err)

client.EXPECT().ListInstances(gomock.Any(), nil).Times(1).Return([]linodego.Instance{validInstance}, nil)
client.EXPECT().GetInstanceIPAddresses(gomock.Any(), gomock.Any()).Times(1).Return(ipsResponse(nil, nil, ""), nil)
client.EXPECT().ListVPCIPAddresses(gomock.Any(), gomock.Any(), gomock.Any()).Times(2).Return(noRoutesInVPC, nil)
routes, err := routeController.ListRoutes(ctx, "abc")
assert.NoError(t, err)
Expand Down Expand Up @@ -127,6 +128,7 @@ func TestListRoutes(t *testing.T) {
assert.NoError(t, err)

client.EXPECT().ListInstances(gomock.Any(), nil).Times(1).Return([]linodego.Instance{validInstance}, nil)
client.EXPECT().GetInstanceIPAddresses(gomock.Any(), gomock.Any()).Times(1).Return(ipsResponse(nil, nil, ""), nil)
client.EXPECT().ListVPCIPAddresses(gomock.Any(), gomock.Any(), gomock.Any()).Times(2).Return(routesInVPC, nil)
routes, err := routeController.ListRoutes(ctx, "abc")
assert.NoError(t, err)
Expand Down Expand Up @@ -168,6 +170,7 @@ func TestListRoutes(t *testing.T) {
assert.NoError(t, err)

client.EXPECT().ListInstances(gomock.Any(), nil).Times(1).Return([]linodego.Instance{validInstance}, nil)
client.EXPECT().GetInstanceIPAddresses(gomock.Any(), gomock.Any()).Times(1).Return(ipsResponse(nil, nil, ""), nil)
client.EXPECT().ListVPCIPAddresses(gomock.Any(), gomock.Any(), gomock.Any()).Times(2).Return(routesInDifferentVPC, nil)
routes, err := routeController.ListRoutes(ctx, "abc")
assert.NoError(t, err)
Expand Down Expand Up @@ -227,6 +230,7 @@ func TestCreateRoute(t *testing.T) {
assert.NoError(t, err)

client.EXPECT().ListInstances(gomock.Any(), nil).Times(1).Return([]linodego.Instance{validInstance}, nil)
client.EXPECT().GetInstanceIPAddresses(gomock.Any(), gomock.Any()).Times(1).Return(ipsResponse(nil, nil, ""), nil)
client.EXPECT().ListVPCIPAddresses(gomock.Any(), gomock.Any(), gomock.Any()).Times(2).Return(noRoutesInVPC, nil)
client.EXPECT().UpdateInstanceConfigInterface(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(1).Return(&instanceConfigIntfWithVPCAndRoute, nil)
err = routeController.CreateRoute(ctx, "dummy", "dummy", route)
Expand Down Expand Up @@ -259,6 +263,7 @@ func TestCreateRoute(t *testing.T) {
assert.NoError(t, err)

client.EXPECT().ListInstances(gomock.Any(), nil).Times(1).Return([]linodego.Instance{validInstance}, nil)
client.EXPECT().GetInstanceIPAddresses(gomock.Any(), gomock.Any()).Times(1).Return(ipsResponse(nil, nil, ""), nil)
client.EXPECT().ListVPCIPAddresses(gomock.Any(), gomock.Any(), gomock.Any()).Times(2).Return(routesInVPC, nil)
err = routeController.CreateRoute(ctx, "dummy", "dummy", route)
assert.NoError(t, err)
Expand Down Expand Up @@ -346,6 +351,7 @@ func TestDeleteRoute(t *testing.T) {
assert.NoError(t, err)

client.EXPECT().ListInstances(gomock.Any(), nil).Times(1).Return([]linodego.Instance{validInstance}, nil)
client.EXPECT().GetInstanceIPAddresses(gomock.Any(), gomock.Any()).Times(1).Return(ipsResponse(nil, nil, ""), nil)
client.EXPECT().ListVPCIPAddresses(gomock.Any(), gomock.Any(), gomock.Any()).Times(2).Return(noRoutesInVPC, nil)
client.EXPECT().UpdateInstanceConfigInterface(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(1).Return(&instanceConfigIntfWithVPCAndNoRoute, nil)
err = routeController.DeleteRoute(ctx, "dummy", route)
Expand Down Expand Up @@ -377,6 +383,7 @@ func TestDeleteRoute(t *testing.T) {
assert.NoError(t, err)

client.EXPECT().ListInstances(gomock.Any(), nil).Times(1).Return([]linodego.Instance{validInstance}, nil)
client.EXPECT().GetInstanceIPAddresses(gomock.Any(), gomock.Any()).Times(1).Return(ipsResponse(nil, nil, ""), nil)
client.EXPECT().ListVPCIPAddresses(gomock.Any(), gomock.Any(), gomock.Any()).Times(2).Return(routesInVPC, nil)
client.EXPECT().UpdateInstanceConfigInterface(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Times(1).Return(&instanceConfigIntfWithVPCAndNoRoute, nil)
err = routeController.DeleteRoute(ctx, "dummy", route)
Expand Down
Loading