client: enhance CNI allocation tests for IPv6 and dualstack scenarios

Add multiple test cases to validate the behavior of CNI allocation when handling IPv6-only and dualstack configurations. The new tests ensure that the first address is selected correctly from multiple addresses across interfaces, maintaining consistent behavior with IPv4. This improves coverage for edge cases in CNI result processing and reinforces the recent fixes for IPv6 support.
This commit is contained in:
Dmitrii Andreev
2025-10-09 12:58:55 +03:00
parent c588527ae4
commit b9bda8f2c1

View File

@@ -521,11 +521,139 @@ func TestCNI_cniToAllocNet_IPv6Only(t *testing.T) {
allocNet, err := c.cniToAllocNet(cniResult)
must.NoError(t, err)
must.NotNil(t, allocNet)
test.Eq(t, "", allocNet.Address)
test.Eq(t, "fd00:a110:c8::b", allocNet.Address) // fallback to IPv6
test.Eq(t, "fd00:a110:c8::b", allocNet.AddressIPv6)
test.Eq(t, "eth0", allocNet.InterfaceName)
}
// TestCNI_cniToAllocNet_IPv6Only_MultipleAddresses asserts that when a CNI result
// contains multiple IPv6 addresses on a single interface, the first address is selected.
// This ensures consistent behavior with the IPv4 case.
func TestCNI_cniToAllocNet_IPv6Only_MultipleAddresses(t *testing.T) {
ci.Parallel(t)
cniResult := &cni.Result{
Interfaces: map[string]*cni.Config{
"eth0": {
Sandbox: "nomad-sandbox",
IPConfigs: []*cni.IPConfig{
{IP: net.ParseIP("fd00:a110:c8::1")}, // first IPv6 - should be selected
{IP: net.ParseIP("fd00:a110:c8::2")}, // second IPv6
{IP: net.ParseIP("fd00:a110:c8::3")}, // third IPv6
},
},
},
}
c := &cniNetworkConfigurator{
logger: testlog.HCLogger(t),
}
allocNet, err := c.cniToAllocNet(cniResult)
must.NoError(t, err)
must.NotNil(t, allocNet)
test.Eq(t, "fd00:a110:c8::1", allocNet.Address) // fallback to IPv6
test.Eq(t, "fd00:a110:c8::1", allocNet.AddressIPv6) // should select first IPv6 address
test.Eq(t, "eth0", allocNet.InterfaceName)
}
// TestCNI_cniToAllocNet_Dualstack_MultipleAddresses asserts that when a CNI result
// contains multiple IPv4 and IPv6 addresses, the first address of each type is selected.
func TestCNI_cniToAllocNet_Dualstack_MultipleAddresses(t *testing.T) {
ci.Parallel(t)
cniResult := &cni.Result{
Interfaces: map[string]*cni.Config{
"eth0": {
Sandbox: "nomad-sandbox",
IPConfigs: []*cni.IPConfig{
{IP: net.IPv4(192, 168, 1, 10)}, // first IPv4 - should be selected
{IP: net.ParseIP("fd00:a110:c8::1")}, // first IPv6 - should be selected
{IP: net.IPv4(192, 168, 1, 11)}, // second IPv4
{IP: net.ParseIP("fd00:a110:c8::2")}, // second IPv6
},
},
},
}
c := &cniNetworkConfigurator{
logger: testlog.HCLogger(t),
}
allocNet, err := c.cniToAllocNet(cniResult)
must.NoError(t, err)
must.NotNil(t, allocNet)
test.Eq(t, "192.168.1.10", allocNet.Address) // should select first IPv4 address
test.Eq(t, "fd00:a110:c8::1", allocNet.AddressIPv6) // should select first IPv6 address
test.Eq(t, "eth0", allocNet.InterfaceName)
}
// TestCNI_cniToAllocNet_MultipleInterfaces_IPv6First asserts that when multiple
// interfaces exist, the first interface (lexicographically) with an address is selected,
// even if it only has IPv6 and a later interface has IPv4.
func TestCNI_cniToAllocNet_MultipleInterfaces_IPv6First(t *testing.T) {
ci.Parallel(t)
cniResult := &cni.Result{
Interfaces: map[string]*cni.Config{
"eth0": {
Sandbox: "nomad-sandbox",
IPConfigs: []*cni.IPConfig{
{IP: net.ParseIP("fd00:a110:c8::1")}, // IPv6 only on first interface
},
},
"eth1": {
Sandbox: "nomad-sandbox",
IPConfigs: []*cni.IPConfig{
{IP: net.IPv4(192, 168, 1, 10)}, // IPv4 on second interface
},
},
},
}
c := &cniNetworkConfigurator{
logger: testlog.HCLogger(t),
}
allocNet, err := c.cniToAllocNet(cniResult)
must.NoError(t, err)
must.NotNil(t, allocNet)
test.Eq(t, "fd00:a110:c8::1", allocNet.Address) // fallback to IPv6
test.Eq(t, "fd00:a110:c8::1", allocNet.AddressIPv6) // IPv6 from first interface
test.Eq(t, "eth0", allocNet.InterfaceName) // first interface should be selected
}
// TestCNI_cniToAllocNet_MultipleInterfaces_IPv6OnMultiple asserts that when multiple
// interfaces each have IPv6 addresses, the first interface is selected.
func TestCNI_cniToAllocNet_MultipleInterfaces_IPv6OnMultiple(t *testing.T) {
ci.Parallel(t)
cniResult := &cni.Result{
Interfaces: map[string]*cni.Config{
"eth0": {
Sandbox: "nomad-sandbox",
IPConfigs: []*cni.IPConfig{
{IP: net.ParseIP("fd00:a110:c8::1")},
{IP: net.ParseIP("fd00:a110:c8::2")}, // multiple on first interface
},
},
"eth1": {
Sandbox: "nomad-sandbox",
IPConfigs: []*cni.IPConfig{
{IP: net.ParseIP("fd00:b220:c8::1")}, // different IPv6 on second interface
},
},
},
}
c := &cniNetworkConfigurator{
logger: testlog.HCLogger(t),
}
allocNet, err := c.cniToAllocNet(cniResult)
must.NoError(t, err)
must.NotNil(t, allocNet)
test.Eq(t, "fd00:a110:c8::1", allocNet.Address) // fallback to IPv6
test.Eq(t, "fd00:a110:c8::1", allocNet.AddressIPv6) // first address from first interface
test.Eq(t, "eth0", allocNet.InterfaceName) // first interface
}
func TestCNI_addCustomCNIArgs(t *testing.T) {
ci.Parallel(t)
cniArgs := map[string]string{