Skip to content

Commit 6f6c5b5

Browse files
authored
Merge pull request #5747 from mainred/comma-separated-provided-ips
fix: handle comma-separated provided IPs
2 parents f67019b + 1bed7b3 commit 6f6c5b5

File tree

2 files changed

+193
-16
lines changed

2 files changed

+193
-16
lines changed

pkg/nodemanager/nodemanager.go

+23-16
Original file line numberDiff line numberDiff line change
@@ -302,10 +302,8 @@ func (cnc *CloudNodeController) updateNodeAddress(ctx context.Context, node *v1.
302302
}
303303
// If nodeIP was suggested by user, ensure that
304304
// it can be found in the cloud as well (consistent with the behaviour in kubelet)
305-
if nodeIP, ok := ensureNodeProvidedIPExists(node, nodeAddresses); ok {
306-
if nodeIP == nil {
307-
return fmt.Errorf("specified Node IP %s not found in cloudprovider for node %q", nodeAddresses, node.Name)
308-
}
305+
if existNodeIPs, ok := ensureNodeProvidedIPsExists(node, nodeAddresses); !ok {
306+
return fmt.Errorf("not all specified Node IP %s found in cloudprovider for node %q, existing Node IPs are %s ", nodeAddresses, node.Name, existNodeIPs)
309307
}
310308
if !nodeAddressesChangeDetected(node.Status.Addresses, nodeAddresses) {
311309
return nil
@@ -468,10 +466,8 @@ func (cnc *CloudNodeController) getNodeModifiersFromCloudProvider(ctx context.Co
468466

469467
// If user provided an IP address, ensure that IP address is found
470468
// in the cloud provider before removing the taint on the node
471-
if nodeIP, ok := ensureNodeProvidedIPExists(node, nodeAddresses); ok {
472-
if nodeIP == nil {
473-
return nil, errors.New("failed to find kubelet node IP from cloud provider")
474-
}
469+
if _, ok := ensureNodeProvidedIPsExists(node, nodeAddresses); !ok {
470+
return nil, errors.New("failed to find kubelet node IP from cloud provider")
475471
}
476472

477473
if instanceType, err := cnc.getInstanceTypeByName(ctx, node); err != nil {
@@ -602,19 +598,30 @@ func nodeAddressesChangeDetected(addressSet1, addressSet2 []v1.NodeAddress) bool
602598
return false
603599
}
604600

605-
func ensureNodeProvidedIPExists(node *v1.Node, nodeAddresses []v1.NodeAddress) (*v1.NodeAddress, bool) {
606-
var nodeIP *v1.NodeAddress
607-
nodeIPExists := false
608-
if providedIP, ok := node.ObjectMeta.Annotations[cloudproviderapi.AnnotationAlphaProvidedIPAddr]; ok {
609-
nodeIPExists = true
610-
for i := range nodeAddresses {
601+
// Ensure all provided node ip addresses are found in the cloud provider, otherwise return false
602+
// When there's no provided node ip addresses, it will return true.
603+
func ensureNodeProvidedIPsExists(node *v1.Node, nodeAddresses []v1.NodeAddress) ([]v1.NodeAddress, bool) {
604+
providedIPStr, ok := node.ObjectMeta.Annotations[cloudproviderapi.AnnotationAlphaProvidedIPAddr]
605+
if !ok || len(providedIPStr) == 0 {
606+
return []v1.NodeAddress{}, true
607+
}
608+
var existNodeIPs []v1.NodeAddress
609+
nodeIPsExists := false
610+
providedIPs := strings.Split(providedIPStr, ",")
611+
for i := range nodeAddresses {
612+
for _, providedIP := range providedIPs {
613+
providedIP = strings.TrimSpace(providedIP)
611614
if nodeAddresses[i].Address == providedIP {
612-
nodeIP = &nodeAddresses[i]
615+
existNodeIPs = append(existNodeIPs, nodeAddresses[i])
613616
break
614617
}
615618
}
616619
}
617-
return nodeIP, nodeIPExists
620+
if len(existNodeIPs) == len(providedIPs) {
621+
nodeIPsExists = true
622+
}
623+
624+
return existNodeIPs, nodeIPsExists
618625
}
619626

620627
func (cnc *CloudNodeController) getInstanceTypeByName(ctx context.Context, node *v1.Node) (string, error) {

pkg/nodemanager/nodemanager_test.go

+170
Original file line numberDiff line numberDiff line change
@@ -1338,3 +1338,173 @@ func TestNodeProviderIDNotSet(t *testing.T) {
13381338
// Node update should fail
13391339
assert.Equal(t, 0, len(fnh.UpdatedNodes), "Node was updated (unexpected)")
13401340
}
1341+
1342+
func Test_ensureNodeProvidedIPsExists(t *testing.T) {
1343+
testcases := []struct {
1344+
name string
1345+
node *v1.Node
1346+
nodeAddresses []v1.NodeAddress
1347+
expectedExistingNodeIPs []v1.NodeAddress
1348+
nodeIPsExists bool
1349+
}{
1350+
{
1351+
name: "return true when there's provide node ip address",
1352+
node: &v1.Node{
1353+
ObjectMeta: metav1.ObjectMeta{
1354+
Name: "node0",
1355+
Labels: map[string]string{},
1356+
Annotations: map[string]string{},
1357+
},
1358+
},
1359+
nodeAddresses: []v1.NodeAddress{
1360+
{
1361+
Address: "10.0.0.1",
1362+
},
1363+
},
1364+
expectedExistingNodeIPs: []v1.NodeAddress{},
1365+
nodeIPsExists: true,
1366+
},
1367+
{
1368+
name: "return true when all provided IPv4 IP address are found",
1369+
node: &v1.Node{
1370+
ObjectMeta: metav1.ObjectMeta{
1371+
Name: "node0",
1372+
Labels: map[string]string{},
1373+
Annotations: map[string]string{
1374+
cloudproviderapi.AnnotationAlphaProvidedIPAddr: "10.0.0.1",
1375+
},
1376+
},
1377+
},
1378+
nodeAddresses: []v1.NodeAddress{
1379+
{
1380+
Address: "10.0.0.1",
1381+
},
1382+
},
1383+
expectedExistingNodeIPs: []v1.NodeAddress{{Address: "10.0.0.1"}},
1384+
nodeIPsExists: true,
1385+
},
1386+
{
1387+
name: "return true when all provided dual stack IP addresses are found",
1388+
node: &v1.Node{
1389+
ObjectMeta: metav1.ObjectMeta{
1390+
Name: "node0",
1391+
Labels: map[string]string{},
1392+
Annotations: map[string]string{
1393+
cloudproviderapi.AnnotationAlphaProvidedIPAddr: "10.0.0.1,fd47:c915:f8a8:e63d::5",
1394+
},
1395+
},
1396+
},
1397+
nodeAddresses: []v1.NodeAddress{
1398+
{
1399+
Address: "10.0.0.1",
1400+
},
1401+
{
1402+
Address: "fd47:c915:f8a8:e63d::5",
1403+
},
1404+
},
1405+
expectedExistingNodeIPs: []v1.NodeAddress{
1406+
{
1407+
Address: "10.0.0.1",
1408+
},
1409+
{
1410+
Address: "fd47:c915:f8a8:e63d::5",
1411+
},
1412+
},
1413+
nodeIPsExists: true,
1414+
},
1415+
{
1416+
name: "return true when all provided dual stack IP addresses are found but joined with extra space",
1417+
node: &v1.Node{
1418+
ObjectMeta: metav1.ObjectMeta{
1419+
Name: "node0",
1420+
Labels: map[string]string{},
1421+
Annotations: map[string]string{
1422+
cloudproviderapi.AnnotationAlphaProvidedIPAddr: "10.0.0.1, fd47:c915:f8a8:e63d::5",
1423+
},
1424+
},
1425+
},
1426+
nodeAddresses: []v1.NodeAddress{
1427+
{
1428+
Address: "10.0.0.1",
1429+
},
1430+
{
1431+
Address: "fd47:c915:f8a8:e63d::5",
1432+
},
1433+
},
1434+
expectedExistingNodeIPs: []v1.NodeAddress{
1435+
{
1436+
Address: "10.0.0.1",
1437+
},
1438+
{
1439+
Address: "fd47:c915:f8a8:e63d::5",
1440+
},
1441+
},
1442+
nodeIPsExists: true,
1443+
},
1444+
{
1445+
name: "return false when not all ip addresses are found for provided dual stack IP addresses",
1446+
node: &v1.Node{
1447+
ObjectMeta: metav1.ObjectMeta{
1448+
Name: "node0",
1449+
Labels: map[string]string{},
1450+
Annotations: map[string]string{
1451+
cloudproviderapi.AnnotationAlphaProvidedIPAddr: "10.0.0.1,fd47:c915:f8a8:e63d::5",
1452+
},
1453+
},
1454+
},
1455+
nodeAddresses: []v1.NodeAddress{
1456+
{
1457+
Address: "10.0.0.1",
1458+
},
1459+
},
1460+
expectedExistingNodeIPs: []v1.NodeAddress{
1461+
{
1462+
Address: "10.0.0.1",
1463+
},
1464+
},
1465+
nodeIPsExists: false,
1466+
},
1467+
{
1468+
name: "return false when wrong ip addresses are provided for provided dual stack IP addresses",
1469+
node: &v1.Node{
1470+
ObjectMeta: metav1.ObjectMeta{
1471+
Name: "node0",
1472+
Labels: map[string]string{},
1473+
Annotations: map[string]string{
1474+
cloudproviderapi.AnnotationAlphaProvidedIPAddr: "10.0.0.1,fd47:c915:f8a8:e63d::10",
1475+
},
1476+
},
1477+
},
1478+
nodeAddresses: []v1.NodeAddress{
1479+
{
1480+
Address: "10.0.0.1",
1481+
},
1482+
{
1483+
Address: "fd47:c915:f8a8:e63d::5",
1484+
},
1485+
},
1486+
expectedExistingNodeIPs: []v1.NodeAddress{
1487+
{
1488+
Address: "10.0.0.1",
1489+
},
1490+
},
1491+
nodeIPsExists: false,
1492+
},
1493+
}
1494+
1495+
for _, test := range testcases {
1496+
t.Run(test.name, func(t *testing.T) {
1497+
1498+
actualNodeIP, actualNodeIPsExists := ensureNodeProvidedIPsExists(test.node, test.nodeAddresses)
1499+
1500+
if !reflect.DeepEqual(actualNodeIP, test.expectedExistingNodeIPs) {
1501+
t.Logf("Actual existing node IPs: %v", actualNodeIP)
1502+
t.Logf("Expected existing node IPs: %v", test.expectedExistingNodeIPs)
1503+
t.Errorf("Actual existing node IP does not match expected existing node IP")
1504+
}
1505+
if actualNodeIPsExists != test.nodeIPsExists {
1506+
t.Errorf("all node ip addresses exist result mismatch, got: %t, wanted: %t", actualNodeIPsExists, test.nodeIPsExists)
1507+
}
1508+
})
1509+
}
1510+
}

0 commit comments

Comments
 (0)