func (az *Cloud) DeleteRouteWithName(routeName string) error {
	ctx, cancel := getContextWithCancel()
	defer cancel()
	rerr := az.RoutesClient.Delete(ctx, az.RouteTableResourceGroup, az.RouteTableName, routeName)
	klog.V(10).Infof("RoutesClient.Delete(%s,%s): end", az.RouteTableName, routeName)
	if rerr == nil {
		return nil
	}
	klog.Errorf("RoutesClient.Delete(%s, %s) failed: %v", az.RouteTableName, routeName, rerr.Error())
	return rerr.Error()
}
DeleteRouteWithName invokes az.RoutesClient.CreateOrUpdate with exponential backoff retry
package azure
import (
	"net/http"
	"regexp"
	"strings"
	"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"
	v1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/types"
	"k8s.io/apimachinery/pkg/util/wait"
	cloudprovider "k8s.io/cloud-provider"
	"k8s.io/klog/v2"
	azcache "k8s.io/legacy-cloud-providers/azure/cache"
	"k8s.io/legacy-cloud-providers/azure/retry"
)
const (
	vmssVMNotActiveErrorMessage = "not an active Virtual Machine Scale Set VM instanceId"
	operationCanceledErrorMessage = "canceledandsupersededduetoanotheroperation"
	cannotDeletePublicIPErrorMessageCode = "PublicIPAddressCannotBeDeleted"
	referencedResourceNotProvisionedMessageCode = "ReferencedResourceNotProvisioned"
)
var (
	pipErrorMessageRE = regexp.MustCompile(`(?:.*)/subscriptions/(?:.*)/resourceGroups/(.*)/providers/Microsoft.Network/publicIPAddresses/([^\s]+)(?:.*)`)
)
func (az *Cloud) RequestBackoff() (resourceRequestBackoff wait.Backoff) {
	if az.CloudProviderBackoff {
		return az.ResourceRequestBackoff
	}
	resourceRequestBackoff = wait.Backoff{
		Steps: 1,
	}
	return resourceRequestBackoff
}
func (az *Cloud) Event(obj runtime.Object, eventType, reason, message string) {
	if obj != nil && reason != "" {
		az.eventRecorder.Event(obj, eventType, reason, message)
	}
}
func (az *Cloud) GetVirtualMachineWithRetry(name types.NodeName, crt azcache.AzureCacheReadType) (compute.VirtualMachine, error) {
	var machine compute.VirtualMachine
	var retryErr error
	err := wait.ExponentialBackoff(az.RequestBackoff(), func() (bool, error) {
		machine, retryErr = az.getVirtualMachine(name, crt)
		if retryErr == cloudprovider.InstanceNotFound {
			return true, cloudprovider.InstanceNotFound
		}
		if retryErr != nil {
			klog.Errorf("GetVirtualMachineWithRetry(%s): backoff failure, will retry, err=%v", name, retryErr)
			return false, nil
		}
		klog.V(2).Infof("GetVirtualMachineWithRetry(%s): backoff success", name)
		return true, nil
	})
	if err == wait.ErrWaitTimeout {
		err = retryErr
	}
	return machine, err
}
func (az *Cloud) ListVirtualMachines(resourceGroup string) ([]compute.VirtualMachine, error) {
	ctx, cancel := getContextWithCancel()
	defer cancel()
	allNodes, rerr := az.VirtualMachinesClient.List(ctx, resourceGroup)
	if rerr != nil {
		klog.Errorf("VirtualMachinesClient.List(%v) failure with err=%v", resourceGroup, rerr)
		return nil, rerr.Error()
	}
	klog.V(2).Infof("VirtualMachinesClient.List(%v) success", resourceGroup)
	return allNodes, nil
}
func (az *Cloud) getPrivateIPsForMachine(nodeName types.NodeName) ([]string, error) {
	return az.getPrivateIPsForMachineWithRetry(nodeName)
}
func (az *Cloud) getPrivateIPsForMachineWithRetry(nodeName types.NodeName) ([]string, error) {
	var privateIPs []string
	err := wait.ExponentialBackoff(az.RequestBackoff(), func() (bool, error) {
		var retryErr error
		privateIPs, retryErr = az.VMSet.GetPrivateIPsByNodeName(string(nodeName))
		if retryErr != nil {
			if retryErr == cloudprovider.InstanceNotFound {
				return true, retryErr
			}
			klog.Errorf("GetPrivateIPsByNodeName(%s): backoff failure, will retry,err=%v", nodeName, retryErr)
			return false, nil
		}
		klog.V(3).Infof("GetPrivateIPsByNodeName(%s): backoff success", nodeName)
		return true, nil
	})
	return privateIPs, err
}
func (az *Cloud) getIPForMachine(nodeName types.NodeName) (string, string, error) {
	return az.GetIPForMachineWithRetry(nodeName)
}
func (az *Cloud) GetIPForMachineWithRetry(name types.NodeName) (string, string, error) {
	var ip, publicIP string
	err := wait.ExponentialBackoff(az.RequestBackoff(), func() (bool, error) {
		var retryErr error
		ip, publicIP, retryErr = az.VMSet.GetIPByNodeName(string(name))
		if retryErr != nil {
			klog.Errorf("GetIPForMachineWithRetry(%s): backoff failure, will retry,err=%v", name, retryErr)
			return false, nil
		}
		klog.V(3).Infof("GetIPForMachineWithRetry(%s): backoff success", name)
		return true, nil
	})
	return ip, publicIP, err
}
func (az *Cloud) CreateOrUpdateSecurityGroup(sg network.SecurityGroup) error {
	ctx, cancel := getContextWithCancel()
	defer cancel()
	rerr := az.SecurityGroupsClient.CreateOrUpdate(ctx, az.SecurityGroupResourceGroup, *sg.Name, sg, to.String(sg.Etag))
	klog.V(10).Infof("SecurityGroupsClient.CreateOrUpdate(%s): end", *sg.Name)
	if rerr == nil {
		az.nsgCache.Delete(*sg.Name)
		return nil
	}
	if rerr.HTTPStatusCode == http.StatusPreconditionFailed {
		klog.V(3).Infof("SecurityGroup cache for %s is cleanup because of http.StatusPreconditionFailed", *sg.Name)
		az.nsgCache.Delete(*sg.Name)
	}
	if strings.Contains(strings.ToLower(rerr.Error().Error()), operationCanceledErrorMessage) {
		klog.V(3).Infof("SecurityGroup cache for %s is cleanup because CreateOrUpdateSecurityGroup is canceled by another operation", *sg.Name)
		az.nsgCache.Delete(*sg.Name)
	}
	return rerr.Error()
}
func cleanupSubnetInFrontendIPConfigurations(lb *network.LoadBalancer) network.LoadBalancer {
	if lb.LoadBalancerPropertiesFormat == nil || lb.FrontendIPConfigurations == nil {
		return *lb
	}
	frontendIPConfigurations := *lb.FrontendIPConfigurations
	for i := range frontendIPConfigurations {
		config := frontendIPConfigurations[i]
		if config.FrontendIPConfigurationPropertiesFormat != nil &&
			config.Subnet != nil &&
			config.Subnet.ID != nil {
			subnet := network.Subnet{
				ID: config.Subnet.ID,
			}
			if config.Subnet.Name != nil {
				subnet.Name = config.FrontendIPConfigurationPropertiesFormat.Subnet.Name
			}
			config.FrontendIPConfigurationPropertiesFormat.Subnet = &subnet
			frontendIPConfigurations[i] = config
			continue
		}
	}
	lb.FrontendIPConfigurations = &frontendIPConfigurations
	return *lb
}
func (az *Cloud) CreateOrUpdateLB(service *v1.Service, lb network.LoadBalancer) error {
	ctx, cancel := getContextWithCancel()
	defer cancel()
	lb = cleanupSubnetInFrontendIPConfigurations(&lb)
	rgName := az.getLoadBalancerResourceGroup()
	rerr := az.LoadBalancerClient.CreateOrUpdate(ctx, rgName, to.String(lb.Name), lb, to.String(lb.Etag))
	klog.V(10).Infof("LoadBalancerClient.CreateOrUpdate(%s): end", *lb.Name)
	if rerr == nil {
		az.lbCache.Delete(*lb.Name)
		return nil
	}
	if rerr.HTTPStatusCode == http.StatusPreconditionFailed {
		klog.V(3).Infof("LoadBalancer cache for %s is cleanup because of http.StatusPreconditionFailed", to.String(lb.Name))
		az.lbCache.Delete(*lb.Name)
	}
	retryErrorMessage := rerr.Error().Error()
	if strings.Contains(strings.ToLower(retryErrorMessage), operationCanceledErrorMessage) {
		klog.V(3).Infof("LoadBalancer cache for %s is cleanup because CreateOrUpdate is canceled by another operation", to.String(lb.Name))
		az.lbCache.Delete(*lb.Name)
	}
	if strings.Contains(strings.ToLower(retryErrorMessage), strings.ToLower(referencedResourceNotProvisionedMessageCode)) {
		matches := pipErrorMessageRE.FindStringSubmatch(retryErrorMessage)
		if len(matches) != 3 {
			klog.Warningf("Failed to parse the retry error message %s", retryErrorMessage)
			return rerr.Error()
		}
		pipRG, pipName := matches[1], matches[2]
		klog.V(3).Infof("The public IP %s referenced by load balancer %s is not in Succeeded provisioning state, will try to update it", pipName, to.String(lb.Name))
		pip, _, err := az.getPublicIPAddress(pipRG, pipName)
		if err != nil {
			klog.Warningf("Failed to get the public IP %s in resource group %s: %v", pipName, pipRG, err)
			return rerr.Error()
		}
		err = az.CreateOrUpdatePIP(service, pipRG, pip)
		if err != nil {
			klog.Warningf("Failed to update the public IP %s in resource group %s: %v", pipName, pipRG, err)
			return rerr.Error()
		}
		az.lbCache.Delete(*lb.Name)
	}
	return rerr.Error()
}
func (az *Cloud) ListLB(service *v1.Service) ([]network.LoadBalancer, error) {
	ctx, cancel := getContextWithCancel()
	defer cancel()
	rgName := az.getLoadBalancerResourceGroup()
	allLBs, rerr := az.LoadBalancerClient.List(ctx, rgName)
	if rerr != nil {
		if rerr.IsNotFound() {
			return nil, nil
		}
		az.Event(service, v1.EventTypeWarning, "ListLoadBalancers", rerr.Error().Error())
		klog.Errorf("LoadBalancerClient.List(%v) failure with err=%v", rgName, rerr)
		return nil, rerr.Error()
	}
	klog.V(2).Infof("LoadBalancerClient.List(%v) success", rgName)
	return allLBs, nil
}
func (az *Cloud) ListPIP(service *v1.Service, pipResourceGroup string) ([]network.PublicIPAddress, error) {
	ctx, cancel := getContextWithCancel()
	defer cancel()
	allPIPs, rerr := az.PublicIPAddressesClient.List(ctx, pipResourceGroup)
	if rerr != nil {
		if rerr.IsNotFound() {
			return nil, nil
		}
		az.Event(service, v1.EventTypeWarning, "ListPublicIPs", rerr.Error().Error())
		klog.Errorf("PublicIPAddressesClient.List(%v) failure with err=%v", pipResourceGroup, rerr)
		return nil, rerr.Error()
	}
	klog.V(2).Infof("PublicIPAddressesClient.List(%v) success", pipResourceGroup)
	return allPIPs, nil
}
func (az *Cloud) CreateOrUpdatePIP(service *v1.Service, pipResourceGroup string, pip network.PublicIPAddress) error {
	ctx, cancel := getContextWithCancel()
	defer cancel()
	rerr := az.PublicIPAddressesClient.CreateOrUpdate(ctx, pipResourceGroup, to.String(pip.Name), pip)
	klog.V(10).Infof("PublicIPAddressesClient.CreateOrUpdate(%s, %s): end", pipResourceGroup, to.String(pip.Name))
	if rerr != nil {
		klog.Errorf("PublicIPAddressesClient.CreateOrUpdate(%s, %s) failed: %s", pipResourceGroup, to.String(pip.Name), rerr.Error().Error())
		az.Event(service, v1.EventTypeWarning, "CreateOrUpdatePublicIPAddress", rerr.Error().Error())
		return rerr.Error()
	}
	return nil
}
func (az *Cloud) CreateOrUpdateInterface(service *v1.Service, nic network.Interface) error {
	ctx, cancel := getContextWithCancel()
	defer cancel()
	rerr := az.InterfacesClient.CreateOrUpdate(ctx, az.ResourceGroup, *nic.Name, nic)
	klog.V(10).Infof("InterfacesClient.CreateOrUpdate(%s): end", *nic.Name)
	if rerr != nil {
		klog.Errorf("InterfacesClient.CreateOrUpdate(%s) failed: %s", *nic.Name, rerr.Error().Error())
		az.Event(service, v1.EventTypeWarning, "CreateOrUpdateInterface", rerr.Error().Error())
		return rerr.Error()
	}
	return nil
}
func (az *Cloud) DeletePublicIP(service *v1.Service, pipResourceGroup string, pipName string) error {
	ctx, cancel := getContextWithCancel()
	defer cancel()
	rerr := az.PublicIPAddressesClient.Delete(ctx, pipResourceGroup, pipName)
	if rerr != nil {
		klog.Errorf("PublicIPAddressesClient.Delete(%s) failed: %s", pipName, rerr.Error().Error())
		az.Event(service, v1.EventTypeWarning, "DeletePublicIPAddress", rerr.Error().Error())
		if strings.Contains(rerr.Error().Error(), cannotDeletePublicIPErrorMessageCode) {
			klog.Warningf("DeletePublicIP for public IP %s failed with error %v, this is because other resources are referencing the public IP. The deletion of the service will continue.", pipName, rerr.Error())
			return nil
		}
		return rerr.Error()
	}
	return nil
}
func (az *Cloud) DeleteLB(service *v1.Service, lbName string) error {
	ctx, cancel := getContextWithCancel()
	defer cancel()
	rgName := az.getLoadBalancerResourceGroup()
	rerr := az.LoadBalancerClient.Delete(ctx, rgName, lbName)
	if rerr == nil {
		az.lbCache.Delete(lbName)
		return nil
	}
	klog.Errorf("LoadBalancerClient.Delete(%s) failed: %s", lbName, rerr.Error().Error())
	az.Event(service, v1.EventTypeWarning, "DeleteLoadBalancer", rerr.Error().Error())
	return rerr.Error()
}
func (az *Cloud) CreateOrUpdateRouteTable(routeTable network.RouteTable) error {
	ctx, cancel := getContextWithCancel()
	defer cancel()
	rerr := az.RouteTablesClient.CreateOrUpdate(ctx, az.RouteTableResourceGroup, az.RouteTableName, routeTable, to.String(routeTable.Etag))
	if rerr == nil {
		az.rtCache.Delete(*routeTable.Name)
		return nil
	}
	if rerr.HTTPStatusCode == http.StatusPreconditionFailed {
		klog.V(3).Infof("Route table cache for %s is cleanup because of http.StatusPreconditionFailed", *routeTable.Name)
		az.rtCache.Delete(*routeTable.Name)
	}
	if strings.Contains(strings.ToLower(rerr.Error().Error()), operationCanceledErrorMessage) {
		klog.V(3).Infof("Route table cache for %s is cleanup because CreateOrUpdateRouteTable is canceled by another operation", *routeTable.Name)
		az.rtCache.Delete(*routeTable.Name)
	}
	klog.Errorf("RouteTablesClient.CreateOrUpdate(%s) failed: %v", az.RouteTableName, rerr.Error())
	return rerr.Error()
}
func (az *Cloud) CreateOrUpdateRoute(route network.Route) error {
	ctx, cancel := getContextWithCancel()
	defer cancel()
	rerr := az.RoutesClient.CreateOrUpdate(ctx, az.RouteTableResourceGroup, az.RouteTableName, *route.Name, route, to.String(route.Etag))
	klog.V(10).Infof("RoutesClient.CreateOrUpdate(%s): end", *route.Name)
	if rerr == nil {
		az.rtCache.Delete(az.RouteTableName)
		return nil
	}
	if rerr.HTTPStatusCode == http.StatusPreconditionFailed {
		klog.V(3).Infof("Route cache for %s is cleanup because of http.StatusPreconditionFailed", *route.Name)
		az.rtCache.Delete(az.RouteTableName)
	}
	if strings.Contains(strings.ToLower(rerr.Error().Error()), operationCanceledErrorMessage) {
		klog.V(3).Infof("Route cache for %s is cleanup because CreateOrUpdateRouteTable is canceled by another operation", *route.Name)
		az.rtCache.Delete(az.RouteTableName)
	}
	return rerr.Error()
}