Change:
What happened: introduced new regex which is too restrictive for some existing installations: This new restriction causes LBs to fail to sync if just one ipConf fails regex. What you expected to happen: This change was to enable optional behavior, any ipConf that fails regex should just be ignored. This will allow existing installs to work as they did prior to the change. How to reproduce it (as minimally and precisely as possible): Anything else we need to know?: Environment: Kubernetes version (use ): Cloud provider or hardware configuration: OS (e.g: ): Kernel (e.g. ): Install tools: Network plugin and version (if this is a network-related bug): Others:
Suggest putting a continue here: This will restore previous functionality and appears to have no undesirable impact.
/sig cloud-provider /area provider/azure
Unclear if we should also put a continue here as well:
/assign
could you share an example of resourceID (please replace your subscription/resourceName with fake ones)? /triage accepted
Here's the error we're seeing: Just the string

Discussion:
return nil, err } primaryVMSetName := az.VMSet.GetPrimaryVMSetName() <del> if !strings.EqualFold(primaryVMSetName, vmSetName) { </del> <ins> if !strings.EqualFold(primaryVMSetName, vmSetName) && vmSetName != "" { </ins> klog.V(2).Infof("cleanBackendpoolForPrimarySLB: found unwanted vmSet %s, decouple it from the LB", vmSetName) // construct a backendPool that only contains the IP config of the node to be deleted interfaceIPConfigToBeDeleted := network.InterfaceIPConfiguration{

if err != nil { return nil, err } <ins> if nodeName == "" { // VM may under deletion continue } </ins> // If a node is not supposed to be included in the LB, it // would not be in the `nodes` slice. We need to check the nodes that // have been added to the LB's backendpool, find the unwanted ones and

}) existingVMForAS1 := buildDefaultTestVirtualMachine("/subscriptions/subscription/resourceGroups/rg/providers/Microsoft.Compute/availabilitySets/agentpool1-availabilitySet-00000000", []string{"/subscriptions/subscription/resourceGroups/rg/providers/Microsoft.Network/networkInterfaces/k8s-agentpool1-00000000-nic-1"}) existingVMForAS2 := buildDefaultTestVirtualMachine("/subscriptions/subscription/resourceGroups/rg/providers/Microsoft.Compute/availabilitySets/agentpool2-availabilitySet-00000000", []string{"/subscriptions/subscription/resourceGroups/rg/providers/Microsoft.Network/networkInterfaces/k8s-agentpool2-00000000-nic-1"}) <del> existingNIC := buildDefaultTestInterface(true, []string{"/subscriptions/sub/resourceGroups/gh/providers/Microsoft.Network/loadBalancers/testCluster/backendAddressPools/testCluster"}) </del> <ins> existingNICForAS1 := buildDefaultTestInterface(true, []string{"/subscriptions/sub/resourceGroups/gh/providers/Microsoft.Network/loadBalancers/testCluster/backendAddressPools/testCluster"}) existingNICForAS1.VirtualMachine = &network.SubResource{ ID: to.StringPtr("/subscriptions/subscription/resourceGroups/rg/providers/Microsoft.Compute/virtualMachines/k8s-agentpool1-00000000-1"), } existingNICForAS2 := buildDefaultTestInterface(true, []string{"/subscriptions/sub/resourceGroups/gh/providers/Microsoft.Network/loadBalancers/testCluster/backendAddressPools/testCluster"}) existingNICForAS2.VirtualMachine = &network.SubResource{ ID: to.StringPtr("/subscriptions/subscription/resourceGroups/rg/providers/Microsoft.Compute/virtualMachines/k8s-agentpool2-00000000-1"), } </ins> mockVMClient := mockvmclient.NewMockInterface(ctrl) mockVMClient.EXPECT().Get(gomock.Any(), cloud.ResourceGroup, "k8s-agentpool1-00000000-1", gomock.Any()).Return(existingVMForAS1, nil) mockVMClient.EXPECT().Get(gomock.Any(), cloud.ResourceGroup, "k8s-agentpool2-00000000-1", gomock.Any()).Return(existingVMForAS2, nil) cloud.VirtualMachinesClient = mockVMClient mockNICClient := mockinterfaceclient.NewMockInterface(ctrl) <del> mockNICClient.EXPECT().Get(gomock.Any(), "rg", "k8s-agentpool2-00000000-nic-1", gomock.Any()).Return(existingNIC, nil) </del> <ins> mockNICClient.EXPECT().Get(gomock.Any(), "rg", "k8s-agentpool1-00000000-nic-1", gomock.Any()).Return(existingNICForAS1, nil) mockNICClient.EXPECT().Get(gomock.Any(), "rg", "k8s-agentpool2-00000000-nic-1", gomock.Any()).Return(existingNICForAS2, nil).Times(3) </ins> mockNICClient.EXPECT().CreateOrUpdate(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) cloud.InterfacesClient = mockNICClient cleanedLB, err := cloud.cleanBackendpoolForPrimarySLB(&lb, &service, clusterName)

providerIDRE       = regexp.MustCompile(`.*/subscriptions/(?:.*)/Microsoft.Compute/virtualMachines/(.+)$`) backendPoolIDRE    = regexp.MustCompile(`^/subscriptions/(?:.*)/resourceGroups/(?:.*)/providers/Microsoft.Network/loadBalancers/(.+)/backendAddressPools/(?:.*)`) nicResourceGroupRE = regexp.MustCompile(`.*/subscriptions/(?:.*)/resourceGroups/(.+)/providers/Microsoft.Network/networkInterfaces/(?:.*)`) <del> nicIDRE            = regexp.MustCompile(`/subscriptions/(?:.*)/resourceGroups/(?:.+)/providers/Microsoft.Network/networkInterfaces/(.+)-nic-(.+)/ipConfigurations/(?:.*)`) </del> <ins> nicIDRE            = regexp.MustCompile(`(?i)/subscriptions/(?:.*)/resourceGroups/(.+)/providers/Microsoft.Network/networkInterfaces/(.+)/ipConfigurations/(?:.*)`) vmIDRE             = regexp.MustCompile(`(?i)/subscriptions/(?:.*)/resourceGroups/(?:.*)/providers/Microsoft.Compute/virtualMachines/(.+)`) </ins> vmasIDRE           = regexp.MustCompile(`/subscriptions/(?:.*)/resourceGroups/(?:.*)/providers/Microsoft.Compute/availabilitySets/(.+)`) )

