func (c *Client) WaitForAsyncOperationCompletion(ctx context.Context, future *azure.Future, asyncOperationName string) error {
	err := future.WaitForCompletionRef(ctx, c.client)
	if err != nil {
		klog.V(5).Infof("Received error in WaitForCompletionRef: '%v'", err)
		return err
	}
	var done bool
	done, err = future.DoneWithContext(ctx, c.client)
	if err != nil {
		klog.V(5).Infof("Received error in DoneWithContext: '%v'", err)
		return autorest.NewErrorWithError(err, asyncOperationName, "Result", future.Response(), "Polling failure")
	}
	if !done {
		return azure.NewAsyncOpIncompleteError(asyncOperationName)
	}
	return nil
}
WaitForAsyncOperationCompletion waits for an operation completion
package armclient
import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
	"sync"
	"time"
	"unicode"
	"github.com/Azure/go-autorest/autorest"
	"github.com/Azure/go-autorest/autorest/azure"
	"k8s.io/client-go/pkg/version"
	"k8s.io/klog/v2"
	"k8s.io/legacy-cloud-providers/azure/retry"
)
var _ Interface = &Client{}
type Client struct {
	client  autorest.Client
	backoff *retry.Backoff
	baseURI      string
	apiVersion   string
	clientRegion string
}
func New(authorizer autorest.Authorizer, baseURI, userAgent, apiVersion, clientRegion string, clientBackoff *retry.Backoff) *Client {
	restClient := autorest.NewClientWithUserAgent(userAgent)
	restClient.PollingDelay = 5 * time.Second
	restClient.RetryAttempts = 3
	restClient.RetryDuration = time.Second * 1
	restClient.Authorizer = authorizer
	if userAgent == "" {
		restClient.UserAgent = GetUserAgent(restClient)
	}
	backoff := clientBackoff
	if backoff == nil {
		backoff = &retry.Backoff{}
	}
	if backoff.Steps == 0 {
		backoff.Steps = 1
	}
	return &Client{
		client:       restClient,
		baseURI:      baseURI,
		backoff:      backoff,
		apiVersion:   apiVersion,
		clientRegion: NormalizeAzureRegion(clientRegion),
	}
}
func GetUserAgent(client autorest.Client) string {
	k8sVersion := version.Get().GitVersion
	return fmt.Sprintf("%s; kubernetes-cloudprovider/%s", client.UserAgent, k8sVersion)
}
func NormalizeAzureRegion(name string) string {
	region := ""
	for _, runeValue := range name {
		if !unicode.IsSpace(runeValue) {
			region += string(runeValue)
		}
	}
	return strings.ToLower(region)
}
func (c *Client) sendRequest(ctx context.Context, request *http.Request) (*http.Response, *retry.Error) {
	sendBackoff := *c.backoff
	response, err := autorest.SendWithSender(
		c.client,
		request,
		retry.DoExponentialBackoffRetry(&sendBackoff),
	)
	if response == nil && err == nil {
		return response, retry.NewError(false, fmt.Errorf("Empty response and no HTTP code"))
	}
	return response, retry.GetError(response, err)
}
func (c *Client) Send(ctx context.Context, request *http.Request) (*http.Response, *retry.Error) {
	response, rerr := c.sendRequest(ctx, request)
	if rerr != nil {
		return response, rerr
	}
	if response.StatusCode != http.StatusNotFound || c.clientRegion == "" {
		return response, rerr
	}
	bodyBytes, _ := ioutil.ReadAll(response.Body)
	defer func() {
		response.Body = ioutil.NopCloser(bytes.NewBuffer(bodyBytes))
	}()
	bodyString := string(bodyBytes)
	klog.V(5).Infof("Send.sendRequest original error message: %s", bodyString)
	var body map[string]interface{}
	if e := json.Unmarshal(bodyBytes, &body); e != nil {
		klog.V(5).Infof("Send.sendRequest: error in parsing response body string: %s, Skip retrying regional host", e)
		return response, rerr
	}
	if err, ok := body["error"].(map[string]interface{}); !ok ||
		err["code"] == nil ||
		!strings.EqualFold(err["code"].(string), "ResourceGroupNotFound") {
		klog.V(5).Infof("Send.sendRequest: response body does not contain ResourceGroupNotFound error code. Skip retrying regional host")
		return response, rerr
	}
	currentHost := request.URL.Host
	if request.Host != "" {
		currentHost = request.Host
	}
	if strings.HasPrefix(strings.ToLower(currentHost), c.clientRegion) {
		klog.V(5).Infof("Send.sendRequest: current host %s is regional host. Skip retrying regional host.", currentHost)
		return response, rerr
	}
	request.Host = fmt.Sprintf("%s.%s", c.clientRegion, strings.ToLower(currentHost))
	klog.V(5).Infof("Send.sendRegionalRequest on ResourceGroupNotFound error. Retrying regional host: %s", request.Host)
	regionalResponse, regionalError := c.sendRequest(ctx, request)
	if regionalResponse == nil || regionalResponse.StatusCode > 299 {
		regionalErrStr := ""
		if regionalError != nil {
			regionalErrStr = regionalError.Error().Error()
		}
		klog.V(5).Infof("Send.sendRegionalRequest failed to get response from regional host, error: '%s'. Ignoring the result.", regionalErrStr)
		return response, rerr
	}
	return regionalResponse, regionalError
}
func (c *Client) PreparePutRequest(ctx context.Context, decorators ...autorest.PrepareDecorator) (*http.Request, error) {
	decorators = append(
		[]autorest.PrepareDecorator{
			autorest.AsContentType("application/json; charset=utf-8"),
			autorest.AsPut(),
			autorest.WithBaseURL(c.baseURI)},
		decorators...)
	return c.prepareRequest(ctx, decorators...)
}
func (c *Client) PreparePatchRequest(ctx context.Context, decorators ...autorest.PrepareDecorator) (*http.Request, error) {
	decorators = append(
		[]autorest.PrepareDecorator{
			autorest.AsContentType("application/json; charset=utf-8"),
			autorest.AsPatch(),
			autorest.WithBaseURL(c.baseURI)},
		decorators...)
	return c.prepareRequest(ctx, decorators...)
}
func (c *Client) PreparePostRequest(ctx context.Context, decorators ...autorest.PrepareDecorator) (*http.Request, error) {
	decorators = append(
		[]autorest.PrepareDecorator{
			autorest.AsContentType("application/json; charset=utf-8"),
			autorest.AsPost(),
			autorest.WithBaseURL(c.baseURI)},
		decorators...)
	return c.prepareRequest(ctx, decorators...)
}
func (c *Client) PrepareGetRequest(ctx context.Context, decorators ...autorest.PrepareDecorator) (*http.Request, error) {
	decorators = append(
		[]autorest.PrepareDecorator{
			autorest.AsGet(),
			autorest.WithBaseURL(c.baseURI)},
		decorators...)
	return c.prepareRequest(ctx, decorators...)
}
func (c *Client) PrepareDeleteRequest(ctx context.Context, decorators ...autorest.PrepareDecorator) (*http.Request, error) {
	decorators = append(
		[]autorest.PrepareDecorator{
			autorest.AsDelete(),
			autorest.WithBaseURL(c.baseURI)},
		decorators...)
	return c.prepareRequest(ctx, decorators...)
}
func (c *Client) PrepareHeadRequest(ctx context.Context, decorators ...autorest.PrepareDecorator) (*http.Request, error) {
	decorators = append(
		[]autorest.PrepareDecorator{
			autorest.AsHead(),
			autorest.WithBaseURL(c.baseURI)},
		decorators...)
	return c.prepareRequest(ctx, decorators...)
}