diff --git a/staging/src/k8s.io/legacy-cloud-providers/azure/azure_instances.go b/staging/src/k8s.io/legacy-cloud-providers/azure/azure_instances.go index 8751b4b5d3d..718e98c6df4 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/azure/azure_instances.go +++ b/staging/src/k8s.io/legacy-cloud-providers/azure/azure_instances.go @@ -21,7 +21,7 @@ package azure import ( "context" "fmt" - "os" + "strconv" "strings" v1 "k8s.io/api/core/v1" @@ -231,18 +231,22 @@ func (az *Cloud) InstanceShutdownByProviderID(ctx context.Context, providerID st } func (az *Cloud) isCurrentInstance(name types.NodeName, metadataVMName string) (bool, error) { - var err error nodeName := mapNodeNameToVMName(name) + if az.VMType == vmTypeVMSS { - // VMSS vmName is not same with hostname, use hostname instead. - metadataVMName, err = os.Hostname() - if err != nil { - return false, err + // VMSS vmName is not same with hostname, construct the node name "{computer-name-prefix}{base-36-instance-id}". + // Refer https://docs.microsoft.com/en-us/azure/virtual-machine-scale-sets/virtual-machine-scale-sets-instance-ids#scale-set-vm-computer-name. + if ssName, instanceID, err := extractVmssVMName(metadataVMName); err == nil { + instance, err := strconv.ParseInt(instanceID, 10, 64) + if err != nil { + return false, fmt.Errorf("failed to parse VMSS instanceID %q: %v", instanceID, err) + } + metadataVMName = fmt.Sprintf("%s%06s", ssName, strconv.FormatInt(instance, 36)) } } metadataVMName = strings.ToLower(metadataVMName) - return (metadataVMName == nodeName), err + return (metadataVMName == nodeName), nil } // InstanceID returns the cloud provider ID of the specified instance. diff --git a/staging/src/k8s.io/legacy-cloud-providers/azure/azure_instances_test.go b/staging/src/k8s.io/legacy-cloud-providers/azure/azure_instances_test.go index 80e9ff85976..d796fd89855 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/azure/azure_instances_test.go +++ b/staging/src/k8s.io/legacy-cloud-providers/azure/azure_instances_test.go @@ -361,3 +361,56 @@ func TestNodeAddresses(t *testing.T) { } } } + +func TestIsCurrentInstance(t *testing.T) { + cloud := &Cloud{ + Config: Config{ + VMType: vmTypeVMSS, + }, + } + testcases := []struct { + nodeName string + metadataVMName string + expected bool + expectError bool + }{ + { + nodeName: "node1", + metadataVMName: "node1", + expected: true, + }, + { + nodeName: "node1", + metadataVMName: "node2", + expected: false, + }, + { + nodeName: "vmss000001", + metadataVMName: "vmss_1", + expected: true, + }, + { + nodeName: "vmss_2", + metadataVMName: "vmss000000", + expected: false, + }, + { + nodeName: "vmss123456", + metadataVMName: "vmss_$123", + expected: false, + expectError: true, + }, + } + + for i, test := range testcases { + real, err := cloud.isCurrentInstance(types.NodeName(test.nodeName), test.metadataVMName) + if test.expectError { + if err == nil { + t.Errorf("Test[%d] unexpected nil err", i) + } + } + if real != test.expected { + t.Errorf("Test[%d] unexpected isCurrentInstance result %v != %v", i, real, test.expected) + } + } +}