return "", "", fmt.Errorf("invalid ip config ID %s", ipConfigurationID) } <del> prefix := matches[1] suffix := matches[2] nodeName := fmt.Sprintf("%s-%s", prefix, suffix) </del> <ins> nicResourceGroup, nicName := matches[1], matches[2] if nicResourceGroup == "" || nicName == "" { return "", "", fmt.Errorf("invalid ip config ID %s", ipConfigurationID) } nic, rerr := as.InterfacesClient.Get(context.Background(), nicResourceGroup, nicName, "") if rerr != nil { return "", "", fmt.Errorf("GetNodeNameByIPConfigurationID(%s): failed to get interface of name %s: %s", ipConfigurationID, nicName, rerr.Error().Error()) } vmID := "" if nic.InterfacePropertiesFormat != nil && nic.VirtualMachine != nil { vmID = to.String(nic.VirtualMachine.ID) } if vmID == "" { klog.V(2).Infof("GetNodeNameByIPConfigurationID(%s): empty vmID", ipConfigurationID) return "", "", nil } </ins> <del> vm, err := as.getVirtualMachine(types.NodeName(nodeName), azcache.CacheReadTypeDefault) </del> <ins> matches = vmIDRE.FindStringSubmatch(vmID) if len(matches) != 2 { return "", "", fmt.Errorf("invalid virtual machine ID %s", vmID) } vmName := matches[1] vm, err := as.getVirtualMachine(types.NodeName(vmName), azcache.CacheReadTypeDefault) </ins> if err != nil { <del> return "", "", fmt.Errorf("cannot get the virtual machine by node name %s", nodeName) </del> <ins> return "", "", fmt.Errorf("cannot get the virtual machine by node name %s", vmName) </ins> } asID := "" if vm.VirtualMachineProperties != nil && vm.AvailabilitySet != nil { asID = to.String(vm.AvailabilitySet.ID) } if asID == "" { <del> return "", "", fmt.Errorf("cannot get the availability set ID from the virtual machine with node name %s", nodeName) </del> <ins> return vmName, "", nil </ins> } asName, err := getAvailabilitySetNameByID(asID) if err != nil { return "", "", fmt.Errorf("cannot get the availability set name by the availability set ID %s", asID) } <del> return nodeName, strings.ToLower(asName), nil </del> <ins> return vmName, strings.ToLower(asName), nil </ins> }

