Skip to content

Commit e432255

Browse files
committed
test: Unit test for validating multiple NICs order and duplicate IPs
1 parent 6d72676 commit e432255

File tree

1 file changed

+131
-0
lines changed

1 file changed

+131
-0
lines changed

pkg/provider/manager_unit_test.go

Lines changed: 131 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,16 @@
11
package provider
22

33
import (
4+
"context"
5+
"net/netip"
6+
"slices"
47
"testing"
58

9+
vmmCommonModels "github.com/nutanix/ntnx-api-golang-clients/vmm-go-client/v4/models/common/v1/config"
10+
vmmModels "github.com/nutanix/ntnx-api-golang-clients/vmm-go-client/v4/models/vmm/v4/ahv/config"
11+
"go4.org/netipx"
612
v1 "k8s.io/api/core/v1"
13+
"k8s.io/utils/ptr"
714
)
815

916
func TestIsNodeAddressesSet(t *testing.T) {
@@ -81,3 +88,127 @@ func TestIsNodeAddressesSet(t *testing.T) {
8188
})
8289
}
8390
}
91+
92+
func TestGetNodeAddresses(t *testing.T) {
93+
ctx := context.Background()
94+
95+
tests := []struct {
96+
name string
97+
vm *vmmModels.Vm
98+
wantErr bool
99+
wantIPs []string
100+
wantLen int
101+
}{
102+
{
103+
name: "VM with no NICs returns error",
104+
vm: &vmmModels.Vm{
105+
ExtId: ptr.To("uuid"),
106+
Name: ptr.To("vm1"),
107+
Nics: nil,
108+
},
109+
wantErr: true,
110+
},
111+
{
112+
name: "VM with one NIC returns internal IP and hostname",
113+
vm: vmWithOneNic(t, "my-vm1", "uuid-1", "10.0.0.1"),
114+
wantErr: false,
115+
wantIPs: []string{"10.0.0.1"},
116+
wantLen: 2, // 1 NodeInternalIP + 1 NodeHostName
117+
},
118+
{
119+
name: "multiple NICs: internal IPs appear in NIC order",
120+
vm: vmWithNics(t, "my-vm", "uuid-2", []string{"10.0.0.1", "10.0.0.2", "10.0.0.3"}),
121+
wantErr: false,
122+
wantIPs: []string{"10.0.0.1", "10.0.0.2", "10.0.0.3"},
123+
wantLen: 4, // 3 NodeInternalIP + 1 NodeHostName
124+
},
125+
{
126+
name: "multiple NICs with same IP: deduplicated to one internal IP",
127+
vm: vmWithNics(t, "my-vm", "uuid-3", []string{"10.0.0.1", "10.0.0.1"}),
128+
wantErr: false,
129+
wantIPs: []string{"10.0.0.1"},
130+
wantLen: 2,
131+
},
132+
}
133+
134+
for _, tt := range tests {
135+
t.Run(tt.name, func(t *testing.T) {
136+
m := &nutanixManager{
137+
ignoredNodeIPs: ignoredIPSet("10.0.0.99"),
138+
}
139+
got, err := m.getNodeAddresses(ctx, tt.vm)
140+
if tt.wantErr {
141+
if err == nil {
142+
t.Errorf("getNodeAddresses() expected error, got nil")
143+
}
144+
return
145+
}
146+
if err != nil {
147+
t.Errorf("getNodeAddresses() err = %v", err)
148+
return
149+
}
150+
if tt.wantLen != 0 && len(got) != tt.wantLen {
151+
t.Errorf("getNodeAddresses() len = %d, want %d", len(got), tt.wantLen)
152+
}
153+
if len(tt.wantIPs) > 0 {
154+
ips := extractInternalIPs(got)
155+
if !slices.Equal(ips, tt.wantIPs) {
156+
t.Errorf("getNodeAddresses() internal IPs = %v, want %v", ips, tt.wantIPs)
157+
}
158+
}
159+
})
160+
}
161+
}
162+
163+
func extractInternalIPs(addrs []v1.NodeAddress) []string {
164+
var out []string
165+
for _, a := range addrs {
166+
if a.Type == v1.NodeInternalIP {
167+
out = append(out, a.Address)
168+
}
169+
}
170+
return out
171+
}
172+
173+
func ignoredIPSet(ips ...string) *netipx.IPSet {
174+
b := netipx.IPSetBuilder{}
175+
for _, s := range ips {
176+
b.Add(netip.MustParseAddr(s))
177+
}
178+
s, _ := b.IPSet()
179+
return s
180+
}
181+
182+
func vmWithOneNic(t *testing.T, name, uuid, ip string) *vmmModels.Vm {
183+
t.Helper()
184+
return vmWithNics(t, name, uuid, []string{ip})
185+
}
186+
187+
// nicWithIP returns a NIC with the given IPv4 address.
188+
func nicWithIP(t *testing.T, ip string) vmmModels.Nic {
189+
t.Helper()
190+
nic := vmmModels.NewNic()
191+
netInfo := vmmModels.NewVirtualEthernetNicNetworkInfo()
192+
netInfo.Ipv4Config = vmmModels.NewIpv4Config()
193+
netInfo.Ipv4Config.IpAddress = &vmmCommonModels.IPv4Address{Value: ptr.To(ip)}
194+
netInfo.Ipv4Info = vmmModels.NewIpv4Info()
195+
netInfo.Ipv4Info.LearnedIpAddresses = []vmmCommonModels.IPv4Address{{Value: ptr.To(ip)}}
196+
if err := nic.SetNicNetworkInfo(*netInfo); err != nil {
197+
t.Fatalf("SetNicNetworkInfo: %v", err)
198+
}
199+
return *nic
200+
}
201+
202+
// vmWithNics returns a VM with one NIC per IP; order of IPs matches order of NICs.
203+
func vmWithNics(t *testing.T, name, uuid string, ips []string) *vmmModels.Vm {
204+
t.Helper()
205+
nics := make([]vmmModels.Nic, 0, len(ips))
206+
for _, ip := range ips {
207+
nics = append(nics, nicWithIP(t, ip))
208+
}
209+
return &vmmModels.Vm{
210+
ExtId: ptr.To(uuid),
211+
Name: ptr.To(name),
212+
Nics: nics,
213+
}
214+
}

0 commit comments

Comments
 (0)