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 b77cd18c306..404b616a04f 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 @@ -29,6 +29,7 @@ import ( "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" @@ -566,6 +567,14 @@ func (fVMSSC *fakeVirtualMachineScaleSetsClient) CreateOrUpdate(ctx context.Cont 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() diff --git a/staging/src/k8s.io/legacy-cloud-providers/azure/clients/vmssclient/azure_vmssclient.go b/staging/src/k8s.io/legacy-cloud-providers/azure/clients/vmssclient/azure_vmssclient.go index 960cf8c9412..facf499e09b 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/azure/clients/vmssclient/azure_vmssclient.go +++ b/staging/src/k8s.io/legacy-cloud-providers/azure/clients/vmssclient/azure_vmssclient.go @@ -234,6 +234,49 @@ func (c *Client) CreateOrUpdate(ctx context.Context, resourceGroupName string, V return nil } +// CreateOrUpdateAsync sends the request to arm client and DO NOT wait for the response +func (c *Client) CreateOrUpdateAsync(ctx context.Context, resourceGroupName string, VMScaleSetName string, parameters compute.VirtualMachineScaleSet) (*azure.Future, *retry.Error) { + mc := metrics.NewMetricContext("vmss", "create_or_update_async", resourceGroupName, c.subscriptionID, "") + + // Report errors if the client is rate limited. + if !c.rateLimiterWriter.TryAccept() { + mc.RateLimitedCount() + return nil, retry.GetRateLimitError(true, "VMSSCreateOrUpdateAsync") + } + + // Report errors if the client is throttled. + if c.RetryAfterWriter.After(time.Now()) { + mc.ThrottledCount() + rerr := retry.GetThrottlingError("VMSSCreateOrUpdateAsync", "client throttled", c.RetryAfterWriter) + return nil, rerr + } + + resourceID := armclient.GetResourceID( + c.subscriptionID, + resourceGroupName, + "Microsoft.Compute/virtualMachineScaleSets", + VMScaleSetName, + ) + + future, rerr := c.armClient.PutResourceAsync(ctx, resourceID, parameters) + mc.Observe(rerr.Error()) + if rerr != nil { + if rerr.IsThrottled() { + // Update RetryAfterReader so that no more requests would be sent until RetryAfter expires. + c.RetryAfterWriter = rerr.RetryAfter + } + + return nil, rerr + } + + return future, nil +} + +// WaitForAsyncOperationResult waits for the response of the request +func (c *Client) WaitForAsyncOperationResult(ctx context.Context, future *azure.Future) (*http.Response, error) { + return c.armClient.WaitForAsyncOperationResult(ctx, future, "VMSSWaitForAsyncOperationResult") +} + // createOrUpdateVMSS creates or updates a VirtualMachineScaleSet. func (c *Client) createOrUpdateVMSS(ctx context.Context, resourceGroupName string, VMScaleSetName string, parameters compute.VirtualMachineScaleSet) *retry.Error { resourceID := armclient.GetResourceID( diff --git a/staging/src/k8s.io/legacy-cloud-providers/azure/clients/vmssclient/interface.go b/staging/src/k8s.io/legacy-cloud-providers/azure/clients/vmssclient/interface.go index ebfebd9ab4f..16aeb41eb42 100644 --- a/staging/src/k8s.io/legacy-cloud-providers/azure/clients/vmssclient/interface.go +++ b/staging/src/k8s.io/legacy-cloud-providers/azure/clients/vmssclient/interface.go @@ -20,8 +20,11 @@ package vmssclient import ( "context" + "net/http" "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2019-12-01/compute" + "github.com/Azure/go-autorest/autorest/azure" + "k8s.io/legacy-cloud-providers/azure/retry" ) @@ -43,6 +46,12 @@ type Interface interface { // CreateOrUpdate creates or updates a VirtualMachineScaleSet. CreateOrUpdate(ctx context.Context, resourceGroupName string, VMScaleSetName string, parameters compute.VirtualMachineScaleSet) *retry.Error + // CreateOrUpdateSync sends the request to arm client and DO NOT wait for the response + CreateOrUpdateAsync(ctx context.Context, resourceGroupName string, VMScaleSetName string, parameters compute.VirtualMachineScaleSet) (*azure.Future, *retry.Error) + + // WaitForAsyncOperationResult waits for the response of the request + WaitForAsyncOperationResult(ctx context.Context, future *azure.Future) (*http.Response, error) + // DeleteInstances deletes the instances for a VirtualMachineScaleSet. DeleteInstances(ctx context.Context, resourceGroupName string, vmScaleSetName string, vmInstanceIDs compute.VirtualMachineScaleSetVMInstanceRequiredIDs) *retry.Error }