mockVMClient.EXPECT().Get(gomock.Any(), cloud.ResourceGroup, "k8s-agentpool1-00000000-1", gomock.Any()).Return(test.existingVM, nil) cloud.VirtualMachinesClient = mockVMClient mockNICClient := mockinterfaceclient.NewMockInterface(ctrl) <del> mockNICClient.EXPECT().Get(gomock.Any(), "rg", "k8s-agentpool1-00000000-nic-1", gomock.Any()).Return(test.existingNIC, nil) </del> <ins> test.existingNIC.VirtualMachine = &network.SubResource{ ID: to.StringPtr("/subscriptions/sub/resourceGroups/rg/providers/Microsoft.Compute/virtualMachines/k8s-agentpool1-00000000-1"), } mockNICClient.EXPECT().Get(gomock.Any(), "rg", "k8s-agentpool1-00000000-nic-1", gomock.Any()).Return(test.existingNIC, nil).Times(2) </ins> mockNICClient.EXPECT().CreateOrUpdate(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) cloud.InterfacesClient = mockNICClient

defer ctrl.Finish() cloud := GetTestCloud(ctrl) expectedVM := buildDefaultTestVirtualMachine("/subscriptions/sub/resourceGroups/rg/providers/Microsoft.Compute/availabilitySets/AGENTPOOL1-AVAILABILITYSET-00000000", []string{}) <ins> expectedVM.Name = to.StringPtr("name") </ins> mockVMClient := cloud.VirtualMachinesClient.(*mockvmclient.MockInterface) mockVMClient.EXPECT().Get(gomock.Any(), "rg", "k8s-agentpool1-00000000-0", gomock.Any()).Return(expectedVM, nil) <ins> expectedNIC := buildDefaultTestInterface(true, []string{}) expectedNIC.VirtualMachine = &network.SubResource{ ID: to.StringPtr("/subscriptions/sub/resourceGroups/rg/providers/Microsoft.Compute/virtualMachines/k8s-agentpool1-00000000-0"), } mockNICClient := cloud.InterfacesClient.(*mockinterfaceclient.MockInterface) mockNICClient.EXPECT().Get(gomock.Any(), "rg", "k8s-agentpool1-00000000-nic-0", gomock.Any()).Return(expectedNIC, nil) </ins> ipConfigurationID := `/subscriptions/sub/resourceGroups/rg/providers/Microsoft.Network/networkInterfaces/k8s-agentpool1-00000000-nic-0/ipConfigurations/ipconfig1` nodeName, asName, err := cloud.VMSet.GetNodeNameByIPConfigurationID(ipConfigurationID) assert.NoError(t, err) <del> assert.Equal(t, nodeName, "k8s-agentpool1-00000000-0") assert.Equal(t, asName, "agentpool1-availabilityset-00000000") </del> <ins> assert.Equal(t, "k8s-agentpool1-00000000-0", nodeName) assert.Equal(t, "agentpool1-availabilityset-00000000", asName) </ins> }