diff --git a/staging/src/k8s.io/legacy-cloud-providers/azure/BUILD b/staging/src/k8s.io/legacy-cloud-providers/azure/BUILD index 0ff763ed382..cbce39f4bbe 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/azure/BUILD +++ b/staging/src/k8s.io/legacy-cloud-providers/azure/BUILD @@ -64,22 +64,31 @@ go_library( "//staging/src/k8s.io/legacy-cloud-providers/azure/cache:go_default_library", "//staging/src/k8s.io/legacy-cloud-providers/azure/clients:go_default_library", "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/diskclient:go_default_library", + "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/diskclient/mockdiskclient:go_default_library", + "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/fileclient:go_default_library", "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/interfaceclient:go_default_library", + "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/interfaceclient/mockinterfaceclient:go_default_library", "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/loadbalancerclient:go_default_library", + "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/loadbalancerclient/mockloadbalancerclient:go_default_library", "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/publicipclient:go_default_library", + "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/publicipclient/mockpublicipclient:go_default_library", "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/routeclient:go_default_library", "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/routeclient/mockrouteclient:go_default_library", "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/routetableclient:go_default_library", "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/routetableclient/mockroutetableclient:go_default_library", "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/securitygroupclient:go_default_library", + "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/securitygroupclient/mocksecuritygroupclient:go_default_library", "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/snapshotclient:go_default_library", "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/storageaccountclient:go_default_library", "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/subnetclient:go_default_library", "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/subnetclient/mocksubnetclient:go_default_library", "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/vmclient:go_default_library", + "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/vmclient/mockvmclient:go_default_library", "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/vmsizeclient:go_default_library", "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/vmssclient:go_default_library", + "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/vmssclient/mockvmssclient:go_default_library", "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/vmssvmclient:go_default_library", + "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/vmssvmclient/mockvmssvmclient:go_default_library", "//staging/src/k8s.io/legacy-cloud-providers/azure/retry:go_default_library", "//vendor/github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-01/compute:go_default_library", "//vendor/github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-06-01/network:go_default_library", @@ -130,8 +139,18 @@ go_test( "//staging/src/k8s.io/legacy-cloud-providers/azure/auth:go_default_library", "//staging/src/k8s.io/legacy-cloud-providers/azure/cache:go_default_library", "//staging/src/k8s.io/legacy-cloud-providers/azure/clients:go_default_library", + "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/diskclient/mockdiskclient:go_default_library", + "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/fileclient/mockfileclient:go_default_library", + "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/interfaceclient/mockinterfaceclient:go_default_library", + "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/loadbalancerclient/mockloadbalancerclient:go_default_library", + "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/publicipclient/mockpublicipclient:go_default_library", "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/routetableclient/mockroutetableclient:go_default_library", + "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/securitygroupclient/mocksecuritygroupclient:go_default_library", + "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/storageaccountclient/mockstorageaccountclient:go_default_library", "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/subnetclient/mocksubnetclient:go_default_library", + "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/vmclient/mockvmclient:go_default_library", + "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/vmssclient/mockvmssclient:go_default_library", + "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/vmssvmclient/mockvmssvmclient:go_default_library", "//staging/src/k8s.io/legacy-cloud-providers/azure/mockvmsets:go_default_library", "//staging/src/k8s.io/legacy-cloud-providers/azure/retry:go_default_library", "//vendor/github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-01/compute:go_default_library", diff --git a/staging/src/k8s.io/legacy-cloud-providers/azure/azure.go b/staging/src/k8s.io/legacy-cloud-providers/azure/azure.go index f2814877227..22be4e88a8d 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/azure/azure.go +++ b/staging/src/k8s.io/legacy-cloud-providers/azure/azure.go @@ -47,6 +47,7 @@ import ( azcache "k8s.io/legacy-cloud-providers/azure/cache" azclients "k8s.io/legacy-cloud-providers/azure/clients" "k8s.io/legacy-cloud-providers/azure/clients/diskclient" + "k8s.io/legacy-cloud-providers/azure/clients/fileclient" "k8s.io/legacy-cloud-providers/azure/clients/interfaceclient" "k8s.io/legacy-cloud-providers/azure/clients/loadbalancerclient" "k8s.io/legacy-cloud-providers/azure/clients/publicipclient" @@ -61,6 +62,7 @@ import ( "k8s.io/legacy-cloud-providers/azure/clients/vmssclient" "k8s.io/legacy-cloud-providers/azure/clients/vmssvmclient" "k8s.io/legacy-cloud-providers/azure/retry" + "sigs.k8s.io/yaml" ) @@ -234,7 +236,7 @@ type Cloud struct { StorageAccountClient storageaccountclient.Interface DisksClient diskclient.Interface SnapshotsClient snapshotclient.Interface - FileClient FileClient + FileClient fileclient.Interface VirtualMachineScaleSetsClient vmssclient.Interface VirtualMachineScaleSetVMsClient vmssvmclient.Interface VirtualMachineSizesClient vmsizeclient.Interface @@ -590,7 +592,7 @@ func (az *Cloud) configAzureClients( az.SecurityGroupsClient = securitygroupclient.New(securityGroupClientConfig) az.PublicIPAddressesClient = publicipclient.New(publicIPClientConfig) // fileClient is not based on armclient, but it's still backoff retried. - az.FileClient = newAzureFileClient(&az.Environment, azClientConfig.Backoff) + az.FileClient = fileclient.NewAzureFileClient(&az.Environment, azClientConfig.Backoff) } func (az *Cloud) getAzureClientConfig(servicePrincipalToken *adal.ServicePrincipalToken) *azclients.ClientConfig { diff --git a/staging/src/k8s.io/legacy-cloud-providers/azure/azure_controller_common_test.go b/staging/src/k8s.io/legacy-cloud-providers/azure/azure_controller_common_test.go index aa1430cc5d4..07417cc7b0a 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/azure/azure_controller_common_test.go +++ b/staging/src/k8s.io/legacy-cloud-providers/azure/azure_controller_common_test.go @@ -20,14 +20,20 @@ package azure import ( "fmt" + "net/http" "reflect" "testing" "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-01/compute" + "github.com/Azure/go-autorest/autorest/to" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" "k8s.io/apimachinery/pkg/types" + cloudprovider "k8s.io/cloud-provider" + "k8s.io/legacy-cloud-providers/azure/clients/diskclient/mockdiskclient" + "k8s.io/legacy-cloud-providers/azure/clients/vmclient/mockvmclient" + "k8s.io/legacy-cloud-providers/azure/retry" "k8s.io/utils/pointer" ) @@ -40,12 +46,14 @@ func TestCommonAttachDisk(t *testing.T) { vmList map[string]string nodeName types.NodeName isDataDisksFull bool + existedDisk compute.Disk expectedLun int32 expectedErr bool }{ { desc: "LUN -1 and error shall be returned if there's no such instance corresponding to given nodeName", nodeName: "vm1", + existedDisk: compute.Disk{Name: to.StringPtr("disk-name")}, expectedLun: -1, expectedErr: true, }, @@ -54,6 +62,7 @@ func TestCommonAttachDisk(t *testing.T) { vmList: map[string]string{"vm1": "PowerState/Running"}, nodeName: "vm1", isDataDisksFull: true, + existedDisk: compute.Disk{Name: to.StringPtr("disk-name")}, expectedLun: -1, expectedErr: true, }, @@ -61,6 +70,15 @@ func TestCommonAttachDisk(t *testing.T) { desc: "correct LUN and no error shall be returned if everything is good", vmList: map[string]string{"vm1": "PowerState/Running"}, nodeName: "vm1", + existedDisk: compute.Disk{Name: to.StringPtr("disk-name")}, + expectedLun: 1, + expectedErr: false, + }, + { + desc: "an error shall be returned if there's no matching disk", + vmList: map[string]string{"vm1": "PowerState/Running"}, + nodeName: "vm1", + existedDisk: compute.Disk{Name: to.StringPtr("disk-name-1")}, expectedLun: -1, expectedErr: true, }, @@ -76,9 +94,21 @@ func TestCommonAttachDisk(t *testing.T) { cloud: testCloud, vmLockMap: newLockMap(), } - diskURI := fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Compute/disks/disk-name", - testCloud.SubscriptionID, testCloud.ResourceGroup) - setTestVirtualMachines(testCloud, test.vmList, test.isDataDisksFull) + diskURI := fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Compute/disks/%s", + testCloud.SubscriptionID, testCloud.ResourceGroup, *test.existedDisk.Name) + expectedVMs := setTestVirtualMachines(testCloud, test.vmList, test.isDataDisksFull) + mockVMsClient := testCloud.VirtualMachinesClient.(*mockvmclient.MockInterface) + for _, vm := range expectedVMs { + mockVMsClient.EXPECT().Get(gomock.Any(), testCloud.ResourceGroup, *vm.Name, gomock.Any()).Return(vm, nil).AnyTimes() + } + if len(expectedVMs) == 0 { + mockVMsClient.EXPECT().Get(gomock.Any(), testCloud.ResourceGroup, gomock.Any(), gomock.Any()).Return(compute.VirtualMachine{}, &retry.Error{HTTPStatusCode: http.StatusNotFound, RawError: cloudprovider.InstanceNotFound}).AnyTimes() + } + mockVMsClient.EXPECT().Update(gomock.Any(), testCloud.ResourceGroup, gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + + mockDisksClient := testCloud.DisksClient.(*mockdiskclient.MockInterface) + mockDisksClient.EXPECT().Get(gomock.Any(), testCloud.ResourceGroup, "disk-name").Return(test.existedDisk, nil).AnyTimes() + mockDisksClient.EXPECT().Get(gomock.Any(), testCloud.ResourceGroup, gomock.Not("disk-name")).Return(compute.Disk{}, &retry.Error{HTTPStatusCode: http.StatusNotFound, RawError: cloudprovider.InstanceNotFound}).AnyTimes() lun, err := common.AttachDisk(true, "", diskURI, test.nodeName, compute.CachingTypesReadOnly) assert.Equal(t, test.expectedLun, lun, "TestCase[%d]: %s", i, test.desc) @@ -130,7 +160,15 @@ func TestCommonDetachDisk(t *testing.T) { } diskURI := fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Compute/disks/disk-name", testCloud.SubscriptionID, testCloud.ResourceGroup) - setTestVirtualMachines(testCloud, test.vmList, false) + expectedVMs := setTestVirtualMachines(testCloud, test.vmList, false) + mockVMsClient := testCloud.VirtualMachinesClient.(*mockvmclient.MockInterface) + for _, vm := range expectedVMs { + mockVMsClient.EXPECT().Get(gomock.Any(), testCloud.ResourceGroup, *vm.Name, gomock.Any()).Return(vm, nil).AnyTimes() + } + if len(expectedVMs) == 0 { + mockVMsClient.EXPECT().Get(gomock.Any(), testCloud.ResourceGroup, gomock.Any(), gomock.Any()).Return(compute.VirtualMachine{}, &retry.Error{HTTPStatusCode: http.StatusNotFound, RawError: cloudprovider.InstanceNotFound}).AnyTimes() + } + mockVMsClient.EXPECT().Update(gomock.Any(), testCloud.ResourceGroup, gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() err := common.DetachDisk(test.diskName, diskURI, test.nodeName) assert.Equal(t, test.expectedErr, err != nil, "TestCase[%d]: %s, err: %v", i, test.desc, err) @@ -172,7 +210,11 @@ func TestGetDiskLun(t *testing.T) { cloud: testCloud, vmLockMap: newLockMap(), } - setTestVirtualMachines(testCloud, map[string]string{"vm1": "PowerState/Running"}, false) + expectedVMs := setTestVirtualMachines(testCloud, map[string]string{"vm1": "PowerState/Running"}, false) + mockVMsClient := testCloud.VirtualMachinesClient.(*mockvmclient.MockInterface) + for _, vm := range expectedVMs { + mockVMsClient.EXPECT().Get(gomock.Any(), testCloud.ResourceGroup, *vm.Name, gomock.Any()).Return(vm, nil).AnyTimes() + } lun, err := common.GetDiskLun(test.diskName, test.diskURI, "vm1") assert.Equal(t, test.expectedLun, lun, "TestCase[%d]: %s", i, test.desc) @@ -214,7 +256,11 @@ func TestGetNextDiskLun(t *testing.T) { cloud: testCloud, vmLockMap: newLockMap(), } - setTestVirtualMachines(testCloud, map[string]string{"vm1": "PowerState/Running"}, test.isDataDisksFull) + expectedVMs := setTestVirtualMachines(testCloud, map[string]string{"vm1": "PowerState/Running"}, test.isDataDisksFull) + mockVMsClient := testCloud.VirtualMachinesClient.(*mockvmclient.MockInterface) + for _, vm := range expectedVMs { + mockVMsClient.EXPECT().Get(gomock.Any(), testCloud.ResourceGroup, *vm.Name, gomock.Any()).Return(vm, nil).AnyTimes() + } lun, err := common.GetNextDiskLun("vm1") assert.Equal(t, test.expectedLun, lun, "TestCase[%d]: %s", i, test.desc) @@ -259,7 +305,12 @@ func TestDisksAreAttached(t *testing.T) { cloud: testCloud, vmLockMap: newLockMap(), } - setTestVirtualMachines(testCloud, map[string]string{"vm1": "PowerState/Running"}, false) + expectedVMs := setTestVirtualMachines(testCloud, map[string]string{"vm1": "PowerState/Running"}, false) + mockVMsClient := testCloud.VirtualMachinesClient.(*mockvmclient.MockInterface) + for _, vm := range expectedVMs { + mockVMsClient.EXPECT().Get(gomock.Any(), testCloud.ResourceGroup, *vm.Name, gomock.Any()).Return(vm, nil).AnyTimes() + } + mockVMsClient.EXPECT().Get(gomock.Any(), testCloud.ResourceGroup, "vm2", gomock.Any()).Return(compute.VirtualMachine{}, &retry.Error{HTTPStatusCode: http.StatusNotFound, RawError: cloudprovider.InstanceNotFound}).AnyTimes() attached, err := common.DisksAreAttached(test.diskNames, test.nodeName) assert.Equal(t, test.expectedAttached, attached, "TestCase[%d]: %s", i, test.desc) @@ -267,7 +318,7 @@ func TestDisksAreAttached(t *testing.T) { } } -func TestFilteredDetatchingDisks(t *testing.T) { +func TestFilteredDetachingDisks(t *testing.T) { disks := []compute.DataDisk{ { @@ -448,10 +499,10 @@ func TestCheckDiskExists(t *testing.T) { newDiskName := "newdisk" newDiskURI := fmt.Sprintf("/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Compute/disks/%s", testCloud.SubscriptionID, testCloud.ResourceGroup, newDiskName) - fDC := newFakeDisksClient() - rerr := fDC.CreateOrUpdate(ctx, testCloud.ResourceGroup, newDiskName, compute.Disk{}) - assert.Equal(t, rerr == nil, true, "return error: %v", rerr) - testCloud.DisksClient = fDC + + mockDisksClient := testCloud.DisksClient.(*mockdiskclient.MockInterface) + mockDisksClient.EXPECT().Get(gomock.Any(), testCloud.ResourceGroup, newDiskName).Return(compute.Disk{}, nil).AnyTimes() + mockDisksClient.EXPECT().Get(gomock.Any(), gomock.Not(testCloud.ResourceGroup), gomock.Any()).Return(compute.Disk{}, &retry.Error{HTTPStatusCode: http.StatusNotFound, RawError: cloudprovider.InstanceNotFound}).AnyTimes() testCases := []struct { diskURI string @@ -503,10 +554,10 @@ func TestFilterNonExistingDisks(t *testing.T) { testCloud.SubscriptionID, testCloud.ResourceGroup) newDiskName := "newdisk" newDiskURI := diskURIPrefix + newDiskName - fDC := newFakeDisksClient() - rerr := fDC.CreateOrUpdate(ctx, testCloud.ResourceGroup, newDiskName, compute.Disk{}) - assert.Equal(t, rerr == nil, true, "return error: %v", rerr) - testCloud.DisksClient = fDC + + mockDisksClient := testCloud.DisksClient.(*mockdiskclient.MockInterface) + mockDisksClient.EXPECT().Get(gomock.Any(), testCloud.ResourceGroup, newDiskName).Return(compute.Disk{}, nil).AnyTimes() + mockDisksClient.EXPECT().Get(gomock.Any(), testCloud.ResourceGroup, gomock.Not(newDiskName)).Return(compute.Disk{}, &retry.Error{HTTPStatusCode: http.StatusNotFound, RawError: cloudprovider.InstanceNotFound}).AnyTimes() disks := []compute.DataDisk{ { diff --git a/staging/src/k8s.io/legacy-cloud-providers/azure/azure_controller_standard_test.go b/staging/src/k8s.io/legacy-cloud-providers/azure/azure_controller_standard_test.go index 0eec68b7b05..e0e214afc73 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/azure/azure_controller_standard_test.go +++ b/staging/src/k8s.io/legacy-cloud-providers/azure/azure_controller_standard_test.go @@ -19,6 +19,7 @@ limitations under the License. package azure import ( + "net/http" "testing" "time" @@ -28,7 +29,10 @@ import ( "github.com/stretchr/testify/assert" "k8s.io/apimachinery/pkg/types" + cloudprovider "k8s.io/cloud-provider" azcache "k8s.io/legacy-cloud-providers/azure/cache" + "k8s.io/legacy-cloud-providers/azure/clients/vmclient/mockvmclient" + "k8s.io/legacy-cloud-providers/azure/retry" ) var ( @@ -59,7 +63,13 @@ func TestStandardAttachDisk(t *testing.T) { for i, test := range testCases { testCloud := GetTestCloud(ctrl) vmSet := testCloud.vmSet - setTestVirtualMachines(testCloud, map[string]string{"vm1": "PowerState/Running"}, false) + expectedVMs := setTestVirtualMachines(testCloud, map[string]string{"vm1": "PowerState/Running"}, false) + mockVMsClient := testCloud.VirtualMachinesClient.(*mockvmclient.MockInterface) + for _, vm := range expectedVMs { + mockVMsClient.EXPECT().Get(gomock.Any(), testCloud.ResourceGroup, *vm.Name, gomock.Any()).Return(vm, nil).AnyTimes() + } + mockVMsClient.EXPECT().Get(gomock.Any(), testCloud.ResourceGroup, "vm2", gomock.Any()).Return(compute.VirtualMachine{}, &retry.Error{HTTPStatusCode: http.StatusNotFound, RawError: cloudprovider.InstanceNotFound}).AnyTimes() + mockVMsClient.EXPECT().Update(gomock.Any(), testCloud.ResourceGroup, gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() err := vmSet.AttachDisk(true, "", "uri", test.nodeName, 0, compute.CachingTypesReadOnly, "", false) @@ -99,7 +109,13 @@ func TestStandardDetachDisk(t *testing.T) { for i, test := range testCases { testCloud := GetTestCloud(ctrl) vmSet := testCloud.vmSet - setTestVirtualMachines(testCloud, map[string]string{"vm1": "PowerState/Running"}, false) + expectedVMs := setTestVirtualMachines(testCloud, map[string]string{"vm1": "PowerState/Running"}, false) + mockVMsClient := testCloud.VirtualMachinesClient.(*mockvmclient.MockInterface) + for _, vm := range expectedVMs { + mockVMsClient.EXPECT().Get(gomock.Any(), testCloud.ResourceGroup, *vm.Name, gomock.Any()).Return(vm, nil).AnyTimes() + } + mockVMsClient.EXPECT().Get(gomock.Any(), testCloud.ResourceGroup, "vm2", gomock.Any()).Return(compute.VirtualMachine{}, &retry.Error{HTTPStatusCode: http.StatusNotFound, RawError: cloudprovider.InstanceNotFound}).AnyTimes() + mockVMsClient.EXPECT().Update(gomock.Any(), testCloud.ResourceGroup, gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() err := vmSet.DetachDisk(test.diskName, "", test.nodeName) assert.Equal(t, test.expectedError, err != nil, "TestCase[%d]: %s", i, test.desc) @@ -152,7 +168,13 @@ func TestGetDataDisks(t *testing.T) { for i, test := range testCases { testCloud := GetTestCloud(ctrl) vmSet := testCloud.vmSet - setTestVirtualMachines(testCloud, map[string]string{"vm1": "PowerState/Running"}, false) + expectedVMs := setTestVirtualMachines(testCloud, map[string]string{"vm1": "PowerState/Running"}, false) + mockVMsClient := testCloud.VirtualMachinesClient.(*mockvmclient.MockInterface) + for _, vm := range expectedVMs { + mockVMsClient.EXPECT().Get(gomock.Any(), testCloud.ResourceGroup, *vm.Name, gomock.Any()).Return(vm, nil).AnyTimes() + } + mockVMsClient.EXPECT().Get(gomock.Any(), testCloud.ResourceGroup, gomock.Not("vm1"), gomock.Any()).Return(compute.VirtualMachine{}, &retry.Error{HTTPStatusCode: http.StatusNotFound, RawError: cloudprovider.InstanceNotFound}).AnyTimes() + mockVMsClient.EXPECT().Update(gomock.Any(), testCloud.ResourceGroup, gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() dataDisks, err := vmSet.GetDataDisks(test.nodeName, test.crt) assert.Equal(t, test.expectedDataDisks, dataDisks, "TestCase[%d]: %s", i, test.desc) diff --git a/staging/src/k8s.io/legacy-cloud-providers/azure/azure_fakes.go b/staging/src/k8s.io/legacy-cloud-providers/azure/azure_fakes.go index 404b616a04f..fafc771e607 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/azure/azure_fakes.go +++ b/staging/src/k8s.io/legacy-cloud-providers/azure/azure_fakes.go @@ -19,757 +19,30 @@ limitations under the License. package azure import ( - "context" - "errors" "fmt" - "math/rand" - "net/http" - "sync" - "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-01/compute" - "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-06-01/network" - "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2019-06-01/storage" - "github.com/Azure/go-autorest/autorest/azure" - "github.com/Azure/go-autorest/autorest/to" "github.com/golang/mock/gomock" "k8s.io/apimachinery/pkg/util/sets" "k8s.io/client-go/tools/record" "k8s.io/legacy-cloud-providers/azure/auth" + "k8s.io/legacy-cloud-providers/azure/clients/diskclient/mockdiskclient" + "k8s.io/legacy-cloud-providers/azure/clients/interfaceclient/mockinterfaceclient" + "k8s.io/legacy-cloud-providers/azure/clients/loadbalancerclient/mockloadbalancerclient" + "k8s.io/legacy-cloud-providers/azure/clients/publicipclient/mockpublicipclient" "k8s.io/legacy-cloud-providers/azure/clients/routeclient/mockrouteclient" "k8s.io/legacy-cloud-providers/azure/clients/routetableclient/mockroutetableclient" + "k8s.io/legacy-cloud-providers/azure/clients/securitygroupclient/mocksecuritygroupclient" "k8s.io/legacy-cloud-providers/azure/clients/subnetclient/mocksubnetclient" - "k8s.io/legacy-cloud-providers/azure/retry" + "k8s.io/legacy-cloud-providers/azure/clients/vmclient/mockvmclient" + "k8s.io/legacy-cloud-providers/azure/clients/vmssclient/mockvmssclient" + "k8s.io/legacy-cloud-providers/azure/clients/vmssvmclient/mockvmssvmclient" ) var ( errPreconditionFailedEtagMismatch = fmt.Errorf("PreconditionFailedEtagMismatch") ) -type fakeAzureLBClient struct { - mutex *sync.Mutex - FakeStore map[string]map[string]network.LoadBalancer -} - -func newFakeAzureLBClient() *fakeAzureLBClient { - fLBC := &fakeAzureLBClient{} - fLBC.FakeStore = make(map[string]map[string]network.LoadBalancer) - fLBC.mutex = &sync.Mutex{} - return fLBC -} - -func (fLBC *fakeAzureLBClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, loadBalancerName string, parameters network.LoadBalancer, etag string) *retry.Error { - fLBC.mutex.Lock() - defer fLBC.mutex.Unlock() - - if _, ok := fLBC.FakeStore[resourceGroupName]; !ok { - fLBC.FakeStore[resourceGroupName] = make(map[string]network.LoadBalancer) - } - - // For dynamic ip allocation, just fill in the PrivateIPAddress - if parameters.FrontendIPConfigurations != nil { - for idx, config := range *parameters.FrontendIPConfigurations { - if config.PrivateIPAllocationMethod == network.Dynamic { - // Here we randomly assign an ip as private ip - // It doesn't smart enough to know whether it is in the subnet's range - (*parameters.FrontendIPConfigurations)[idx].PrivateIPAddress = getRandomIPPtr() - } - } - } - fLBC.FakeStore[resourceGroupName][loadBalancerName] = parameters - - return nil -} - -func (fLBC *fakeAzureLBClient) Delete(ctx context.Context, resourceGroupName string, loadBalancerName string) *retry.Error { - fLBC.mutex.Lock() - defer fLBC.mutex.Unlock() - - if rgLBs, ok := fLBC.FakeStore[resourceGroupName]; ok { - if _, ok := rgLBs[loadBalancerName]; ok { - delete(rgLBs, loadBalancerName) - return nil - } - } - - return nil -} - -func (fLBC *fakeAzureLBClient) Get(ctx context.Context, resourceGroupName string, loadBalancerName string, expand string) (result network.LoadBalancer, err *retry.Error) { - fLBC.mutex.Lock() - defer fLBC.mutex.Unlock() - if _, ok := fLBC.FakeStore[resourceGroupName]; ok { - if entity, ok := fLBC.FakeStore[resourceGroupName][loadBalancerName]; ok { - return entity, nil - } - } - return result, retry.GetError( - &http.Response{ - StatusCode: http.StatusNotFound, - }, - errors.New("Not such LB")) -} - -func (fLBC *fakeAzureLBClient) List(ctx context.Context, resourceGroupName string) (result []network.LoadBalancer, err *retry.Error) { - fLBC.mutex.Lock() - defer fLBC.mutex.Unlock() - - var value []network.LoadBalancer - if _, ok := fLBC.FakeStore[resourceGroupName]; ok { - for _, v := range fLBC.FakeStore[resourceGroupName] { - value = append(value, v) - } - } - return value, nil -} - -type fakeAzurePIPClient struct { - mutex *sync.Mutex - FakeStore map[string]map[string]network.PublicIPAddress - SubscriptionID string -} - -const publicIPAddressIDTemplate = "/subscriptions/%s/resourceGroups/%s/providers/Microsoft.Network/publicIPAddresses/%s" - -// returns the full identifier of a publicIPAddress. -func getpublicIPAddressID(subscriptionID string, resourceGroupName, pipName string) string { - return fmt.Sprintf( - publicIPAddressIDTemplate, - subscriptionID, - resourceGroupName, - pipName) -} - -func newFakeAzurePIPClient(subscriptionID string) *fakeAzurePIPClient { - fAPC := &fakeAzurePIPClient{} - fAPC.FakeStore = make(map[string]map[string]network.PublicIPAddress) - fAPC.SubscriptionID = subscriptionID - fAPC.mutex = &sync.Mutex{} - return fAPC -} - -func (fAPC *fakeAzurePIPClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, publicIPAddressName string, parameters network.PublicIPAddress) *retry.Error { - fAPC.mutex.Lock() - defer fAPC.mutex.Unlock() - - if _, ok := fAPC.FakeStore[resourceGroupName]; !ok { - fAPC.FakeStore[resourceGroupName] = make(map[string]network.PublicIPAddress) - } - - // assign id - pipID := getpublicIPAddressID(fAPC.SubscriptionID, resourceGroupName, publicIPAddressName) - parameters.ID = &pipID - - // only create in the case user has not provided - if parameters.PublicIPAddressPropertiesFormat != nil && - parameters.PublicIPAddressPropertiesFormat.PublicIPAllocationMethod == network.Static { - // assign ip - parameters.IPAddress = getRandomIPPtr() - } - - fAPC.FakeStore[resourceGroupName][publicIPAddressName] = parameters - - return nil -} - -func (fAPC *fakeAzurePIPClient) Delete(ctx context.Context, resourceGroupName string, publicIPAddressName string) *retry.Error { - fAPC.mutex.Lock() - defer fAPC.mutex.Unlock() - - if rgPIPs, ok := fAPC.FakeStore[resourceGroupName]; ok { - if _, ok := rgPIPs[publicIPAddressName]; ok { - delete(rgPIPs, publicIPAddressName) - return nil - } - } - - return retry.GetError( - &http.Response{ - StatusCode: http.StatusNotFound, - }, - errors.New("Not such PIP")) -} - -func (fAPC *fakeAzurePIPClient) Get(ctx context.Context, resourceGroupName string, publicIPAddressName string, expand string) (result network.PublicIPAddress, err *retry.Error) { - fAPC.mutex.Lock() - defer fAPC.mutex.Unlock() - if _, ok := fAPC.FakeStore[resourceGroupName]; ok { - if entity, ok := fAPC.FakeStore[resourceGroupName][publicIPAddressName]; ok { - return entity, nil - } - } - return result, retry.GetError( - &http.Response{ - StatusCode: http.StatusNotFound, - }, - errors.New("Not such PIP")) -} - -func (fAPC *fakeAzurePIPClient) GetVirtualMachineScaleSetPublicIPAddress(ctx context.Context, resourceGroupName string, virtualMachineScaleSetName string, virtualmachineIndex string, networkInterfaceName string, IPConfigurationName string, publicIPAddressName string, expand string) (result network.PublicIPAddress, err *retry.Error) { - fAPC.mutex.Lock() - defer fAPC.mutex.Unlock() - if _, ok := fAPC.FakeStore[resourceGroupName]; ok { - if entity, ok := fAPC.FakeStore[resourceGroupName][publicIPAddressName]; ok { - return entity, nil - } - } - return result, retry.GetError( - &http.Response{ - StatusCode: http.StatusNotFound, - }, - errors.New("Not such PIP")) -} - -func (fAPC *fakeAzurePIPClient) List(ctx context.Context, resourceGroupName string) (result []network.PublicIPAddress, err *retry.Error) { - fAPC.mutex.Lock() - defer fAPC.mutex.Unlock() - - var value []network.PublicIPAddress - if _, ok := fAPC.FakeStore[resourceGroupName]; ok { - for _, v := range fAPC.FakeStore[resourceGroupName] { - value = append(value, v) - } - } - - return value, nil -} - -func (fAPC *fakeAzurePIPClient) setFakeStore(store map[string]map[string]network.PublicIPAddress) { - fAPC.mutex.Lock() - defer fAPC.mutex.Unlock() - - fAPC.FakeStore = store -} - -type fakeAzureInterfacesClient struct { - mutex *sync.Mutex - FakeStore map[string]map[string]network.Interface -} - -func newFakeAzureInterfacesClient() *fakeAzureInterfacesClient { - fIC := &fakeAzureInterfacesClient{} - fIC.FakeStore = make(map[string]map[string]network.Interface) - fIC.mutex = &sync.Mutex{} - - return fIC -} - -func (fIC *fakeAzureInterfacesClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, networkInterfaceName string, parameters network.Interface) *retry.Error { - fIC.mutex.Lock() - defer fIC.mutex.Unlock() - - if _, ok := fIC.FakeStore[resourceGroupName]; !ok { - fIC.FakeStore[resourceGroupName] = make(map[string]network.Interface) - } - fIC.FakeStore[resourceGroupName][networkInterfaceName] = parameters - - return nil -} - -func (fIC *fakeAzureInterfacesClient) Get(ctx context.Context, resourceGroupName string, networkInterfaceName string, expand string) (result network.Interface, err *retry.Error) { - fIC.mutex.Lock() - defer fIC.mutex.Unlock() - if _, ok := fIC.FakeStore[resourceGroupName]; ok { - if entity, ok := fIC.FakeStore[resourceGroupName][networkInterfaceName]; ok { - return entity, nil - } - } - return result, retry.GetError( - &http.Response{ - StatusCode: http.StatusNotFound, - }, - errors.New("Not such Interface")) -} - -func (fIC *fakeAzureInterfacesClient) GetVirtualMachineScaleSetNetworkInterface(ctx context.Context, resourceGroupName string, virtualMachineScaleSetName string, virtualmachineIndex string, networkInterfaceName string, expand string) (result network.Interface, err *retry.Error) { - fIC.mutex.Lock() - defer fIC.mutex.Unlock() - if _, ok := fIC.FakeStore[resourceGroupName]; ok { - if entity, ok := fIC.FakeStore[resourceGroupName][networkInterfaceName]; ok { - return entity, nil - } - } - return result, retry.GetError( - &http.Response{ - StatusCode: http.StatusNotFound, - }, - errors.New("Not such Interface")) -} - -func (fIC *fakeAzureInterfacesClient) Delete(ctx context.Context, resourceGroupName string, networkInterfaceName string) *retry.Error { - return nil -} - -func (fIC *fakeAzureInterfacesClient) setFakeStore(store map[string]map[string]network.Interface) { - fIC.mutex.Lock() - defer fIC.mutex.Unlock() - - fIC.FakeStore = store -} - -type fakeAzureVirtualMachinesClient struct { - mutex *sync.Mutex - FakeStore map[string]map[string]compute.VirtualMachine -} - -func newFakeAzureVirtualMachinesClient() *fakeAzureVirtualMachinesClient { - fVMC := &fakeAzureVirtualMachinesClient{} - fVMC.FakeStore = make(map[string]map[string]compute.VirtualMachine) - fVMC.mutex = &sync.Mutex{} - return fVMC -} - -func (fVMC *fakeAzureVirtualMachinesClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, VMName string, parameters compute.VirtualMachine, source string) *retry.Error { - fVMC.mutex.Lock() - defer fVMC.mutex.Unlock() - - if _, ok := fVMC.FakeStore[resourceGroupName]; !ok { - fVMC.FakeStore[resourceGroupName] = make(map[string]compute.VirtualMachine) - } - fVMC.FakeStore[resourceGroupName][VMName] = parameters - - return nil -} - -func (fVMC *fakeAzureVirtualMachinesClient) Update(ctx context.Context, resourceGroupName string, VMName string, parameters compute.VirtualMachineUpdate, source string) *retry.Error { - fVMC.mutex.Lock() - defer fVMC.mutex.Unlock() - - if _, ok := fVMC.FakeStore[resourceGroupName]; !ok { - fVMC.FakeStore[resourceGroupName] = make(map[string]compute.VirtualMachine) - } - - return nil -} - -func (fVMC *fakeAzureVirtualMachinesClient) Get(ctx context.Context, resourceGroupName string, VMName string, expand compute.InstanceViewTypes) (result compute.VirtualMachine, err *retry.Error) { - fVMC.mutex.Lock() - defer fVMC.mutex.Unlock() - if _, ok := fVMC.FakeStore[resourceGroupName]; ok { - if entity, ok := fVMC.FakeStore[resourceGroupName][VMName]; ok { - return entity, nil - } - } - return result, retry.GetError( - &http.Response{ - StatusCode: http.StatusNotFound, - }, - errors.New("Not such VM")) -} - -func (fVMC *fakeAzureVirtualMachinesClient) List(ctx context.Context, resourceGroupName string) (result []compute.VirtualMachine, err *retry.Error) { - fVMC.mutex.Lock() - defer fVMC.mutex.Unlock() - - result = []compute.VirtualMachine{} - if _, ok := fVMC.FakeStore[resourceGroupName]; ok { - for _, v := range fVMC.FakeStore[resourceGroupName] { - result = append(result, v) - } - } - - return result, nil -} - -func (fVMC *fakeAzureVirtualMachinesClient) Delete(ctx context.Context, resourceGroupName string, VMName string) *retry.Error { - return nil -} - -func (fVMC *fakeAzureVirtualMachinesClient) setFakeStore(store map[string]map[string]compute.VirtualMachine) { - fVMC.mutex.Lock() - defer fVMC.mutex.Unlock() - - fVMC.FakeStore = store -} - -type fakeAzureNSGClient struct { - mutex *sync.Mutex - FakeStore map[string]map[string]network.SecurityGroup -} - -func newFakeAzureNSGClient() *fakeAzureNSGClient { - fNSG := &fakeAzureNSGClient{} - fNSG.FakeStore = make(map[string]map[string]network.SecurityGroup) - fNSG.mutex = &sync.Mutex{} - return fNSG -} - -func (fNSG *fakeAzureNSGClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, networkSecurityGroupName string, parameters network.SecurityGroup, etag string) *retry.Error { - fNSG.mutex.Lock() - defer fNSG.mutex.Unlock() - - if _, ok := fNSG.FakeStore[resourceGroupName]; !ok { - fNSG.FakeStore[resourceGroupName] = make(map[string]network.SecurityGroup) - } - - if nsg, ok := fNSG.FakeStore[resourceGroupName][networkSecurityGroupName]; ok { - if etag != "" && to.String(nsg.Etag) != "" && etag != to.String(nsg.Etag) { - return retry.GetError(&http.Response{ - StatusCode: http.StatusPreconditionFailed, - }, errPreconditionFailedEtagMismatch) - } - } - fNSG.FakeStore[resourceGroupName][networkSecurityGroupName] = parameters - - return nil -} - -func (fNSG *fakeAzureNSGClient) Delete(ctx context.Context, resourceGroupName string, networkSecurityGroupName string) *retry.Error { - fNSG.mutex.Lock() - defer fNSG.mutex.Unlock() - - if rgSGs, ok := fNSG.FakeStore[resourceGroupName]; ok { - if _, ok := rgSGs[networkSecurityGroupName]; ok { - delete(rgSGs, networkSecurityGroupName) - return nil - } - } - - return retry.GetError( - &http.Response{ - StatusCode: http.StatusNotFound, - }, - errors.New("Not such NSG")) -} - -func (fNSG *fakeAzureNSGClient) Get(ctx context.Context, resourceGroupName string, networkSecurityGroupName string, expand string) (result network.SecurityGroup, err *retry.Error) { - fNSG.mutex.Lock() - defer fNSG.mutex.Unlock() - if _, ok := fNSG.FakeStore[resourceGroupName]; ok { - if entity, ok := fNSG.FakeStore[resourceGroupName][networkSecurityGroupName]; ok { - return entity, nil - } - } - return result, retry.GetError( - &http.Response{ - StatusCode: http.StatusNotFound, - }, - errors.New("Not such NSG")) -} - -func (fNSG *fakeAzureNSGClient) List(ctx context.Context, resourceGroupName string) (result []network.SecurityGroup, err *retry.Error) { - fNSG.mutex.Lock() - defer fNSG.mutex.Unlock() - - var value []network.SecurityGroup - if _, ok := fNSG.FakeStore[resourceGroupName]; ok { - for _, v := range fNSG.FakeStore[resourceGroupName] { - value = append(value, v) - } - } - - return value, nil -} - -func getRandomIPPtr() *string { - return to.StringPtr(fmt.Sprintf("%d.%d.%d.%d", rand.Intn(256), rand.Intn(256), rand.Intn(256), rand.Intn(256))) -} - -type fakeVirtualMachineScaleSetVMsClient struct { - mutex *sync.Mutex - FakeStore map[string]map[string]compute.VirtualMachineScaleSetVM -} - -func newFakeVirtualMachineScaleSetVMsClient() *fakeVirtualMachineScaleSetVMsClient { - fVMC := &fakeVirtualMachineScaleSetVMsClient{} - fVMC.FakeStore = make(map[string]map[string]compute.VirtualMachineScaleSetVM) - fVMC.mutex = &sync.Mutex{} - - return fVMC -} - -func (fVMC *fakeVirtualMachineScaleSetVMsClient) setFakeStore(store map[string]map[string]compute.VirtualMachineScaleSetVM) { - fVMC.mutex.Lock() - defer fVMC.mutex.Unlock() - - fVMC.FakeStore = store -} - -func (fVMC *fakeVirtualMachineScaleSetVMsClient) List(ctx context.Context, resourceGroupName string, virtualMachineScaleSetName string, expand string) (result []compute.VirtualMachineScaleSetVM, err *retry.Error) { - fVMC.mutex.Lock() - defer fVMC.mutex.Unlock() - - result = []compute.VirtualMachineScaleSetVM{} - if _, ok := fVMC.FakeStore[resourceGroupName]; ok { - for _, v := range fVMC.FakeStore[resourceGroupName] { - result = append(result, v) - } - } - - return result, nil -} - -func (fVMC *fakeVirtualMachineScaleSetVMsClient) Get(ctx context.Context, resourceGroupName string, VMScaleSetName string, instanceID string, expand compute.InstanceViewTypes) (result compute.VirtualMachineScaleSetVM, err *retry.Error) { - fVMC.mutex.Lock() - defer fVMC.mutex.Unlock() - - vmKey := fmt.Sprintf("%s_%s", VMScaleSetName, instanceID) - if scaleSetMap, ok := fVMC.FakeStore[resourceGroupName]; ok { - if entity, ok := scaleSetMap[vmKey]; ok { - return entity, nil - } - } - - return result, retry.GetError( - &http.Response{ - StatusCode: http.StatusNotFound, - }, - errors.New("Not such VirtualMachineScaleSetVM")) -} - -func (fVMC *fakeVirtualMachineScaleSetVMsClient) Update(ctx context.Context, resourceGroupName string, VMScaleSetName string, instanceID string, parameters compute.VirtualMachineScaleSetVM, source string) *retry.Error { - fVMC.mutex.Lock() - defer fVMC.mutex.Unlock() - - vmKey := fmt.Sprintf("%s_%s", VMScaleSetName, instanceID) - if scaleSetMap, ok := fVMC.FakeStore[resourceGroupName]; ok { - if _, ok := scaleSetMap[vmKey]; ok { - scaleSetMap[vmKey] = parameters - } - } - - return nil -} - -func (fVMC *fakeVirtualMachineScaleSetVMsClient) UpdateVMs(ctx context.Context, resourceGroupName string, VMScaleSetName string, instances map[string]compute.VirtualMachineScaleSetVM, source string) *retry.Error { - return nil -} - -type fakeVirtualMachineScaleSetsClient struct { - mutex *sync.Mutex - FakeStore map[string]map[string]compute.VirtualMachineScaleSet -} - -func newFakeVirtualMachineScaleSetsClient() *fakeVirtualMachineScaleSetsClient { - fVMSSC := &fakeVirtualMachineScaleSetsClient{} - fVMSSC.FakeStore = make(map[string]map[string]compute.VirtualMachineScaleSet) - fVMSSC.mutex = &sync.Mutex{} - - return fVMSSC -} - -func (fVMSSC *fakeVirtualMachineScaleSetsClient) setFakeStore(store map[string]map[string]compute.VirtualMachineScaleSet) { - fVMSSC.mutex.Lock() - defer fVMSSC.mutex.Unlock() - - fVMSSC.FakeStore = store -} - -func (fVMSSC *fakeVirtualMachineScaleSetsClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, VMScaleSetName string, parameters compute.VirtualMachineScaleSet) *retry.Error { - fVMSSC.mutex.Lock() - defer fVMSSC.mutex.Unlock() - - if _, ok := fVMSSC.FakeStore[resourceGroupName]; !ok { - fVMSSC.FakeStore[resourceGroupName] = make(map[string]compute.VirtualMachineScaleSet) - } - fVMSSC.FakeStore[resourceGroupName][VMScaleSetName] = parameters - - return nil -} - -func (fVMSSC *fakeVirtualMachineScaleSetsClient) CreateOrUpdateAsync(ctx context.Context, resourceGroupName string, VMScaleSetName string, parameters compute.VirtualMachineScaleSet) (*azure.Future, *retry.Error) { - return nil, nil -} - -func (fVMSSC *fakeVirtualMachineScaleSetsClient) WaitForAsyncOperationResult(ctx context.Context, future *azure.Future) (*http.Response, error) { - return nil, nil -} - -func (fVMSSC *fakeVirtualMachineScaleSetsClient) Get(ctx context.Context, resourceGroupName string, VMScaleSetName string) (result compute.VirtualMachineScaleSet, err *retry.Error) { - fVMSSC.mutex.Lock() - defer fVMSSC.mutex.Unlock() - - if scaleSetMap, ok := fVMSSC.FakeStore[resourceGroupName]; ok { - if entity, ok := scaleSetMap[VMScaleSetName]; ok { - return entity, nil - } - } - - return result, retry.GetError( - &http.Response{ - StatusCode: http.StatusNotFound, - }, - errors.New("Not such ScaleSet")) -} - -func (fVMSSC *fakeVirtualMachineScaleSetsClient) List(ctx context.Context, resourceGroupName string) (result []compute.VirtualMachineScaleSet, err *retry.Error) { - fVMSSC.mutex.Lock() - defer fVMSSC.mutex.Unlock() - - result = []compute.VirtualMachineScaleSet{} - if _, ok := fVMSSC.FakeStore[resourceGroupName]; ok { - for _, v := range fVMSSC.FakeStore[resourceGroupName] { - result = append(result, v) - } - } - - return result, nil -} - -func (fVMSSC *fakeVirtualMachineScaleSetsClient) UpdateInstances(ctx context.Context, resourceGroupName string, VMScaleSetName string, VMInstanceIDs compute.VirtualMachineScaleSetVMInstanceRequiredIDs) *retry.Error { - return nil -} - -func (fVMSSC *fakeVirtualMachineScaleSetsClient) DeleteInstances(ctx context.Context, resourceGroupName string, vmScaleSetName string, vmInstanceIDs compute.VirtualMachineScaleSetVMInstanceRequiredIDs) *retry.Error { - return nil -} - -type fakeFileClient struct { -} - -func (fFC *fakeFileClient) createFileShare(accountName, accountKey, name string, sizeGiB int) error { - return nil -} - -func (fFC *fakeFileClient) deleteFileShare(accountName, accountKey, name string) error { - return nil -} - -func (fFC *fakeFileClient) resizeFileShare(accountName, accountKey, name string, sizeGiB int) error { - return nil -} - -type fakeStorageAccountClient struct { - mutex *sync.Mutex - FakeStore map[string]map[string]storage.Account - Keys storage.AccountListKeysResult - Accounts []storage.Account - Err error -} - -func newFakeStorageAccountClient() *fakeStorageAccountClient { - fSAC := &fakeStorageAccountClient{} - fSAC.FakeStore = make(map[string]map[string]storage.Account) - fSAC.mutex = &sync.Mutex{} - return fSAC -} - -func (fSAC *fakeStorageAccountClient) Create(ctx context.Context, resourceGroupName string, accountName string, parameters storage.AccountCreateParameters) *retry.Error { - fSAC.mutex.Lock() - defer fSAC.mutex.Unlock() - - if _, ok := fSAC.FakeStore[resourceGroupName]; !ok { - fSAC.FakeStore[resourceGroupName] = make(map[string]storage.Account) - } - fSAC.FakeStore[resourceGroupName][accountName] = storage.Account{ - Name: &accountName, - Sku: parameters.Sku, - Kind: parameters.Kind, - Location: parameters.Location, - Identity: parameters.Identity, - Tags: parameters.Tags, - AccountProperties: &storage.AccountProperties{}, - } - - return nil -} - -func (fSAC *fakeStorageAccountClient) Delete(ctx context.Context, resourceGroupName string, accountName string) *retry.Error { - fSAC.mutex.Lock() - defer fSAC.mutex.Unlock() - - if rgAccounts, ok := fSAC.FakeStore[resourceGroupName]; ok { - if _, ok := rgAccounts[accountName]; ok { - delete(rgAccounts, accountName) - return nil - } - } - - return retry.GetError( - &http.Response{ - StatusCode: http.StatusNotFound, - }, - errors.New("Not such StorageAccount")) -} - -func (fSAC *fakeStorageAccountClient) ListKeys(ctx context.Context, resourceGroupName string, accountName string) (result storage.AccountListKeysResult, err *retry.Error) { - return fSAC.Keys, nil -} - -func (fSAC *fakeStorageAccountClient) ListByResourceGroup(ctx context.Context, resourceGroupName string) (result []storage.Account, err *retry.Error) { - return fSAC.Accounts, nil -} - -func (fSAC *fakeStorageAccountClient) GetProperties(ctx context.Context, resourceGroupName string, accountName string) (result storage.Account, err *retry.Error) { - fSAC.mutex.Lock() - defer fSAC.mutex.Unlock() - - if _, ok := fSAC.FakeStore[resourceGroupName]; ok { - if entity, ok := fSAC.FakeStore[resourceGroupName][accountName]; ok { - return entity, nil - } - } - - return result, retry.GetError( - &http.Response{ - StatusCode: http.StatusNotFound, - }, - errors.New("Not such StorageAccount")) -} - -type fakeDisksClient struct { - mutex *sync.Mutex - FakeStore map[string]map[string]compute.Disk -} - -func newFakeDisksClient() *fakeDisksClient { - fDC := &fakeDisksClient{} - fDC.FakeStore = make(map[string]map[string]compute.Disk) - fDC.mutex = &sync.Mutex{} - return fDC -} - -func (fDC *fakeDisksClient) CreateOrUpdate(ctx context.Context, resourceGroupName string, diskName string, diskParameter compute.Disk) *retry.Error { - fDC.mutex.Lock() - defer fDC.mutex.Unlock() - - provisioningStateSucceeded := string(compute.ProvisioningStateSucceeded) - diskParameter.DiskProperties = &compute.DiskProperties{ProvisioningState: &provisioningStateSucceeded} - diskParameter.ID = &diskName - - if _, ok := fDC.FakeStore[resourceGroupName]; !ok { - fDC.FakeStore[resourceGroupName] = make(map[string]compute.Disk) - } - fDC.FakeStore[resourceGroupName][diskName] = diskParameter - - return nil -} - -func (fDC *fakeDisksClient) Delete(ctx context.Context, resourceGroupName string, diskName string) *retry.Error { - fDC.mutex.Lock() - defer fDC.mutex.Unlock() - - if rgDisks, ok := fDC.FakeStore[resourceGroupName]; ok { - if _, ok := rgDisks[diskName]; ok { - delete(rgDisks, diskName) - return nil - } - } - - return retry.GetError( - &http.Response{ - StatusCode: http.StatusNotFound, - }, - errors.New("Not such Disk")) -} - -func (fDC *fakeDisksClient) Get(ctx context.Context, resourceGroupName string, diskName string) (result compute.Disk, err *retry.Error) { - fDC.mutex.Lock() - defer fDC.mutex.Unlock() - - if _, ok := fDC.FakeStore[resourceGroupName]; ok { - if entity, ok := fDC.FakeStore[resourceGroupName][diskName]; ok { - return entity, nil - } - } - - return result, retry.GetError( - &http.Response{ - StatusCode: http.StatusNotFound, - }, - errors.New("Not such Disk")) -} - // GetTestCloud returns a fake azure cloud for unit tests in Azure related CSI drivers func GetTestCloud(ctrl *gomock.Controller) (az *Cloud) { az = &Cloud{ @@ -798,17 +71,17 @@ func GetTestCloud(ctrl *gomock.Controller) (az *Cloud) { routeCIDRs: map[string]string{}, eventRecorder: &record.FakeRecorder{}, } - az.DisksClient = newFakeDisksClient() - az.InterfacesClient = newFakeAzureInterfacesClient() - az.LoadBalancerClient = newFakeAzureLBClient() - az.PublicIPAddressesClient = newFakeAzurePIPClient(az.Config.SubscriptionID) + az.DisksClient = mockdiskclient.NewMockInterface(ctrl) + az.InterfacesClient = mockinterfaceclient.NewMockInterface(ctrl) + az.LoadBalancerClient = mockloadbalancerclient.NewMockInterface(ctrl) + az.PublicIPAddressesClient = mockpublicipclient.NewMockInterface(ctrl) az.RoutesClient = mockrouteclient.NewMockInterface(ctrl) az.RouteTablesClient = mockroutetableclient.NewMockInterface(ctrl) - az.SecurityGroupsClient = newFakeAzureNSGClient() + az.SecurityGroupsClient = mocksecuritygroupclient.NewMockInterface(ctrl) az.SubnetsClient = mocksubnetclient.NewMockInterface(ctrl) - az.VirtualMachineScaleSetsClient = newFakeVirtualMachineScaleSetsClient() - az.VirtualMachineScaleSetVMsClient = newFakeVirtualMachineScaleSetVMsClient() - az.VirtualMachinesClient = newFakeAzureVirtualMachinesClient() + az.VirtualMachineScaleSetsClient = mockvmssclient.NewMockInterface(ctrl) + az.VirtualMachineScaleSetVMsClient = mockvmssvmclient.NewMockInterface(ctrl) + az.VirtualMachinesClient = mockvmclient.NewMockInterface(ctrl) az.vmSet = newAvailabilitySet(az) az.vmCache, _ = az.newVMCache() az.lbCache, _ = az.newLBCache() diff --git a/staging/src/k8s.io/legacy-cloud-providers/azure/azure_file.go b/staging/src/k8s.io/legacy-cloud-providers/azure/azure_file.go index ad158ecc9f9..5fbfc3b025d 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/azure/azure_file.go +++ b/staging/src/k8s.io/legacy-cloud-providers/azure/azure_file.go @@ -18,124 +18,15 @@ limitations under the License. package azure -import ( - "fmt" - "net/http" - - azs "github.com/Azure/azure-sdk-for-go/storage" - "github.com/Azure/go-autorest/autorest/azure" - - "k8s.io/klog" - "k8s.io/legacy-cloud-providers/azure/retry" -) - -const ( - useHTTPS = true -) - -var ( - // refer https://github.com/Azure/azure-sdk-for-go/blob/master/storage/client.go#L88. - defaultValidStatusCodes = []int{ - http.StatusRequestTimeout, // 408 - http.StatusInternalServerError, // 500 - http.StatusBadGateway, // 502 - http.StatusServiceUnavailable, // 503 - http.StatusGatewayTimeout, // 504 - } -) - -// FileClient is the interface for creating file shares, interface for test -// injection. -type FileClient interface { - createFileShare(accountName, accountKey, name string, sizeGiB int) error - deleteFileShare(accountName, accountKey, name string) error - resizeFileShare(accountName, accountKey, name string, sizeGiB int) error -} - // create file share func (az *Cloud) createFileShare(accountName, accountKey, name string, sizeGiB int) error { - return az.FileClient.createFileShare(accountName, accountKey, name, sizeGiB) + return az.FileClient.CreateFileShare(accountName, accountKey, name, sizeGiB) } func (az *Cloud) deleteFileShare(accountName, accountKey, name string) error { - return az.FileClient.deleteFileShare(accountName, accountKey, name) + return az.FileClient.DeleteFileShare(accountName, accountKey, name) } func (az *Cloud) resizeFileShare(accountName, accountKey, name string, sizeGiB int) error { - return az.FileClient.resizeFileShare(accountName, accountKey, name, sizeGiB) -} - -type azureFileClient struct { - env *azure.Environment - backoff *retry.Backoff -} - -func newAzureFileClient(env *azure.Environment, backoff *retry.Backoff) *azureFileClient { - return &azureFileClient{ - env: env, - backoff: backoff, - } -} - -func (f *azureFileClient) createFileShare(accountName, accountKey, name string, sizeGiB int) error { - fileClient, err := f.getFileSvcClient(accountName, accountKey) - if err != nil { - return err - } - share := fileClient.GetShareReference(name) - share.Properties.Quota = sizeGiB - newlyCreated, err := share.CreateIfNotExists(nil) - if err != nil { - return fmt.Errorf("failed to create file share, err: %v", err) - } - if !newlyCreated { - klog.V(2).Infof("file share(%s) under account(%s) already exists", name, accountName) - } - return nil -} - -// delete a file share -func (f *azureFileClient) deleteFileShare(accountName, accountKey, name string) error { - fileClient, err := f.getFileSvcClient(accountName, accountKey) - if err != nil { - return err - } - return fileClient.GetShareReference(name).Delete(nil) -} - -func (f *azureFileClient) resizeFileShare(accountName, accountKey, name string, sizeGiB int) error { - fileClient, err := f.getFileSvcClient(accountName, accountKey) - if err != nil { - return err - } - share := fileClient.GetShareReference(name) - if share.Properties.Quota >= sizeGiB { - klog.Warningf("file share size(%dGi) is already greater or equal than requested size(%dGi), accountName: %s, shareName: %s", - share.Properties.Quota, sizeGiB, accountName, name) - return nil - } - share.Properties.Quota = sizeGiB - if err = share.SetProperties(nil); err != nil { - return fmt.Errorf("failed to set quota on file share %s, err: %v", name, err) - } - klog.V(4).Infof("resize file share completed, accountName: %s, shareName: %s, sizeGiB: %d", accountName, name, sizeGiB) - return nil -} - -func (f *azureFileClient) getFileSvcClient(accountName, accountKey string) (*azs.FileServiceClient, error) { - fileClient, err := azs.NewClient(accountName, accountKey, f.env.StorageEndpointSuffix, azs.DefaultAPIVersion, useHTTPS) - if err != nil { - return nil, fmt.Errorf("error creating azure client: %v", err) - } - - if f.backoff != nil { - fileClient.Sender = &azs.DefaultSender{ - RetryAttempts: f.backoff.Steps, - ValidStatusCodes: defaultValidStatusCodes, - RetryDuration: f.backoff.Duration, - } - } - - fc := fileClient.GetFileService() - return &fc, nil + return az.FileClient.ResizeFileShare(accountName, accountKey, name, sizeGiB) } 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 86ee2a3362d..8cec90ba444 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 @@ -32,14 +32,14 @@ import ( v1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/types" + cloudprovider "k8s.io/cloud-provider" + "k8s.io/legacy-cloud-providers/azure/clients/vmclient/mockvmclient" + "k8s.io/legacy-cloud-providers/azure/retry" ) // setTestVirtualMachines sets test virtual machine with powerstate. -func setTestVirtualMachines(c *Cloud, vmList map[string]string, isDataDisksFull bool) { - virtualMachineClient := c.VirtualMachinesClient.(*fakeAzureVirtualMachinesClient) - store := map[string]map[string]compute.VirtualMachine{ - "rg": make(map[string]compute.VirtualMachine), - } +func setTestVirtualMachines(c *Cloud, vmList map[string]string, isDataDisksFull bool) []compute.VirtualMachine { + expectedVMs := make([]compute.VirtualMachine, 0) for nodeName, powerState := range vmList { instanceID := fmt.Sprintf("/subscriptions/subscription/resourceGroups/rg/providers/Microsoft.Compute/virtualMachines/%s", nodeName) @@ -76,10 +76,11 @@ func setTestVirtualMachines(c *Cloud, vmList map[string]string, isDataDisksFull } vm.StorageProfile.DataDisks = &dataDisks } - store["rg"][nodeName] = vm + + expectedVMs = append(expectedVMs, vm) } - virtualMachineClient.setFakeStore(store) + return expectedVMs } func TestInstanceID(t *testing.T) { @@ -142,7 +143,14 @@ func TestInstanceID(t *testing.T) { for _, vm := range test.vmList { vmListWithPowerState[vm] = "" } - setTestVirtualMachines(cloud, vmListWithPowerState, false) + expectedVMs := setTestVirtualMachines(cloud, vmListWithPowerState, false) + mockVMsClient := cloud.VirtualMachinesClient.(*mockvmclient.MockInterface) + for _, vm := range expectedVMs { + mockVMsClient.EXPECT().Get(gomock.Any(), cloud.ResourceGroup, *vm.Name, gomock.Any()).Return(vm, nil).AnyTimes() + } + mockVMsClient.EXPECT().Get(gomock.Any(), cloud.ResourceGroup, "vm3", gomock.Any()).Return(compute.VirtualMachine{}, &retry.Error{HTTPStatusCode: http.StatusNotFound, RawError: cloudprovider.InstanceNotFound}).AnyTimes() + mockVMsClient.EXPECT().Update(gomock.Any(), cloud.ResourceGroup, gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + instanceID, err := cloud.InstanceID(context.Background(), types.NodeName(test.nodeName)) if test.expectError { if err == nil { @@ -222,7 +230,13 @@ func TestInstanceShutdownByProviderID(t *testing.T) { defer ctrl.Finish() for _, test := range testcases { cloud := GetTestCloud(ctrl) - setTestVirtualMachines(cloud, test.vmList, false) + expectedVMs := setTestVirtualMachines(cloud, test.vmList, false) + mockVMsClient := cloud.VirtualMachinesClient.(*mockvmclient.MockInterface) + for _, vm := range expectedVMs { + mockVMsClient.EXPECT().Get(gomock.Any(), cloud.ResourceGroup, *vm.Name, gomock.Any()).Return(vm, nil).AnyTimes() + } + mockVMsClient.EXPECT().Get(gomock.Any(), cloud.ResourceGroup, "vm8", gomock.Any()).Return(compute.VirtualMachine{}, &retry.Error{HTTPStatusCode: http.StatusNotFound, RawError: cloudprovider.InstanceNotFound}).AnyTimes() + providerID := "azure://" + cloud.getStandardMachineID("subscription", "rg", test.nodeName) hasShutdown, err := cloud.InstanceShutdownByProviderID(context.Background(), providerID) if test.expectError { diff --git a/staging/src/k8s.io/legacy-cloud-providers/azure/azure_loadbalancer_test.go b/staging/src/k8s.io/legacy-cloud-providers/azure/azure_loadbalancer_test.go index 614210693ed..f4a82b82131 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/azure/azure_loadbalancer_test.go +++ b/staging/src/k8s.io/legacy-cloud-providers/azure/azure_loadbalancer_test.go @@ -21,6 +21,7 @@ package azure import ( "context" "fmt" + "net/http" "reflect" "strconv" "strings" @@ -34,7 +35,11 @@ import ( v1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/legacy-cloud-providers/azure/clients/loadbalancerclient/mockloadbalancerclient" + "k8s.io/legacy-cloud-providers/azure/clients/publicipclient/mockpublicipclient" + "k8s.io/legacy-cloud-providers/azure/clients/securitygroupclient/mocksecuritygroupclient" "k8s.io/legacy-cloud-providers/azure/clients/subnetclient/mocksubnetclient" + "k8s.io/legacy-cloud-providers/azure/retry" ) func TestFindProbe(t *testing.T) { @@ -359,23 +364,25 @@ func TestEnsureLoadBalancerDeleted(t *testing.T) { tests := []struct { desc string service v1.Service + isInternalSvc bool expectCreateError bool }{ { desc: "external service should be created and deleted successfully", - service: getTestService("test1", v1.ProtocolTCP, nil, false, 80), + service: getTestService("service1", v1.ProtocolTCP, nil, false, 80), }, { - desc: "internal service should be created and deleted successfully", - service: getInternalTestService("test2", 80), + desc: "internal service should be created and deleted successfully", + service: getInternalTestService("service2", 80), + isInternalSvc: true, }, { desc: "annotated service with same resourceGroup should be created and deleted successfully", - service: getResourceGroupTestService("test3", "rg", "", 80), + service: getResourceGroupTestService("service3", "rg", "", 80), }, { desc: "annotated service with different resourceGroup shouldn't be created but should be deleted successfully", - service: getResourceGroupTestService("test4", "random-rg", "1.2.3.4", 80), + service: getResourceGroupTestService("service4", "random-rg", "1.2.3.4", 80), expectCreateError: true, }, } @@ -383,13 +390,19 @@ func TestEnsureLoadBalancerDeleted(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() az := GetTestCloud(ctrl) + + clusterResources, expectedInterfaces, expectedVirtualMachines := getClusterResources(az, vmCount, availabilitySetCount) + setMockEnv(az, ctrl, expectedInterfaces, expectedVirtualMachines, 4) + for i, c := range tests { - clusterResources := getClusterResources(az, vmCount, availabilitySetCount) - getTestSecurityGroup(az) + if c.service.Annotations[ServiceAnnotationLoadBalancerInternal] == "true" { validateTestSubnet(t, az, &c.service) } + expectedLBs := make([]network.LoadBalancer, 0) + setMockLBs(az, ctrl, &expectedLBs, "service", 1, i+1, c.isInternalSvc) + // create the service first. lbStatus, err := az.EnsureLoadBalancer(context.TODO(), testClusterName, &c.service, clusterResources.nodes) if c.expectCreateError { @@ -403,12 +416,18 @@ func TestEnsureLoadBalancerDeleted(t *testing.T) { assert.Equal(t, len(*result[0].LoadBalancingRules), 1, "TestCase[%d]: %s", i, c.desc) } + expectedLBs = make([]network.LoadBalancer, 0) + setMockLBs(az, ctrl, &expectedLBs, "service", 1, i+1, c.isInternalSvc) // finally, delete it. err = az.EnsureLoadBalancerDeleted(context.TODO(), testClusterName, &c.service) + expectedLBs = make([]network.LoadBalancer, 0) + mockLBsClient := mockloadbalancerclient.NewMockInterface(ctrl) + mockLBsClient.EXPECT().List(gomock.Any(), az.Config.ResourceGroup).Return(expectedLBs, nil) + az.LoadBalancerClient = mockLBsClient assert.Nil(t, err, "TestCase[%d]: %s", i, c.desc) result, rerr := az.LoadBalancerClient.List(context.Background(), az.Config.ResourceGroup) assert.Nil(t, rerr, "TestCase[%d]: %s", i, c.desc) - assert.Equal(t, len(result), 0, "TestCase[%d]: %s", i, c.desc) + assert.Equal(t, 0, len(result), "TestCase[%d]: %s", i, c.desc) } } @@ -596,44 +615,44 @@ func TestGetServiceLoadBalancer(t *testing.T) { expectedError bool }{ { - desc: "getServiceLoadBalancer shall return corresponding lb, status, exists if there are exsisted lbs", + desc: "getServiceLoadBalancer shall return corresponding lb, status, exists if there are existed lbs", existingLBs: []network.LoadBalancer{ { Name: to.StringPtr("lb1"), LoadBalancerPropertiesFormat: &network.LoadBalancerPropertiesFormat{ FrontendIPConfigurations: &[]network.FrontendIPConfiguration{ { - Name: to.StringPtr("atest1"), + Name: to.StringPtr("aservice1"), FrontendIPConfigurationPropertiesFormat: &network.FrontendIPConfigurationPropertiesFormat{ - PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("id1")}, + PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("testCluster-aservice1")}, }, }, }, }, }, }, - service: getTestService("test1", v1.ProtocolTCP, nil, false, 80), + service: getTestService("service1", v1.ProtocolTCP, nil, false, 80), wantLB: false, expectedLB: &network.LoadBalancer{ Name: to.StringPtr("lb1"), LoadBalancerPropertiesFormat: &network.LoadBalancerPropertiesFormat{ FrontendIPConfigurations: &[]network.FrontendIPConfiguration{ { - Name: to.StringPtr("atest1"), + Name: to.StringPtr("aservice1"), FrontendIPConfigurationPropertiesFormat: &network.FrontendIPConfigurationPropertiesFormat{ - PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("id1")}, + PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("testCluster-aservice1")}, }, }, }, }, }, - expectedStatus: &v1.LoadBalancerStatus{Ingress: []v1.LoadBalancerIngress{{IP: "", Hostname: ""}}}, + expectedStatus: &v1.LoadBalancerStatus{Ingress: []v1.LoadBalancerIngress{{IP: "1.2.3.4", Hostname: ""}}}, expectedExists: true, expectedError: false, }, { desc: "getServiceLoadBalancer shall report error if there're loadbalancer mode annotations on a standard lb", - service: getTestService("test1", v1.ProtocolTCP, nil, false, 80), + service: getTestService("service1", v1.ProtocolTCP, nil, false, 80), annotations: map[string]string{ServiceAnnotationLoadBalancerMode: "__auto__"}, sku: "standard", expectedExists: false, @@ -671,7 +690,7 @@ func TestGetServiceLoadBalancer(t *testing.T) { }, }, }, - service: getTestService("test1", v1.ProtocolTCP, nil, false, 80), + service: getTestService("service1", v1.ProtocolTCP, nil, false, 80), annotations: map[string]string{ServiceAnnotationLoadBalancerMode: "__auto__"}, wantLB: true, expectedLB: &network.LoadBalancer{ @@ -687,7 +706,7 @@ func TestGetServiceLoadBalancer(t *testing.T) { }, { desc: "getServiceLoadBalancer shall create a new lb otherwise", - service: getTestService("test1", v1.ProtocolTCP, nil, false, 80), + service: getTestService("service1", v1.ProtocolTCP, nil, false, 80), expectedLB: &network.LoadBalancer{ Name: to.StringPtr("testCluster"), Location: to.StringPtr("westus"), @@ -702,7 +721,13 @@ func TestGetServiceLoadBalancer(t *testing.T) { defer ctrl.Finish() for i, test := range testCases { az := GetTestCloud(ctrl) - clusterResources := getClusterResources(az, 3, 3) + clusterResources, expectedInterfaces, expectedVirtualMachines := getClusterResources(az, 3, 3) + setMockEnv(az, ctrl, expectedInterfaces, expectedVirtualMachines, 1) + + mockLBsClient := mockloadbalancerclient.NewMockInterface(ctrl) + mockLBsClient.EXPECT().CreateOrUpdate(gomock.Any(), "rg", gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + mockLBsClient.EXPECT().List(gomock.Any(), "rg").Return(test.existingLBs, nil) + az.LoadBalancerClient = mockLBsClient for _, existingLB := range test.existingLBs { err := az.LoadBalancerClient.CreateOrUpdate(context.TODO(), "rg", *existingLB.Name, existingLB, "") @@ -732,8 +757,8 @@ func TestIsFrontendIPChanged(t *testing.T) { lbFrontendIPConfigName string annotations string loadBalancerIP string - exsistingSubnet network.Subnet - exsistingPIPs []network.PublicIPAddress + existingSubnet network.Subnet + existingPIPs []network.PublicIPAddress expectedFlag bool expectedError bool }{ @@ -794,7 +819,7 @@ func TestIsFrontendIPChanged(t *testing.T) { lbFrontendIPConfigName: "btest1-name", service: getInternalTestService("test1", 80), annotations: "testSubnet", - exsistingSubnet: network.Subnet{Name: to.StringPtr("testSubnet1")}, + existingSubnet: network.Subnet{Name: to.StringPtr("testSubnet1")}, expectedFlag: true, expectedError: false, }, @@ -854,7 +879,7 @@ func TestIsFrontendIPChanged(t *testing.T) { lbFrontendIPConfigName: "btest1-name", service: getTestService("test1", v1.ProtocolTCP, nil, false, 80), loadBalancerIP: "1.1.1.1", - exsistingPIPs: []network.PublicIPAddress{ + existingPIPs: []network.PublicIPAddress{ { Name: to.StringPtr("pipName"), PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{ @@ -877,12 +902,14 @@ func TestIsFrontendIPChanged(t *testing.T) { lbFrontendIPConfigName: "btest1-name", service: getTestService("test1", v1.ProtocolTCP, nil, false, 80), loadBalancerIP: "1.1.1.1", - exsistingPIPs: []network.PublicIPAddress{ + existingPIPs: []network.PublicIPAddress{ { Name: to.StringPtr("pipName"), PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{ IPAddress: to.StringPtr("1.1.1.1"), }, + ID: to.StringPtr("/subscriptions/subscription" + + "/resourceGroups/rg/providers/Microsoft.Network/publicIPAddresses/pipName"), }, }, expectedFlag: false, @@ -900,7 +927,7 @@ func TestIsFrontendIPChanged(t *testing.T) { lbFrontendIPConfigName: "btest1-name", service: getTestService("test1", v1.ProtocolTCP, nil, false, 80), loadBalancerIP: "1.1.1.1", - exsistingPIPs: []network.PublicIPAddress{ + existingPIPs: []network.PublicIPAddress{ { Name: to.StringPtr("pipName"), PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{ @@ -916,14 +943,19 @@ func TestIsFrontendIPChanged(t *testing.T) { for i, test := range testCases { az := GetTestCloud(ctrl) mockSubnetsClient := az.SubnetsClient.(*mocksubnetclient.MockInterface) - mockSubnetsClient.EXPECT().Get(gomock.Any(), "rg", "vnet", "testSubnet", "").Return(test.exsistingSubnet, nil).AnyTimes() - mockSubnetsClient.EXPECT().CreateOrUpdate(gomock.Any(), "rg", "vnet", "testSubnet", test.exsistingSubnet).Return(nil) - err := az.SubnetsClient.CreateOrUpdate(context.TODO(), "rg", "vnet", "testSubnet", test.exsistingSubnet) + mockSubnetsClient.EXPECT().Get(gomock.Any(), "rg", "vnet", "testSubnet", "").Return(test.existingSubnet, nil).AnyTimes() + mockSubnetsClient.EXPECT().CreateOrUpdate(gomock.Any(), "rg", "vnet", "testSubnet", test.existingSubnet).Return(nil) + err := az.SubnetsClient.CreateOrUpdate(context.TODO(), "rg", "vnet", "testSubnet", test.existingSubnet) if err != nil { t.Fatalf("TestCase[%d] meets unexpected error: %v", i, err) } - for _, existingPIP := range test.exsistingPIPs { - err := az.PublicIPAddressesClient.CreateOrUpdate(context.TODO(), "rg", "pipName", existingPIP) + + mockPIPsClient := az.PublicIPAddressesClient.(*mockpublicipclient.MockInterface) + mockPIPsClient.EXPECT().List(gomock.Any(), "rg").Return(test.existingPIPs, nil).AnyTimes() + mockPIPsClient.EXPECT().CreateOrUpdate(gomock.Any(), "rg", gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + for _, existingPIP := range test.existingPIPs { + mockPIPsClient.EXPECT().Get(gomock.Any(), "rg", *existingPIP.Name, gomock.Any()).Return(existingPIP, nil).AnyTimes() + err := az.PublicIPAddressesClient.CreateOrUpdate(context.TODO(), "rg", *existingPIP.Name, existingPIP) if err != nil { t.Fatalf("TestCase[%d] meets unexpected error: %v", i, err) } @@ -944,7 +976,7 @@ func TestDeterminePublicIPName(t *testing.T) { testCases := []struct { desc string loadBalancerIP string - exsistingPIPs []network.PublicIPAddress + existingPIPs []network.PublicIPAddress expectedIP string expectedError bool }{ @@ -964,7 +996,7 @@ func TestDeterminePublicIPName(t *testing.T) { desc: "determinePublicIpName shall return loadBalancerIP in service.Spec if it's in the " + "resource group", loadBalancerIP: "1.2.3.4", - exsistingPIPs: []network.PublicIPAddress{ + existingPIPs: []network.PublicIPAddress{ { Name: to.StringPtr("pipName"), PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{ @@ -980,8 +1012,13 @@ func TestDeterminePublicIPName(t *testing.T) { az := GetTestCloud(ctrl) service := getTestService("test1", v1.ProtocolTCP, nil, false, 80) service.Spec.LoadBalancerIP = test.loadBalancerIP - for _, existingPIP := range test.exsistingPIPs { - err := az.PublicIPAddressesClient.CreateOrUpdate(context.TODO(), "rg", "test", existingPIP) + + mockPIPsClient := az.PublicIPAddressesClient.(*mockpublicipclient.MockInterface) + mockPIPsClient.EXPECT().List(gomock.Any(), "rg").Return(test.existingPIPs, nil).AnyTimes() + mockPIPsClient.EXPECT().CreateOrUpdate(gomock.Any(), "rg", gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + for _, existingPIP := range test.existingPIPs { + mockPIPsClient.EXPECT().Get(gomock.Any(), "rg", *existingPIP.Name, gomock.Any()).Return(existingPIP, nil).AnyTimes() + err := az.PublicIPAddressesClient.CreateOrUpdate(context.TODO(), "rg", *existingPIP.Name, existingPIP) if err != nil { t.Fatalf("TestCase[%d] meets unexpected error: %v", i, err) } @@ -1163,7 +1200,7 @@ func getTestLoadBalancer(name, rgName, clusterName, identifier *string, service { Name: identifier, FrontendIPConfigurationPropertiesFormat: &network.FrontendIPConfigurationPropertiesFormat{ - PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("id1")}, + PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("testCluster-aservice1")}, }, }, }, @@ -1188,7 +1225,7 @@ func getTestLoadBalancer(name, rgName, clusterName, identifier *string, service strings.ToLower(string(service.Spec.Ports[0].Protocol)))), FrontendIPConfiguration: &network.SubResource{ ID: to.StringPtr("/subscriptions/subscription/resourceGroups/" + *rgName + "/providers/" + - "Microsoft.Network/loadBalancers/" + *name + "/frontendIPConfigurations/atest1"), + "Microsoft.Network/loadBalancers/" + *name + "/frontendIPConfigurations/aservice1"), }, BackendAddressPool: &network.SubResource{ ID: to.StringPtr("/subscriptions/subscription/resourceGroups/" + *rgName + "/providers/" + @@ -1200,7 +1237,7 @@ func getTestLoadBalancer(name, rgName, clusterName, identifier *string, service EnableFloatingIP: to.BoolPtr(true), EnableTCPReset: to.BoolPtr(strings.EqualFold(lbSku, "standard")), Probe: &network.SubResource{ - ID: to.StringPtr("/subscriptions/subscription/resourceGroups/" + *rgName + "/providers/Microsoft.Network/loadBalancers/testCluster/probes/atest1-TCP-80"), + ID: to.StringPtr("/subscriptions/subscription/resourceGroups/" + *rgName + "/providers/Microsoft.Network/loadBalancers/testCluster/probes/aservice1-TCP-80"), }, }, }, @@ -1214,98 +1251,97 @@ func TestReconcileLoadBalancer(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() - service1 := getTestService("test1", v1.ProtocolTCP, nil, false, 80) - basicLb1 := getTestLoadBalancer(to.StringPtr("lb1"), to.StringPtr("rg"), to.StringPtr("testCluster"), to.StringPtr("atest1"), service1, "Basic") + service1 := getTestService("service1", v1.ProtocolTCP, nil, false, 80) + basicLb1 := getTestLoadBalancer(to.StringPtr("lb1"), to.StringPtr("rg"), to.StringPtr("testCluster"), to.StringPtr("aservice1"), service1, "Basic") service2 := getTestService("test1", v1.ProtocolTCP, nil, false, 80) - basicLb2 := getTestLoadBalancer(to.StringPtr("lb1"), to.StringPtr("rg"), to.StringPtr("testCluster"), to.StringPtr("btest1"), service2, "Basic") + basicLb2 := getTestLoadBalancer(to.StringPtr("lb1"), to.StringPtr("rg"), to.StringPtr("testCluster"), to.StringPtr("bservice1"), service2, "Basic") basicLb2.Name = to.StringPtr("testCluster") basicLb2.FrontendIPConfigurations = &[]network.FrontendIPConfiguration{ { - Name: to.StringPtr("btest1"), + Name: to.StringPtr("bservice1"), FrontendIPConfigurationPropertiesFormat: &network.FrontendIPConfigurationPropertiesFormat{ - PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("id1")}, + PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("testCluster-bservice1")}, }, }, } - service3 := getTestService("test1", v1.ProtocolTCP, nil, false, 80) - modifiedLb1 := getTestLoadBalancer(to.StringPtr("testCluster"), to.StringPtr("rg"), to.StringPtr("testCluster"), to.StringPtr("atest1"), service3, "Basic") + service3 := getTestService("service1", v1.ProtocolTCP, nil, false, 80) + modifiedLb1 := getTestLoadBalancer(to.StringPtr("testCluster"), to.StringPtr("rg"), to.StringPtr("testCluster"), to.StringPtr("aservice1"), service3, "Basic") modifiedLb1.FrontendIPConfigurations = &[]network.FrontendIPConfiguration{ { - Name: to.StringPtr("atest1"), + Name: to.StringPtr("aservice1"), FrontendIPConfigurationPropertiesFormat: &network.FrontendIPConfigurationPropertiesFormat{ - PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("id1")}, + PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("testCluster-aservice1")}, }, }, { - Name: to.StringPtr("btest1"), + Name: to.StringPtr("bservice1"), FrontendIPConfigurationPropertiesFormat: &network.FrontendIPConfigurationPropertiesFormat{ - PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("id1")}, + PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("testCluster-bservice1")}, }, }, } modifiedLb1.Probes = &[]network.Probe{ { - Name: to.StringPtr("atest1-" + string(service3.Spec.Ports[0].Protocol) + + Name: to.StringPtr("aservice1-" + string(service3.Spec.Ports[0].Protocol) + "-" + strconv.Itoa(int(service3.Spec.Ports[0].Port))), ProbePropertiesFormat: &network.ProbePropertiesFormat{ Port: to.Int32Ptr(10080), }, }, { - Name: to.StringPtr("atest1-" + string(service3.Spec.Ports[0].Protocol) + + Name: to.StringPtr("aservice1-" + string(service3.Spec.Ports[0].Protocol) + "-" + strconv.Itoa(int(service3.Spec.Ports[0].Port))), ProbePropertiesFormat: &network.ProbePropertiesFormat{ Port: to.Int32Ptr(10081), }, }, } - expectedLb1 := getTestLoadBalancer(to.StringPtr("testCluster"), to.StringPtr("rg"), to.StringPtr("testCluster"), to.StringPtr("atest1"), service3, "Basic") + expectedLb1 := getTestLoadBalancer(to.StringPtr("testCluster"), to.StringPtr("rg"), to.StringPtr("testCluster"), to.StringPtr("aservice1"), service3, "Basic") (*expectedLb1.LoadBalancerPropertiesFormat.LoadBalancingRules)[0].DisableOutboundSnat = to.BoolPtr(false) (*expectedLb1.LoadBalancerPropertiesFormat.LoadBalancingRules)[0].EnableTCPReset = nil expectedLb1.FrontendIPConfigurations = &[]network.FrontendIPConfiguration{ { - Name: to.StringPtr("btest1"), + Name: to.StringPtr("aservice1"), FrontendIPConfigurationPropertiesFormat: &network.FrontendIPConfigurationPropertiesFormat{ - PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("id1")}, + PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("testCluster-aservice1")}, }, }, { - Name: to.StringPtr("atest1"), + Name: to.StringPtr("bservice1"), FrontendIPConfigurationPropertiesFormat: &network.FrontendIPConfigurationPropertiesFormat{ - PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("/subscriptions/subscription/" + - "resourceGroups/rg/providers/Microsoft.Network/publicIPAddresses/pipName")}, + PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("testCluster-bservice1")}, }, }, } - service4 := getTestService("test1", v1.ProtocolTCP, map[string]string{"service.beta.kubernetes.io/azure-load-balancer-disable-tcp-reset": "true"}, false, 80) - existingSLB := getTestLoadBalancer(to.StringPtr("testCluster"), to.StringPtr("rg"), to.StringPtr("testCluster"), to.StringPtr("atest1"), service4, "Standard") + service4 := getTestService("service1", v1.ProtocolTCP, map[string]string{"service.beta.kubernetes.io/azure-load-balancer-disable-tcp-reset": "true"}, false, 80) + existingSLB := getTestLoadBalancer(to.StringPtr("testCluster"), to.StringPtr("rg"), to.StringPtr("testCluster"), to.StringPtr("aservice1"), service4, "Standard") existingSLB.FrontendIPConfigurations = &[]network.FrontendIPConfiguration{ { - Name: to.StringPtr("atest1"), + Name: to.StringPtr("aservice1"), FrontendIPConfigurationPropertiesFormat: &network.FrontendIPConfigurationPropertiesFormat{ - PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("id1")}, + PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("testCluster-aservice1")}, }, }, { - Name: to.StringPtr("btest1"), + Name: to.StringPtr("bservice1"), FrontendIPConfigurationPropertiesFormat: &network.FrontendIPConfigurationPropertiesFormat{ - PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("id1")}, + PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("testCluster-bservice1")}, }, }, } existingSLB.Probes = &[]network.Probe{ { - Name: to.StringPtr("atest1-" + string(service4.Spec.Ports[0].Protocol) + + Name: to.StringPtr("aservice1-" + string(service4.Spec.Ports[0].Protocol) + "-" + strconv.Itoa(int(service4.Spec.Ports[0].Port))), ProbePropertiesFormat: &network.ProbePropertiesFormat{ Port: to.Int32Ptr(10080), }, }, { - Name: to.StringPtr("atest1-" + string(service4.Spec.Ports[0].Protocol) + + Name: to.StringPtr("aservice1-" + string(service4.Spec.Ports[0].Protocol) + "-" + strconv.Itoa(int(service4.Spec.Ports[0].Port))), ProbePropertiesFormat: &network.ProbePropertiesFormat{ Port: to.Int32Ptr(10081), @@ -1313,51 +1349,50 @@ func TestReconcileLoadBalancer(t *testing.T) { }, } - expectedSLb := getTestLoadBalancer(to.StringPtr("testCluster"), to.StringPtr("rg"), to.StringPtr("testCluster"), to.StringPtr("atest1"), service4, "Standard") + expectedSLb := getTestLoadBalancer(to.StringPtr("testCluster"), to.StringPtr("rg"), to.StringPtr("testCluster"), to.StringPtr("aservice1"), service4, "Standard") (*expectedSLb.LoadBalancerPropertiesFormat.LoadBalancingRules)[0].DisableOutboundSnat = to.BoolPtr(true) (*expectedSLb.LoadBalancerPropertiesFormat.LoadBalancingRules)[0].EnableTCPReset = to.BoolPtr(false) expectedSLb.FrontendIPConfigurations = &[]network.FrontendIPConfiguration{ { - Name: to.StringPtr("btest1"), + Name: to.StringPtr("aservice1"), FrontendIPConfigurationPropertiesFormat: &network.FrontendIPConfigurationPropertiesFormat{ - PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("id1")}, + PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("testCluster-aservice1")}, }, }, { - Name: to.StringPtr("atest1"), + Name: to.StringPtr("bservice1"), FrontendIPConfigurationPropertiesFormat: &network.FrontendIPConfigurationPropertiesFormat{ - PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("/subscriptions/subscription/" + - "resourceGroups/rg/providers/Microsoft.Network/publicIPAddresses/pipName")}, + PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("testCluster-bservice1")}, }, }, } - service5 := getTestService("test1", v1.ProtocolTCP, nil, false, 80) - slb5 := getTestLoadBalancer(to.StringPtr("testCluster"), to.StringPtr("rg"), to.StringPtr("testCluster"), to.StringPtr("atest1"), service5, "Standard") + service5 := getTestService("service1", v1.ProtocolTCP, nil, false, 80) + slb5 := getTestLoadBalancer(to.StringPtr("testCluster"), to.StringPtr("rg"), to.StringPtr("testCluster"), to.StringPtr("aservice1"), service5, "Standard") slb5.FrontendIPConfigurations = &[]network.FrontendIPConfiguration{ { - Name: to.StringPtr("atest1"), + Name: to.StringPtr("aservice1"), FrontendIPConfigurationPropertiesFormat: &network.FrontendIPConfigurationPropertiesFormat{ - PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("id1")}, + PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("testCluster-aservice1")}, }, }, { - Name: to.StringPtr("btest1"), + Name: to.StringPtr("bservice1"), FrontendIPConfigurationPropertiesFormat: &network.FrontendIPConfigurationPropertiesFormat{ - PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("id1")}, + PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("testCluster-bservice1")}, }, }, } slb5.Probes = &[]network.Probe{ { - Name: to.StringPtr("atest1-" + string(service4.Spec.Ports[0].Protocol) + + Name: to.StringPtr("aservice1-" + string(service4.Spec.Ports[0].Protocol) + "-" + strconv.Itoa(int(service4.Spec.Ports[0].Port))), ProbePropertiesFormat: &network.ProbePropertiesFormat{ Port: to.Int32Ptr(10080), }, }, { - Name: to.StringPtr("atest1-" + string(service4.Spec.Ports[0].Protocol) + + Name: to.StringPtr("aservice1-" + string(service4.Spec.Ports[0].Protocol) + "-" + strconv.Itoa(int(service4.Spec.Ports[0].Port))), ProbePropertiesFormat: &network.ProbePropertiesFormat{ Port: to.Int32Ptr(10081), @@ -1365,70 +1400,67 @@ func TestReconcileLoadBalancer(t *testing.T) { }, } - //change to false to test that reconcilication will fix it + //change to false to test that reconciliation will fix it (*slb5.LoadBalancerPropertiesFormat.LoadBalancingRules)[0].EnableTCPReset = to.BoolPtr(false) - expectedSLb5 := getTestLoadBalancer(to.StringPtr("testCluster"), to.StringPtr("rg"), to.StringPtr("testCluster"), to.StringPtr("atest1"), service5, "Standard") + expectedSLb5 := getTestLoadBalancer(to.StringPtr("testCluster"), to.StringPtr("rg"), to.StringPtr("testCluster"), to.StringPtr("aservice1"), service5, "Standard") (*expectedSLb5.LoadBalancerPropertiesFormat.LoadBalancingRules)[0].DisableOutboundSnat = to.BoolPtr(true) expectedSLb5.FrontendIPConfigurations = &[]network.FrontendIPConfiguration{ { - Name: to.StringPtr("btest1"), + Name: to.StringPtr("aservice1"), FrontendIPConfigurationPropertiesFormat: &network.FrontendIPConfigurationPropertiesFormat{ - PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("id1")}, + PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("testCluster-aservice1")}, }, }, { - Name: to.StringPtr("atest1"), + Name: to.StringPtr("bservice1"), FrontendIPConfigurationPropertiesFormat: &network.FrontendIPConfigurationPropertiesFormat{ - PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("/subscriptions/subscription/" + - "resourceGroups/rg/providers/Microsoft.Network/publicIPAddresses/pipName")}, + PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("testCluster-bservice1")}, }, }, } - service6 := getTestService("test1", v1.ProtocolUDP, nil, false, 80) - lb6 := getTestLoadBalancer(to.StringPtr("testCluster"), to.StringPtr("rg"), to.StringPtr("testCluster"), to.StringPtr("atest1"), service6, "basic") + service6 := getTestService("service1", v1.ProtocolUDP, nil, false, 80) + lb6 := getTestLoadBalancer(to.StringPtr("testCluster"), to.StringPtr("rg"), to.StringPtr("testCluster"), to.StringPtr("aservice1"), service6, "basic") lb6.FrontendIPConfigurations = &[]network.FrontendIPConfiguration{} lb6.Probes = &[]network.Probe{} - expectedLB6 := getTestLoadBalancer(to.StringPtr("testCluster"), to.StringPtr("rg"), to.StringPtr("testCluster"), to.StringPtr("atest1"), service6, "basic") + expectedLB6 := getTestLoadBalancer(to.StringPtr("testCluster"), to.StringPtr("rg"), to.StringPtr("testCluster"), to.StringPtr("aservice1"), service6, "basic") expectedLB6.Probes = &[]network.Probe{} (*expectedLB6.LoadBalancerPropertiesFormat.LoadBalancingRules)[0].Probe = nil (*expectedLB6.LoadBalancerPropertiesFormat.LoadBalancingRules)[0].EnableTCPReset = nil (*expectedLB6.LoadBalancerPropertiesFormat.LoadBalancingRules)[0].DisableOutboundSnat = to.BoolPtr(false) expectedLB6.FrontendIPConfigurations = &[]network.FrontendIPConfiguration{ { - Name: to.StringPtr("atest1"), + Name: to.StringPtr("aservice1"), FrontendIPConfigurationPropertiesFormat: &network.FrontendIPConfigurationPropertiesFormat{ - PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("/subscriptions/subscription/" + - "resourceGroups/rg/providers/Microsoft.Network/publicIPAddresses/pipName")}, + PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("testCluster-aservice1")}, }, }, } - service7 := getTestService("test1", v1.ProtocolUDP, nil, false, 80) + service7 := getTestService("service1", v1.ProtocolUDP, nil, false, 80) service7.Spec.HealthCheckNodePort = 10081 service7.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeLocal - lb7 := getTestLoadBalancer(to.StringPtr("testCluster"), to.StringPtr("rg"), to.StringPtr("testCluster"), to.StringPtr("atest1"), service7, "basic") + lb7 := getTestLoadBalancer(to.StringPtr("testCluster"), to.StringPtr("rg"), to.StringPtr("testCluster"), to.StringPtr("aservice1"), service7, "basic") lb7.FrontendIPConfigurations = &[]network.FrontendIPConfiguration{} lb7.Probes = &[]network.Probe{} - expectedLB7 := getTestLoadBalancer(to.StringPtr("testCluster"), to.StringPtr("rg"), to.StringPtr("testCluster"), to.StringPtr("atest1"), service7, "basic") + expectedLB7 := getTestLoadBalancer(to.StringPtr("testCluster"), to.StringPtr("rg"), to.StringPtr("testCluster"), to.StringPtr("aservice1"), service7, "basic") (*expectedLB7.LoadBalancerPropertiesFormat.LoadBalancingRules)[0].Probe = &network.SubResource{ - ID: to.StringPtr("/subscriptions/subscription/resourceGroups/rg/providers/Microsoft.Network/loadBalancers/testCluster/probes/atest1-UDP-80"), + ID: to.StringPtr("/subscriptions/subscription/resourceGroups/rg/providers/Microsoft.Network/loadBalancers/testCluster/probes/aservice1-UDP-80"), } (*expectedLB7.LoadBalancerPropertiesFormat.LoadBalancingRules)[0].EnableTCPReset = nil (*expectedLB7.LoadBalancerPropertiesFormat.LoadBalancingRules)[0].DisableOutboundSnat = to.BoolPtr(false) expectedLB7.FrontendIPConfigurations = &[]network.FrontendIPConfiguration{ { - Name: to.StringPtr("atest1"), + Name: to.StringPtr("aservice1"), FrontendIPConfigurationPropertiesFormat: &network.FrontendIPConfigurationPropertiesFormat{ - PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("/subscriptions/subscription/" + - "resourceGroups/rg/providers/Microsoft.Network/publicIPAddresses/pipName")}, + PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("testCluster-aservice1")}, }, }, } expectedLB7.Probes = &[]network.Probe{ { - Name: to.StringPtr("atest1-" + string(service7.Spec.Ports[0].Protocol) + + Name: to.StringPtr("aservice1-" + string(service7.Spec.Ports[0].Protocol) + "-" + strconv.Itoa(int(service7.Spec.Ports[0].Port))), ProbePropertiesFormat: &network.ProbePropertiesFormat{ Port: to.Int32Ptr(10081), @@ -1440,24 +1472,23 @@ func TestReconcileLoadBalancer(t *testing.T) { }, } - service8 := getTestService("test1", v1.ProtocolTCP, nil, false, 80) - lb8 := getTestLoadBalancer(to.StringPtr("testCluster"), to.StringPtr("anotherRG"), to.StringPtr("testCluster"), to.StringPtr("atest1"), service8, "Standard") + service8 := getTestService("service1", v1.ProtocolTCP, nil, false, 80) + lb8 := getTestLoadBalancer(to.StringPtr("testCluster"), to.StringPtr("anotherRG"), to.StringPtr("testCluster"), to.StringPtr("aservice1"), service8, "Standard") lb8.FrontendIPConfigurations = &[]network.FrontendIPConfiguration{} lb8.Probes = &[]network.Probe{} - expectedLB8 := getTestLoadBalancer(to.StringPtr("testCluster"), to.StringPtr("anotherRG"), to.StringPtr("testCluster"), to.StringPtr("atest1"), service8, "Standard") + expectedLB8 := getTestLoadBalancer(to.StringPtr("testCluster"), to.StringPtr("anotherRG"), to.StringPtr("testCluster"), to.StringPtr("aservice1"), service8, "Standard") (*expectedLB8.LoadBalancerPropertiesFormat.LoadBalancingRules)[0].DisableOutboundSnat = to.BoolPtr(false) expectedLB8.FrontendIPConfigurations = &[]network.FrontendIPConfiguration{ { - Name: to.StringPtr("atest1"), + Name: to.StringPtr("aservice1"), FrontendIPConfigurationPropertiesFormat: &network.FrontendIPConfigurationPropertiesFormat{ - PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("/subscriptions/subscription/" + - "resourceGroups/rg/providers/Microsoft.Network/publicIPAddresses/pipName")}, + PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("testCluster-aservice1")}, }, }, } expectedLB8.Probes = &[]network.Probe{ { - Name: to.StringPtr("atest1-" + string(service8.Spec.Ports[0].Protocol) + + Name: to.StringPtr("aservice1-" + string(service8.Spec.Ports[0].Protocol) + "-" + strconv.Itoa(int(service7.Spec.Ports[0].Port))), ProbePropertiesFormat: &network.ProbePropertiesFormat{ Port: to.Int32Ptr(10080), @@ -1501,7 +1532,7 @@ func TestReconcileLoadBalancer(t *testing.T) { expectedError: nil, }, { - desc: "reconcileLoadBalancer shall remove and reconstruct the correspoind field of lb", + desc: "reconcileLoadBalancer shall remove and reconstruct the correspond field of lb", loadBalancerSku: "basic", service: service3, existingLB: modifiedLb1, @@ -1578,7 +1609,9 @@ func TestReconcileLoadBalancer(t *testing.T) { } az.LoadBalancerResourceGroup = test.loadBalancerResourceGroup - clusterResources := getClusterResources(az, 3, 3) + clusterResources, expectedInterfaces, expectedVirtualMachines := getClusterResources(az, 3, 3) + setMockEnv(az, ctrl, expectedInterfaces, expectedVirtualMachines, 1) + test.service.Spec.LoadBalancerIP = "1.2.3.4" err := az.PublicIPAddressesClient.CreateOrUpdate(context.TODO(), "rg", "pipName", network.PublicIPAddress{ @@ -1591,6 +1624,12 @@ func TestReconcileLoadBalancer(t *testing.T) { t.Fatalf("TestCase[%d] meets unexpected error: %v", i, err) } + mockLBsClient := mockloadbalancerclient.NewMockInterface(ctrl) + mockLBsClient.EXPECT().List(gomock.Any(), az.getLoadBalancerResourceGroup()).Return([]network.LoadBalancer{test.existingLB}, nil) + mockLBsClient.EXPECT().Get(gomock.Any(), az.getLoadBalancerResourceGroup(), *test.existingLB.Name, gomock.Any()).Return(test.existingLB, nil).AnyTimes() + mockLBsClient.EXPECT().CreateOrUpdate(gomock.Any(), az.getLoadBalancerResourceGroup(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + az.LoadBalancerClient = mockLBsClient + err = az.LoadBalancerClient.CreateOrUpdate(context.TODO(), az.getLoadBalancerResourceGroup(), "lb1", test.existingLB, "") if err != nil { t.Fatalf("TestCase[%d] meets unexpected error: %v", i, err) @@ -1610,29 +1649,21 @@ func TestGetServiceLoadBalancerStatus(t *testing.T) { defer ctrl.Finish() az := GetTestCloud(ctrl) - service := getTestService("test1", v1.ProtocolTCP, nil, false, 80) - internalService := getInternalTestService("test1", 80) + service := getTestService("service1", v1.ProtocolTCP, nil, false, 80) + internalService := getInternalTestService("service1", 80) - PIPClient := newFakeAzurePIPClient(az.Config.SubscriptionID) - PIPClient.setFakeStore(map[string]map[string]network.PublicIPAddress{ - "rg": {"id1": network.PublicIPAddress{ - PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{ - IPAddress: to.StringPtr("1.2.3.4"), - }, - }}, - }) - az.PublicIPAddressesClient = PIPClient + setMockPublicIPs(az, ctrl, 1) lb1 := getTestLoadBalancer(to.StringPtr("lb1"), to.StringPtr("rg"), to.StringPtr("testCluster"), - to.StringPtr("test1"), internalService, "Basic") + to.StringPtr("aservice1"), internalService, "Basic") lb1.FrontendIPConfigurations = nil lb2 := getTestLoadBalancer(to.StringPtr("lb2"), to.StringPtr("rg"), to.StringPtr("testCluster"), - to.StringPtr("test1"), internalService, "Basic") + to.StringPtr("aservice1"), internalService, "Basic") lb2.FrontendIPConfigurations = &[]network.FrontendIPConfiguration{ { - Name: to.StringPtr("atest1"), + Name: to.StringPtr("aservice1"), FrontendIPConfigurationPropertiesFormat: &network.FrontendIPConfigurationPropertiesFormat{ - PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("id1")}, + PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("testCluster-aservice1")}, PrivateIPAddress: to.StringPtr("private"), }, }, @@ -1641,18 +1672,18 @@ func TestGetServiceLoadBalancerStatus(t *testing.T) { to.StringPtr("test1"), internalService, "Basic") lb3.FrontendIPConfigurations = &[]network.FrontendIPConfiguration{ { - Name: to.StringPtr("btest1"), + Name: to.StringPtr("bservice1"), FrontendIPConfigurationPropertiesFormat: &network.FrontendIPConfigurationPropertiesFormat{ - PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("id1")}, + PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("testCluster-bservice1")}, PrivateIPAddress: to.StringPtr("private"), }, }, } lb4 := getTestLoadBalancer(to.StringPtr("lb4"), to.StringPtr("rg"), to.StringPtr("testCluster"), - to.StringPtr("test1"), service, "Basic") + to.StringPtr("aservice1"), service, "Basic") lb4.FrontendIPConfigurations = &[]network.FrontendIPConfiguration{ { - Name: to.StringPtr("atest1"), + Name: to.StringPtr("aservice1"), FrontendIPConfigurationPropertiesFormat: &network.FrontendIPConfigurationPropertiesFormat{ PublicIPAddress: &network.PublicIPAddress{ID: nil}, PrivateIPAddress: to.StringPtr("private"), @@ -1660,10 +1691,10 @@ func TestGetServiceLoadBalancerStatus(t *testing.T) { }, } lb5 := getTestLoadBalancer(to.StringPtr("lb5"), to.StringPtr("rg"), to.StringPtr("testCluster"), - to.StringPtr("test1"), service, "Basic") + to.StringPtr("aservice1"), service, "Basic") lb5.FrontendIPConfigurations = &[]network.FrontendIPConfiguration{ { - Name: to.StringPtr("atest1"), + Name: to.StringPtr("aservice1"), FrontendIPConfigurationPropertiesFormat: &network.FrontendIPConfigurationPropertiesFormat{ PublicIPAddress: nil, PrivateIPAddress: to.StringPtr("private"), @@ -1671,10 +1702,10 @@ func TestGetServiceLoadBalancerStatus(t *testing.T) { }, } lb6 := getTestLoadBalancer(to.StringPtr("lb6"), to.StringPtr("rg"), to.StringPtr("testCluster"), - to.StringPtr("test1"), service, "Basic") + to.StringPtr("aservice1"), service, "Basic") lb6.FrontendIPConfigurations = &[]network.FrontendIPConfiguration{ { - Name: to.StringPtr("atest1"), + Name: to.StringPtr("aservice1"), FrontendIPConfigurationPropertiesFormat: &network.FrontendIPConfigurationPropertiesFormat{ PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("illegal/id/")}, PrivateIPAddress: to.StringPtr("private"), @@ -1834,7 +1865,13 @@ func TestReconcileSecurityGroup(t *testing.T) { for i, test := range testCases { az := GetTestCloud(ctrl) + mockSGsClient := az.SecurityGroupsClient.(*mocksecuritygroupclient.MockInterface) + mockSGsClient.EXPECT().CreateOrUpdate(gomock.Any(), "rg", gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + if len(test.existingSgs) == 0 { + mockSGsClient.EXPECT().Get(gomock.Any(), "rg", gomock.Any(), gomock.Any()).Return(network.SecurityGroup{}, &retry.Error{HTTPStatusCode: http.StatusNotFound}).AnyTimes() + } for name, sg := range test.existingSgs { + mockSGsClient.EXPECT().Get(gomock.Any(), "rg", name, gomock.Any()).Return(sg, nil).AnyTimes() err := az.SecurityGroupsClient.CreateOrUpdate(context.TODO(), "rg", name, sg, "") if err != nil { t.Fatalf("TestCase[%d] meets unexpected error: %v", i, err) @@ -1885,6 +1922,9 @@ func TestSafeDeletePublicIP(t *testing.T) { for i, test := range testCases { az := GetTestCloud(ctrl) + mockPIPsClient := az.PublicIPAddressesClient.(*mockpublicipclient.MockInterface) + mockPIPsClient.EXPECT().CreateOrUpdate(gomock.Any(), "rg", "pip1", gomock.Any()).Return(nil).AnyTimes() + mockPIPsClient.EXPECT().Delete(gomock.Any(), "rg", "pip1").Return(nil).AnyTimes() err := az.PublicIPAddressesClient.CreateOrUpdate(context.TODO(), "rg", "pip1", network.PublicIPAddress{ Name: to.StringPtr("pip1"), PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{ @@ -1897,6 +1937,9 @@ func TestSafeDeletePublicIP(t *testing.T) { t.Fatalf("TestCase[%d] meets unexpected error: %v", i, err) } service := getTestService("test1", v1.ProtocolTCP, nil, false, 80) + mockLBsClient := mockloadbalancerclient.NewMockInterface(ctrl) + mockLBsClient.EXPECT().CreateOrUpdate(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) + az.LoadBalancerClient = mockLBsClient rerr := az.safeDeletePublicIP(&service, "rg", test.pip, test.lb) assert.Equal(t, 0, len(*test.lb.FrontendIPConfigurations), "TestCase[%d]: %s", i, test.desc) assert.Equal(t, 0, len(*test.lb.LoadBalancingRules), "TestCase[%d]: %s", i, test.desc) @@ -2007,9 +2050,18 @@ func TestReconcilePublicIP(t *testing.T) { for i, test := range testCases { az := GetTestCloud(ctrl) + mockPIPsClient := az.PublicIPAddressesClient.(*mockpublicipclient.MockInterface) + mockPIPsClient.EXPECT().CreateOrUpdate(gomock.Any(), "rg", gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + mockPIPsClient.EXPECT().List(gomock.Any(), "rg").Return(test.existingPIPs, nil).AnyTimes() + if i == 2 { + mockPIPsClient.EXPECT().Get(gomock.Any(), "rg", "testCluster-atest1", gomock.Any()).Return(network.PublicIPAddress{}, &retry.Error{HTTPStatusCode: http.StatusNotFound}).Times(1) + mockPIPsClient.EXPECT().Get(gomock.Any(), "rg", "testCluster-atest1", gomock.Any()).Return(network.PublicIPAddress{ID: to.StringPtr("/subscriptions/subscription/resourceGroups/rg/providers/Microsoft.Network/publicIPAddresses/testCluster-atest1")}, nil).Times(1) + } service := getTestService("test1", v1.ProtocolTCP, nil, false, 80) service.Annotations = test.annotations for _, pip := range test.existingPIPs { + mockPIPsClient.EXPECT().Get(gomock.Any(), "rg", *pip.Name, gomock.Any()).Return(pip, nil).AnyTimes() + mockPIPsClient.EXPECT().Delete(gomock.Any(), "rg", *pip.Name).Return(nil).AnyTimes() err := az.PublicIPAddressesClient.CreateOrUpdate(context.TODO(), "rg", to.String(pip.Name), pip) if err != nil { t.Fatalf("TestCase[%d] meets unexpected error: %v", i, err) @@ -2152,6 +2204,43 @@ func TestEnsurePublicIPExists(t *testing.T) { for i, test := range testCases { az := GetTestCloud(ctrl) service := getTestService("test1", v1.ProtocolTCP, nil, test.isIPv6, 80) + mockPIPsClient := az.PublicIPAddressesClient.(*mockpublicipclient.MockInterface) + mockPIPsClient.EXPECT().CreateOrUpdate(gomock.Any(), "rg", gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + mockPIPsClient.EXPECT().Get(gomock.Any(), "rg", "pip1", gomock.Any()).DoAndReturn(func(ctx context.Context, resourceGroupName string, publicIPAddressName string, expand string) (network.PublicIPAddress, *retry.Error) { + var basicPIP network.PublicIPAddress + if len(test.existingPIPs) == 0 { + basicPIP = network.PublicIPAddress{ + Name: to.StringPtr("pip1"), + } + } else { + basicPIP = test.existingPIPs[0] + } + + basicPIP.ID = to.StringPtr("/subscriptions/subscription/resourceGroups/rg" + + "/providers/Microsoft.Network/publicIPAddresses/pip1") + + if basicPIP.PublicIPAddressPropertiesFormat == nil { + return basicPIP, nil + } + + if test.foundDNSLabelAnnotation { + if test.inputDNSLabel != "" { + basicPIP.DNSSettings.DomainNameLabel = &test.inputDNSLabel + } else { + basicPIP.DNSSettings = nil + } + } + + if test.isIPv6 { + basicPIP.PublicIPAddressPropertiesFormat.PublicIPAddressVersion = "IPv6" + basicPIP.PublicIPAllocationMethod = "Dynamic" + } else { + basicPIP.PublicIPAddressPropertiesFormat.PublicIPAddressVersion = "IPv4" + } + + return basicPIP, nil + }).AnyTimes() + for _, pip := range test.existingPIPs { err := az.PublicIPAddressesClient.CreateOrUpdate(context.TODO(), "rg", to.String(pip.Name), pip) if err != nil { @@ -2207,6 +2296,10 @@ func TestShouldUpdateLoadBalancer(t *testing.T) { for i, test := range testCases { az := GetTestCloud(ctrl) service := getTestService("test1", v1.ProtocolTCP, nil, false, 80) + setMockPublicIPs(az, ctrl, 1) + mockLBsClient := mockloadbalancerclient.NewMockInterface(ctrl) + az.LoadBalancerClient = mockLBsClient + mockLBsClient.EXPECT().CreateOrUpdate(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() if test.lbHasDeletionTimestamp { service.ObjectMeta.DeletionTimestamp = &metav1.Time{Time: time.Now()} } @@ -2218,7 +2311,7 @@ func TestShouldUpdateLoadBalancer(t *testing.T) { { Name: to.StringPtr("atest1"), FrontendIPConfigurationPropertiesFormat: &network.FrontendIPConfigurationPropertiesFormat{ - PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("id1")}, + PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr("testCluster-aservice1")}, }, }, }, @@ -2228,6 +2321,9 @@ func TestShouldUpdateLoadBalancer(t *testing.T) { if err != nil { t.Fatalf("TestCase[%d] meets unexpected error: %v", i, err) } + mockLBsClient.EXPECT().List(gomock.Any(), "rg").Return([]network.LoadBalancer{lb}, nil) + } else { + mockLBsClient.EXPECT().List(gomock.Any(), "rg").Return(nil, nil) } shouldUpdateLoadBalancer := az.shouldUpdateLoadBalancer(testClusterName, &service) assert.Equal(t, test.expectedOutput, shouldUpdateLoadBalancer, "TestCase[%d]: %s", i, test.desc) diff --git a/staging/src/k8s.io/legacy-cloud-providers/azure/azure_storage_test.go b/staging/src/k8s.io/legacy-cloud-providers/azure/azure_storage_test.go index 631c4dab82a..5bc240f52f9 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/azure/azure_storage_test.go +++ b/staging/src/k8s.io/legacy-cloud-providers/azure/azure_storage_test.go @@ -22,13 +22,20 @@ import ( "testing" "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2019-06-01/storage" + "github.com/golang/mock/gomock" + + "k8s.io/legacy-cloud-providers/azure/clients/fileclient/mockfileclient" + "k8s.io/legacy-cloud-providers/azure/clients/storageaccountclient/mockstorageaccountclient" ) func TestCreateFileShare(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + cloud := &Cloud{} - fake := newFakeStorageAccountClient() - cloud.StorageAccountClient = fake - cloud.FileClient = &fakeFileClient{} + mockFileClient := mockfileclient.NewMockInterface(ctrl) + mockFileClient.EXPECT().CreateFileShare(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + cloud.FileClient = mockFileClient name := "baz" sku := "sku" @@ -115,9 +122,11 @@ func TestCreateFileShare(t *testing.T) { } for _, test := range tests { - fake.Accounts = test.accounts - fake.Keys = test.keys - fake.Err = test.err + mockStorageAccountsClient := mockstorageaccountclient.NewMockInterface(ctrl) + cloud.StorageAccountClient = mockStorageAccountsClient + mockStorageAccountsClient.EXPECT().ListKeys(gomock.Any(), "rg", gomock.Any()).Return(test.keys, nil).AnyTimes() + mockStorageAccountsClient.EXPECT().ListByResourceGroup(gomock.Any(), "rg").Return(test.accounts, nil).AnyTimes() + mockStorageAccountsClient.EXPECT().Create(gomock.Any(), "rg", gomock.Any(), gomock.Any()).Return(nil).AnyTimes() account, key, err := cloud.CreateFileShare(test.name, test.acct, test.acctType, test.acctKind, "rg", test.loc, test.gb) if test.expectErr && err == nil { diff --git a/staging/src/k8s.io/legacy-cloud-providers/azure/azure_storageaccount_test.go b/staging/src/k8s.io/legacy-cloud-providers/azure/azure_storageaccount_test.go index 02bbdebca5b..79ef06026ea 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/azure/azure_storageaccount_test.go +++ b/staging/src/k8s.io/legacy-cloud-providers/azure/azure_storageaccount_test.go @@ -22,13 +22,17 @@ import ( "fmt" "testing" + "k8s.io/legacy-cloud-providers/azure/clients/storageaccountclient/mockstorageaccountclient" + "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2019-06-01/storage" + "github.com/golang/mock/gomock" ) func TestGetStorageAccessKeys(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + cloud := &Cloud{} - fake := newFakeStorageAccountClient() - cloud.StorageAccountClient = fake value := "foo bar" tests := []struct { @@ -63,9 +67,9 @@ func TestGetStorageAccessKeys(t *testing.T) { } for _, test := range tests { - expectedKey := test.expectedKey - fake.Keys = test.results - fake.Err = test.err + mockStorageAccountsClient := mockstorageaccountclient.NewMockInterface(ctrl) + cloud.StorageAccountClient = mockStorageAccountsClient + mockStorageAccountsClient.EXPECT().ListKeys(gomock.Any(), "rg", gomock.Any()).Return(test.results, nil).AnyTimes() key, err := cloud.GetStorageAccesskey("acct", "rg") if test.expectErr && err == nil { t.Errorf("Unexpected non-error") @@ -75,8 +79,8 @@ func TestGetStorageAccessKeys(t *testing.T) { t.Errorf("Unexpected error: %v", err) continue } - if key != expectedKey { - t.Errorf("expected: %s, saw %s", expectedKey, key) + if key != test.expectedKey { + t.Errorf("expected: %s, saw %s", test.expectedKey, key) } } } diff --git a/staging/src/k8s.io/legacy-cloud-providers/azure/azure_test.go b/staging/src/k8s.io/legacy-cloud-providers/azure/azure_test.go index 9b26ba2826c..3b9eeff627c 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/azure/azure_test.go +++ b/staging/src/k8s.io/legacy-cloud-providers/azure/azure_test.go @@ -26,6 +26,8 @@ import ( "strings" "testing" + cloudprovider "k8s.io/cloud-provider" + "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-01/compute" "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-06-01/network" "github.com/Azure/go-autorest/autorest/to" @@ -37,7 +39,12 @@ import ( "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/sets" servicehelpers "k8s.io/cloud-provider/service/helpers" + "k8s.io/legacy-cloud-providers/azure/clients/interfaceclient/mockinterfaceclient" + "k8s.io/legacy-cloud-providers/azure/clients/loadbalancerclient/mockloadbalancerclient" + "k8s.io/legacy-cloud-providers/azure/clients/publicipclient/mockpublicipclient" + "k8s.io/legacy-cloud-providers/azure/clients/securitygroupclient/mocksecuritygroupclient" "k8s.io/legacy-cloud-providers/azure/clients/subnetclient/mocksubnetclient" + "k8s.io/legacy-cloud-providers/azure/clients/vmclient/mockvmclient" "k8s.io/legacy-cloud-providers/azure/retry" ) @@ -73,8 +80,9 @@ func TestAddPort(t *testing.T) { defer ctrl.Finish() az := GetTestCloud(ctrl) - svc := getTestService("servicea", v1.ProtocolTCP, nil, false, 80) - clusterResources := getClusterResources(az, 1, 1) + svc := getTestService("service1", v1.ProtocolTCP, nil, false, 80) + clusterResources, expectedInterfaces, expectedVirtualMachines := getClusterResources(az, 1, 1) + setMockEnv(az, ctrl, expectedInterfaces, expectedVirtualMachines, 1) svc.Spec.Ports = append(svc.Spec.Ports, v1.ServicePort{ Name: fmt.Sprintf("port-udp-%d", 1234), @@ -83,6 +91,9 @@ func TestAddPort(t *testing.T) { NodePort: getBackendPort(1234), }) + expectedLBs := make([]network.LoadBalancer, 0) + setMockLBs(az, ctrl, &expectedLBs, "service", 1, 1, false) + lb, err := az.reconcileLoadBalancer(testClusterName, &svc, clusterResources.nodes, true /* wantLb */) if err != nil { t.Errorf("Unexpected error: %q", err) @@ -112,6 +123,155 @@ func TestLoadBalancerExternalServiceModeSelection(t *testing.T) { testLoadBalancerServiceAutoModeDeleteSelection(t, false) } +func setMockEnv(az *Cloud, ctrl *gomock.Controller, expectedInterfaces []network.Interface, expectedVirtualMachines []compute.VirtualMachine, serviceCount int, services ...v1.Service) { + mockInterfacesClient := mockinterfaceclient.NewMockInterface(ctrl) + az.InterfacesClient = mockInterfacesClient + for i := range expectedInterfaces { + mockInterfacesClient.EXPECT().Get(gomock.Any(), az.ResourceGroup, fmt.Sprintf("vm-%d", i), gomock.Any()).Return(expectedInterfaces[i], nil).AnyTimes() + mockInterfacesClient.EXPECT().CreateOrUpdate(gomock.Any(), az.ResourceGroup, fmt.Sprintf("vm-%d", i), gomock.Any()).Return(nil).AnyTimes() + } + + mockVirtualMachinesClient := mockvmclient.NewMockInterface(ctrl) + az.VirtualMachinesClient = mockVirtualMachinesClient + mockVirtualMachinesClient.EXPECT().List(gomock.Any(), az.ResourceGroup).Return(expectedVirtualMachines, nil).AnyTimes() + for i := range expectedVirtualMachines { + mockVirtualMachinesClient.EXPECT().Get(gomock.Any(), az.ResourceGroup, fmt.Sprintf("vm-%d", i), gomock.Any()).Return(expectedVirtualMachines[i], nil).AnyTimes() + } + + setMockPublicIPs(az, ctrl, serviceCount) + + sg := getTestSecurityGroup(az, services...) + setMockSecurityGroup(az, ctrl, sg) +} + +func setMockPublicIPs(az *Cloud, ctrl *gomock.Controller, serviceCount int) { + expectedPIPs := []network.PublicIPAddress{ + { + Name: to.StringPtr("testCluster-aservicea"), + Location: &az.Location, + PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{ + PublicIPAllocationMethod: network.Static, + PublicIPAddressVersion: network.IPv4, + IPAddress: to.StringPtr("1.2.3.4"), + }, + Tags: map[string]*string{ + serviceTagKey: to.StringPtr("default/servicea"), + clusterNameKey: &testClusterName, + }, + Sku: &network.PublicIPAddressSku{ + Name: network.PublicIPAddressSkuNameStandard, + }, + ID: to.StringPtr("testCluster-aservice1"), + }, + } + + mockPIPsClient := mockpublicipclient.NewMockInterface(ctrl) + az.PublicIPAddressesClient = mockPIPsClient + mockPIPsClient.EXPECT().CreateOrUpdate(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + mockPIPsClient.EXPECT().List(gomock.Any(), az.ResourceGroup).Return(expectedPIPs, nil).AnyTimes() + mockPIPsClient.EXPECT().List(gomock.Any(), gomock.Not(az.ResourceGroup)).Return(nil, nil).AnyTimes() + mockPIPsClient.EXPECT().Get(gomock.Any(), gomock.Not(az.ResourceGroup), gomock.Any(), gomock.Any()).Return(network.PublicIPAddress{}, &retry.Error{HTTPStatusCode: http.StatusNotFound, RawError: cloudprovider.InstanceNotFound}).AnyTimes() + + a := 'a' + for i := 1; i <= serviceCount; i++ { + expectedPIPs[0].Name = to.StringPtr(fmt.Sprintf("testCluster-aservice%d", i)) + expectedPIPs[0].Tags[serviceTagKey] = to.StringPtr(fmt.Sprintf("default/service%d", i)) + mockPIPsClient.EXPECT().Get(gomock.Any(), az.ResourceGroup, fmt.Sprintf("testCluster-aservice%d", i), gomock.Any()).Return(expectedPIPs[0], nil).AnyTimes() + mockPIPsClient.EXPECT().Delete(gomock.Any(), az.ResourceGroup, fmt.Sprintf("testCluster-aservice%d", i)).Return(nil).AnyTimes() + expectedPIPs[0].Name = to.StringPtr(fmt.Sprintf("testCluster-aservice%c", a)) + expectedPIPs[0].Tags[serviceTagKey] = to.StringPtr(fmt.Sprintf("default/service%c", a)) + mockPIPsClient.EXPECT().Get(gomock.Any(), az.ResourceGroup, fmt.Sprintf("testCluster-aservice%c", a), gomock.Any()).Return(expectedPIPs[0], nil).AnyTimes() + mockPIPsClient.EXPECT().Delete(gomock.Any(), az.ResourceGroup, fmt.Sprintf("testCluster-aservice%c", a)).Return(nil).AnyTimes() + a++ + } +} + +func setMockSecurityGroup(az *Cloud, ctrl *gomock.Controller, sgs ...*network.SecurityGroup) { + mockSGsClient := mocksecuritygroupclient.NewMockInterface(ctrl) + az.SecurityGroupsClient = mockSGsClient + for _, sg := range sgs { + mockSGsClient.EXPECT().Get(gomock.Any(), az.SecurityGroupResourceGroup, az.SecurityGroupName, gomock.Any()).Return(*sg, nil).AnyTimes() + } + mockSGsClient.EXPECT().CreateOrUpdate(gomock.Any(), az.SecurityGroupResourceGroup, az.SecurityGroupName, gomock.Any(), gomock.Any()).Return(nil).AnyTimes() +} + +func setMockLBs(az *Cloud, ctrl *gomock.Controller, expectedLBs *[]network.LoadBalancer, svcName string, lbCount, serviceIndex int, isInternal bool) string { + lbIndex := (serviceIndex - 1) % lbCount + expectedLBName := "" + if lbIndex == 0 { + expectedLBName = testClusterName + } else { + expectedLBName = fmt.Sprintf("as-%d", lbIndex) + } + if isInternal { + expectedLBName += "-internal" + } + + fullServiceName := strings.Replace(svcName, "-", "", -1) + + if lbIndex >= len(*expectedLBs) { + lb := network.LoadBalancer{ + Location: &az.Location, + LoadBalancerPropertiesFormat: &network.LoadBalancerPropertiesFormat{ + BackendAddressPools: &[]network.BackendAddressPool{ + { + Name: to.StringPtr("testCluster"), + }, + }, + }, + } + lb.Name = &expectedLBName + lb.LoadBalancingRules = &[]network.LoadBalancingRule{ + { + Name: to.StringPtr(fmt.Sprintf("a%s%d-TCP-8081", fullServiceName, serviceIndex)), + }, + } + fips := []network.FrontendIPConfiguration{ + { + Name: to.StringPtr(fmt.Sprintf("a%s%d", fullServiceName, serviceIndex)), + FrontendIPConfigurationPropertiesFormat: &network.FrontendIPConfigurationPropertiesFormat{ + PrivateIPAllocationMethod: "Dynamic", + PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr(fmt.Sprintf("testCluster-a%s%d", fullServiceName, serviceIndex))}, + }, + }, + } + if isInternal { + fips[0].Subnet = &network.Subnet{Name: to.StringPtr("subnet")} + } + lb.FrontendIPConfigurations = &fips + + *expectedLBs = append(*expectedLBs, lb) + } else { + *(*expectedLBs)[lbIndex].LoadBalancingRules = append(*(*expectedLBs)[lbIndex].LoadBalancingRules, network.LoadBalancingRule{ + Name: to.StringPtr(fmt.Sprintf("a%s%d-TCP-8081", fullServiceName, serviceIndex)), + }) + fip := network.FrontendIPConfiguration{ + Name: to.StringPtr(fmt.Sprintf("a%s%d", fullServiceName, serviceIndex)), + FrontendIPConfigurationPropertiesFormat: &network.FrontendIPConfigurationPropertiesFormat{ + PrivateIPAllocationMethod: "Dynamic", + PublicIPAddress: &network.PublicIPAddress{ID: to.StringPtr(fmt.Sprintf("testCluster-a%s%d", fullServiceName, serviceIndex))}, + }, + } + if isInternal { + fip.Subnet = &network.Subnet{Name: to.StringPtr("subnet")} + } + *(*expectedLBs)[lbIndex].FrontendIPConfigurations = append(*(*expectedLBs)[lbIndex].FrontendIPConfigurations, fip) + } + + mockLBsClient := mockloadbalancerclient.NewMockInterface(ctrl) + az.LoadBalancerClient = mockLBsClient + mockLBsClient.EXPECT().CreateOrUpdate(gomock.Any(), az.ResourceGroup, gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + for _, lb := range *expectedLBs { + mockLBsClient.EXPECT().Get(gomock.Any(), az.ResourceGroup, *lb.Name, gomock.Any()).Return((*expectedLBs)[lbIndex], nil).MaxTimes(2) + } + mockLBsClient.EXPECT().List(gomock.Any(), az.ResourceGroup).Return(*expectedLBs, nil).MaxTimes(3) + mockLBsClient.EXPECT().List(gomock.Any(), gomock.Not(az.ResourceGroup)).Return([]network.LoadBalancer{}, &retry.Error{HTTPStatusCode: http.StatusNotFound, RawError: cloudprovider.InstanceNotFound}).AnyTimes() + mockLBsClient.EXPECT().Get(gomock.Any(), gomock.Not(az.ResourceGroup), gomock.Any(), gomock.Any()).Return(network.LoadBalancer{}, &retry.Error{HTTPStatusCode: http.StatusNotFound, RawError: cloudprovider.InstanceNotFound}).AnyTimes() + mockLBsClient.EXPECT().Delete(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).MaxTimes(1) + + return expectedLBName +} + func testLoadBalancerServiceDefaultModeSelection(t *testing.T, isInternal bool) { ctrl := gomock.NewController(t) defer ctrl.Finish() @@ -121,8 +281,10 @@ func testLoadBalancerServiceDefaultModeSelection(t *testing.T, isInternal bool) const availabilitySetCount = 4 const serviceCount = 9 - clusterResources := getClusterResources(az, vmCount, availabilitySetCount) - getTestSecurityGroup(az) + clusterResources, expectedInterfaces, expectedVirtualMachines := getClusterResources(az, vmCount, availabilitySetCount) + setMockEnv(az, ctrl, expectedInterfaces, expectedVirtualMachines, serviceCount) + + expectedLBs := make([]network.LoadBalancer, 0) for index := 1; index <= serviceCount; index++ { svcName := fmt.Sprintf("service-%d", index) @@ -134,6 +296,8 @@ func testLoadBalancerServiceDefaultModeSelection(t *testing.T, isInternal bool) svc = getTestService(svcName, v1.ProtocolTCP, nil, false, 8081) } + expectedLBName := setMockLBs(az, ctrl, &expectedLBs, "service", 1, index, isInternal) + lbStatus, err := az.EnsureLoadBalancer(context.TODO(), testClusterName, &svc, clusterResources.nodes) if err != nil { t.Errorf("Unexpected error: %q", err) @@ -142,11 +306,6 @@ func testLoadBalancerServiceDefaultModeSelection(t *testing.T, isInternal bool) t.Errorf("Unexpected error: %s", svcName) } - expectedLBName := testClusterName - if isInternal { - expectedLBName = testClusterName + "-internal" - } - ctx, cancel := getContextWithCancel() defer cancel() result, _ := az.LoadBalancerClient.List(ctx, az.Config.ResourceGroup) @@ -179,8 +338,10 @@ func testLoadBalancerServiceAutoModeSelection(t *testing.T, isInternal bool) { const availabilitySetCount = 4 const serviceCount = 9 - clusterResources := getClusterResources(az, vmCount, availabilitySetCount) - getTestSecurityGroup(az) + clusterResources, expectedInterfaces, expectedVirtualMachines := getClusterResources(az, vmCount, availabilitySetCount) + setMockEnv(az, ctrl, expectedInterfaces, expectedVirtualMachines, serviceCount) + + expectedLBs := make([]network.LoadBalancer, 0) for index := 1; index <= serviceCount; index++ { svcName := fmt.Sprintf("service-%d", index) @@ -192,6 +353,9 @@ func testLoadBalancerServiceAutoModeSelection(t *testing.T, isInternal bool) { svc = getTestService(svcName, v1.ProtocolTCP, nil, false, 8081) } setLoadBalancerAutoModeAnnotation(&svc) + + setMockLBs(az, ctrl, &expectedLBs, "service", availabilitySetCount, index, isInternal) + lbStatus, err := az.EnsureLoadBalancer(context.TODO(), testClusterName, &svc, clusterResources.nodes) if err != nil { t.Errorf("Unexpected error: %q", err) @@ -243,11 +407,14 @@ func testLoadBalancerServicesSpecifiedSelection(t *testing.T, isInternal bool) { const availabilitySetCount = 4 const serviceCount = 9 - clusterResources := getClusterResources(az, vmCount, availabilitySetCount) - getTestSecurityGroup(az) + clusterResources, expectedInterfaces, expectedVirtualMachines := getClusterResources(az, vmCount, availabilitySetCount) + setMockEnv(az, ctrl, expectedInterfaces, expectedVirtualMachines, serviceCount) + + selectedAvailabilitySetName1 := getAvailabilitySetName(az, 0, availabilitySetCount) + selectedAvailabilitySetName2 := getAvailabilitySetName(az, 1, availabilitySetCount) + + expectedLBs := make([]network.LoadBalancer, 0) - selectedAvailabilitySetName1 := getAvailabilitySetName(az, 1, availabilitySetCount) - selectedAvailabilitySetName2 := getAvailabilitySetName(az, 2, availabilitySetCount) for index := 1; index <= serviceCount; index++ { svcName := fmt.Sprintf("service-%d", index) var svc v1.Service @@ -260,6 +427,8 @@ func testLoadBalancerServicesSpecifiedSelection(t *testing.T, isInternal bool) { lbMode := fmt.Sprintf("%s,%s", selectedAvailabilitySetName1, selectedAvailabilitySetName2) setLoadBalancerModeAnnotation(&svc, lbMode) + setMockLBs(az, ctrl, &expectedLBs, "service", 2, index, isInternal) + lbStatus, err := az.EnsureLoadBalancer(context.TODO(), testClusterName, &svc, clusterResources.nodes) if err != nil { t.Errorf("Unexpected error: %q", err) @@ -288,11 +457,13 @@ func testLoadBalancerMaxRulesServices(t *testing.T, isInternal bool) { const vmCount = 1 const availabilitySetCount = 1 - clusterResources := getClusterResources(az, vmCount, availabilitySetCount) - getTestSecurityGroup(az) + clusterResources, expectedInterfaces, expectedVirtualMachines := getClusterResources(az, vmCount, availabilitySetCount) + setMockEnv(az, ctrl, expectedInterfaces, expectedVirtualMachines, 1) az.Config.MaximumLoadBalancerRuleCount = 1 + expectedLBs := make([]network.LoadBalancer, 0) + for index := 1; index <= az.Config.MaximumLoadBalancerRuleCount; index++ { svcName := fmt.Sprintf("service-%d", index) var svc v1.Service @@ -303,6 +474,8 @@ func testLoadBalancerMaxRulesServices(t *testing.T, isInternal bool) { svc = getTestService(svcName, v1.ProtocolTCP, nil, false, 8081) } + setMockLBs(az, ctrl, &expectedLBs, "service", az.Config.MaximumLoadBalancerRuleCount, index, isInternal) + lbStatus, err := az.EnsureLoadBalancer(context.TODO(), testClusterName, &svc, clusterResources.nodes) if err != nil { t.Errorf("Unexpected error: %q", err) @@ -331,6 +504,21 @@ func testLoadBalancerMaxRulesServices(t *testing.T, isInternal bool) { } else { svc = getTestService(svcName, v1.ProtocolTCP, nil, false, 8081) } + //*expectedLBs[0].FrontendIPConfigurations = append(*expectedLBs[0].FrontendIPConfigurations, network.FrontendIPConfiguration{ + // Name: to.StringPtr(fmt.Sprintf("aservice%d", 2)), + // FrontendIPConfigurationPropertiesFormat: &network.FrontendIPConfigurationPropertiesFormat{ + // PrivateIPAllocationMethod: "Dynamic", + // }, + //}) + + mockLBsClient := mockloadbalancerclient.NewMockInterface(ctrl) + az.LoadBalancerClient = mockLBsClient + mockLBsClient.EXPECT().CreateOrUpdate(gomock.Any(), az.ResourceGroup, gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + for _, lb := range expectedLBs { + mockLBsClient.EXPECT().Get(gomock.Any(), az.ResourceGroup, *lb.Name, gomock.Any()).Return(expectedLBs[0], nil).MaxTimes(2) + } + mockLBsClient.EXPECT().List(gomock.Any(), az.ResourceGroup).Return(expectedLBs, nil).MaxTimes(2) + _, err := az.EnsureLoadBalancer(context.TODO(), testClusterName, &svc, clusterResources.nodes) if err == nil { t.Errorf("Expect any new service to fail as max limit in lb has reached") @@ -352,8 +540,10 @@ func testLoadBalancerServiceAutoModeDeleteSelection(t *testing.T, isInternal boo const availabilitySetCount = 4 const serviceCount = 9 - clusterResources := getClusterResources(az, vmCount, availabilitySetCount) - getTestSecurityGroup(az) + clusterResources, expectedInterfaces, expectedVirtualMachines := getClusterResources(az, vmCount, availabilitySetCount) + setMockEnv(az, ctrl, expectedInterfaces, expectedVirtualMachines, serviceCount) + + expectedLBs := make([]network.LoadBalancer, 0) for index := 1; index <= serviceCount; index++ { svcName := fmt.Sprintf("service-%d", index) @@ -365,6 +555,9 @@ func testLoadBalancerServiceAutoModeDeleteSelection(t *testing.T, isInternal boo svc = getTestService(svcName, v1.ProtocolTCP, nil, false, 8081) } setLoadBalancerAutoModeAnnotation(&svc) + + setMockLBs(az, ctrl, &expectedLBs, "service", availabilitySetCount, index, isInternal) + lbStatus, err := az.EnsureLoadBalancer(context.TODO(), testClusterName, &svc, clusterResources.nodes) if err != nil { t.Errorf("Unexpected error: %q", err) @@ -386,6 +579,15 @@ func testLoadBalancerServiceAutoModeDeleteSelection(t *testing.T, isInternal boo setLoadBalancerAutoModeAnnotation(&svc) + mockLBsClient := mockloadbalancerclient.NewMockInterface(ctrl) + az.LoadBalancerClient = mockLBsClient + mockLBsClient.EXPECT().CreateOrUpdate(gomock.Any(), az.ResourceGroup, gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + for _, lb := range expectedLBs { + mockLBsClient.EXPECT().Get(gomock.Any(), az.ResourceGroup, *lb.Name, gomock.Any()).Return(expectedLBs[0], nil).MaxTimes(2) + } + mockLBsClient.EXPECT().Delete(gomock.Any(), az.ResourceGroup, gomock.Any()).Return(nil).AnyTimes() + mockLBsClient.EXPECT().List(gomock.Any(), az.ResourceGroup).Return(expectedLBs, nil).MaxTimes(3) + // expected is MIN(index, availabilitySetCount) expectedNumOfLB := int(math.Min(float64(index), float64(availabilitySetCount))) ctx, cancel := getContextWithCancel() @@ -400,6 +602,10 @@ func testLoadBalancerServiceAutoModeDeleteSelection(t *testing.T, isInternal boo if err != nil { t.Errorf("Unexpected error: %q", err) } + + if index <= availabilitySetCount { + expectedLBs = expectedLBs[:len(expectedLBs)-1] + } } } @@ -409,10 +615,15 @@ func TestReconcileLoadBalancerAddServiceOnInternalSubnet(t *testing.T) { defer ctrl.Finish() az := GetTestCloud(ctrl) - clusterResources := getClusterResources(az, 1, 1) - svc := getInternalTestService("svc1", 80) + clusterResources, expectedInterfaces, expectedVirtualMachines := getClusterResources(az, 1, 1) + setMockEnv(az, ctrl, expectedInterfaces, expectedVirtualMachines, 1) + + svc := getInternalTestService("service1", 80) validateTestSubnet(t, az, &svc) + expectedLBs := make([]network.LoadBalancer, 0) + setMockLBs(az, ctrl, &expectedLBs, "service", 1, 1, true) + lb, err := az.reconcileLoadBalancer(testClusterName, &svc, clusterResources.nodes, true /* wantLb */) if err != nil { t.Errorf("Unexpected error: %q", err) @@ -433,13 +644,16 @@ func TestReconcileSecurityGroupFromAnyDestinationAddressPrefixToLoadBalancerIP(t az := GetTestCloud(ctrl) svc1 := getTestService("serviceea", v1.ProtocolTCP, nil, false, 80) svc1.Spec.LoadBalancerIP = "192.168.0.0" - getTestSecurityGroup(az) + + sg := getTestSecurityGroup(az) + setMockSecurityGroup(az, ctrl, sg) + // Simulate a pre-Kubernetes 1.8 NSG, where we do not specify the destination address prefix _, err := az.reconcileSecurityGroup(testClusterName, &svc1, to.StringPtr(""), true) if err != nil { t.Errorf("Unexpected error: %q", err) } - sg, err := az.reconcileSecurityGroup(testClusterName, &svc1, to.StringPtr(svc1.Spec.LoadBalancerIP), true) + sg, err = az.reconcileSecurityGroup(testClusterName, &svc1, to.StringPtr(svc1.Spec.LoadBalancerIP), true) if err != nil { t.Errorf("Unexpected error: %q", err) } @@ -453,7 +667,10 @@ func TestReconcileSecurityGroupDynamicLoadBalancerIP(t *testing.T) { az := GetTestCloud(ctrl) svc1 := getTestService("servicea", v1.ProtocolTCP, nil, false, 80) svc1.Spec.LoadBalancerIP = "" - getTestSecurityGroup(az) + + sg := getTestSecurityGroup(az) + setMockSecurityGroup(az, ctrl, sg) + dynamicallyAssignedIP := "192.168.0.0" sg, err := az.reconcileSecurityGroup(testClusterName, &svc1, to.StringPtr(dynamicallyAssignedIP), true) if err != nil { @@ -468,10 +685,15 @@ func TestReconcileLoadBalancerAddServicesOnMultipleSubnets(t *testing.T) { defer ctrl.Finish() az := GetTestCloud(ctrl) - clusterResources := getClusterResources(az, 1, 1) + clusterResources, expectedInterfaces, expectedVirtualMachines := getClusterResources(az, 1, 1) + setMockEnv(az, ctrl, expectedInterfaces, expectedVirtualMachines, 1) + svc1 := getTestService("service1", v1.ProtocolTCP, nil, false, 8081) svc2 := getInternalTestService("service2", 8081) + expectedLBs := make([]network.LoadBalancer, 0) + setMockLBs(az, ctrl, &expectedLBs, "service", 1, 1, false) + // svc1 is using LB without "-internal" suffix lb, err := az.reconcileLoadBalancer(testClusterName, &svc1, clusterResources.nodes, true /* wantLb */) if err != nil { @@ -488,6 +710,9 @@ func TestReconcileLoadBalancerAddServicesOnMultipleSubnets(t *testing.T) { // Internal and External service cannot reside on the same LB resource validateTestSubnet(t, az, &svc2) + expectedLBs = make([]network.LoadBalancer, 0) + setMockLBs(az, ctrl, &expectedLBs, "service", 1, 2, true) + // svc2 is using LB with "-internal" suffix lb, err = az.reconcileLoadBalancer(testClusterName, &svc2, nil, true /* wantLb */) if err != nil { @@ -508,10 +733,15 @@ func TestReconcileLoadBalancerEditServiceSubnet(t *testing.T) { defer ctrl.Finish() az := GetTestCloud(ctrl) - clusterResources := getClusterResources(az, 1, 1) + clusterResources, expectedInterfaces, expectedVirtualMachines := getClusterResources(az, 1, 1) + setMockEnv(az, ctrl, expectedInterfaces, expectedVirtualMachines, 1) + svc := getInternalTestService("service1", 8081) validateTestSubnet(t, az, &svc) + expectedLBs := make([]network.LoadBalancer, 0) + setMockLBs(az, ctrl, &expectedLBs, "service", 1, 1, true) + lb, err := az.reconcileLoadBalancer(testClusterName, &svc, clusterResources.nodes, true /* wantLb */) if err != nil { t.Errorf("Unexpected error reconciling initial svc: %q", err) @@ -519,9 +749,12 @@ func TestReconcileLoadBalancerEditServiceSubnet(t *testing.T) { validateLoadBalancer(t, lb, svc) - svc.Annotations[ServiceAnnotationLoadBalancerInternalSubnet] = "NewSubnet" + svc.Annotations[ServiceAnnotationLoadBalancerInternalSubnet] = "subnet" validateTestSubnet(t, az, &svc) + expectedLBs = make([]network.LoadBalancer, 0) + setMockLBs(az, ctrl, &expectedLBs, "service", 1, 1, true) + lb, err = az.reconcileLoadBalancer(testClusterName, &svc, clusterResources.nodes, true /* wantLb */) if err != nil { t.Errorf("Unexpected error reconciling edits to svc: %q", err) @@ -540,11 +773,16 @@ func TestReconcileLoadBalancerNodeHealth(t *testing.T) { defer ctrl.Finish() az := GetTestCloud(ctrl) - clusterResources := getClusterResources(az, 1, 1) - svc := getTestService("servicea", v1.ProtocolTCP, nil, false, 80) + clusterResources, expectedInterfaces, expectedVirtualMachines := getClusterResources(az, 1, 1) + setMockEnv(az, ctrl, expectedInterfaces, expectedVirtualMachines, 1) + + svc := getTestService("service1", v1.ProtocolTCP, nil, false, 80) svc.Spec.ExternalTrafficPolicy = v1.ServiceExternalTrafficPolicyTypeLocal svc.Spec.HealthCheckNodePort = int32(32456) + expectedLBs := make([]network.LoadBalancer, 0) + setMockLBs(az, ctrl, &expectedLBs, "service", 1, 1, false) + lb, err := az.reconcileLoadBalancer(testClusterName, &svc, clusterResources.nodes, true /* wantLb */) if err != nil { t.Errorf("Unexpected error: %q", err) @@ -564,14 +802,27 @@ func TestReconcileLoadBalancerRemoveService(t *testing.T) { defer ctrl.Finish() az := GetTestCloud(ctrl) - clusterResources := getClusterResources(az, 1, 1) - svc := getTestService("servicea", v1.ProtocolTCP, nil, false, 80, 443) + clusterResources, expectedInterfaces, expectedVirtualMachines := getClusterResources(az, 1, 1) + setMockEnv(az, ctrl, expectedInterfaces, expectedVirtualMachines, 1) + + svc := getTestService("service1", v1.ProtocolTCP, nil, false, 80, 443) + + expectedLBs := make([]network.LoadBalancer, 0) + setMockLBs(az, ctrl, &expectedLBs, "service", 1, 1, false) _, err := az.reconcileLoadBalancer(testClusterName, &svc, clusterResources.nodes, true /* wantLb */) if err != nil { t.Errorf("Unexpected error: %q", err) } + expectedLBs[0].FrontendIPConfigurations = &[]network.FrontendIPConfiguration{} + mockLBsClient := mockloadbalancerclient.NewMockInterface(ctrl) + az.LoadBalancerClient = mockLBsClient + mockLBsClient.EXPECT().CreateOrUpdate(gomock.Any(), az.ResourceGroup, gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + mockLBsClient.EXPECT().Get(gomock.Any(), az.ResourceGroup, *expectedLBs[0].Name, gomock.Any()).Return(expectedLBs[0], nil).MaxTimes(2) + mockLBsClient.EXPECT().List(gomock.Any(), az.ResourceGroup).Return(expectedLBs, nil).MaxTimes(3) + mockLBsClient.EXPECT().Delete(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) + lb, err := az.reconcileLoadBalancer(testClusterName, &svc, clusterResources.nodes, false /* wantLb */) if err != nil { t.Errorf("Unexpected error: %q", err) @@ -591,8 +842,13 @@ func TestReconcileLoadBalancerRemoveAllPortsRemovesFrontendConfig(t *testing.T) defer ctrl.Finish() az := GetTestCloud(ctrl) - clusterResources := getClusterResources(az, 1, 1) - svc := getTestService("servicea", v1.ProtocolTCP, nil, false, 80) + clusterResources, expectedInterfaces, expectedVirtualMachines := getClusterResources(az, 1, 1) + setMockEnv(az, ctrl, expectedInterfaces, expectedVirtualMachines, 1) + + svc := getTestService("service1", v1.ProtocolTCP, nil, false, 80) + + expectedLBs := make([]network.LoadBalancer, 0) + setMockLBs(az, ctrl, &expectedLBs, "service", 1, 1, false) lb, err := az.reconcileLoadBalancer(testClusterName, &svc, clusterResources.nodes, true /* wantLb */) if err != nil { @@ -600,7 +856,16 @@ func TestReconcileLoadBalancerRemoveAllPortsRemovesFrontendConfig(t *testing.T) } validateLoadBalancer(t, lb, svc) - svcUpdated := getTestService("servicea", v1.ProtocolTCP, nil, false) + svcUpdated := getTestService("service1", v1.ProtocolTCP, nil, false) + + expectedLBs[0].FrontendIPConfigurations = &[]network.FrontendIPConfiguration{} + mockLBsClient := mockloadbalancerclient.NewMockInterface(ctrl) + az.LoadBalancerClient = mockLBsClient + mockLBsClient.EXPECT().CreateOrUpdate(gomock.Any(), az.ResourceGroup, gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + mockLBsClient.EXPECT().Get(gomock.Any(), az.ResourceGroup, *expectedLBs[0].Name, gomock.Any()).Return(expectedLBs[0], nil).MaxTimes(2) + mockLBsClient.EXPECT().List(gomock.Any(), az.ResourceGroup).Return(expectedLBs, nil).MaxTimes(3) + mockLBsClient.EXPECT().Delete(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) + lb, err = az.reconcileLoadBalancer(testClusterName, &svcUpdated, clusterResources.nodes, false /* wantLb*/) if err != nil { t.Errorf("Unexpected error: %q", err) @@ -620,15 +885,20 @@ func TestReconcileLoadBalancerRemovesPort(t *testing.T) { defer ctrl.Finish() az := GetTestCloud(ctrl) - clusterResources := getClusterResources(az, 1, 1) + clusterResources, expectedInterfaces, expectedVirtualMachines := getClusterResources(az, 1, 1) + setMockEnv(az, ctrl, expectedInterfaces, expectedVirtualMachines, 1) - svc := getTestService("servicea", v1.ProtocolTCP, nil, false, 80, 443) + expectedLBs := make([]network.LoadBalancer, 0) + setMockLBs(az, ctrl, &expectedLBs, "service", 1, 1, false) + svc := getTestService("service1", v1.ProtocolTCP, nil, false, 80, 443) _, err := az.reconcileLoadBalancer(testClusterName, &svc, clusterResources.nodes, true /* wantLb */) if err != nil { t.Errorf("Unexpected error: %q", err) } - svcUpdated := getTestService("servicea", v1.ProtocolTCP, nil, false, 80) + expectedLBs = make([]network.LoadBalancer, 0) + setMockLBs(az, ctrl, &expectedLBs, "service", 1, 1, false) + svcUpdated := getTestService("service1", v1.ProtocolTCP, nil, false, 80) lb, err := az.reconcileLoadBalancer(testClusterName, &svcUpdated, clusterResources.nodes, true /* wantLb */) if err != nil { t.Errorf("Unexpected error: %q", err) @@ -643,15 +913,22 @@ func TestReconcileLoadBalancerMultipleServices(t *testing.T) { defer ctrl.Finish() az := GetTestCloud(ctrl) - clusterResources := getClusterResources(az, 1, 1) - svc1 := getTestService("servicea", v1.ProtocolTCP, nil, false, 80, 443) - svc2 := getTestService("serviceb", v1.ProtocolTCP, nil, false, 80) + clusterResources, expectedInterfaces, expectedVirtualMachines := getClusterResources(az, 1, 1) + setMockEnv(az, ctrl, expectedInterfaces, expectedVirtualMachines, 2) + + svc1 := getTestService("service1", v1.ProtocolTCP, nil, false, 80, 443) + svc2 := getTestService("service2", v1.ProtocolTCP, nil, false, 80) + + expectedLBs := make([]network.LoadBalancer, 0) + setMockLBs(az, ctrl, &expectedLBs, "service", 1, 1, false) _, err := az.reconcileLoadBalancer(testClusterName, &svc1, clusterResources.nodes, true /* wantLb */) if err != nil { t.Errorf("Unexpected error: %q", err) } + setMockLBs(az, ctrl, &expectedLBs, "service", 1, 2, false) + updatedLoadBalancer, err := az.reconcileLoadBalancer(testClusterName, &svc2, clusterResources.nodes, true /* wantLb */) if err != nil { t.Errorf("Unexpected error: %q", err) @@ -674,15 +951,41 @@ func TestServiceDefaultsToNoSessionPersistence(t *testing.T) { defer ctrl.Finish() az := GetTestCloud(ctrl) - svc := getTestService("service-sa-omitted", v1.ProtocolTCP, nil, false, 7170) - clusterResources := getClusterResources(az, 1, 1) + svc := getTestService("service-sa-omitted1", v1.ProtocolTCP, nil, false, 8081) + clusterResources, expectedInterfaces, expectedVirtualMachines := getClusterResources(az, 1, 1) + setMockEnv(az, ctrl, expectedInterfaces, expectedVirtualMachines, 1) + + expectedLBs := make([]network.LoadBalancer, 0) + setMockLBs(az, ctrl, &expectedLBs, "service-sa-omitted", 1, 1, false) + + expectedPIP := network.PublicIPAddress{ + Name: to.StringPtr("testCluster-aservicesaomitted1"), + Location: &az.Location, + PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{ + PublicIPAllocationMethod: network.Static, + PublicIPAddressVersion: network.IPv4, + }, + Tags: map[string]*string{ + serviceTagKey: to.StringPtr("aservicesaomitted1"), + clusterNameKey: &testClusterName, + }, + Sku: &network.PublicIPAddressSku{ + Name: network.PublicIPAddressSkuNameStandard, + }, + ID: to.StringPtr("testCluster-aservicesaomitted1"), + } + + mockPIPsClient := mockpublicipclient.NewMockInterface(ctrl) + az.PublicIPAddressesClient = mockPIPsClient + mockPIPsClient.EXPECT().CreateOrUpdate(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + mockPIPsClient.EXPECT().Get(gomock.Any(), az.ResourceGroup, "testCluster-aservicesaomitted1", gomock.Any()).Return(expectedPIP, nil).AnyTimes() lb, err := az.reconcileLoadBalancer(testClusterName, &svc, clusterResources.nodes, true /* wantLb */) if err != nil { t.Errorf("Unexpected error reconciling svc1: %q", err) } validateLoadBalancer(t, lb, svc) - lbRule, err := findLBRuleForPort(*lb.LoadBalancingRules, 7170) + lbRule, err := findLBRuleForPort(*lb.LoadBalancingRules, 8081) if err != nil { t.Error(err) } @@ -697,9 +1000,35 @@ func TestServiceRespectsNoSessionAffinity(t *testing.T) { defer ctrl.Finish() az := GetTestCloud(ctrl) - svc := getTestService("service-sa-none", v1.ProtocolTCP, nil, false, 7170) + svc := getTestService("service-sa-none", v1.ProtocolTCP, nil, false, 8081) svc.Spec.SessionAffinity = v1.ServiceAffinityNone - clusterResources := getClusterResources(az, 1, 1) + clusterResources, expectedInterfaces, expectedVirtualMachines := getClusterResources(az, 1, 1) + setMockEnv(az, ctrl, expectedInterfaces, expectedVirtualMachines, 1) + + expectedLBs := make([]network.LoadBalancer, 0) + setMockLBs(az, ctrl, &expectedLBs, "service-sa-none", 1, 1, false) + + expectedPIP := network.PublicIPAddress{ + Name: to.StringPtr("testCluster-aservicesanone"), + Location: &az.Location, + PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{ + PublicIPAllocationMethod: network.Static, + PublicIPAddressVersion: network.IPv4, + }, + Tags: map[string]*string{ + serviceTagKey: to.StringPtr("aservicesanone"), + clusterNameKey: &testClusterName, + }, + Sku: &network.PublicIPAddressSku{ + Name: network.PublicIPAddressSkuNameStandard, + }, + ID: to.StringPtr("testCluster-aservicesanone"), + } + + mockPIPsClient := mockpublicipclient.NewMockInterface(ctrl) + az.PublicIPAddressesClient = mockPIPsClient + mockPIPsClient.EXPECT().CreateOrUpdate(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + mockPIPsClient.EXPECT().Get(gomock.Any(), az.ResourceGroup, "testCluster-aservicesanone", gomock.Any()).Return(expectedPIP, nil).AnyTimes() lb, err := az.reconcileLoadBalancer(testClusterName, &svc, clusterResources.nodes, true /* wantLb */) if err != nil { @@ -708,7 +1037,7 @@ func TestServiceRespectsNoSessionAffinity(t *testing.T) { validateLoadBalancer(t, lb, svc) - lbRule, err := findLBRuleForPort(*lb.LoadBalancingRules, 7170) + lbRule, err := findLBRuleForPort(*lb.LoadBalancingRules, 8081) if err != nil { t.Error(err) } @@ -723,9 +1052,35 @@ func TestServiceRespectsClientIPSessionAffinity(t *testing.T) { defer ctrl.Finish() az := GetTestCloud(ctrl) - svc := getTestService("service-sa-clientip", v1.ProtocolTCP, nil, false, 7170) + svc := getTestService("service-sa-clientip", v1.ProtocolTCP, nil, false, 8081) svc.Spec.SessionAffinity = v1.ServiceAffinityClientIP - clusterResources := getClusterResources(az, 1, 1) + clusterResources, expectedInterfaces, expectedVirtualMachines := getClusterResources(az, 1, 1) + setMockEnv(az, ctrl, expectedInterfaces, expectedVirtualMachines, 1) + + expectedLBs := make([]network.LoadBalancer, 0) + setMockLBs(az, ctrl, &expectedLBs, "service-sa-clientip", 1, 1, false) + + expectedPIP := network.PublicIPAddress{ + Name: to.StringPtr("testCluster-aservicesaclientip"), + Location: &az.Location, + PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{ + PublicIPAllocationMethod: network.Static, + PublicIPAddressVersion: network.IPv4, + }, + Tags: map[string]*string{ + serviceTagKey: to.StringPtr("aservicesaclientip"), + clusterNameKey: &testClusterName, + }, + Sku: &network.PublicIPAddressSku{ + Name: network.PublicIPAddressSkuNameStandard, + }, + ID: to.StringPtr("testCluster-aservicesaclientip"), + } + + mockPIPsClient := mockpublicipclient.NewMockInterface(ctrl) + az.PublicIPAddressesClient = mockPIPsClient + mockPIPsClient.EXPECT().CreateOrUpdate(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil).AnyTimes() + mockPIPsClient.EXPECT().Get(gomock.Any(), az.ResourceGroup, "testCluster-aservicesaclientip", gomock.Any()).Return(expectedPIP, nil).AnyTimes() lb, err := az.reconcileLoadBalancer(testClusterName, &svc, clusterResources.nodes, true /* wantLb */) if err != nil { @@ -734,7 +1089,7 @@ func TestServiceRespectsClientIPSessionAffinity(t *testing.T) { validateLoadBalancer(t, lb, svc) - lbRule, err := findLBRuleForPort(*lb.LoadBalancingRules, 7170) + lbRule, err := findLBRuleForPort(*lb.LoadBalancingRules, 8081) if err != nil { t.Error(err) } @@ -750,8 +1105,11 @@ func TestReconcileSecurityGroupNewServiceAddsPort(t *testing.T) { az := GetTestCloud(ctrl) getTestSecurityGroup(az) - svc1 := getTestService("servicea", v1.ProtocolTCP, nil, false, 80) - clusterResources := getClusterResources(az, 1, 1) + svc1 := getTestService("service1", v1.ProtocolTCP, nil, false, 80) + clusterResources, expectedInterfaces, expectedVirtualMachines := getClusterResources(az, 1, 1) + setMockEnv(az, ctrl, expectedInterfaces, expectedVirtualMachines, 1) + expectedLBs := make([]network.LoadBalancer, 0) + setMockLBs(az, ctrl, &expectedLBs, "service", 1, 1, false) lb, _ := az.reconcileLoadBalancer(testClusterName, &svc1, clusterResources.nodes, true) lbStatus, _ := az.getServiceLoadBalancerStatus(&svc1, lb) @@ -769,9 +1127,13 @@ func TestReconcileSecurityGroupNewInternalServiceAddsPort(t *testing.T) { az := GetTestCloud(ctrl) getTestSecurityGroup(az) - svc1 := getInternalTestService("serviceea", 80) + svc1 := getInternalTestService("service1", 80) validateTestSubnet(t, az, &svc1) - clusterResources := getClusterResources(az, 1, 1) + clusterResources, expectedInterfaces, expectedVirtualMachines := getClusterResources(az, 1, 1) + setMockEnv(az, ctrl, expectedInterfaces, expectedVirtualMachines, 1) + + expectedLBs := make([]network.LoadBalancer, 0) + setMockLBs(az, ctrl, &expectedLBs, "service", 1, 1, true) lb, _ := az.reconcileLoadBalancer(testClusterName, &svc1, clusterResources.nodes, true) lbStatus, _ := az.getServiceLoadBalancerStatus(&svc1, lb) @@ -788,9 +1150,13 @@ func TestReconcileSecurityGroupRemoveService(t *testing.T) { defer ctrl.Finish() az := GetTestCloud(ctrl) - service1 := getTestService("servicea", v1.ProtocolTCP, nil, false, 81) - service2 := getTestService("serviceb", v1.ProtocolTCP, nil, false, 82) - clusterResources := getClusterResources(az, 1, 1) + service1 := getTestService("service1", v1.ProtocolTCP, nil, false, 81) + service2 := getTestService("service2", v1.ProtocolTCP, nil, false, 82) + clusterResources, expectedInterfaces, expectedVirtualMachines := getClusterResources(az, 1, 1) + setMockEnv(az, ctrl, expectedInterfaces, expectedVirtualMachines, 2, service1, service2) + + expectedLBs := make([]network.LoadBalancer, 0) + setMockLBs(az, ctrl, &expectedLBs, "service", 1, 1, true) lb, _ := az.reconcileLoadBalancer(testClusterName, &service1, clusterResources.nodes, true) az.reconcileLoadBalancer(testClusterName, &service2, clusterResources.nodes, true) @@ -813,11 +1179,14 @@ func TestReconcileSecurityGroupRemoveServiceRemovesPort(t *testing.T) { defer ctrl.Finish() az := GetTestCloud(ctrl) - svc := getTestService("servicea", v1.ProtocolTCP, nil, false, 80, 443) - clusterResources := getClusterResources(az, 1, 1) + svc := getTestService("service1", v1.ProtocolTCP, nil, false, 80, 443) + clusterResources, expectedInterfaces, expectedVirtualMachines := getClusterResources(az, 1, 1) + setMockEnv(az, ctrl, expectedInterfaces, expectedVirtualMachines, 1) getTestSecurityGroup(az, svc) - svcUpdated := getTestService("servicea", v1.ProtocolTCP, nil, false, 80) + svcUpdated := getTestService("service1", v1.ProtocolTCP, nil, false, 80) + expectedLBs := make([]network.LoadBalancer, 0) + setMockLBs(az, ctrl, &expectedLBs, "service", 1, 1, true) lb, _ := az.reconcileLoadBalancer(testClusterName, &svc, clusterResources.nodes, true) lbStatus, _ := az.getServiceLoadBalancerStatus(&svc, lb) @@ -834,14 +1203,17 @@ func TestReconcileSecurityWithSourceRanges(t *testing.T) { defer ctrl.Finish() az := GetTestCloud(ctrl) - svc := getTestService("servicea", v1.ProtocolTCP, nil, false, 80, 443) + svc := getTestService("service1", v1.ProtocolTCP, nil, false, 80, 443) svc.Spec.LoadBalancerSourceRanges = []string{ "192.168.0.0/24", "10.0.0.0/32", } - clusterResources := getClusterResources(az, 1, 1) + clusterResources, expectedInterfaces, expectedVirtualMachines := getClusterResources(az, 1, 1) + setMockEnv(az, ctrl, expectedInterfaces, expectedVirtualMachines, 1) getTestSecurityGroup(az, svc) + expectedLBs := make([]network.LoadBalancer, 0) + setMockLBs(az, ctrl, &expectedLBs, "service", 1, 1, false) lb, _ := az.reconcileLoadBalancer(testClusterName, &svc, clusterResources.nodes, true) lbStatus, _ := az.getServiceLoadBalancerStatus(&svc, lb) @@ -863,28 +1235,40 @@ func TestReconcileSecurityGroupEtagMismatch(t *testing.T) { cachedSG.Etag = to.StringPtr("1111111-0000-0000-0000-000000000000") az.nsgCache.Set(to.String(sg.Name), &cachedSG) - svc1 := getTestService("servicea", v1.ProtocolTCP, nil, false, 80) - clusterResources := getClusterResources(az, 1, 1) + svc1 := getTestService("service1", v1.ProtocolTCP, nil, false, 80) + clusterResources, expectedInterfaces, expectedVirtualMachines := getClusterResources(az, 1, 1) + setMockEnv(az, ctrl, expectedInterfaces, expectedVirtualMachines, 1) + mockSGsClient := mocksecuritygroupclient.NewMockInterface(ctrl) + az.SecurityGroupsClient = mockSGsClient + mockSGsClient.EXPECT().Get(gomock.Any(), az.SecurityGroupResourceGroup, az.SecurityGroupName, gomock.Any()).Return(cachedSG, nil).AnyTimes() + expectedError := &retry.Error{ + HTTPStatusCode: http.StatusPreconditionFailed, + RawError: errPreconditionFailedEtagMismatch, + } + mockSGsClient.EXPECT().CreateOrUpdate(gomock.Any(), az.SecurityGroupResourceGroup, az.SecurityGroupName, gomock.Any(), gomock.Any()).Return(expectedError).AnyTimes() + + expectedLBs := make([]network.LoadBalancer, 0) + setMockLBs(az, ctrl, &expectedLBs, "service", 1, 1, true) + lb, _ := az.reconcileLoadBalancer(testClusterName, &svc1, clusterResources.nodes, true) lbStatus, _ := az.getServiceLoadBalancerStatus(&svc1, lb) newSG, err := az.reconcileSecurityGroup(testClusterName, &svc1, &lbStatus.Ingress[0].IP, true /* wantLb */) assert.Nil(t, newSG) assert.NotNil(t, err) - expectedError := &retry.Error{ - HTTPStatusCode: http.StatusPreconditionFailed, - RawError: errPreconditionFailedEtagMismatch, - } + assert.Equal(t, expectedError.Error(), err) } -func TestReconcilePuablicIPWithNewService(t *testing.T) { +func TestReconcilePublicIPWithNewService(t *testing.T) { ctrl := gomock.NewController(t) defer ctrl.Finish() az := GetTestCloud(ctrl) svc := getTestService("servicea", v1.ProtocolTCP, nil, false, 80, 443) + setMockPublicIPs(az, ctrl, 1) + pip, err := az.reconcilePublicIP(testClusterName, &svc, "", true /* wantLb*/) if err != nil { t.Errorf("Unexpected error: %q", err) @@ -909,6 +1293,8 @@ func TestReconcilePublicIPRemoveService(t *testing.T) { az := GetTestCloud(ctrl) svc := getTestService("servicea", v1.ProtocolTCP, nil, false, 80, 443) + setMockPublicIPs(az, ctrl, 1) + pip, err := az.reconcilePublicIP(testClusterName, &svc, "", true /* wantLb*/) if err != nil { t.Errorf("Unexpected error: %q", err) @@ -932,6 +1318,8 @@ func TestReconcilePublicIPWithInternalService(t *testing.T) { az := GetTestCloud(ctrl) svc := getInternalTestService("servicea", 80, 443) + setMockPublicIPs(az, ctrl, 1) + pip, err := az.reconcilePublicIP(testClusterName, &svc, "", true /* wantLb*/) if err != nil { t.Errorf("Unexpected error: %q", err) @@ -947,6 +1335,8 @@ func TestReconcilePublicIPWithExternalAndInternalSwitch(t *testing.T) { az := GetTestCloud(ctrl) svc := getInternalTestService("servicea", 80, 443) + setMockPublicIPs(az, ctrl, 1) + pip, err := az.reconcilePublicIP(testClusterName, &svc, "", true /* wantLb*/) if err != nil { t.Errorf("Unexpected error: %q", err) @@ -1021,9 +1411,9 @@ type ClusterResources struct { availabilitySetNames []string } -func getClusterResources(az *Cloud, vmCount int, availabilitySetCount int) (clusterResources *ClusterResources) { +func getClusterResources(az *Cloud, vmCount int, availabilitySetCount int) (clusterResources *ClusterResources, expectedInterfaces []network.Interface, expectedVirtualMachines []compute.VirtualMachine) { if vmCount < availabilitySetCount { - return nil + return nil, expectedInterfaces, expectedVirtualMachines } clusterResources = &ClusterResources{} clusterResources.nodes = []*v1.Node{} @@ -1052,9 +1442,7 @@ func getClusterResources(az *Cloud, vmCount int, availabilitySetCount int) (clus }, }, } - ctx, cancel := getContextWithCancel() - defer cancel() - az.InterfacesClient.CreateOrUpdate(ctx, az.Config.ResourceGroup, nicName, newNIC) + expectedInterfaces = append(expectedInterfaces, newNIC) // create vm asID := az.getAvailabilitySetID(az.Config.ResourceGroup, asName) @@ -1074,10 +1462,8 @@ func getClusterResources(az *Cloud, vmCount int, availabilitySetCount int) (clus }, }, } + expectedVirtualMachines = append(expectedVirtualMachines, newVM) - vmCtx, vmCancel := getContextWithCancel() - defer vmCancel() - az.VirtualMachinesClient.CreateOrUpdate(vmCtx, az.Config.ResourceGroup, vmName, newVM, "") // add to kubernetes newNode := &v1.Node{ ObjectMeta: metav1.ObjectMeta{ @@ -1090,7 +1476,7 @@ func getClusterResources(az *Cloud, vmCount int, availabilitySetCount int) (clus clusterResources.nodes = append(clusterResources.nodes, newNode) } - return clusterResources + return clusterResources, expectedInterfaces, expectedVirtualMachines } func getBackendPort(port int32) int32 { @@ -1189,15 +1575,6 @@ func getTestSecurityGroup(az *Cloud, services ...v1.Service) *network.SecurityGr }, } - ctx, cancel := getContextWithCancel() - defer cancel() - az.SecurityGroupsClient.CreateOrUpdate( - ctx, - az.SecurityGroupResourceGroup, - az.SecurityGroupName, - sg, - "") - return &sg } @@ -1839,11 +2216,12 @@ func TestIfServiceSpecifiesSharedRuleAndRuleDoesNotExistItIsCreated(t *testing.T defer ctrl.Finish() az := GetTestCloud(ctrl) - svc := getTestService("servicesr", v1.ProtocolTCP, nil, false, 80) + svc := getTestService("servicea", v1.ProtocolTCP, nil, false, 80) svc.Spec.LoadBalancerIP = "192.168.77.88" svc.Annotations[ServiceAnnotationSharedSecurityRule] = "true" - getTestSecurityGroup(az) + sg := getTestSecurityGroup(az) + setMockSecurityGroup(az, ctrl, sg) sg, err := az.reconcileSecurityGroup(testClusterName, &svc, to.StringPtr(svc.Spec.LoadBalancerIP), true) if err != nil { @@ -1902,6 +2280,7 @@ func TestIfServiceSpecifiesSharedRuleAndRuleExistsThenTheServicesPortAndAddressA }, }, } + setMockSecurityGroup(az, ctrl, sg) sg, err := az.reconcileSecurityGroup(testClusterName, &svc, to.StringPtr(svc.Spec.LoadBalancerIP), true) if err != nil { @@ -1947,14 +2326,15 @@ func TestIfServicesSpecifySharedRuleButDifferentPortsThenSeparateRulesAreCreated expectedRuleName1 := "shared-TCP-4444-Internet" expectedRuleName2 := "shared-TCP-8888-Internet" - getTestSecurityGroup(az) + sg := getTestSecurityGroup(az) + setMockSecurityGroup(az, ctrl, sg) _, err := az.reconcileSecurityGroup(testClusterName, &svc1, to.StringPtr(svc1.Spec.LoadBalancerIP), true) if err != nil { t.Errorf("Unexpected error adding svc1: %q", err) } - sg, err := az.reconcileSecurityGroup(testClusterName, &svc2, to.StringPtr(svc2.Spec.LoadBalancerIP), true) + sg, err = az.reconcileSecurityGroup(testClusterName, &svc2, to.StringPtr(svc2.Spec.LoadBalancerIP), true) if err != nil { t.Errorf("Unexpected error adding svc2: %q", err) } @@ -2018,14 +2398,15 @@ func TestIfServicesSpecifySharedRuleButDifferentProtocolsThenSeparateRulesAreCre expectedRuleName1 := "shared-TCP-4444-Internet" expectedRuleName2 := "shared-UDP-4444-Internet" - getTestSecurityGroup(az) + sg := getTestSecurityGroup(az) + setMockSecurityGroup(az, ctrl, sg) _, err := az.reconcileSecurityGroup(testClusterName, &svc1, to.StringPtr(svc1.Spec.LoadBalancerIP), true) if err != nil { t.Errorf("Unexpected error adding svc1: %q", err) } - sg, err := az.reconcileSecurityGroup(testClusterName, &svc2, to.StringPtr(svc2.Spec.LoadBalancerIP), true) + sg, err = az.reconcileSecurityGroup(testClusterName, &svc2, to.StringPtr(svc2.Spec.LoadBalancerIP), true) if err != nil { t.Errorf("Unexpected error adding svc2: %q", err) } @@ -2089,14 +2470,15 @@ func TestIfServicesSpecifySharedRuleButDifferentSourceAddressesThenSeparateRules expectedRuleName1 := "shared-TCP-80-192.168.12.0_24" expectedRuleName2 := "shared-TCP-80-192.168.34.0_24" - getTestSecurityGroup(az) + sg := getTestSecurityGroup(az) + setMockSecurityGroup(az, ctrl, sg) _, err := az.reconcileSecurityGroup(testClusterName, &svc1, to.StringPtr(svc1.Spec.LoadBalancerIP), true) if err != nil { t.Errorf("Unexpected error adding svc1: %q", err) } - sg, err := az.reconcileSecurityGroup(testClusterName, &svc2, to.StringPtr(svc2.Spec.LoadBalancerIP), true) + sg, err = az.reconcileSecurityGroup(testClusterName, &svc2, to.StringPtr(svc2.Spec.LoadBalancerIP), true) if err != nil { t.Errorf("Unexpected error adding svc2: %q", err) } @@ -2164,7 +2546,8 @@ func TestIfServicesSpecifySharedRuleButSomeAreOnDifferentPortsThenRulesAreSepara expectedRuleName13 := "shared-TCP-4444-Internet" expectedRuleName2 := "shared-TCP-8888-Internet" - getTestSecurityGroup(az) + sg := getTestSecurityGroup(az) + setMockSecurityGroup(az, ctrl, sg) _, err := az.reconcileSecurityGroup(testClusterName, &svc1, to.StringPtr(svc1.Spec.LoadBalancerIP), true) if err != nil { @@ -2176,7 +2559,7 @@ func TestIfServicesSpecifySharedRuleButSomeAreOnDifferentPortsThenRulesAreSepara t.Errorf("Unexpected error adding svc2: %q", err) } - sg, err := az.reconcileSecurityGroup(testClusterName, &svc3, to.StringPtr(svc3.Spec.LoadBalancerIP), true) + sg, err = az.reconcileSecurityGroup(testClusterName, &svc3, to.StringPtr(svc3.Spec.LoadBalancerIP), true) if err != nil { t.Errorf("Unexpected error adding svc3: %q", err) } @@ -2261,14 +2644,15 @@ func TestIfServiceSpecifiesSharedRuleAndServiceIsDeletedThenTheServicesPortAndAd expectedRuleName := "shared-TCP-80-Internet" - getTestSecurityGroup(az) + sg := getTestSecurityGroup(az) + setMockSecurityGroup(az, ctrl, sg) _, err := az.reconcileSecurityGroup(testClusterName, &svc1, to.StringPtr(svc1.Spec.LoadBalancerIP), true) if err != nil { t.Errorf("Unexpected error adding svc1: %q", err) } - sg, err := az.reconcileSecurityGroup(testClusterName, &svc2, to.StringPtr(svc2.Spec.LoadBalancerIP), true) + sg, err = az.reconcileSecurityGroup(testClusterName, &svc2, to.StringPtr(svc2.Spec.LoadBalancerIP), true) if err != nil { t.Errorf("Unexpected error adding svc2: %q", err) } @@ -2323,7 +2707,8 @@ func TestIfSomeServicesShareARuleAndOneIsDeletedItIsRemovedFromTheRightRule(t *t expectedRuleName13 := "shared-TCP-4444-Internet" expectedRuleName2 := "shared-TCP-8888-Internet" - getTestSecurityGroup(az) + sg := getTestSecurityGroup(az) + setMockSecurityGroup(az, ctrl, sg) _, err := az.reconcileSecurityGroup(testClusterName, &svc1, to.StringPtr(svc1.Spec.LoadBalancerIP), true) if err != nil { @@ -2335,7 +2720,7 @@ func TestIfSomeServicesShareARuleAndOneIsDeletedItIsRemovedFromTheRightRule(t *t t.Errorf("Unexpected error adding svc2: %q", err) } - sg, err := az.reconcileSecurityGroup(testClusterName, &svc3, to.StringPtr(svc3.Spec.LoadBalancerIP), true) + sg, err = az.reconcileSecurityGroup(testClusterName, &svc3, to.StringPtr(svc3.Spec.LoadBalancerIP), true) if err != nil { t.Errorf("Unexpected error adding svc3: %q", err) } @@ -2432,7 +2817,8 @@ func TestIfServiceSpecifiesSharedRuleAndLastServiceIsDeletedThenRuleIsDeleted(t expectedRuleName13 := "shared-TCP-4444-Internet" expectedRuleName2 := "shared-TCP-8888-Internet" - getTestSecurityGroup(az) + sg := getTestSecurityGroup(az) + setMockSecurityGroup(az, ctrl, sg) _, err := az.reconcileSecurityGroup(testClusterName, &svc1, to.StringPtr(svc1.Spec.LoadBalancerIP), true) if err != nil { @@ -2444,7 +2830,7 @@ func TestIfServiceSpecifiesSharedRuleAndLastServiceIsDeletedThenRuleIsDeleted(t t.Errorf("Unexpected error adding svc2: %q", err) } - sg, err := az.reconcileSecurityGroup(testClusterName, &svc3, to.StringPtr(svc3.Spec.LoadBalancerIP), true) + sg, err = az.reconcileSecurityGroup(testClusterName, &svc3, to.StringPtr(svc3.Spec.LoadBalancerIP), true) if err != nil { t.Errorf("Unexpected error adding svc3: %q", err) } @@ -2524,7 +2910,8 @@ func TestCanCombineSharedAndPrivateRulesInSameGroup(t *testing.T) { expectedRuleName4 := az.getSecurityRuleName(&svc4, v1.ServicePort{Port: 4444, Protocol: v1.ProtocolTCP}, "Internet") expectedRuleName5 := az.getSecurityRuleName(&svc5, v1.ServicePort{Port: 8888, Protocol: v1.ProtocolTCP}, "Internet") - getTestSecurityGroup(az) + sg := getTestSecurityGroup(az) + setMockSecurityGroup(az, ctrl, sg) _, err := az.reconcileSecurityGroup(testClusterName, &svc1, to.StringPtr(svc1.Spec.LoadBalancerIP), true) if err != nil { @@ -2546,7 +2933,7 @@ func TestCanCombineSharedAndPrivateRulesInSameGroup(t *testing.T) { t.Errorf("Unexpected error adding svc4: %q", err) } - sg, err := az.reconcileSecurityGroup(testClusterName, &svc5, to.StringPtr(svc5.Spec.LoadBalancerIP), true) + sg, err = az.reconcileSecurityGroup(testClusterName, &svc5, to.StringPtr(svc5.Spec.LoadBalancerIP), true) if err != nil { t.Errorf("Unexpected error adding svc4: %q", err) } diff --git a/staging/src/k8s.io/legacy-cloud-providers/azure/azure_vmss.go b/staging/src/k8s.io/legacy-cloud-providers/azure/azure_vmss.go index d4e195a6827..f70ad7e535f 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/azure/azure_vmss.go +++ b/staging/src/k8s.io/legacy-cloud-providers/azure/azure_vmss.go @@ -413,11 +413,11 @@ func (ss *scaleSet) GetIPByNodeName(nodeName string) (string, string, error) { if len(matches) == 7 { resourceGroupName := matches[1] virtualMachineScaleSetName := matches[2] - virtualmachineIndex := matches[3] + virtualMachineIndex := matches[3] networkInterfaceName := matches[4] IPConfigurationName := matches[5] publicIPAddressName := matches[6] - pip, existsPip, err := ss.getVMSSPublicIPAddress(resourceGroupName, virtualMachineScaleSetName, virtualmachineIndex, networkInterfaceName, IPConfigurationName, publicIPAddressName) + pip, existsPip, err := ss.getVMSSPublicIPAddress(resourceGroupName, virtualMachineScaleSetName, virtualMachineIndex, networkInterfaceName, IPConfigurationName, publicIPAddressName) if err != nil { klog.Errorf("ss.getVMSSPublicIPAddress() failed with error: %v", err) return "", "", err diff --git a/staging/src/k8s.io/legacy-cloud-providers/azure/azure_vmss_cache_test.go b/staging/src/k8s.io/legacy-cloud-providers/azure/azure_vmss_cache_test.go index c4dcc21a3a1..d01a86caee6 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/azure/azure_vmss_cache_test.go +++ b/staging/src/k8s.io/legacy-cloud-providers/azure/azure_vmss_cache_test.go @@ -19,7 +19,6 @@ limitations under the License. package azure import ( - "context" "sync" "testing" @@ -27,8 +26,11 @@ import ( "github.com/Azure/go-autorest/autorest/to" "github.com/golang/mock/gomock" "github.com/stretchr/testify/assert" + cloudprovider "k8s.io/cloud-provider" azcache "k8s.io/legacy-cloud-providers/azure/cache" + "k8s.io/legacy-cloud-providers/azure/clients/vmssclient/mockvmssclient" + "k8s.io/legacy-cloud-providers/azure/clients/vmssvmclient/mockvmssvmclient" ) func TestExtractVmssVMName(t *testing.T) { @@ -81,16 +83,23 @@ func TestVMSSVMCache(t *testing.T) { vmssName := "vmss" vmList := []string{"vmssee6c2000000", "vmssee6c2000001", "vmssee6c2000002"} - ss, err := newTestScaleSet(ctrl, vmssName, "", 0, vmList) + ss, err := newTestScaleSet(ctrl) assert.NoError(t, err) + mockVMSSClient := mockvmssclient.NewMockInterface(ctrl) + mockVMSSVMClient := mockvmssvmclient.NewMockInterface(ctrl) + ss.cloud.VirtualMachineScaleSetsClient = mockVMSSClient + ss.cloud.VirtualMachineScaleSetVMsClient = mockVMSSVMClient + + expectedScaleSet := compute.VirtualMachineScaleSet{Name: &vmssName} + mockVMSSClient.EXPECT().List(gomock.Any(), gomock.Any()).Return([]compute.VirtualMachineScaleSet{expectedScaleSet}, nil).AnyTimes() + + expectedVMs, _, _ := buildTestVirtualMachineEnv(ss.cloud, vmssName, "", 0, vmList, "") + mockVMSSVMClient.EXPECT().List(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(expectedVMs, nil).AnyTimes() + // validate getting VMSS VM via cache. - virtualMachines, rerr := ss.VirtualMachineScaleSetVMsClient.List( - context.Background(), "rg", "vmss", "") - assert.Nil(t, rerr) - assert.Equal(t, 3, len(virtualMachines)) - for i := range virtualMachines { - vm := virtualMachines[i] + for i := range expectedVMs { + vm := expectedVMs[i] vmName := to.String(vm.OsProfile.ComputerName) ssName, instanceID, realVM, err := ss.getVmssVM(vmName, azcache.CacheReadTypeDefault) assert.Nil(t, err) @@ -100,7 +109,7 @@ func TestVMSSVMCache(t *testing.T) { } // validate deleteCacheForNode(). - vm := virtualMachines[0] + vm := expectedVMs[0] vmName := to.String(vm.OsProfile.ComputerName) err = ss.deleteCacheForNode(vmName) assert.NoError(t, err) @@ -112,7 +121,7 @@ func TestVMSSVMCache(t *testing.T) { _, ok := cachedVirtualMachines.Load(vmName) assert.Equal(t, false, ok) - // the VM should be get back after another cache refresh. + // the VM should be back after another cache refresh. ssName, instanceID, realVM, err := ss.getVmssVM(vmName, azcache.CacheReadTypeDefault) assert.NoError(t, err) assert.Equal(t, "vmss", ssName) @@ -126,15 +135,22 @@ func TestVMSSVMCacheWithDeletingNodes(t *testing.T) { vmssName := "vmss" vmList := []string{"vmssee6c2000000", "vmssee6c2000001", "vmssee6c2000002"} - ss, err := newTestScaleSetWithState(ctrl, vmssName, "", 0, vmList, "Deleting") + ss, err := newTestScaleSetWithState(ctrl) assert.NoError(t, err) - virtualMachines, rerr := ss.VirtualMachineScaleSetVMsClient.List( - context.Background(), "rg", "vmss", "") - assert.Nil(t, rerr) - assert.Equal(t, 3, len(virtualMachines)) - for i := range virtualMachines { - vm := virtualMachines[i] + mockVMSSClient := mockvmssclient.NewMockInterface(ctrl) + mockVMSSVMClient := mockvmssvmclient.NewMockInterface(ctrl) + ss.cloud.VirtualMachineScaleSetsClient = mockVMSSClient + ss.cloud.VirtualMachineScaleSetVMsClient = mockVMSSVMClient + + expectedScaleSet := compute.VirtualMachineScaleSet{Name: &vmssName} + mockVMSSClient.EXPECT().List(gomock.Any(), gomock.Any()).Return([]compute.VirtualMachineScaleSet{expectedScaleSet}, nil).AnyTimes() + + expectedVMs, _, _ := buildTestVirtualMachineEnv(ss.cloud, vmssName, "", 0, vmList, string(compute.ProvisioningStateDeleting)) + mockVMSSVMClient.EXPECT().List(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(expectedVMs, nil).AnyTimes() + + for i := range expectedVMs { + vm := expectedVMs[i] vmName := to.String(vm.OsProfile.ComputerName) assert.Equal(t, vm.ProvisioningState, to.StringPtr(string(compute.ProvisioningStateDeleting))) diff --git a/staging/src/k8s.io/legacy-cloud-providers/azure/azure_vmss_test.go b/staging/src/k8s.io/legacy-cloud-providers/azure/azure_vmss_test.go index 24c63d5596d..fa4d473bff3 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/azure/azure_vmss_test.go +++ b/staging/src/k8s.io/legacy-cloud-providers/azure/azure_vmss_test.go @@ -23,6 +23,15 @@ import ( "strings" "testing" + cloudprovider "k8s.io/cloud-provider" + azcache "k8s.io/legacy-cloud-providers/azure/cache" + "k8s.io/legacy-cloud-providers/azure/clients/interfaceclient/mockinterfaceclient" + "k8s.io/legacy-cloud-providers/azure/clients/publicipclient/mockpublicipclient" + "k8s.io/legacy-cloud-providers/azure/clients/vmclient/mockvmclient" + "k8s.io/legacy-cloud-providers/azure/clients/vmssclient/mockvmssclient" + "k8s.io/legacy-cloud-providers/azure/clients/vmssvmclient/mockvmssvmclient" + "k8s.io/legacy-cloud-providers/azure/retry" + "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-01/compute" "github.com/Azure/azure-sdk-for-go/services/network/mgmt/2019-06-01/network" "github.com/Azure/go-autorest/autorest/to" @@ -35,13 +44,12 @@ const ( fakePublicIP = "10.10.10.10" ) -func newTestScaleSet(ctrl *gomock.Controller, scaleSetName, zone string, faultDomain int32, vmList []string) (*scaleSet, error) { - return newTestScaleSetWithState(ctrl, scaleSetName, zone, faultDomain, vmList, "Running") +func newTestScaleSet(ctrl *gomock.Controller) (*scaleSet, error) { + return newTestScaleSetWithState(ctrl) } -func newTestScaleSetWithState(ctrl *gomock.Controller, scaleSetName, zone string, faultDomain int32, vmList []string, state string) (*scaleSet, error) { +func newTestScaleSetWithState(ctrl *gomock.Controller) (*scaleSet, error) { cloud := GetTestCloud(ctrl) - setTestVirtualMachineCloud(cloud, scaleSetName, zone, faultDomain, vmList, state) ss, err := newScaleSet(cloud) if err != nil { return nil, err @@ -50,37 +58,18 @@ func newTestScaleSetWithState(ctrl *gomock.Controller, scaleSetName, zone string return ss.(*scaleSet), nil } -func setTestVirtualMachineCloud(ss *Cloud, scaleSetName, zone string, faultDomain int32, vmList []string, state string) { - virtualMachineScaleSetsClient := newFakeVirtualMachineScaleSetsClient() - virtualMachineScaleSetVMsClient := newFakeVirtualMachineScaleSetVMsClient() - publicIPAddressesClient := newFakeAzurePIPClient("rg") - interfaceClient := newFakeAzureInterfacesClient() +func buildTestVirtualMachineEnv(ss *Cloud, scaleSetName, zone string, faultDomain int32, vmList []string, state string) ([]compute.VirtualMachineScaleSetVM, network.Interface, network.PublicIPAddress) { + expectedVMSSVMs := make([]compute.VirtualMachineScaleSetVM, 0) + expectedInterface := network.Interface{} + expectedPIP := network.PublicIPAddress{} - // set test scale sets. - scaleSets := make(map[string]map[string]compute.VirtualMachineScaleSet) - scaleSets["rg"] = map[string]compute.VirtualMachineScaleSet{ - scaleSetName: { - Name: &scaleSetName, - }, - } - virtualMachineScaleSetsClient.setFakeStore(scaleSets) - - testInterfaces := map[string]map[string]network.Interface{ - "rg": make(map[string]network.Interface), - } - testPIPs := map[string]map[string]network.PublicIPAddress{ - "rg": make(map[string]network.PublicIPAddress), - } - ssVMs := map[string]map[string]compute.VirtualMachineScaleSetVM{ - "rg": make(map[string]compute.VirtualMachineScaleSetVM), - } for i := range vmList { nodeName := vmList[i] ID := fmt.Sprintf("/subscriptions/script/resourceGroups/rg/providers/Microsoft.Compute/virtualMachineScaleSets/%s/virtualMachines/%d", scaleSetName, i) interfaceID := fmt.Sprintf("/subscriptions/script/resourceGroups/rg/providers/Microsoft.Compute/virtualMachineScaleSets/%s/virtualMachines/%d/networkInterfaces/%s", scaleSetName, i, nodeName) - publicAddressID := fmt.Sprintf("/subscriptions/script/resourceGroups/rg/providers/Microsoft.Compute/virtualMachineScaleSets/%s/virtualMachines/%d/networkInterfaces/%s/ipConfigurations/ipconfig1/publicIPAddresses/%s", scaleSetName, i, nodeName, nodeName) instanceID := fmt.Sprintf("%d", i) vmName := fmt.Sprintf("%s_%s", scaleSetName, instanceID) + publicAddressID := fmt.Sprintf("/subscriptions/script/resourceGroups/rg/providers/Microsoft.Compute/virtualMachineScaleSets/%s/virtualMachines/%d/networkInterfaces/%s/ipConfigurations/ipconfig1/publicIPAddresses/%s", scaleSetName, i, nodeName, nodeName) // set vmss virtual machine. networkInterfaces := []compute.NetworkInterfaceReference{ @@ -128,10 +117,9 @@ func setTestVirtualMachineCloud(ss *Cloud, scaleSetName, zone string, faultDomai zones := []string{zone} vmssVM.Zones = &zones } - ssVMs["rg"][vmName] = vmssVM // set interfaces. - testInterfaces["rg"][nodeName] = network.Interface{ + expectedInterface = network.Interface{ ID: &interfaceID, InterfacePropertiesFormat: &network.InterfacePropertiesFormat{ IPConfigurations: &[]network.InterfaceIPConfiguration{ @@ -149,21 +137,17 @@ func setTestVirtualMachineCloud(ss *Cloud, scaleSetName, zone string, faultDomai } // set public IPs. - testPIPs["rg"][nodeName] = network.PublicIPAddress{ + expectedPIP = network.PublicIPAddress{ ID: to.StringPtr(publicAddressID), PublicIPAddressPropertiesFormat: &network.PublicIPAddressPropertiesFormat{ IPAddress: to.StringPtr(fakePublicIP), }, } - } - virtualMachineScaleSetVMsClient.setFakeStore(ssVMs) - interfaceClient.setFakeStore(testInterfaces) - publicIPAddressesClient.setFakeStore(testPIPs) - ss.VirtualMachineScaleSetsClient = virtualMachineScaleSetsClient - ss.VirtualMachineScaleSetVMsClient = virtualMachineScaleSetVMsClient - ss.InterfacesClient = interfaceClient - ss.PublicIPAddressesClient = publicIPAddressesClient + expectedVMSSVMs = append(expectedVMSSVMs, vmssVM) + } + + return expectedVMSSVMs, expectedInterface, expectedPIP } func TestGetScaleSetVMInstanceID(t *testing.T) { @@ -231,9 +215,23 @@ func TestGetInstanceIDByNodeName(t *testing.T) { } for _, test := range testCases { - ss, err := newTestScaleSet(ctrl, test.scaleSet, "", 0, test.vmList) + ss, err := newTestScaleSet(ctrl) assert.NoError(t, err, test.description) + mockVMSSClient := mockvmssclient.NewMockInterface(ctrl) + mockVMSSVMClient := mockvmssvmclient.NewMockInterface(ctrl) + ss.cloud.VirtualMachineScaleSetsClient = mockVMSSClient + ss.cloud.VirtualMachineScaleSetVMsClient = mockVMSSVMClient + + expectedScaleSet := compute.VirtualMachineScaleSet{Name: &test.scaleSet} + mockVMSSClient.EXPECT().List(gomock.Any(), gomock.Any()).Return([]compute.VirtualMachineScaleSet{expectedScaleSet}, nil).AnyTimes() + + expectedVMs, _, _ := buildTestVirtualMachineEnv(ss.cloud, test.scaleSet, "", 0, test.vmList, "") + mockVMSSVMClient.EXPECT().List(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(expectedVMs, nil).AnyTimes() + + mockVMsClient := ss.cloud.VirtualMachinesClient.(*mockvmclient.MockInterface) + mockVMsClient.EXPECT().List(gomock.Any(), gomock.Any()).Return([]compute.VirtualMachine{}, nil).AnyTimes() + real, err := ss.GetInstanceIDByNodeName(test.nodeName) if test.expectError { assert.Error(t, err, test.description) @@ -302,10 +300,22 @@ func TestGetZoneByNodeName(t *testing.T) { if test.location != "" { cloud.Location = test.location } - setTestVirtualMachineCloud(cloud, test.scaleSet, test.zone, test.faultDomain, test.vmList, "Running") - scaleset, err := newScaleSet(cloud) + ss, err := newTestScaleSet(ctrl) assert.NoError(t, err, test.description) - ss := scaleset.(*scaleSet) + + mockVMSSClient := mockvmssclient.NewMockInterface(ctrl) + mockVMSSVMClient := mockvmssvmclient.NewMockInterface(ctrl) + ss.cloud.VirtualMachineScaleSetsClient = mockVMSSClient + ss.cloud.VirtualMachineScaleSetVMsClient = mockVMSSVMClient + + expectedScaleSet := compute.VirtualMachineScaleSet{Name: &test.scaleSet} + mockVMSSClient.EXPECT().List(gomock.Any(), gomock.Any()).Return([]compute.VirtualMachineScaleSet{expectedScaleSet}, nil).AnyTimes() + + expectedVMs, _, _ := buildTestVirtualMachineEnv(ss.cloud, test.scaleSet, test.zone, test.faultDomain, test.vmList, "") + mockVMSSVMClient.EXPECT().List(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(expectedVMs, nil).AnyTimes() + + mockVMsClient := ss.cloud.VirtualMachinesClient.(*mockvmclient.MockInterface) + mockVMsClient.EXPECT().List(gomock.Any(), gomock.Any()).Return([]compute.VirtualMachine{}, nil).AnyTimes() real, err := ss.GetZoneByNodeName(test.nodeName) if test.expectError { @@ -348,9 +358,29 @@ func TestGetIPByNodeName(t *testing.T) { } for _, test := range testCases { - ss, err := newTestScaleSet(ctrl, test.scaleSet, "", 0, test.vmList) + ss, err := newTestScaleSet(ctrl) assert.NoError(t, err, test.description) + mockVMSSClient := mockvmssclient.NewMockInterface(ctrl) + mockVMSSVMClient := mockvmssvmclient.NewMockInterface(ctrl) + mockInterfaceClient := mockinterfaceclient.NewMockInterface(ctrl) + mockPIPClient := mockpublicipclient.NewMockInterface(ctrl) + ss.cloud.VirtualMachineScaleSetsClient = mockVMSSClient + ss.cloud.VirtualMachineScaleSetVMsClient = mockVMSSVMClient + ss.cloud.InterfacesClient = mockInterfaceClient + ss.cloud.PublicIPAddressesClient = mockPIPClient + + expectedScaleSet := compute.VirtualMachineScaleSet{Name: &test.scaleSet} + mockVMSSClient.EXPECT().List(gomock.Any(), gomock.Any()).Return([]compute.VirtualMachineScaleSet{expectedScaleSet}, nil).AnyTimes() + + expectedVMs, expectedInterface, expectedPIP := buildTestVirtualMachineEnv(ss.cloud, test.scaleSet, "", 0, test.vmList, "") + mockVMSSVMClient.EXPECT().List(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(expectedVMs, nil).AnyTimes() + mockInterfaceClient.EXPECT().GetVirtualMachineScaleSetNetworkInterface(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(expectedInterface, nil).AnyTimes() + mockPIPClient.EXPECT().GetVirtualMachineScaleSetPublicIPAddress(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(expectedPIP, nil).AnyTimes() + + mockVMsClient := ss.cloud.VirtualMachinesClient.(*mockvmclient.MockInterface) + mockVMsClient.EXPECT().List(gomock.Any(), gomock.Any()).Return([]compute.VirtualMachine{}, nil).AnyTimes() + privateIP, publicIP, err := ss.GetIPByNodeName(test.nodeName) if test.expectError { assert.Error(t, err, test.description) @@ -400,9 +430,20 @@ func TestGetNodeNameByIPConfigurationID(t *testing.T) { } for _, test := range testCases { - ss, err := newTestScaleSet(ctrl, test.scaleSet, "", 0, test.vmList) + ss, err := newTestScaleSet(ctrl) assert.NoError(t, err, test.description) + mockVMSSClient := mockvmssclient.NewMockInterface(ctrl) + mockVMSSVMClient := mockvmssvmclient.NewMockInterface(ctrl) + ss.cloud.VirtualMachineScaleSetsClient = mockVMSSClient + ss.cloud.VirtualMachineScaleSetVMsClient = mockVMSSVMClient + + expectedScaleSet := compute.VirtualMachineScaleSet{Name: &test.scaleSet} + mockVMSSClient.EXPECT().List(gomock.Any(), gomock.Any()).Return([]compute.VirtualMachineScaleSet{expectedScaleSet}, nil).AnyTimes() + + expectedVMs, _, _ := buildTestVirtualMachineEnv(ss.cloud, test.scaleSet, "", 0, test.vmList, "") + mockVMSSVMClient.EXPECT().List(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(expectedVMs, nil).AnyTimes() + nodeName, err := ss.getNodeNameByIPConfigurationID(test.ipConfigurationID) if test.expectError { assert.Error(t, err, test.description) @@ -451,3 +492,105 @@ func TestExtractResourceGroupByVMSSNicID(t *testing.T) { assert.Equal(t, test.expected, resourceGroup, test.description) } } + +func TestGetVMSS(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + testCases := []struct { + description string + existedVMSSName string + vmssName string + vmssListError *retry.Error + expectedErr error + }{ + { + description: "getVMSS should return the correct VMSS", + existedVMSSName: "vmss-1", + vmssName: "vmss-1", + }, + { + description: "getVMSS should return cloudprovider.InstanceNotFound if there's no matching VMSS", + existedVMSSName: "vmss-1", + vmssName: "vmss-2", + expectedErr: cloudprovider.InstanceNotFound, + }, + { + description: "getVMSS should report an error if there's something wrong during an api call", + existedVMSSName: "vmss-1", + vmssName: "vmss-1", + vmssListError: &retry.Error{RawError: fmt.Errorf("error during vmss list")}, + expectedErr: fmt.Errorf("Retriable: false, RetryAfter: 0s, HTTPStatusCode: 0, RawError: error during vmss list"), + }, + } + + for _, test := range testCases { + ss, err := newTestScaleSet(ctrl) + assert.NoError(t, err, test.description) + + mockVMSSClient := mockvmssclient.NewMockInterface(ctrl) + ss.cloud.VirtualMachineScaleSetsClient = mockVMSSClient + + expected := compute.VirtualMachineScaleSet{Name: to.StringPtr(test.existedVMSSName)} + mockVMSSClient.EXPECT().List(gomock.Any(), gomock.Any()).Return([]compute.VirtualMachineScaleSet{expected}, test.vmssListError).AnyTimes() + + actual, err := ss.getVMSS(test.vmssName, azcache.CacheReadTypeDefault) + assert.Equal(t, test.expectedErr, err, test.description) + if actual != nil { + assert.Equal(t, expected, *actual, test.description) + } + } +} + +func TestGetVmssVM(t *testing.T) { + ctrl := gomock.NewController(t) + defer ctrl.Finish() + + testCases := []struct { + description string + nodeName string + existedNodeNames []string + existedVMSSName string + expectedError error + }{ + { + description: "getVmssVM should return the correct name of vmss, the instance id of the node, and the corresponding vmss instance", + nodeName: "vmss-vm-000000", + existedNodeNames: []string{"vmss-vm-000000"}, + existedVMSSName: "vmss", + }, + { + description: "getVmssVM should report an error of instance not found if there's no matches", + nodeName: "vmss-vm-000001", + existedNodeNames: []string{"vmss-vm-000000"}, + existedVMSSName: "vmss", + expectedError: cloudprovider.InstanceNotFound, + }, + } + + for _, test := range testCases { + ss, err := newTestScaleSet(ctrl) + assert.NoError(t, err, test.description) + + expectedVMSS := compute.VirtualMachineScaleSet{Name: to.StringPtr(test.existedVMSSName)} + mockVMSSClient := ss.cloud.VirtualMachineScaleSetsClient.(*mockvmssclient.MockInterface) + mockVMSSClient.EXPECT().List(gomock.Any(), ss.ResourceGroup).Return([]compute.VirtualMachineScaleSet{expectedVMSS}, nil).AnyTimes() + + expectedVMSSVMs, _, _ := buildTestVirtualMachineEnv(ss.cloud, test.existedVMSSName, "", 0, test.existedNodeNames, "") + var expectedVMSSVM compute.VirtualMachineScaleSetVM + for _, expected := range expectedVMSSVMs { + if strings.EqualFold(*expected.OsProfile.ComputerName, test.nodeName) { + expectedVMSSVM = expected + } + } + + mockVMSSVMClient := ss.cloud.VirtualMachineScaleSetVMsClient.(*mockvmssvmclient.MockInterface) + mockVMSSVMClient.EXPECT().List(gomock.Any(), ss.ResourceGroup, test.existedVMSSName, gomock.Any()).Return(expectedVMSSVMs, nil).AnyTimes() + + _, _, vmssVM, err := ss.getVmssVM(test.nodeName, azcache.CacheReadTypeDefault) + if vmssVM != nil { + assert.Equal(t, expectedVMSSVM, *vmssVM, test.description) + } + assert.Equal(t, test.expectedError, err, test.description) + } +} diff --git a/staging/src/k8s.io/legacy-cloud-providers/azure/clients/BUILD b/staging/src/k8s.io/legacy-cloud-providers/azure/clients/BUILD index 38048941035..dc03e943ec6 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/azure/clients/BUILD +++ b/staging/src/k8s.io/legacy-cloud-providers/azure/clients/BUILD @@ -29,6 +29,7 @@ filegroup( ":package-srcs", "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/armclient:all-srcs", "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/diskclient:all-srcs", + "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/fileclient:all-srcs", "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/interfaceclient:all-srcs", "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/loadbalancerclient:all-srcs", "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/publicipclient:all-srcs", diff --git a/staging/src/k8s.io/legacy-cloud-providers/azure/clients/fileclient/BUILD b/staging/src/k8s.io/legacy-cloud-providers/azure/clients/fileclient/BUILD new file mode 100644 index 00000000000..f86dcab702b --- /dev/null +++ b/staging/src/k8s.io/legacy-cloud-providers/azure/clients/fileclient/BUILD @@ -0,0 +1,36 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "azure_fileclient.go", + "doc.go", + "interface.go", + ], + importmap = "k8s.io/kubernetes/vendor/k8s.io/legacy-cloud-providers/azure/clients/fileclient", + importpath = "k8s.io/legacy-cloud-providers/azure/clients/fileclient", + visibility = ["//visibility:public"], + deps = [ + "//staging/src/k8s.io/legacy-cloud-providers/azure/retry:go_default_library", + "//vendor/github.com/Azure/azure-sdk-for-go/storage:go_default_library", + "//vendor/github.com/Azure/go-autorest/autorest/azure:go_default_library", + "//vendor/k8s.io/klog:go_default_library", + ], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [ + ":package-srcs", + "//staging/src/k8s.io/legacy-cloud-providers/azure/clients/fileclient/mockfileclient:all-srcs", + ], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/staging/src/k8s.io/legacy-cloud-providers/azure/clients/fileclient/azure_fileclient.go b/staging/src/k8s.io/legacy-cloud-providers/azure/clients/fileclient/azure_fileclient.go new file mode 100644 index 00000000000..a4a5f258929 --- /dev/null +++ b/staging/src/k8s.io/legacy-cloud-providers/azure/clients/fileclient/azure_fileclient.go @@ -0,0 +1,124 @@ +// +build !providerless + +/* +Copyright 2020 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package fileclient + +import ( + "fmt" + "net/http" + + azs "github.com/Azure/azure-sdk-for-go/storage" + "github.com/Azure/go-autorest/autorest/azure" + + "k8s.io/klog" + "k8s.io/legacy-cloud-providers/azure/retry" +) + +const ( + useHTTPS = true +) + +var ( + // refer https://github.com/Azure/azure-sdk-for-go/blob/master/storage/client.go#L88. + defaultValidStatusCodes = []int{ + http.StatusRequestTimeout, // 408 + http.StatusInternalServerError, // 500 + http.StatusBadGateway, // 502 + http.StatusServiceUnavailable, // 503 + http.StatusGatewayTimeout, // 504 + } +) + +// AzureFileClient implements the azure file client interface +type AzureFileClient struct { + env *azure.Environment + backoff *retry.Backoff +} + +// NewAzureFileClient creates a azure file client +func NewAzureFileClient(env *azure.Environment, backoff *retry.Backoff) *AzureFileClient { + return &AzureFileClient{ + env: env, + backoff: backoff, + } +} + +// CreateFileShare creates a file share +func (f *AzureFileClient) CreateFileShare(accountName, accountKey, name string, sizeGiB int) error { + fileClient, err := f.getFileSvcClient(accountName, accountKey) + if err != nil { + return err + } + share := fileClient.GetShareReference(name) + share.Properties.Quota = sizeGiB + newlyCreated, err := share.CreateIfNotExists(nil) + if err != nil { + return fmt.Errorf("failed to create file share, err: %v", err) + } + if !newlyCreated { + klog.V(2).Infof("file share(%s) under account(%s) already exists", name, accountName) + } + return nil +} + +// DeleteFileShare deletes a file share +func (f *AzureFileClient) DeleteFileShare(accountName, accountKey, name string) error { + fileClient, err := f.getFileSvcClient(accountName, accountKey) + if err != nil { + return err + } + return fileClient.GetShareReference(name).Delete(nil) +} + +// ResizeFileShare resizes a file share +func (f *AzureFileClient) ResizeFileShare(accountName, accountKey, name string, sizeGiB int) error { + fileClient, err := f.getFileSvcClient(accountName, accountKey) + if err != nil { + return err + } + share := fileClient.GetShareReference(name) + if share.Properties.Quota >= sizeGiB { + klog.Warningf("file share size(%dGi) is already greater or equal than requested size(%dGi), accountName: %s, shareName: %s", + share.Properties.Quota, sizeGiB, accountName, name) + return nil + } + share.Properties.Quota = sizeGiB + if err = share.SetProperties(nil); err != nil { + return fmt.Errorf("failed to set quota on file share %s, err: %v", name, err) + } + klog.V(4).Infof("resize file share completed, accountName: %s, shareName: %s, sizeGiB: %d", accountName, name, sizeGiB) + return nil +} + +func (f *AzureFileClient) getFileSvcClient(accountName, accountKey string) (*azs.FileServiceClient, error) { + fileClient, err := azs.NewClient(accountName, accountKey, f.env.StorageEndpointSuffix, azs.DefaultAPIVersion, useHTTPS) + if err != nil { + return nil, fmt.Errorf("error creating azure client: %v", err) + } + + if f.backoff != nil { + fileClient.Sender = &azs.DefaultSender{ + RetryAttempts: f.backoff.Steps, + ValidStatusCodes: defaultValidStatusCodes, + RetryDuration: f.backoff.Duration, + } + } + + fc := fileClient.GetFileService() + return &fc, nil +} diff --git a/staging/src/k8s.io/legacy-cloud-providers/azure/clients/fileclient/doc.go b/staging/src/k8s.io/legacy-cloud-providers/azure/clients/fileclient/doc.go new file mode 100644 index 00000000000..81d7a527003 --- /dev/null +++ b/staging/src/k8s.io/legacy-cloud-providers/azure/clients/fileclient/doc.go @@ -0,0 +1,20 @@ +// +build !providerless + +/* +Copyright 2020 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package fileclient implements the client for azure file. +package fileclient // import "k8s.io/legacy-cloud-providers/azure/clients/fileclient" diff --git a/staging/src/k8s.io/legacy-cloud-providers/azure/clients/fileclient/interface.go b/staging/src/k8s.io/legacy-cloud-providers/azure/clients/fileclient/interface.go new file mode 100644 index 00000000000..a5e22927bb3 --- /dev/null +++ b/staging/src/k8s.io/legacy-cloud-providers/azure/clients/fileclient/interface.go @@ -0,0 +1,27 @@ +// +build !providerless + +/* +Copyright 2020 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package fileclient + +// Interface is the client interface for creating file shares, interface for test injection. +// mockgen -source=$GOPATH/src/k8s.io/kubernetes/staging/src/k8s.io/legacy-cloud-providers/azure/clients/fileclient/interface.go -package=mockfileclient Interface > $GOPATH/src/k8s.io/kubernetes/staging/src/k8s.io/legacy-cloud-providers/azure/clients/fileclient/mockfileclient/interface.go +type Interface interface { + CreateFileShare(accountName, accountKey, name string, sizeGiB int) error + DeleteFileShare(accountName, accountKey, name string) error + ResizeFileShare(accountName, accountKey, name string, sizeGiB int) error +} diff --git a/staging/src/k8s.io/legacy-cloud-providers/azure/clients/fileclient/mockfileclient/BUILD b/staging/src/k8s.io/legacy-cloud-providers/azure/clients/fileclient/mockfileclient/BUILD new file mode 100644 index 00000000000..e49267c2968 --- /dev/null +++ b/staging/src/k8s.io/legacy-cloud-providers/azure/clients/fileclient/mockfileclient/BUILD @@ -0,0 +1,27 @@ +load("@io_bazel_rules_go//go:def.bzl", "go_library") + +go_library( + name = "go_default_library", + srcs = [ + "doc.go", + "interface.go", + ], + importmap = "k8s.io/kubernetes/vendor/k8s.io/legacy-cloud-providers/azure/clients/fileclient/mockfileclient", + importpath = "k8s.io/legacy-cloud-providers/azure/clients/fileclient/mockfileclient", + visibility = ["//visibility:public"], + deps = ["//vendor/github.com/golang/mock/gomock:go_default_library"], +) + +filegroup( + name = "package-srcs", + srcs = glob(["**"]), + tags = ["automanaged"], + visibility = ["//visibility:private"], +) + +filegroup( + name = "all-srcs", + srcs = [":package-srcs"], + tags = ["automanaged"], + visibility = ["//visibility:public"], +) diff --git a/staging/src/k8s.io/legacy-cloud-providers/azure/clients/fileclient/mockfileclient/doc.go b/staging/src/k8s.io/legacy-cloud-providers/azure/clients/fileclient/mockfileclient/doc.go new file mode 100644 index 00000000000..176e8ac8d7b --- /dev/null +++ b/staging/src/k8s.io/legacy-cloud-providers/azure/clients/fileclient/mockfileclient/doc.go @@ -0,0 +1,20 @@ +// +build !providerless + +/* +Copyright 2020 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package mockfileclient implements the mock client for azure file. +package mockfileclient // import "k8s.io/legacy-cloud-providers/azure/clients/filelient/mockfileclient" diff --git a/staging/src/k8s.io/legacy-cloud-providers/azure/clients/fileclient/mockfileclient/interface.go b/staging/src/k8s.io/legacy-cloud-providers/azure/clients/fileclient/mockfileclient/interface.go new file mode 100644 index 00000000000..7362218b80e --- /dev/null +++ b/staging/src/k8s.io/legacy-cloud-providers/azure/clients/fileclient/mockfileclient/interface.go @@ -0,0 +1,90 @@ +// +build !providerless + +/* +Copyright 2020 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package mockfileclient + +import ( + reflect "reflect" + + gomock "github.com/golang/mock/gomock" +) + +// MockInterface is a mock of Interface interface +type MockInterface struct { + ctrl *gomock.Controller + recorder *MockInterfaceMockRecorder +} + +// MockInterfaceMockRecorder is the mock recorder for MockInterface +type MockInterfaceMockRecorder struct { + mock *MockInterface +} + +// NewMockInterface creates a new mock instance +func NewMockInterface(ctrl *gomock.Controller) *MockInterface { + mock := &MockInterface{ctrl: ctrl} + mock.recorder = &MockInterfaceMockRecorder{mock} + return mock +} + +// EXPECT returns an object that allows the caller to indicate expected use +func (m *MockInterface) EXPECT() *MockInterfaceMockRecorder { + return m.recorder +} + +// CreateFileShare mocks base method +func (m *MockInterface) CreateFileShare(accountName, accountKey, name string, sizeGiB int) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateFileShare", accountName, accountKey, name, sizeGiB) + ret0, _ := ret[0].(error) + return ret0 +} + +// CreateFileShare indicates an expected call of CreateFileShare +func (mr *MockInterfaceMockRecorder) CreateFileShare(accountName, accountKey, name, sizeGiB interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateFileShare", reflect.TypeOf((*MockInterface)(nil).CreateFileShare), accountName, accountKey, name, sizeGiB) +} + +// DeleteFileShare mocks base method +func (m *MockInterface) DeleteFileShare(accountName, accountKey, name string) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "DeleteFileShare", accountName, accountKey, name) + ret0, _ := ret[0].(error) + return ret0 +} + +// DeleteFileShare indicates an expected call of DeleteFileShare +func (mr *MockInterfaceMockRecorder) DeleteFileShare(accountName, accountKey, name interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteFileShare", reflect.TypeOf((*MockInterface)(nil).DeleteFileShare), accountName, accountKey, name) +} + +// ResizeFileShare mocks base method +func (m *MockInterface) ResizeFileShare(accountName, accountKey, name string, sizeGiB int) error { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "ResizeFileShare", accountName, accountKey, name, sizeGiB) + ret0, _ := ret[0].(error) + return ret0 +} + +// ResizeFileShare indicates an expected call of ResizeFileShare +func (mr *MockInterfaceMockRecorder) ResizeFileShare(accountName, accountKey, name, sizeGiB interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "ResizeFileShare", reflect.TypeOf((*MockInterface)(nil).ResizeFileShare), accountName, accountKey, name, sizeGiB) +} diff --git a/staging/src/k8s.io/legacy-cloud-providers/azure/clients/vmssclient/mockvmssclient/BUILD b/staging/src/k8s.io/legacy-cloud-providers/azure/clients/vmssclient/mockvmssclient/BUILD index 054edfd9d1a..2ffffb33bfd 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/azure/clients/vmssclient/mockvmssclient/BUILD +++ b/staging/src/k8s.io/legacy-cloud-providers/azure/clients/vmssclient/mockvmssclient/BUILD @@ -12,6 +12,7 @@ go_library( deps = [ "//staging/src/k8s.io/legacy-cloud-providers/azure/retry:go_default_library", "//vendor/github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-01/compute:go_default_library", + "//vendor/github.com/Azure/go-autorest/autorest/azure:go_default_library", "//vendor/github.com/golang/mock/gomock:go_default_library", ], ) diff --git a/staging/src/k8s.io/legacy-cloud-providers/azure/clients/vmssclient/mockvmssclient/interface.go b/staging/src/k8s.io/legacy-cloud-providers/azure/clients/vmssclient/mockvmssclient/interface.go index b148af9f316..b5143764064 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/azure/clients/vmssclient/mockvmssclient/interface.go +++ b/staging/src/k8s.io/legacy-cloud-providers/azure/clients/vmssclient/mockvmssclient/interface.go @@ -20,9 +20,11 @@ package mockvmssclient import ( context "context" + http "net/http" reflect "reflect" compute "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-01/compute" + azure "github.com/Azure/go-autorest/autorest/azure" gomock "github.com/golang/mock/gomock" retry "k8s.io/legacy-cloud-providers/azure/retry" ) @@ -94,6 +96,36 @@ func (mr *MockInterfaceMockRecorder) CreateOrUpdate(ctx, resourceGroupName, VMSc return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateOrUpdate", reflect.TypeOf((*MockInterface)(nil).CreateOrUpdate), ctx, resourceGroupName, VMScaleSetName, parameters) } +// CreateOrUpdateAsync mocks base method +func (m *MockInterface) CreateOrUpdateAsync(ctx context.Context, resourceGroupName, VMScaleSetName string, parameters compute.VirtualMachineScaleSet) (*azure.Future, *retry.Error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "CreateOrUpdateAsync", ctx, resourceGroupName, VMScaleSetName, parameters) + ret0, _ := ret[0].(*azure.Future) + ret1, _ := ret[1].(*retry.Error) + return ret0, ret1 +} + +// CreateOrUpdateAsync indicates an expected call of CreateOrUpdateAsync +func (mr *MockInterfaceMockRecorder) CreateOrUpdateAsync(ctx, resourceGroupName, VMScaleSetName, parameters interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "CreateOrUpdateAsync", reflect.TypeOf((*MockInterface)(nil).CreateOrUpdateAsync), ctx, resourceGroupName, VMScaleSetName, parameters) +} + +// WaitForAsyncOperationResult mocks base method +func (m *MockInterface) WaitForAsyncOperationResult(ctx context.Context, future *azure.Future) (*http.Response, error) { + m.ctrl.T.Helper() + ret := m.ctrl.Call(m, "WaitForAsyncOperationResult", ctx, future) + ret0, _ := ret[0].(*http.Response) + ret1, _ := ret[1].(error) + return ret0, ret1 +} + +// WaitForAsyncOperationResult indicates an expected call of WaitForAsyncOperationResult +func (mr *MockInterfaceMockRecorder) WaitForAsyncOperationResult(ctx, future interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "WaitForAsyncOperationResult", reflect.TypeOf((*MockInterface)(nil).WaitForAsyncOperationResult), ctx, future) +} + // DeleteInstances mocks base method func (m *MockInterface) DeleteInstances(ctx context.Context, resourceGroupName, vmScaleSetName string, vmInstanceIDs compute.VirtualMachineScaleSetVMInstanceRequiredIDs) *retry.Error { m.ctrl.T.Helper() diff --git a/vendor/modules.txt b/vendor/modules.txt index fe303e1e29c..63a72f05069 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1873,22 +1873,31 @@ k8s.io/legacy-cloud-providers/azure/cache k8s.io/legacy-cloud-providers/azure/clients k8s.io/legacy-cloud-providers/azure/clients/armclient k8s.io/legacy-cloud-providers/azure/clients/diskclient +k8s.io/legacy-cloud-providers/azure/clients/diskclient/mockdiskclient +k8s.io/legacy-cloud-providers/azure/clients/fileclient k8s.io/legacy-cloud-providers/azure/clients/interfaceclient +k8s.io/legacy-cloud-providers/azure/clients/interfaceclient/mockinterfaceclient k8s.io/legacy-cloud-providers/azure/clients/loadbalancerclient +k8s.io/legacy-cloud-providers/azure/clients/loadbalancerclient/mockloadbalancerclient k8s.io/legacy-cloud-providers/azure/clients/publicipclient +k8s.io/legacy-cloud-providers/azure/clients/publicipclient/mockpublicipclient k8s.io/legacy-cloud-providers/azure/clients/routeclient k8s.io/legacy-cloud-providers/azure/clients/routeclient/mockrouteclient k8s.io/legacy-cloud-providers/azure/clients/routetableclient k8s.io/legacy-cloud-providers/azure/clients/routetableclient/mockroutetableclient k8s.io/legacy-cloud-providers/azure/clients/securitygroupclient +k8s.io/legacy-cloud-providers/azure/clients/securitygroupclient/mocksecuritygroupclient k8s.io/legacy-cloud-providers/azure/clients/snapshotclient k8s.io/legacy-cloud-providers/azure/clients/storageaccountclient k8s.io/legacy-cloud-providers/azure/clients/subnetclient k8s.io/legacy-cloud-providers/azure/clients/subnetclient/mocksubnetclient k8s.io/legacy-cloud-providers/azure/clients/vmclient +k8s.io/legacy-cloud-providers/azure/clients/vmclient/mockvmclient k8s.io/legacy-cloud-providers/azure/clients/vmsizeclient k8s.io/legacy-cloud-providers/azure/clients/vmssclient +k8s.io/legacy-cloud-providers/azure/clients/vmssclient/mockvmssclient k8s.io/legacy-cloud-providers/azure/clients/vmssvmclient +k8s.io/legacy-cloud-providers/azure/clients/vmssvmclient/mockvmssvmclient k8s.io/legacy-cloud-providers/azure/metrics k8s.io/legacy-cloud-providers/azure/retry k8s.io/legacy-cloud-providers/gce