Repository: kubernetes-sigs/cloud-provider-azure
Pull request #7044 (2024-09-12 05:26:27)

Track2 sdk: add msi client
<!--  Thanks for sending a pull request!  Here are some tips for you:

1. If this is your first time, please read our contributor guidelines: https://git.k8s.io/community/contributors/guide/first-contribution.md#your-first-contribution and developer guide https://git.k8s.io/community/contributors/devel/development.md#development-guide
2. Please label this pull request according to what type of issue you are addressing, especially if this is a release targeted pull request. For reference on required PR/issue labels, read here:
https://git.k8s.io/community/contributors/devel/sig-release/release.md#issuepr-kind-label
3. Ensure you have added or ran the appropriate tests for your PR: https://git.k8s.io/community/contributors/devel/sig-testing/testing.md
4. If you want *faster* PR reviews, read how: https://git.k8s.io/community/contributors/guide/pull-requests.md#best-practices-for-faster-reviews
5. If the PR is unfinished, see how to mark it: https://git.k8s.io/community/contributors/guide/pull-requests.md#marking-unfinished-pull-requests
-->

#### What type of PR is this?
/kind feature

<!--
Add one of the following kinds:
/kind bug
/kind cleanup
/kind documentation
/kind feature
/kind design

Optionally add one or more of the following kinds if applicable:
/kind api-change
/kind deprecation
/kind failing-test
/kind flake
/kind regression
-->

#### What this PR does / why we need it:
Track2 sdk: add msi client
#### Which issue(s) this PR fixes:
<!--
*Automatically closes linked issue when PR is merged.
Usage: `Fixes #<issue number>`, or `Fixes (paste link of issue)`.
_If PR is about `failing-tests or flakes`, please post the related issues/tests in a comment and do not use `Fixes`_*
-->
Fixes #

#### Special notes for your reviewer:

#### Does this PR introduce a user-facing change?
<!--
If no, just write "NONE" in the release-note block below.
If yes, a release note is required:
Enter your extended release note in the block below. If the PR requires additional action from users switching to the new release, include the string "action required".

For more information on release notes see: https://git.k8s.io/community/contributors/guide/release-notes.md
-->
```release-note
NONE
```

#### Additional documentation e.g., KEPs (Kubernetes Enhancement Proposals), usage docs, etc.:

<!--
This section can be blank if this pull request does not require a release note.

When adding links which point to resources within git repositories, like
KEPs or supporting documentation, please reference a specific commit and avoid
linking directly to the master branch. This ensures that links reference a
specific point in time, rather than a document that may change over time.

See here for guidance on getting permanent links to files: https://help.github.com/en/articles/getting-permanent-links-to-files

Please use the following format for linking documentation:
- [KEP]: <link>
- [Usage]: <link>
- [Other doc]: <link>
-->
```docs

```



Patch:
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index ff9ac12e1..42c6393c0 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -55,7 +55,7 @@ jobs:
 
     steps:
     - name: Harden Runner
-      uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
+      uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
       with:
         egress-policy: audit
 
diff --git a/.github/workflows/codespell.yaml b/.github/workflows/codespell.yaml
index 692975021..1d7c69f2f 100644
--- a/.github/workflows/codespell.yaml
+++ b/.github/workflows/codespell.yaml
@@ -12,7 +12,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - name: Harden Runner
-        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
+        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
         with:
           egress-policy: audit
 
diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml
index b9da4ef25..0905292bc 100644
--- a/.github/workflows/dependency-review.yml
+++ b/.github/workflows/dependency-review.yml
@@ -17,7 +17,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - name: Harden Runner
-        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
+        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
         with:
           egress-policy: audit
 
diff --git a/.github/workflows/lint-ci-weekly.yaml b/.github/workflows/lint-ci-weekly.yaml
index 5a4002138..f9b6a6aba 100644
--- a/.github/workflows/lint-ci-weekly.yaml
+++ b/.github/workflows/lint-ci-weekly.yaml
@@ -14,7 +14,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - name: Harden Runner
-        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
+        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
         with:
           egress-policy: audit
       - name: Setup Golang
diff --git a/.github/workflows/lint.yaml b/.github/workflows/lint.yaml
index f2a007f8c..39495afa6 100644
--- a/.github/workflows/lint.yaml
+++ b/.github/workflows/lint.yaml
@@ -16,7 +16,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - name: Harden Runner
-        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
+        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
         with:
           egress-policy: audit
       - name: Checkout
diff --git a/.github/workflows/release-azclient-trace.yml b/.github/workflows/release-azclient-trace.yml
index 5c5655a15..0c27c17c5 100644
--- a/.github/workflows/release-azclient-trace.yml
+++ b/.github/workflows/release-azclient-trace.yml
@@ -15,7 +15,7 @@ jobs:
       contents: write
     steps:
     - name: Harden Runner
-      uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
+      uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
       with:
         egress-policy: audit
 
diff --git a/.github/workflows/release-azclient.yml b/.github/workflows/release-azclient.yml
index d1dd96192..7851218c2 100644
--- a/.github/workflows/release-azclient.yml
+++ b/.github/workflows/release-azclient.yml
@@ -18,7 +18,7 @@ jobs:
       contents: write
     steps:
     - name: Harden Runner
-      uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
+      uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
       with:
         egress-policy: audit
 
diff --git a/.github/workflows/release-configloader.yml b/.github/workflows/release-configloader.yml
index 7ce9b9e64..651519a22 100644
--- a/.github/workflows/release-configloader.yml
+++ b/.github/workflows/release-configloader.yml
@@ -15,7 +15,7 @@ jobs:
       contents: write
     steps:
     - name: Harden Runner
-      uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
+      uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
       with:
         egress-policy: audit
 
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index eaf51a02b..97fad11a1 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -23,7 +23,7 @@ jobs:
             arch: arm64
     steps:
       - name: Harden Runner
-        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
+        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
         with:
           egress-policy: audit
 
@@ -59,7 +59,7 @@ jobs:
             arch: amd64
     steps:
       - name: Harden Runner
-        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
+        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
         with:
           egress-policy: audit
 
@@ -111,7 +111,7 @@ jobs:
             arch: amd64
     steps:
       - name: Harden Runner
-        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
+        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
         with:
           egress-policy: audit
 
@@ -158,7 +158,7 @@ jobs:
       pull-requests: write
     steps:
       - name: Harden Runner
-        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
+        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
         with:
           egress-policy: audit
 
diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml
index bc2f1cfe6..6a35e64d4 100644
--- a/.github/workflows/scorecards.yml
+++ b/.github/workflows/scorecards.yml
@@ -32,7 +32,7 @@ jobs:
 
     steps:
       - name: Harden Runner
-        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
+        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
         with:
           egress-policy: audit
 
diff --git a/.github/workflows/trivy.yaml b/.github/workflows/trivy.yaml
index c51fb0860..1b17cf4a4 100644
--- a/.github/workflows/trivy.yaml
+++ b/.github/workflows/trivy.yaml
@@ -7,6 +7,7 @@ on:
     paths:
       - '.github/workflows/trivy.yaml'
       - 'pkg/**.go'
+      - '!pkg/azureclients/v2/**.go'
       - '!kubetest2-aks/**.go'
       - 'cmd/**.go'
       - 'go.*'
@@ -17,25 +18,26 @@ on:
     paths:
       - '.github/workflows/trivy.yaml'
       - 'pkg/**.go'
+      - '!pkg/azureclients/v2/**.go'
       - '!kubetest2-aks/**.go'
       - 'cmd/**.go'
       - 'go.*'
       - '!vendor/**'
       - 'health-probe-proxy/**'
   schedule:
-    - cron: '0 */24 * * *'
+    - cron: '35 12 * * 4'
 permissions:
   contents: read
 jobs:
   build:
     permissions:
-      contents: write # for sbom
+      contents: read # for actions/checkout to fetch code
       security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
     name: Build
     runs-on: ubuntu-latest
     steps:
       - name: Harden Runner
-        uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
+        uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
         with:
           egress-policy: audit
 
@@ -102,7 +104,8 @@ jobs:
         uses: aquasecurity/trivy-action@6e7b7d1fd3e4fef0c5fa8cce1229c54b2c9bd0d8 # master
         with:
           scan-type: 'fs'
+          ignore-unfixed: true
           format: 'github'
           output: 'dependency-results.sbom.json'
-          scan-ref: '.'
+          image-ref: '.'
           github-pat: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.github/workflows/update-vendor-license.yml b/.github/workflows/update-vendor-license.yml
index 32eccad9e..d5ad51840 100644
--- a/.github/workflows/update-vendor-license.yml
+++ b/.github/workflows/update-vendor-license.yml
@@ -37,7 +37,7 @@ jobs:
 
     steps:
     - name: Harden Runner
-      uses: step-security/harden-runner@91182cccc01eb5e619899d80e4e971d6181294a7 # v2.10.1
+      uses: step-security/harden-runner@5c7944e73c4c2a096b17a9cb74d65b6c2bbafbde # v2.9.1
       with:
         egress-policy: audit
 
diff --git a/cmd/acr-credential-provider/main.go b/cmd/acr-credential-provider/main.go
index 9cb1840ec..93a78925b 100644
--- a/cmd/acr-credential-provider/main.go
+++ b/cmd/acr-credential-provider/main.go
@@ -33,9 +33,6 @@ import (
 
 func main() {
 	rand.Seed(time.Now().UnixNano())
-
-	var RegistryMirrorStr string
-
 	command := &cobra.Command{
 		Use:   "acr-credential-provider configFile",
 		Short: "Acr credential provider for Kubelet",
@@ -47,7 +44,7 @@ func main() {
 				os.Exit(1)
 			}
 
-			acrProvider, err := credentialprovider.NewAcrProviderFromConfig(args[0], RegistryMirrorStr)
+			acrProvider, err := credentialprovider.NewAcrProviderFromConfig(args[0])
 			if err != nil {
 				klog.Errorf("Failed to initialize ACR provider: %v", err)
 				os.Exit(1)
@@ -63,10 +60,6 @@ func main() {
 	logs.InitLogs()
 	defer logs.FlushLogs()
 
-	// Flags
-	command.Flags().StringVarP(&RegistryMirrorStr, "registry-mirror", "r", "",
-		"Mirror a source registry host to a target registry host, and image pull credential will be requested to the target registry host when the image is from source registry host")
-
 	if err := command.Execute(); err != nil {
 		os.Exit(1)
 	}
diff --git a/examples/out-of-tree/credential-provider-config.yaml b/examples/out-of-tree/credential-provider-config.yaml
index f9f6e3b6b..f079b0539 100644
--- a/examples/out-of-tree/credential-provider-config.yaml
+++ b/examples/out-of-tree/credential-provider-config.yaml
@@ -9,7 +9,5 @@ providers:
   - "*.azurecr.cn"
   - "*.azurecr.de"
   - "*.azurecr.us"
-  - "mcr.microsoft.com"
   args:
   - /etc/kubernetes/azure.json
-  - --registry-mirror=mcr.microsoft.com:xxx.azurecr.io
diff --git a/go.mod b/go.mod
index e1e891d6c..00392ff41 100644
--- a/go.mod
+++ b/go.mod
@@ -1,6 +1,6 @@
 module sigs.k8s.io/cloud-provider-azure
 
-go 1.23.1
+go 1.23.0
 
 require (
 	github.com/Azure/azure-kusto-go v0.16.1
@@ -36,7 +36,7 @@ require (
 	go.opentelemetry.io/otel/trace v1.29.0
 	go.uber.org/mock v0.4.0
 	golang.org/x/sync v0.8.0
-	golang.org/x/sys v0.25.0
+	golang.org/x/sys v0.24.0
 	golang.org/x/text v0.17.0
 	k8s.io/api v0.31.0
 	k8s.io/apimachinery v0.31.0
diff --git a/go.sum b/go.sum
index c8f354cf6..b57234313 100644
--- a/go.sum
+++ b/go.sum
@@ -348,8 +348,8 @@ golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
-golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg=
+golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
diff --git a/health-probe-proxy/go.mod b/health-probe-proxy/go.mod
index 66be3d838..9adf4c871 100644
--- a/health-probe-proxy/go.mod
+++ b/health-probe-proxy/go.mod
@@ -1,6 +1,6 @@
 module health-probe-proxy
 
-go 1.23.1
+go 1.22.0
 
 require (
 	github.com/pires/go-proxyproto v0.7.0
diff --git a/pkg/azclient/Makefile b/pkg/azclient/Makefile
index 95591516a..13cfddf1d 100644
--- a/pkg/azclient/Makefile
+++ b/pkg/azclient/Makefile
@@ -79,7 +79,7 @@ generatecode: build ## Generate client
 	$(TYPESCAFFOLD) --package github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 --package-alias armcompute --resource Disk --client-name DisksClient --ratelimitkey diskRateLimit
 	$(TYPESCAFFOLD) --package github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 --package-alias armcompute --resource AvailabilitySet --client-name AvailabilitySetsClient --verbs get,list --ratelimitkey availabilitySetRateLimit
 	$(TYPESCAFFOLD) --package github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 --package-alias armcompute --resource VirtualMachine --client-name VirtualMachinesClient --verbs createorupdate,delete,list --expand --ratelimitkey virtualMachineRateLimit
-	$(TYPESCAFFOLD) --package github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 --package-alias armcompute --resource VirtualMachineScaleSet --client-name VirtualMachineScaleSetsClient --verbs get,createorupdate,delete,list --ratelimitkey virtualMachineScaleSetRateLimit --expand
+	$(TYPESCAFFOLD) --package github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 --package-alias armcompute --resource VirtualMachineScaleSet --client-name VirtualMachineScaleSetsClient --verbs get,createorupdate,delete,list --ratelimitkey virtualMachineSizesRateLimit --expand
 	$(TYPESCAFFOLD) --package github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 --package-alias armcompute --resource VirtualMachineScaleSet --subresource VirtualMachineScaleSetVM --client-name VirtualMachineScaleSetVMsClient --verbs get,delete,list 
 	$(TYPESCAFFOLD) --package github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 --package-alias armcompute --resource Snapshot --client-name SnapshotsClient --verbs get,createorupdate,delete --ratelimitkey snapshotRateLimit
 	$(TYPESCAFFOLD) --package github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 --package-alias armcompute --resource SSHPublicKeyResource --client-name SSHPublicKeysClient --verbs get,listbyrg
@@ -94,7 +94,7 @@ generatecode: build ## Generate client
 	$(TYPESCAFFOLD) --package github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 --package-alias armnetwork --resource SecurityGroup --client-name SecurityGroupsClient --verbs get,createorupdate,delete,list --ratelimitkey securityGroupRateLimit
 	$(TYPESCAFFOLD) --package github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 --package-alias armnetwork --resource PrivateLinkService --client-name PrivateLinkServicesClient --verbs get,createorupdate,delete,list --expand --ratelimitkey privateLinkServiceRateLimit
 	$(TYPESCAFFOLD) --package github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 --package-alias armnetwork --resource IPGroup --client-name IPGroupsClient --verbs get,createorupdate,delete,listbyrg --expand --ratelimitkey ipGroupRateLimit
-	$(TYPESCAFFOLD) --package github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage --package-alias armstorage --resource Account --client-name AccountsClient --verbs listbyrg --expand --ratelimitkey storageAccountRateLimit
+	$(TYPESCAFFOLD) --package github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage --package-alias armstorage --resource Account --client-name AccountsClient --verbs listbyrg --expand
 	$(TYPESCAFFOLD) --package github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns --package-alias armprivatedns --resource PrivateZone --client-name PrivateZonesClient  --verbs get,createorupdate --ratelimitkey privateDNSRateLimit
 	$(TYPESCAFFOLD) --package github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns --package-alias armprivatedns --resource PrivateZone --subresource VirtualNetworkLink --client-name VirtualNetworkLinksClient --verbs get,createorupdate --ratelimitkey virtualNetworkRateLimit
 	$(TYPESCAFFOLD) --package github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage --package-alias armstorage --resource Account --subresource FileShare --client-name FileSharesClient --verbs get,createorupdate,delete,list
@@ -105,6 +105,7 @@ generatecode: build ## Generate client
 	$(TYPESCAFFOLD) --package github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources --package-alias armresources --resource Provider --client-name ProvidersClient 
 	$(TYPESCAFFOLD) --package github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v2 --package-alias armauthorization --resource RoleAssignment --client-name RoleAssignmentsClient
 	$(TYPESCAFFOLD) --package github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/authorization/armauthorization/v2 --package-alias armauthorization --resource RoleDefinition --client-name RoleDefinitionsClient
+	$(TYPESCAFFOLD) --package github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/msi/armmsi --package-alias armmsi --resource Identity --client-name UserAssignedIdentitiesClient
 
 
 .PHONY: generateimpl
diff --git a/pkg/azclient/accountclient/interface.go b/pkg/azclient/accountclient/interface.go
index ae83f8d16..0a8ff91de 100644
--- a/pkg/azclient/accountclient/interface.go
+++ b/pkg/azclient/accountclient/interface.go
@@ -25,7 +25,7 @@ import (
 	"sigs.k8s.io/cloud-provider-azure/pkg/azclient/utils"
 )
 
-// +azure:client:verbs=listbyrg,resource=Account,packageName=github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage,packageAlias=armstorage,clientName=AccountsClient,expand=true,crossSubFactory=true,rateLimitKey=storageAccountRateLimit
+// +azure:client:verbs=listbyrg,resource=Account,packageName=github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage,packageAlias=armstorage,clientName=AccountsClient,expand=true,crossSubFactory=true
 type Interface interface {
 	utils.ListFunc[armstorage.Account]
 	Create(ctx context.Context, resourceGroupName string, accountName string, resource *armstorage.AccountCreateParameters) (*armstorage.Account, error)
diff --git a/pkg/azclient/client-gen/generator/template.go b/pkg/azclient/client-gen/generator/template.go
index 84c0c7ebd..3d9dd54c8 100644
--- a/pkg/azclient/client-gen/generator/template.go
+++ b/pkg/azclient/client-gen/generator/template.go
@@ -40,7 +40,7 @@ type Client struct{
 `))
 
 var ClientFactoryTemplate = template.Must(template.New("object-scaffolding-factory").Parse(`
-func New({{if not .OutOfSubscriptionScope}}subscriptionID string, {{end}}credential azcore.TokenCredential, options *arm.ClientOptions) (Interface, error) {
+func New(subscriptionID string, credential azcore.TokenCredential, options *arm.ClientOptions) (Interface, error) {
 	if options == nil {
 		options = utils.GetDefaultOption()
 	}
@@ -227,7 +227,7 @@ var _ = ginkgo.BeforeSuite(func(ctx context.Context) {
 		},
 	})
 	gomega.Expect(err).NotTo(gomega.HaveOccurred())
-	realClient, err = New({{if not .OutOfSubscriptionScope}}subscriptionID, {{end}}recorder.TokenCredential(), &arm.ClientOptions{
+	realClient, err = New(subscriptionID, recorder.TokenCredential(), &arm.ClientOptions{
 		ClientOptions: azcore.ClientOptions{
 			Transport: recorder.HTTPClient(),
 			TracingProvider: utils.TracingProvider,
diff --git a/pkg/azclient/client-gen/go.mod b/pkg/azclient/client-gen/go.mod
index 0a55a83f6..5794cf304 100644
--- a/pkg/azclient/client-gen/go.mod
+++ b/pkg/azclient/client-gen/go.mod
@@ -1,6 +1,6 @@
 module sigs.k8s.io/cloud-provider-azure/pkg/azclient/client-gen
 
-go 1.23.1
+go 1.22.5
 
 require (
 	github.com/spf13/cobra v1.8.1
diff --git a/pkg/azclient/configloader/go.mod b/pkg/azclient/configloader/go.mod
index ab18ad1eb..6d14e295b 100644
--- a/pkg/azclient/configloader/go.mod
+++ b/pkg/azclient/configloader/go.mod
@@ -1,6 +1,8 @@
 module sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader
 
-go 1.23.1
+go 1.22.0
+
+toolchain go1.22.3
 
 require (
 	github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0
diff --git a/pkg/azclient/factory.go b/pkg/azclient/factory.go
index 697f9d24d..c1adfeccc 100644
--- a/pkg/azclient/factory.go
+++ b/pkg/azclient/factory.go
@@ -25,6 +25,7 @@ import (
 	"sigs.k8s.io/cloud-provider-azure/pkg/azclient/deploymentclient"
 	"sigs.k8s.io/cloud-provider-azure/pkg/azclient/diskclient"
 	"sigs.k8s.io/cloud-provider-azure/pkg/azclient/fileshareclient"
+	"sigs.k8s.io/cloud-provider-azure/pkg/azclient/identityclient"
 	"sigs.k8s.io/cloud-provider-azure/pkg/azclient/interfaceclient"
 	"sigs.k8s.io/cloud-provider-azure/pkg/azclient/ipgroupclient"
 	"sigs.k8s.io/cloud-provider-azure/pkg/azclient/loadbalancerclient"
@@ -64,6 +65,7 @@ type ClientFactory interface {
 	GetDiskClientForSub(subscriptionID string) (diskclient.Interface, error)
 	GetFileShareClient() fileshareclient.Interface
 	GetFileShareClientForSub(subscriptionID string) (fileshareclient.Interface, error)
+	GetIdentityClient() identityclient.Interface
 	GetInterfaceClient() interfaceclient.Interface
 	GetIPGroupClient() ipgroupclient.Interface
 	GetLoadBalancerClient() loadbalancerclient.Interface
diff --git a/pkg/azclient/factory_gen.go b/pkg/azclient/factory_gen.go
index c31196fb7..9c820a0f6 100644
--- a/pkg/azclient/factory_gen.go
+++ b/pkg/azclient/factory_gen.go
@@ -32,6 +32,7 @@ import (
 	"sigs.k8s.io/cloud-provider-azure/pkg/azclient/deploymentclient"
 	"sigs.k8s.io/cloud-provider-azure/pkg/azclient/diskclient"
 	"sigs.k8s.io/cloud-provider-azure/pkg/azclient/fileshareclient"
+	"sigs.k8s.io/cloud-provider-azure/pkg/azclient/identityclient"
 	"sigs.k8s.io/cloud-provider-azure/pkg/azclient/interfaceclient"
 	"sigs.k8s.io/cloud-provider-azure/pkg/azclient/ipgroupclient"
 	"sigs.k8s.io/cloud-provider-azure/pkg/azclient/loadbalancerclient"
@@ -72,6 +73,7 @@ type ClientFactoryImpl struct {
 	deploymentclientInterface               deploymentclient.Interface
 	diskclientInterface                     sync.Map
 	fileshareclientInterface                sync.Map
+	identityclientInterface                 identityclient.Interface
 	interfaceclientInterface                interfaceclient.Interface
 	ipgroupclientInterface                  ipgroupclient.Interface
 	loadbalancerclientInterface             loadbalancerclient.Interface
@@ -158,6 +160,12 @@ func NewClientFactory(config *ClientFactoryConfig, armConfig *ARMClientConfig, c
 		return nil, err
 	}
 
+	//initialize identityclient
+	factory.identityclientInterface, err = factory.createIdentityClient(config.SubscriptionID)
+	if err != nil {
+		return nil, err
+	}
+
 	//initialize interfaceclient
 	factory.interfaceclientInterface, err = factory.createInterfaceClient(config.SubscriptionID)
 	if err != nil {
@@ -317,12 +325,6 @@ func (factory *ClientFactoryImpl) createAccountClient(subscription string) (acco
 		return nil, err
 	}
 
-	//add ratelimit policy
-	ratelimitOption := factory.facotryConfig.GetRateLimitConfig("storageAccountRateLimit")
-	rateLimitPolicy := ratelimit.NewRateLimitPolicy(ratelimitOption)
-	if rateLimitPolicy != nil {
-		options.ClientOptions.PerCallPolicies = append(options.ClientOptions.PerCallPolicies, rateLimitPolicy)
-	}
 	for _, optionMutFn := range factory.clientOptionsMutFn {
 		if optionMutFn != nil {
 			optionMutFn(options)
@@ -535,6 +537,25 @@ func (factory *ClientFactoryImpl) GetFileShareClientForSub(subscriptionID string
 	return clientImp.(fileshareclient.Interface), nil
 }
 
+func (factory *ClientFactoryImpl) createIdentityClient(subscription string) (identityclient.Interface, error) {
+	//initialize identityclient
+	options, err := GetDefaultResourceClientOption(factory.armConfig, factory.facotryConfig)
+	if err != nil {
+		return nil, err
+	}
+
+	for _, optionMutFn := range factory.clientOptionsMutFn {
+		if optionMutFn != nil {
+			optionMutFn(options)
+		}
+	}
+	return identityclient.New(subscription, factory.cred, options)
+}
+
+func (factory *ClientFactoryImpl) GetIdentityClient() identityclient.Interface {
+	return factory.identityclientInterface
+}
+
 func (factory *ClientFactoryImpl) createInterfaceClient(subscription string) (interfaceclient.Interface, error) {
 	//initialize interfaceclient
 	options, err := GetDefaultResourceClientOption(factory.armConfig, factory.facotryConfig)
@@ -1037,7 +1058,7 @@ func (factory *ClientFactoryImpl) createVirtualMachineScaleSetClient(subscriptio
 	}
 
 	//add ratelimit policy
-	ratelimitOption := factory.facotryConfig.GetRateLimitConfig("virtualMachineScaleSetRateLimit")
+	ratelimitOption := factory.facotryConfig.GetRateLimitConfig("virtualMachineSizesRateLimit")
 	rateLimitPolicy := ratelimit.NewRateLimitPolicy(ratelimitOption)
 	if rateLimitPolicy != nil {
 		options.ClientOptions.PerCallPolicies = append(options.ClientOptions.PerCallPolicies, rateLimitPolicy)
diff --git a/pkg/azclient/go.mod b/pkg/azclient/go.mod
index bfc0b127a..361ce2835 100644
--- a/pkg/azclient/go.mod
+++ b/pkg/azclient/go.mod
@@ -1,6 +1,8 @@
 module sigs.k8s.io/cloud-provider-azure/pkg/azclient
 
-go 1.23.1
+go 1.22
+
+toolchain go1.23.0
 
 require (
 	github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0
@@ -10,6 +12,7 @@ require (
 	github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerregistry/armcontainerregistry v1.2.0
 	github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v4 v4.8.0
 	github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault v1.4.0
+	github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/msi/armmsi v1.2.0
 	github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.3.0
 	github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.2.0
 	github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources v1.2.0
@@ -18,8 +21,8 @@ require (
 	github.com/google/uuid v1.6.0
 	github.com/onsi/ginkgo/v2 v2.20.2
 	github.com/onsi/gomega v1.34.2
-	go.opentelemetry.io/otel v1.30.0
-	go.opentelemetry.io/otel/metric v1.30.0
+	go.opentelemetry.io/otel v1.29.0
+	go.opentelemetry.io/otel/metric v1.29.0
 	go.uber.org/mock v0.4.0
 	golang.org/x/crypto v0.27.0
 	golang.org/x/sync v0.8.0
diff --git a/pkg/azclient/go.sum b/pkg/azclient/go.sum
index 38d1d8e3d..c706cdb4a 100644
--- a/pkg/azclient/go.sum
+++ b/pkg/azclient/go.sum
@@ -20,6 +20,8 @@ github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault v1.4.
 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault v1.4.0/go.mod h1:StGsLbuJh06Bd8IBfnAlIFV3fLb+gkczONWf15hpX2E=
 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/managementgroups/armmanagementgroups v1.0.0 h1:pPvTJ1dY0sA35JOeFq6TsY2xj6Z85Yo23Pj4wCCvu4o=
 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/managementgroups/armmanagementgroups v1.0.0/go.mod h1:mLfWfj8v3jfWKsL9G4eoBoXVcsqcIUTapmdKy7uGOp0=
+github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/msi/armmsi v1.2.0 h1:z4YeiSXxnUI+PqB46Yj6MZA3nwb1CcJIkEMDrzUd8Cs=
+github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/msi/armmsi v1.2.0/go.mod h1:rko9SzMxcMk0NJsNAxALEGaTYyy79bNRwxgJfrH0Spw=
 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.3.0 h1:bXwSugBiSbgtz7rOtbfGf+woewp4f06orW9OP5BjHLA=
 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4 v4.3.0/go.mod h1:Y/HgrePTmGy9HjdSGTqZNa+apUpTVIEVKXJyARP2lrk=
 github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/privatedns/armprivatedns v1.2.0 h1:9Eih8XcEeQnFD0ntMlUDleKMzfeCeUfa+VbnDCI4AZs=
@@ -68,12 +70,12 @@ github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU
 github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4=
 github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
 github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
-go.opentelemetry.io/otel v1.30.0 h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts=
-go.opentelemetry.io/otel v1.30.0/go.mod h1:tFw4Br9b7fOS+uEao81PJjVMjW/5fvNCbpsDIXqP0pc=
-go.opentelemetry.io/otel/metric v1.30.0 h1:4xNulvn9gjzo4hjg+wzIKG7iNFEaBMX00Qd4QIZs7+w=
-go.opentelemetry.io/otel/metric v1.30.0/go.mod h1:aXTfST94tswhWEb+5QjlSqG+cZlmyXy/u8jFpor3WqQ=
-go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8dQ9wmc=
-go.opentelemetry.io/otel/trace v1.30.0/go.mod h1:5EyKqTzzmyqB9bwtCCq6pDLktPK6fmGf/Dph+8VI02o=
+go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw=
+go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8=
+go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc=
+go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8=
+go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4=
+go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ=
 go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
 go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
 golang.org/x/crypto v0.27.0 h1:GXm2NjJrPaiv/h1tb2UH8QfgC/hOf/+z0p6PT8o1w7A=
diff --git a/pkg/azclient/identityclient/interface.go b/pkg/azclient/identityclient/interface.go
new file mode 100644
index 000000000..3e754ae82
--- /dev/null
+++ b/pkg/azclient/identityclient/interface.go
@@ -0,0 +1,29 @@
+/*
+Copyright 2024 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.
+*/
+
+// +azure:enableclientgen:=true
+package identityclient
+
+import (
+	armmsi "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/msi/armmsi"
+
+	"sigs.k8s.io/cloud-provider-azure/pkg/azclient/utils"
+)
+
+// +azure:client:verbs=get,resource=Identity,packageName=github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/msi/armmsi,packageAlias=armmsi,clientName=UserAssignedIdentitiesClient,expand=false
+type Interface interface {
+	utils.GetFunc[armmsi.Identity]
+}
diff --git a/pkg/azclient/identityclient/mock_identityclient/interface.go b/pkg/azclient/identityclient/mock_identityclient/interface.go
new file mode 100644
index 000000000..f5944d385
--- /dev/null
+++ b/pkg/azclient/identityclient/mock_identityclient/interface.go
@@ -0,0 +1,72 @@
+// /*
+// Copyright 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.
+// */
+
+// Code generated by MockGen. DO NOT EDIT.
+// Source: identityclient/interface.go
+//
+// Generated by this command:
+//
+//	mockgen -package mock_identityclient -source identityclient/interface.go
+//
+
+// Package mock_identityclient is a generated GoMock package.
+package mock_identityclient
+
+import (
+	context "context"
+	reflect "reflect"
+
+	armmsi "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/msi/armmsi"
+	gomock "go.uber.org/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
+}
+
+// Get mocks base method.
+func (m *MockInterface) Get(ctx context.Context, resourceGroupName, resourceName string) (*armmsi.Identity, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "Get", ctx, resourceGroupName, resourceName)
+	ret0, _ := ret[0].(*armmsi.Identity)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// Get indicates an expected call of Get.
+func (mr *MockInterfaceMockRecorder) Get(ctx, resourceGroupName, resourceName any) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Get", reflect.TypeOf((*MockInterface)(nil).Get), ctx, resourceGroupName, resourceName)
+}
diff --git a/pkg/azclient/identityclient/zz_generated_client.go b/pkg/azclient/identityclient/zz_generated_client.go
new file mode 100644
index 000000000..c0ad05151
--- /dev/null
+++ b/pkg/azclient/identityclient/zz_generated_client.go
@@ -0,0 +1,71 @@
+// /*
+// Copyright 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.
+// */
+
+// Code generated by client-gen. DO NOT EDIT.
+package identityclient
+
+import (
+	"context"
+
+	"github.com/Azure/azure-sdk-for-go/sdk/azcore"
+	"github.com/Azure/azure-sdk-for-go/sdk/azcore/arm"
+	"github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
+	"github.com/Azure/azure-sdk-for-go/sdk/azcore/tracing"
+	armmsi "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/msi/armmsi"
+
+	"sigs.k8s.io/cloud-provider-azure/pkg/azclient/metrics"
+	"sigs.k8s.io/cloud-provider-azure/pkg/azclient/utils"
+)
+
+type Client struct {
+	*armmsi.UserAssignedIdentitiesClient
+	subscriptionID string
+	tracer         tracing.Tracer
+}
+
+func New(subscriptionID string, credential azcore.TokenCredential, options *arm.ClientOptions) (Interface, error) {
+	if options == nil {
+		options = utils.GetDefaultOption()
+	}
+	tr := options.TracingProvider.NewTracer(utils.ModuleName, utils.ModuleVersion)
+
+	client, err := armmsi.NewUserAssignedIdentitiesClient(subscriptionID, credential, options)
+	if err != nil {
+		return nil, err
+	}
+	return &Client{
+		UserAssignedIdentitiesClient: client,
+		subscriptionID:               subscriptionID,
+		tracer:                       tr,
+	}, nil
+}
+
+const GetOperationName = "UserAssignedIdentitiesClient.Get"
+
+// Get gets the Identity
+func (client *Client) Get(ctx context.Context, resourceGroupName string, resourceName string) (result *armmsi.Identity, err error) {
+
+	metricsCtx := metrics.BeginARMRequest(client.subscriptionID, resourceGroupName, "Identity", "get")
+	defer func() { metricsCtx.Observe(ctx, err) }()
+	ctx, endSpan := runtime.StartSpan(ctx, GetOperationName, client.tracer, nil)
+	defer endSpan(err)
+	resp, err := client.UserAssignedIdentitiesClient.Get(ctx, resourceGroupName, resourceName, nil)
+	if err != nil {
+		return nil, err
+	}
+	//handle statuscode
+	return &resp.Identity, nil
+}
diff --git a/pkg/azclient/mock_azclient/interface.go b/pkg/azclient/mock_azclient/interface.go
index 7d7f0cac8..392cbdcb3 100644
--- a/pkg/azclient/mock_azclient/interface.go
+++ b/pkg/azclient/mock_azclient/interface.go
@@ -37,6 +37,7 @@ import (
 	deploymentclient "sigs.k8s.io/cloud-provider-azure/pkg/azclient/deploymentclient"
 	diskclient "sigs.k8s.io/cloud-provider-azure/pkg/azclient/diskclient"
 	fileshareclient "sigs.k8s.io/cloud-provider-azure/pkg/azclient/fileshareclient"
+	identityclient "sigs.k8s.io/cloud-provider-azure/pkg/azclient/identityclient"
 	interfaceclient "sigs.k8s.io/cloud-provider-azure/pkg/azclient/interfaceclient"
 	ipgroupclient "sigs.k8s.io/cloud-provider-azure/pkg/azclient/ipgroupclient"
 	loadbalancerclient "sigs.k8s.io/cloud-provider-azure/pkg/azclient/loadbalancerclient"
@@ -259,6 +260,20 @@ func (mr *MockClientFactoryMockRecorder) GetIPGroupClient() *gomock.Call {
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetIPGroupClient", reflect.TypeOf((*MockClientFactory)(nil).GetIPGroupClient))
 }
 
+// GetIdentityClient mocks base method.
+func (m *MockClientFactory) GetIdentityClient() identityclient.Interface {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "GetIdentityClient")
+	ret0, _ := ret[0].(identityclient.Interface)
+	return ret0
+}
+
+// GetIdentityClient indicates an expected call of GetIdentityClient.
+func (mr *MockClientFactoryMockRecorder) GetIdentityClient() *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetIdentityClient", reflect.TypeOf((*MockClientFactory)(nil).GetIdentityClient))
+}
+
 // GetInterfaceClient mocks base method.
 func (m *MockClientFactory) GetInterfaceClient() interfaceclient.Interface {
 	m.ctrl.T.Helper()
diff --git a/pkg/azclient/roledefinitionclient/zz_generated_client.go b/pkg/azclient/roledefinitionclient/zz_generated_client.go
index e4c66843d..8d94af4a5 100644
--- a/pkg/azclient/roledefinitionclient/zz_generated_client.go
+++ b/pkg/azclient/roledefinitionclient/zz_generated_client.go
@@ -32,7 +32,7 @@ type Client struct {
 	tracer tracing.Tracer
 }
 
-func New(credential azcore.TokenCredential, options *arm.ClientOptions) (Interface, error) {
+func New(subscriptionID string, credential azcore.TokenCredential, options *arm.ClientOptions) (Interface, error) {
 	if options == nil {
 		options = utils.GetDefaultOption()
 	}
diff --git a/pkg/azclient/trace/go.mod b/pkg/azclient/trace/go.mod
index ec3491dee..52ae49406 100644
--- a/pkg/azclient/trace/go.mod
+++ b/pkg/azclient/trace/go.mod
@@ -1,19 +1,19 @@
 module sigs.k8s.io/cloud-provider-azure/pkg/azclient/trace
 
-go 1.23.1
+go 1.22.5
 
 require (
 	github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0
-	go.opentelemetry.io/otel v1.30.0
-	go.opentelemetry.io/otel/trace v1.30.0
-	sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.0.53
+	go.opentelemetry.io/otel v1.29.0
+	go.opentelemetry.io/otel/trace v1.29.0
+	sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.0.48
 )
 
 require (
 	github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
 	github.com/go-logr/logr v1.4.2 // indirect
 	github.com/go-logr/stdr v1.2.2 // indirect
-	go.opentelemetry.io/otel/metric v1.30.0 // indirect
+	go.opentelemetry.io/otel/metric v1.29.0 // indirect
 	golang.org/x/net v0.28.0 // indirect
 	golang.org/x/text v0.18.0 // indirect
 )
diff --git a/pkg/azclient/trace/go.sum b/pkg/azclient/trace/go.sum
index 7fa52a4c9..4bef6185c 100644
--- a/pkg/azclient/trace/go.sum
+++ b/pkg/azclient/trace/go.sum
@@ -23,12 +23,12 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
 github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
-go.opentelemetry.io/otel v1.30.0 h1:F2t8sK4qf1fAmY9ua4ohFS/K+FUuOPemHUIXHtktrts=
-go.opentelemetry.io/otel v1.30.0/go.mod h1:tFw4Br9b7fOS+uEao81PJjVMjW/5fvNCbpsDIXqP0pc=
-go.opentelemetry.io/otel/metric v1.30.0 h1:4xNulvn9gjzo4hjg+wzIKG7iNFEaBMX00Qd4QIZs7+w=
-go.opentelemetry.io/otel/metric v1.30.0/go.mod h1:aXTfST94tswhWEb+5QjlSqG+cZlmyXy/u8jFpor3WqQ=
-go.opentelemetry.io/otel/trace v1.30.0 h1:7UBkkYzeg3C7kQX8VAidWh2biiQbtAKjyIML8dQ9wmc=
-go.opentelemetry.io/otel/trace v1.30.0/go.mod h1:5EyKqTzzmyqB9bwtCCq6pDLktPK6fmGf/Dph+8VI02o=
+go.opentelemetry.io/otel v1.29.0 h1:PdomN/Al4q/lN6iBJEN3AwPvUiHPMlt93c8bqTG5Llw=
+go.opentelemetry.io/otel v1.29.0/go.mod h1:N/WtXPs1CNCUEx+Agz5uouwCba+i+bJGFicT8SR4NP8=
+go.opentelemetry.io/otel/metric v1.29.0 h1:vPf/HFWTNkPu1aYeIsc98l4ktOQaL6LeSoeV2g+8YLc=
+go.opentelemetry.io/otel/metric v1.29.0/go.mod h1:auu/QWieFVWx+DmQOUMgj0F8LHWdgalxXqvp7BII/W8=
+go.opentelemetry.io/otel/trace v1.29.0 h1:J/8ZNK4XgR7a21DZUAsbF8pZ5Jcw1VhACmnYt39JTi4=
+go.opentelemetry.io/otel/trace v1.29.0/go.mod h1:eHl3w0sp3paPkYstJOmAimxhiFXPg+MMTlEh3nsQgWQ=
 golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE=
 golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg=
 golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
@@ -39,5 +39,5 @@ golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24=
 golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ=
 gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
 gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
-sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.0.53 h1:MGXhj7OeEx5uIWzEJ5f+KckZ0QjknWpPdxVxsUvr7c8=
-sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.0.53/go.mod h1:85bpBY1g3Ecsjf8ZCNz5rVfzEKgW3mZ9iJ7YmD0cSiM=
+sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.0.48 h1:SgFz1OTl7X3WA0okx4sJ+zZFfy29rrmttUBPyjRqAZ8=
+sigs.k8s.io/cloud-provider-azure/pkg/azclient v0.0.48/go.mod h1:tsXh9gmmPDbX/Pcji58hLBEXB4x5o/v17PIsu9Nd42w=
diff --git a/pkg/azclient/virtualmachinescalesetclient/interface.go b/pkg/azclient/virtualmachinescalesetclient/interface.go
index 8f189cfc4..852a73470 100644
--- a/pkg/azclient/virtualmachinescalesetclient/interface.go
+++ b/pkg/azclient/virtualmachinescalesetclient/interface.go
@@ -25,7 +25,7 @@ import (
 	"sigs.k8s.io/cloud-provider-azure/pkg/azclient/utils"
 )
 
-// +azure:client:verbs=createorupdate;delete;list,resource=VirtualMachineScaleSet,packageName=github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5,packageAlias=armcompute,clientName=VirtualMachineScaleSetsClient,expand=true,rateLimitKey=virtualMachineScaleSetRateLimit
+// +azure:client:verbs=createorupdate;delete;list,resource=VirtualMachineScaleSet,packageName=github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5,packageAlias=armcompute,clientName=VirtualMachineScaleSetsClient,expand=true,rateLimitKey=virtualMachineSizesRateLimit
 type Interface interface {
 	Get(ctx context.Context, resourceGroupName string, resourceName string, expand *armcompute.ExpandTypesForGetVMScaleSets) (result *armcompute.VirtualMachineScaleSet, rerr error)
 	utils.CreateOrUpdateFunc[armcompute.VirtualMachineScaleSet]
diff --git a/pkg/credentialprovider/azure_credentials.go b/pkg/credentialprovider/azure_credentials.go
index 2ffdceee7..2b929b9ab 100644
--- a/pkg/credentialprovider/azure_credentials.go
+++ b/pkg/credentialprovider/azure_credentials.go
@@ -27,6 +27,7 @@ import (
 	"time"
 
 	"sigs.k8s.io/cloud-provider-azure/pkg/azclient"
+	"sigs.k8s.io/cloud-provider-azure/pkg/azclient/armauth"
 	"sigs.k8s.io/cloud-provider-azure/pkg/azclient/configloader"
 	providerconfig "sigs.k8s.io/cloud-provider-azure/pkg/provider/config"
 
@@ -59,10 +60,9 @@ type CredentialProvider interface {
 
 // acrProvider implements the credential provider interface for Azure Container Registry.
 type acrProvider struct {
-	config         *providerconfig.AzureAuthConfig
-	environment    *azclient.Environment
-	credential     azcore.TokenCredential
-	registryMirror map[string]string // Registry mirror relation: source registry -> target registry
+	config      *providerconfig.AzureAuthConfig
+	environment *azclient.Environment
+	credential  azcore.TokenCredential
 }
 
 func NewAcrProvider(config *providerconfig.AzureAuthConfig, environment *azclient.Environment, credential azcore.TokenCredential) CredentialProvider {
@@ -74,7 +74,7 @@ func NewAcrProvider(config *providerconfig.AzureAuthConfig, environment *azclien
 }
 
 // NewAcrProvider creates a new instance of the ACR provider.
-func NewAcrProviderFromConfig(configFile string, registryMirrorStr string) (CredentialProvider, error) {
+func NewAcrProviderFromConfig(configFile string) (CredentialProvider, error) {
 	if len(configFile) == 0 {
 		return nil, errors.New("no azure credential file is provided")
 	}
@@ -116,19 +116,19 @@ func NewAcrProviderFromConfig(configFile string, registryMirrorStr string) (Cred
 		if err != nil {
 			return nil, err
 		}
+		managedIdentityCredential = armauth.NewExpireEarlyTokenWrapper(managedIdentityCredential)
 	}
 
 	return &acrProvider{
-		config:         config,
-		credential:     managedIdentityCredential,
-		environment:    &envConfig,
-		registryMirror: parseRegistryMirror(registryMirrorStr),
+		config:      config,
+		credential:  managedIdentityCredential,
+		environment: &envConfig,
 	}, nil
 }
 
 func (a *acrProvider) GetCredentials(ctx context.Context, image string, _ []string) (*v1.CredentialProviderResponse, error) {
-	targetloginServer, sourceloginServer := a.parseACRLoginServerFromImage(image)
-	if targetloginServer == "" {
+	loginServer := a.parseACRLoginServerFromImage(image)
+	if loginServer == "" {
 		klog.V(2).Infof("image(%s) is not from ACR, return empty authentication", image)
 		return &v1.CredentialProviderResponse{
 			CacheKeyType:  v1.RegistryPluginCacheKeyType,
@@ -150,20 +150,16 @@ func (a *acrProvider) GetCredentials(ctx context.Context, image string, _ []stri
 	}
 
 	if a.config.UseManagedIdentityExtension {
-		username, password, err := a.getFromACR(ctx, targetloginServer)
+		username, password, err := a.getFromACR(ctx, loginServer)
 		if err != nil {
-			klog.Errorf("error getting credentials from ACR for %s: %s", targetloginServer, err)
+			klog.Errorf("error getting credentials from ACR for %s: %s", loginServer, err)
 			return nil, err
 		}
 
-		authConfig := v1.AuthConfig{
+		response.Auth[loginServer] = v1.AuthConfig{
 			Username: username,
 			Password: password,
 		}
-		response.Auth[targetloginServer] = authConfig
-		if sourceloginServer != "" {
-			response.Auth[sourceloginServer] = authConfig
-		}
 	} else {
 		// Add our entry for each of the supported container registry URLs
 		for _, url := range containerRegistryUrls {
@@ -233,16 +229,13 @@ func (a *acrProvider) getFromACR(ctx context.Context, loginServer string) (strin
 	return dockerTokenLoginUsernameGUID, registryRefreshToken, nil
 }
 
-// parseACRLoginServerFromImage inputs an image URL and outputs login servers of target registry and source registry if --registry-mirror is set.
-// Input is expected in following format: foo.azurecr.io/bar/imageName:version
+// parseACRLoginServerFromImage takes image as parameter and returns login server of it.
+// Parameter `image` is expected in following format: foo.azurecr.io/bar/imageName:version
 // If the provided image is not an acr image, this function will return an empty string.
-func (a *acrProvider) parseACRLoginServerFromImage(image string) (string, string) {
-	targetImage, sourceRegistry := a.processImageWithRegistryMirror(image)
-
-	match := acrRE.FindAllString(targetImage, -1)
+func (a *acrProvider) parseACRLoginServerFromImage(image string) string {
+	match := acrRE.FindAllString(image, -1)
 	if len(match) == 1 {
-		targetRegistry := match[0]
-		return targetRegistry, sourceRegistry
+		return match[0]
 	}
 
 	// handle the custom cloud case
@@ -250,42 +243,13 @@ func (a *acrProvider) parseACRLoginServerFromImage(image string) (string, string
 		cloudAcrSuffix := a.environment.ContainerRegistryDNSSuffix
 		cloudAcrSuffixLength := len(cloudAcrSuffix)
 		if cloudAcrSuffixLength > 0 {
-			customAcrSuffixIndex := strings.Index(targetImage, cloudAcrSuffix)
+			customAcrSuffixIndex := strings.Index(image, cloudAcrSuffix)
 			if customAcrSuffixIndex != -1 {
 				endIndex := customAcrSuffixIndex + cloudAcrSuffixLength
-				return targetImage[0:endIndex], sourceRegistry
+				return image[0:endIndex]
 			}
 		}
 	}
 
-	return "", ""
-}
-
-// With acrProvider registry mirror, e.g. {"mcr.microsoft.com": "abc.azurecr.io"}
-// processImageWithRegistryMirror input format: "mcr.microsoft.com/bar/image:version"
-// output format: "abc.azurecr.io/bar/image:version", "mcr.microsoft.com"
-func (a *acrProvider) processImageWithRegistryMirror(image string) (string, string) {
-	for sourceRegistry, targetRegistry := range a.registryMirror {
-		if strings.HasPrefix(image, sourceRegistry) {
-			return strings.Replace(image, sourceRegistry, targetRegistry, 1), sourceRegistry
-		}
-	}
-	return image, ""
-}
-
-// parseRegistryMirror input format: "--registry-mirror=aaa:bbb,ccc:ddd"
-// output format: map[string]string{"aaa": "bbb", "ccc": "ddd"}
-func parseRegistryMirror(registryMirrorStr string) map[string]string {
-	registryMirror := map[string]string{}
-
-	registryMirrorStr = strings.ReplaceAll(registryMirrorStr, " ", "")
-	for _, mapping := range strings.Split(registryMirrorStr, ",") {
-		parts := strings.Split(mapping, ":")
-		if len(parts) != 2 {
-			klog.Errorf("Invalid registry mirror format: %s", mapping)
-			continue
-		}
-		registryMirror[parts[0]] = parts[1]
-	}
-	return registryMirror
+	return ""
 }
diff --git a/pkg/provider/azure_loadbalancer.go b/pkg/provider/azure_loadbalancer.go
index 90400b4ca..4a4528beb 100644
--- a/pkg/provider/azure_loadbalancer.go
+++ b/pkg/provider/azure_loadbalancer.go
@@ -1650,7 +1650,7 @@ func (az *Cloud) reconcileMultipleStandardLoadBalancerConfigurations(
 		}
 	}
 
-	return az.reconcileMultipleStandardLoadBalancerBackendNodes(clusterName, "", lbs, service, nodes, true)
+	return az.reconcileMultipleStandardLoadBalancerBackendNodes("", lbs, service, nodes)
 }
 
 // reconcileLoadBalancer ensures load balancer exists and the frontend ip config is setup.
@@ -1852,7 +1852,7 @@ func (az *Cloud) reconcileLoadBalancer(ctx context.Context, clusterName string,
 		}()
 
 		if az.useMultipleStandardLoadBalancers() {
-			err := az.reconcileMultipleStandardLoadBalancerBackendNodes(clusterName, lbName, existingLBs, service, nodes, false)
+			err := az.reconcileMultipleStandardLoadBalancerBackendNodes(lbName, existingLBs, service, nodes)
 			if err != nil {
 				return nil, err
 			}
@@ -2151,27 +2151,11 @@ func isLBInList(lbs *[]network.LoadBalancer, lbConfigName string) bool {
 // 2. We only check nodes that are not matched by primary vmSet before we ensure
 // hosts in pool. So the number API calls is under control.
 func (az *Cloud) reconcileMultipleStandardLoadBalancerBackendNodes(
-	clusterName string,
 	lbName string,
 	lbs *[]network.LoadBalancer,
 	service *v1.Service,
 	nodes []*v1.Node,
-	init bool,
 ) error {
-	logger := klog.Background().WithName("reconcileMultipleStandardLoadBalancerBackendNodes").
-		WithValues(
-			"clusterName", clusterName,
-			"lbName", lbName,
-			"service", service.Name,
-			"init", init,
-		)
-	if init {
-		if err := az.recordExistingNodesOnLoadBalancers(clusterName, lbs); err != nil {
-			logger.Error(err, "failed to record existing nodes on load balancers")
-			return err
-		}
-	}
-
 	// Remove the nodes from the load balancer configurations if they are not in the node list.
 	nodeNameToLBConfigIDXMap := az.removeDeletedNodesFromLoadBalancerConfigurations(nodes)
 
@@ -2188,38 +2172,6 @@ func (az *Cloud) reconcileMultipleStandardLoadBalancerBackendNodes(
 	return nil
 }
 
-// recordExistingNodesOnLoadBalancers restores the node distribution
-// across multiple load balancers each time the cloud provider restarts.
-func (az *Cloud) recordExistingNodesOnLoadBalancers(clusterName string, lbs *[]network.LoadBalancer) error {
-	bi, ok := az.LoadBalancerBackendPool.(*backendPoolTypeNodeIP)
-	if !ok {
-		return errors.New("must use backend pool type nodeIP")
-	}
-	bpNames := getBackendPoolNames(clusterName)
-	for _, lb := range *lbs {
-		if lb.LoadBalancerPropertiesFormat == nil ||
-			lb.LoadBalancerPropertiesFormat.BackendAddressPools == nil {
-			continue
-		}
-		lbName := ptr.Deref(lb.Name, "")
-		for _, backendPool := range *lb.LoadBalancerPropertiesFormat.BackendAddressPools {
-			backendPool := backendPool
-			if found, _ := isLBBackendPoolsExisting(bpNames, backendPool.Name); found {
-				nodeNames := bi.getBackendPoolNodeNames(&backendPool)
-				for i, multiSLBConfig := range az.MultipleStandardLoadBalancerConfigurations {
-					if strings.EqualFold(trimSuffixIgnoreCase(
-						lbName, consts.InternalLoadBalancerNameSuffix,
-					), multiSLBConfig.Name) {
-						az.MultipleStandardLoadBalancerConfigurations[i].ActiveNodes =
-							utilsets.SafeInsert(multiSLBConfig.ActiveNodes, nodeNames...)
-					}
-				}
-			}
-		}
-	}
-	return nil
-}
-
 func (az *Cloud) reconcileMultipleStandardLoadBalancerConfigurationStatus(wantLb bool, svcName, lbName string) {
 	lbName = trimSuffixIgnoreCase(lbName, consts.InternalLoadBalancerNameSuffix)
 	for i := range az.MultipleStandardLoadBalancerConfigurations {
diff --git a/pkg/provider/azure_loadbalancer_backendpool.go b/pkg/provider/azure_loadbalancer_backendpool.go
index 2cf104761..2962f47d2 100644
--- a/pkg/provider/azure_loadbalancer_backendpool.go
+++ b/pkg/provider/azure_loadbalancer_backendpool.go
@@ -774,20 +774,6 @@ func (bi *backendPoolTypeNodeIP) GetBackendPrivateIPs(clusterName string, servic
 	return backendPrivateIPv4s.UnsortedList(), backendPrivateIPv6s.UnsortedList()
 }
 
-// getBackendPoolNameForService returns all node names in the backend pool.
-func (bi *backendPoolTypeNodeIP) getBackendPoolNodeNames(bp *network.BackendAddressPool) []string {
-	nodeNames := utilsets.NewString()
-	if bp.BackendAddressPoolPropertiesFormat != nil && bp.LoadBalancerBackendAddresses != nil {
-		for _, backendAddress := range *bp.LoadBalancerBackendAddresses {
-			if backendAddress.LoadBalancerBackendAddressPropertiesFormat != nil {
-				ip := ptr.Deref(backendAddress.IPAddress, "")
-				nodeNames.Insert(bi.nodePrivateIPToNodeNameMap[ip])
-			}
-		}
-	}
-	return nodeNames.UnsortedList()
-}
-
 func newBackendPool(lb *network.LoadBalancer, isBackendPoolPreConfigured bool, preConfiguredBackendPoolLoadBalancerTypes, serviceName, lbBackendPoolName string) bool {
 	if isBackendPoolPreConfigured {
 		klog.V(2).Infof("newBackendPool for service (%s)(true): lb backendpool - PreConfiguredBackendPoolLoadBalancerTypes %s has been set but can not find corresponding backend pool %q, ignoring it",
diff --git a/pkg/provider/loadbalancer/iputil/prefix_tree.go b/pkg/provider/loadbalancer/iputil/prefix_tree.go
index 2399c09eb..f8cb78c96 100644
--- a/pkg/provider/loadbalancer/iputil/prefix_tree.go
+++ b/pkg/provider/loadbalancer/iputil/prefix_tree.go
@@ -16,37 +16,14 @@ limitations under the License.
 
 package iputil
 
-import (
-	"net/netip"
-)
+import "net/netip"
 
 type prefixTreeNode struct {
 	masked bool
 	prefix netip.Prefix
 
-	p *prefixTreeNode // parent node
-	l *prefixTreeNode // left child node
-	r *prefixTreeNode // right child node
-}
-
-// pruneToRoot prunes the tree to the root.
-// If a node's left and right children are both masked,
-// it is masked and its children are pruned.
-// This is done recursively up to the root.
-func (n *prefixTreeNode) pruneToRoot() {
-	var node = n
-	for node.p != nil {
-		p := node.p
-		if p.l == nil || !p.l.masked {
-			break
-		}
-		if p.r == nil || !p.r.masked {
-			break
-		}
-		p.masked = true
-		p.l, p.r = nil, nil
-		node = p
-	}
+	l *prefixTreeNode
+	r *prefixTreeNode
 }
 
 type prefixTree struct {
@@ -93,7 +70,6 @@ func (t *prefixTree) Add(prefix netip.Prefix) {
 				}
 				n.l = &prefixTreeNode{
 					prefix: next,
-					p:      n,
 				}
 			}
 			n = n.l
@@ -105,7 +81,6 @@ func (t *prefixTree) Add(prefix netip.Prefix) {
 				}
 				n.r = &prefixTreeNode{
 					prefix: next,
-					p:      n,
 				}
 			}
 			n = n.r
@@ -115,18 +90,10 @@ func (t *prefixTree) Add(prefix netip.Prefix) {
 	}
 
 	n.masked = true
-	n.l, n.r = nil, nil
-	n.pruneToRoot()
 }
 
 // List returns all prefixes in the tree.
 // Overlapping prefixes are merged.
-// It will also collapse the neighboring prefixes.
-// The order of the prefixes in the output is guaranteed.
-//
-// Example:
-//   - [192.168.0.0/16, 192.168.1.0/24, 192.168.0.1/32] -> [192.168.0.0/16]
-//   - [192.168.0.0/32, 192.168.0.1/32] -> [192.168.0.0/31]
 func (t *prefixTree) List() []netip.Prefix {
 	var (
 		rv []netip.Prefix
diff --git a/vendor/golang.org/x/sys/cpu/cpu.go b/vendor/golang.org/x/sys/cpu/cpu.go
index 02609d5b2..ec07aab05 100644
--- a/vendor/golang.org/x/sys/cpu/cpu.go
+++ b/vendor/golang.org/x/sys/cpu/cpu.go
@@ -201,25 +201,6 @@ var S390X struct {
 	_         CacheLinePad
 }
 
-// RISCV64 contains the supported CPU features and performance characteristics for riscv64
-// platforms. The booleans in RISCV64, with the exception of HasFastMisaligned, indicate
-// the presence of RISC-V extensions.
-//
-// It is safe to assume that all the RV64G extensions are supported and so they are omitted from
-// this structure. As riscv64 Go programs require at least RV64G, the code that populates
-// this structure cannot run successfully if some of the RV64G extensions are missing.
-// The struct is padded to avoid false sharing.
-var RISCV64 struct {
-	_                 CacheLinePad
-	HasFastMisaligned bool // Fast misaligned accesses
-	HasC              bool // Compressed instruction-set extension
-	HasV              bool // Vector extension compatible with RVV 1.0
-	HasZba            bool // Address generation instructions extension
-	HasZbb            bool // Basic bit-manipulation extension
-	HasZbs            bool // Single-bit instructions extension
-	_                 CacheLinePad
-}
-
 func init() {
 	archInit()
 	initOptions()
diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go b/vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go
index 7d902b684..cd63e7335 100644
--- a/vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go
+++ b/vendor/golang.org/x/sys/cpu/cpu_linux_noinit.go
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style
 // license that can be found in the LICENSE file.
 
-//go:build linux && !arm && !arm64 && !mips64 && !mips64le && !ppc64 && !ppc64le && !s390x && !riscv64
+//go:build linux && !arm && !arm64 && !mips64 && !mips64le && !ppc64 && !ppc64le && !s390x
 
 package cpu
 
diff --git a/vendor/golang.org/x/sys/cpu/cpu_linux_riscv64.go b/vendor/golang.org/x/sys/cpu/cpu_linux_riscv64.go
deleted file mode 100644
index cb4a0c572..000000000
--- a/vendor/golang.org/x/sys/cpu/cpu_linux_riscv64.go
+++ /dev/null
@@ -1,137 +0,0 @@
-// Copyright 2024 The Go Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style
-// license that can be found in the LICENSE file.
-
-package cpu
-
-import (
-	"syscall"
-	"unsafe"
-)
-
-// RISC-V extension discovery code for Linux. The approach here is to first try the riscv_hwprobe
-// syscall falling back to HWCAP to check for the C extension if riscv_hwprobe is not available.
-//
-// A note on detection of the Vector extension using HWCAP.
-//
-// Support for the Vector extension version 1.0 was added to the Linux kernel in release 6.5.
-// Support for the riscv_hwprobe syscall was added in 6.4. It follows that if the riscv_hwprobe
-// syscall is not available then neither is the Vector extension (which needs kernel support).
-// The riscv_hwprobe syscall should then be all we need to detect the Vector extension.
-// However, some RISC-V board manufacturers ship boards with an older kernel on top of which
-// they have back-ported various versions of the Vector extension patches but not the riscv_hwprobe
-// patches. These kernels advertise support for the Vector extension using HWCAP. Falling
-// back to HWCAP to detect the Vector extension, if riscv_hwprobe is not available, or simply not
-// bothering with riscv_hwprobe at all and just using HWCAP may then seem like an attractive option.
-//
-// Unfortunately, simply checking the 'V' bit in AT_HWCAP will not work as this bit is used by
-// RISC-V board and cloud instance providers to mean different things. The Lichee Pi 4A board
-// and the Scaleway RV1 cloud instances use the 'V' bit to advertise their support for the unratified
-// 0.7.1 version of the Vector Specification. The Banana Pi BPI-F3 and the CanMV-K230 board use
-// it to advertise support for 1.0 of the Vector extension. Versions 0.7.1 and 1.0 of the Vector
-// extension are binary incompatible. HWCAP can then not be used in isolation to populate the
-// HasV field as this field indicates that the underlying CPU is compatible with RVV 1.0.
-//
-// There is a way at runtime to distinguish between versions 0.7.1 and 1.0 of the Vector
-// specification by issuing a RVV 1.0 vsetvli instruction and checking the vill bit of the vtype
-// register. This check would allow us to safely detect version 1.0 of the Vector extension
-// with HWCAP, if riscv_hwprobe were not available. However, the check cannot
-// be added until the assembler supports the Vector instructions.
-//
-// Note the riscv_hwprobe syscall does not suffer from these ambiguities by design as all of the
-// extensions it advertises support for are explicitly versioned. It's also worth noting that
-// the riscv_hwprobe syscall is the only way to detect multi-letter RISC-V extensions, e.g., Zba.
-// These cannot be detected using HWCAP and so riscv_hwprobe must be used to detect the majority
-// of RISC-V extensions.
-//
-// Please see https://docs.kernel.org/arch/riscv/hwprobe.html for more information.
-
-// golang.org/x/sys/cpu is not allowed to depend on golang.org/x/sys/unix so we must
-// reproduce the constants, types and functions needed to make the riscv_hwprobe syscall
-// here.
-
-const (
-	// Copied from golang.org/x/sys/unix/ztypes_linux_riscv64.go.
-	riscv_HWPROBE_KEY_IMA_EXT_0   = 0x4
-	riscv_HWPROBE_IMA_C           = 0x2
-	riscv_HWPROBE_IMA_V           = 0x4
-	riscv_HWPROBE_EXT_ZBA         = 0x8
-	riscv_HWPROBE_EXT_ZBB         = 0x10
-	riscv_HWPROBE_EXT_ZBS         = 0x20
-	riscv_HWPROBE_KEY_CPUPERF_0   = 0x5
-	riscv_HWPROBE_MISALIGNED_FAST = 0x3
-	riscv_HWPROBE_MISALIGNED_MASK = 0x7
-)
-
-const (
-	// sys_RISCV_HWPROBE is copied from golang.org/x/sys/unix/zsysnum_linux_riscv64.go.
-	sys_RISCV_HWPROBE = 258
-)
-
-// riscvHWProbePairs is copied from golang.org/x/sys/unix/ztypes_linux_riscv64.go.
-type riscvHWProbePairs struct {
-	key   int64
-	value uint64
-}
-
-const (
-	// CPU features
-	hwcap_RISCV_ISA_C = 1 << ('C' - 'A')
-)
-
-func doinit() {
-	// A slice of key/value pair structures is passed to the RISCVHWProbe syscall. The key
-	// field should be initialised with one of the key constants defined above, e.g.,
-	// RISCV_HWPROBE_KEY_IMA_EXT_0. The syscall will set the value field to the appropriate value.
-	// If the kernel does not recognise a key it will set the key field to -1 and the value field to 0.
-
-	pairs := []riscvHWProbePairs{
-		{riscv_HWPROBE_KEY_IMA_EXT_0, 0},
-		{riscv_HWPROBE_KEY_CPUPERF_0, 0},
-	}
-
-	// This call only indicates that extensions are supported if they are implemented on all cores.
-	if riscvHWProbe(pairs, 0) {
-		if pairs[0].key != -1 {
-			v := uint(pairs[0].value)
-			RISCV64.HasC = isSet(v, riscv_HWPROBE_IMA_C)
-			RISCV64.HasV = isSet(v, riscv_HWPROBE_IMA_V)
-			RISCV64.HasZba = isSet(v, riscv_HWPROBE_EXT_ZBA)
-			RISCV64.HasZbb = isSet(v, riscv_HWPROBE_EXT_ZBB)
-			RISCV64.HasZbs = isSet(v, riscv_HWPROBE_EXT_ZBS)
-		}
-		if pairs[1].key != -1 {
-			v := pairs[1].value & riscv_HWPROBE_MISALIGNED_MASK
-			RISCV64.HasFastMisaligned = v == riscv_HWPROBE_MISALIGNED_FAST
-		}
-	}
-
-	// Let's double check with HWCAP if the C extension does not appear to be supported.
-	// This may happen if we're running on a kernel older than 6.4.
-
-	if !RISCV64.HasC {
-		RISCV64.HasC = isSet(hwCap, hwcap_RISCV_ISA_C)
-	}
-}
-
-func isSet(hwc uint, value uint) bool {
-	return hwc&value != 0
-}
-
-// riscvHWProbe is a simplified version of the generated wrapper function found in
-// golang.org/x/sys/unix/zsyscall_linux_riscv64.go. We simplify it by removing the
-// cpuCount and cpus parameters which we do not need. We always want to pass 0 for
-// these parameters here so the kernel only reports the extensions that are present
-// on all cores.
-func riscvHWProbe(pairs []riscvHWProbePairs, flags uint) bool {
-	var _zero uintptr
-	var p0 unsafe.Pointer
-	if len(pairs) > 0 {
-		p0 = unsafe.Pointer(&pairs[0])
-	} else {
-		p0 = unsafe.Pointer(&_zero)
-	}
-
-	_, _, e1 := syscall.Syscall6(sys_RISCV_HWPROBE, uintptr(p0), uintptr(len(pairs)), uintptr(0), uintptr(0), uintptr(flags), 0)
-	return e1 == 0
-}
diff --git a/vendor/golang.org/x/sys/cpu/cpu_riscv64.go b/vendor/golang.org/x/sys/cpu/cpu_riscv64.go
index aca3199c9..7f0c79c00 100644
--- a/vendor/golang.org/x/sys/cpu/cpu_riscv64.go
+++ b/vendor/golang.org/x/sys/cpu/cpu_riscv64.go
@@ -8,13 +8,4 @@ package cpu
 
 const cacheLineSize = 64
 
-func initOptions() {
-	options = []option{
-		{Name: "fastmisaligned", Feature: &RISCV64.HasFastMisaligned},
-		{Name: "c", Feature: &RISCV64.HasC},
-		{Name: "v", Feature: &RISCV64.HasV},
-		{Name: "zba", Feature: &RISCV64.HasZba},
-		{Name: "zbb", Feature: &RISCV64.HasZbb},
-		{Name: "zbs", Feature: &RISCV64.HasZbs},
-	}
-}
+func initOptions() {}
diff --git a/vendor/golang.org/x/sys/unix/mkerrors.sh b/vendor/golang.org/x/sys/unix/mkerrors.sh
index e14b766a3..d07dd09eb 100644
--- a/vendor/golang.org/x/sys/unix/mkerrors.sh
+++ b/vendor/golang.org/x/sys/unix/mkerrors.sh
@@ -552,7 +552,6 @@ ccflags="$@"
 		$2 !~ /^RTC_VL_(ACCURACY|BACKUP|DATA)/ &&
 		$2 ~ /^(NETLINK|NLM|NLMSG|NLA|IFA|IFAN|RT|RTC|RTCF|RTN|RTPROT|RTNH|ARPHRD|ETH_P|NETNSA)_/ ||
 		$2 ~ /^SOCK_|SK_DIAG_|SKNLGRP_$/ ||
-		$2 ~ /^(CONNECT|SAE)_/ ||
 		$2 ~ /^FIORDCHK$/ ||
 		$2 ~ /^SIOC/ ||
 		$2 ~ /^TIOC/ ||
diff --git a/vendor/golang.org/x/sys/unix/syscall_darwin.go b/vendor/golang.org/x/sys/unix/syscall_darwin.go
index 099867dee..2d15200ad 100644
--- a/vendor/golang.org/x/sys/unix/syscall_darwin.go
+++ b/vendor/golang.org/x/sys/unix/syscall_darwin.go
@@ -566,43 +566,6 @@ func PthreadFchdir(fd int) (err error) {
 	return pthread_fchdir_np(fd)
 }
 
-// Connectx calls connectx(2) to initiate a connection on a socket.
-//
-// srcIf, srcAddr, and dstAddr are filled into a [SaEndpoints] struct and passed as the endpoints argument.
-//
-//   - srcIf is the optional source interface index. 0 means unspecified.
-//   - srcAddr is the optional source address. nil means unspecified.
-//   - dstAddr is the destination address.
-//
-// On success, Connectx returns the number of bytes enqueued for transmission.
-func Connectx(fd int, srcIf uint32, srcAddr, dstAddr Sockaddr, associd SaeAssocID, flags uint32, iov []Iovec, connid *SaeConnID) (n uintptr, err error) {
-	endpoints := SaEndpoints{
-		Srcif: srcIf,
-	}
-
-	if srcAddr != nil {
-		addrp, addrlen, err := srcAddr.sockaddr()
-		if err != nil {
-			return 0, err
-		}
-		endpoints.Srcaddr = (*RawSockaddr)(addrp)
-		endpoints.Srcaddrlen = uint32(addrlen)
-	}
-
-	if dstAddr != nil {
-		addrp, addrlen, err := dstAddr.sockaddr()
-		if err != nil {
-			return 0, err
-		}
-		endpoints.Dstaddr = (*RawSockaddr)(addrp)
-		endpoints.Dstaddrlen = uint32(addrlen)
-	}
-
-	err = connectx(fd, &endpoints, associd, flags, iov, &n, connid)
-	return
-}
-
-//sys	connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error)
 //sys	sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error)
 
 //sys	shmat(id int, addr uintptr, flag int) (ret uintptr, err error)
diff --git a/vendor/golang.org/x/sys/unix/syscall_hurd.go b/vendor/golang.org/x/sys/unix/syscall_hurd.go
index a6a2d2fc2..ba46651f8 100644
--- a/vendor/golang.org/x/sys/unix/syscall_hurd.go
+++ b/vendor/golang.org/x/sys/unix/syscall_hurd.go
@@ -11,7 +11,6 @@ package unix
 int ioctl(int, unsigned long int, uintptr_t);
 */
 import "C"
-import "unsafe"
 
 func ioctl(fd int, req uint, arg uintptr) (err error) {
 	r0, er := C.ioctl(C.int(fd), C.ulong(req), C.uintptr_t(arg))
diff --git a/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go b/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go
index d73c4652e..4308ac177 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_darwin_amd64.go
@@ -237,9 +237,6 @@ const (
 	CLOCK_UPTIME_RAW_APPROX                 = 0x9
 	CLONE_NOFOLLOW                          = 0x1
 	CLONE_NOOWNERCOPY                       = 0x2
-	CONNECT_DATA_AUTHENTICATED              = 0x4
-	CONNECT_DATA_IDEMPOTENT                 = 0x2
-	CONNECT_RESUME_ON_READ_WRITE            = 0x1
 	CR0                                     = 0x0
 	CR1                                     = 0x1000
 	CR2                                     = 0x2000
@@ -1268,10 +1265,6 @@ const (
 	RTV_SSTHRESH                            = 0x20
 	RUSAGE_CHILDREN                         = -0x1
 	RUSAGE_SELF                             = 0x0
-	SAE_ASSOCID_ALL                         = 0xffffffff
-	SAE_ASSOCID_ANY                         = 0x0
-	SAE_CONNID_ALL                          = 0xffffffff
-	SAE_CONNID_ANY                          = 0x0
 	SCM_CREDS                               = 0x3
 	SCM_RIGHTS                              = 0x1
 	SCM_TIMESTAMP                           = 0x2
diff --git a/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go b/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go
index 4a55a4005..c8068a7a1 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_darwin_arm64.go
@@ -237,9 +237,6 @@ const (
 	CLOCK_UPTIME_RAW_APPROX                 = 0x9
 	CLONE_NOFOLLOW                          = 0x1
 	CLONE_NOOWNERCOPY                       = 0x2
-	CONNECT_DATA_AUTHENTICATED              = 0x4
-	CONNECT_DATA_IDEMPOTENT                 = 0x2
-	CONNECT_RESUME_ON_READ_WRITE            = 0x1
 	CR0                                     = 0x0
 	CR1                                     = 0x1000
 	CR2                                     = 0x2000
@@ -1268,10 +1265,6 @@ const (
 	RTV_SSTHRESH                            = 0x20
 	RUSAGE_CHILDREN                         = -0x1
 	RUSAGE_SELF                             = 0x0
-	SAE_ASSOCID_ALL                         = 0xffffffff
-	SAE_ASSOCID_ANY                         = 0x0
-	SAE_CONNID_ALL                          = 0xffffffff
-	SAE_CONNID_ANY                          = 0x0
 	SCM_CREDS                               = 0x3
 	SCM_RIGHTS                              = 0x1
 	SCM_TIMESTAMP                           = 0x2
diff --git a/vendor/golang.org/x/sys/unix/zerrors_zos_s390x.go b/vendor/golang.org/x/sys/unix/zerrors_zos_s390x.go
index 1ec2b1407..da08b2ab3 100644
--- a/vendor/golang.org/x/sys/unix/zerrors_zos_s390x.go
+++ b/vendor/golang.org/x/sys/unix/zerrors_zos_s390x.go
@@ -581,8 +581,6 @@ const (
 	AT_EMPTY_PATH                   = 0x1000
 	AT_REMOVEDIR                    = 0x200
 	RENAME_NOREPLACE                = 1 << 0
-	ST_RDONLY                       = 1
-	ST_NOSUID                       = 2
 )
 
 const (
diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go
index 24b346e1a..b622533ef 100644
--- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go
+++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.go
@@ -841,26 +841,6 @@ var libc_pthread_fchdir_np_trampoline_addr uintptr
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error) {
-	var _p0 unsafe.Pointer
-	if len(iov) > 0 {
-		_p0 = unsafe.Pointer(&iov[0])
-	} else {
-		_p0 = unsafe.Pointer(&_zero)
-	}
-	_, _, e1 := syscall_syscall9(libc_connectx_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(endpoints)), uintptr(associd), uintptr(flags), uintptr(_p0), uintptr(len(iov)), uintptr(unsafe.Pointer(n)), uintptr(unsafe.Pointer(connid)), 0)
-	if e1 != 0 {
-		err = errnoErr(e1)
-	}
-	return
-}
-
-var libc_connectx_trampoline_addr uintptr
-
-//go:cgo_import_dynamic libc_connectx connectx "/usr/lib/libSystem.B.dylib"
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
 func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) {
 	_, _, e1 := syscall_syscall6(libc_sendfile_trampoline_addr, uintptr(infd), uintptr(outfd), uintptr(offset), uintptr(unsafe.Pointer(len)), uintptr(hdtr), uintptr(flags))
 	if e1 != 0 {
diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s
index ebd213100..cfe6646ba 100644
--- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s
+++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_amd64.s
@@ -248,11 +248,6 @@ TEXT libc_pthread_fchdir_np_trampoline<>(SB),NOSPLIT,$0-0
 GLOBL	·libc_pthread_fchdir_np_trampoline_addr(SB), RODATA, $8
 DATA	·libc_pthread_fchdir_np_trampoline_addr(SB)/8, $libc_pthread_fchdir_np_trampoline<>(SB)
 
-TEXT libc_connectx_trampoline<>(SB),NOSPLIT,$0-0
-	JMP	libc_connectx(SB)
-GLOBL	·libc_connectx_trampoline_addr(SB), RODATA, $8
-DATA	·libc_connectx_trampoline_addr(SB)/8, $libc_connectx_trampoline<>(SB)
-
 TEXT libc_sendfile_trampoline<>(SB),NOSPLIT,$0-0
 	JMP	libc_sendfile(SB)
 GLOBL	·libc_sendfile_trampoline_addr(SB), RODATA, $8
diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go
index 824b9c2d5..13f624f69 100644
--- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go
+++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.go
@@ -841,26 +841,6 @@ var libc_pthread_fchdir_np_trampoline_addr uintptr
 
 // THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
 
-func connectx(fd int, endpoints *SaEndpoints, associd SaeAssocID, flags uint32, iov []Iovec, n *uintptr, connid *SaeConnID) (err error) {
-	var _p0 unsafe.Pointer
-	if len(iov) > 0 {
-		_p0 = unsafe.Pointer(&iov[0])
-	} else {
-		_p0 = unsafe.Pointer(&_zero)
-	}
-	_, _, e1 := syscall_syscall9(libc_connectx_trampoline_addr, uintptr(fd), uintptr(unsafe.Pointer(endpoints)), uintptr(associd), uintptr(flags), uintptr(_p0), uintptr(len(iov)), uintptr(unsafe.Pointer(n)), uintptr(unsafe.Pointer(connid)), 0)
-	if e1 != 0 {
-		err = errnoErr(e1)
-	}
-	return
-}
-
-var libc_connectx_trampoline_addr uintptr
-
-//go:cgo_import_dynamic libc_connectx connectx "/usr/lib/libSystem.B.dylib"
-
-// THIS FILE IS GENERATED BY THE COMMAND AT THE TOP; DO NOT EDIT
-
 func sendfile(infd int, outfd int, offset int64, len *int64, hdtr unsafe.Pointer, flags int) (err error) {
 	_, _, e1 := syscall_syscall6(libc_sendfile_trampoline_addr, uintptr(infd), uintptr(outfd), uintptr(offset), uintptr(unsafe.Pointer(len)), uintptr(hdtr), uintptr(flags))
 	if e1 != 0 {
diff --git a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s
index 4f178a229..fe222b75d 100644
--- a/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s
+++ b/vendor/golang.org/x/sys/unix/zsyscall_darwin_arm64.s
@@ -248,11 +248,6 @@ TEXT libc_pthread_fchdir_np_trampoline<>(SB),NOSPLIT,$0-0
 GLOBL	·libc_pthread_fchdir_np_trampoline_addr(SB), RODATA, $8
 DATA	·libc_pthread_fchdir_np_trampoline_addr(SB)/8, $libc_pthread_fchdir_np_trampoline<>(SB)
 
-TEXT libc_connectx_trampoline<>(SB),NOSPLIT,$0-0
-	JMP	libc_connectx(SB)
-GLOBL	·libc_connectx_trampoline_addr(SB), RODATA, $8
-DATA	·libc_connectx_trampoline_addr(SB)/8, $libc_connectx_trampoline<>(SB)
-
 TEXT libc_sendfile_trampoline<>(SB),NOSPLIT,$0-0
 	JMP	libc_sendfile(SB)
 GLOBL	·libc_sendfile_trampoline_addr(SB), RODATA, $8
diff --git a/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go
index d003c3d43..091d107f3 100644
--- a/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go
+++ b/vendor/golang.org/x/sys/unix/ztypes_darwin_amd64.go
@@ -306,19 +306,6 @@ type XVSockPgen struct {
 
 type _Socklen uint32
 
-type SaeAssocID uint32
-
-type SaeConnID uint32
-
-type SaEndpoints struct {
-	Srcif      uint32
-	Srcaddr    *RawSockaddr
-	Srcaddrlen uint32
-	Dstaddr    *RawSockaddr
-	Dstaddrlen uint32
-	_          [4]byte
-}
-
 type Xucred struct {
 	Version uint32
 	Uid     uint32
diff --git a/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go b/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go
index 0d45a941a..28ff4ef74 100644
--- a/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go
+++ b/vendor/golang.org/x/sys/unix/ztypes_darwin_arm64.go
@@ -306,19 +306,6 @@ type XVSockPgen struct {
 
 type _Socklen uint32
 
-type SaeAssocID uint32
-
-type SaeConnID uint32
-
-type SaEndpoints struct {
-	Srcif      uint32
-	Srcaddr    *RawSockaddr
-	Srcaddrlen uint32
-	Dstaddr    *RawSockaddr
-	Dstaddrlen uint32
-	_          [4]byte
-}
-
 type Xucred struct {
 	Version uint32
 	Uid     uint32
diff --git a/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go b/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go
index 51e13eb05..6cbd094a3 100644
--- a/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go
+++ b/vendor/golang.org/x/sys/unix/ztypes_freebsd_386.go
@@ -625,7 +625,6 @@ const (
 	POLLRDNORM   = 0x40
 	POLLWRBAND   = 0x100
 	POLLWRNORM   = 0x4
-	POLLRDHUP    = 0x4000
 )
 
 type CapRights struct {
diff --git a/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go b/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go
index d002d8ef3..7c03b6ee7 100644
--- a/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go
+++ b/vendor/golang.org/x/sys/unix/ztypes_freebsd_amd64.go
@@ -630,7 +630,6 @@ const (
 	POLLRDNORM   = 0x40
 	POLLWRBAND   = 0x100
 	POLLWRNORM   = 0x4
-	POLLRDHUP    = 0x4000
 )
 
 type CapRights struct {
diff --git a/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go b/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go
index 3f863d898..422107ee8 100644
--- a/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go
+++ b/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm.go
@@ -616,7 +616,6 @@ const (
 	POLLRDNORM   = 0x40
 	POLLWRBAND   = 0x100
 	POLLWRNORM   = 0x4
-	POLLRDHUP    = 0x4000
 )
 
 type CapRights struct {
diff --git a/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go b/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go
index 61c729310..505a12acf 100644
--- a/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go
+++ b/vendor/golang.org/x/sys/unix/ztypes_freebsd_arm64.go
@@ -610,7 +610,6 @@ const (
 	POLLRDNORM   = 0x40
 	POLLWRBAND   = 0x100
 	POLLWRNORM   = 0x4
-	POLLRDHUP    = 0x4000
 )
 
 type CapRights struct {
diff --git a/vendor/golang.org/x/sys/unix/ztypes_freebsd_riscv64.go b/vendor/golang.org/x/sys/unix/ztypes_freebsd_riscv64.go
index b5d17414f..cc986c790 100644
--- a/vendor/golang.org/x/sys/unix/ztypes_freebsd_riscv64.go
+++ b/vendor/golang.org/x/sys/unix/ztypes_freebsd_riscv64.go
@@ -612,7 +612,6 @@ const (
 	POLLRDNORM   = 0x40
 	POLLWRBAND   = 0x100
 	POLLWRNORM   = 0x4
-	POLLRDHUP    = 0x4000
 )
 
 type CapRights struct {
diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux.go b/vendor/golang.org/x/sys/unix/ztypes_linux.go
index 9f2550dc3..7f1961b90 100644
--- a/vendor/golang.org/x/sys/unix/ztypes_linux.go
+++ b/vendor/golang.org/x/sys/unix/ztypes_linux.go
@@ -2486,7 +2486,7 @@ type XDPMmapOffsets struct {
 type XDPUmemReg struct {
 	Addr            uint64
 	Len             uint64
-	Size            uint32
+	Chunk_size      uint32
 	Headroom        uint32
 	Flags           uint32
 	Tx_metadata_len uint32
diff --git a/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go b/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go
index ad05b51a6..15adc0414 100644
--- a/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go
+++ b/vendor/golang.org/x/sys/unix/ztypes_linux_riscv64.go
@@ -727,37 +727,6 @@ const (
 	RISCV_HWPROBE_EXT_ZBA                = 0x8
 	RISCV_HWPROBE_EXT_ZBB                = 0x10
 	RISCV_HWPROBE_EXT_ZBS                = 0x20
-	RISCV_HWPROBE_EXT_ZICBOZ             = 0x40
-	RISCV_HWPROBE_EXT_ZBC                = 0x80
-	RISCV_HWPROBE_EXT_ZBKB               = 0x100
-	RISCV_HWPROBE_EXT_ZBKC               = 0x200
-	RISCV_HWPROBE_EXT_ZBKX               = 0x400
-	RISCV_HWPROBE_EXT_ZKND               = 0x800
-	RISCV_HWPROBE_EXT_ZKNE               = 0x1000
-	RISCV_HWPROBE_EXT_ZKNH               = 0x2000
-	RISCV_HWPROBE_EXT_ZKSED              = 0x4000
-	RISCV_HWPROBE_EXT_ZKSH               = 0x8000
-	RISCV_HWPROBE_EXT_ZKT                = 0x10000
-	RISCV_HWPROBE_EXT_ZVBB               = 0x20000
-	RISCV_HWPROBE_EXT_ZVBC               = 0x40000
-	RISCV_HWPROBE_EXT_ZVKB               = 0x80000
-	RISCV_HWPROBE_EXT_ZVKG               = 0x100000
-	RISCV_HWPROBE_EXT_ZVKNED             = 0x200000
-	RISCV_HWPROBE_EXT_ZVKNHA             = 0x400000
-	RISCV_HWPROBE_EXT_ZVKNHB             = 0x800000
-	RISCV_HWPROBE_EXT_ZVKSED             = 0x1000000
-	RISCV_HWPROBE_EXT_ZVKSH              = 0x2000000
-	RISCV_HWPROBE_EXT_ZVKT               = 0x4000000
-	RISCV_HWPROBE_EXT_ZFH                = 0x8000000
-	RISCV_HWPROBE_EXT_ZFHMIN             = 0x10000000
-	RISCV_HWPROBE_EXT_ZIHINTNTL          = 0x20000000
-	RISCV_HWPROBE_EXT_ZVFH               = 0x40000000
-	RISCV_HWPROBE_EXT_ZVFHMIN            = 0x80000000
-	RISCV_HWPROBE_EXT_ZFA                = 0x100000000
-	RISCV_HWPROBE_EXT_ZTSO               = 0x200000000
-	RISCV_HWPROBE_EXT_ZACAS              = 0x400000000
-	RISCV_HWPROBE_EXT_ZICOND             = 0x800000000
-	RISCV_HWPROBE_EXT_ZIHINTPAUSE        = 0x1000000000
 	RISCV_HWPROBE_KEY_CPUPERF_0          = 0x5
 	RISCV_HWPROBE_MISALIGNED_UNKNOWN     = 0x0
 	RISCV_HWPROBE_MISALIGNED_EMULATED    = 0x1
@@ -765,6 +734,4 @@ const (
 	RISCV_HWPROBE_MISALIGNED_FAST        = 0x3
 	RISCV_HWPROBE_MISALIGNED_UNSUPPORTED = 0x4
 	RISCV_HWPROBE_MISALIGNED_MASK        = 0x7
-	RISCV_HWPROBE_KEY_ZICBOZ_BLOCK_SIZE  = 0x6
-	RISCV_HWPROBE_WHICH_CPUS             = 0x1
 )
diff --git a/vendor/golang.org/x/sys/windows/syscall_windows.go b/vendor/golang.org/x/sys/windows/syscall_windows.go
index 5cee9a314..1fa34fd17 100644
--- a/vendor/golang.org/x/sys/windows/syscall_windows.go
+++ b/vendor/golang.org/x/sys/windows/syscall_windows.go
@@ -313,10 +313,6 @@ func NewCallbackCDecl(fn interface{}) uintptr {
 //sys	SetConsoleMode(console Handle, mode uint32) (err error) = kernel32.SetConsoleMode
 //sys	GetConsoleScreenBufferInfo(console Handle, info *ConsoleScreenBufferInfo) (err error) = kernel32.GetConsoleScreenBufferInfo
 //sys	setConsoleCursorPosition(console Handle, position uint32) (err error) = kernel32.SetConsoleCursorPosition
-//sys	GetConsoleCP() (cp uint32, err error) = kernel32.GetConsoleCP
-//sys	GetConsoleOutputCP() (cp uint32, err error) = kernel32.GetConsoleOutputCP
-//sys	SetConsoleCP(cp uint32) (err error) = kernel32.SetConsoleCP
-//sys	SetConsoleOutputCP(cp uint32) (err error) = kernel32.SetConsoleOutputCP
 //sys	WriteConsole(console Handle, buf *uint16, towrite uint32, written *uint32, reserved *byte) (err error) = kernel32.WriteConsoleW
 //sys	ReadConsole(console Handle, buf *uint16, toread uint32, read *uint32, inputControl *byte) (err error) = kernel32.ReadConsoleW
 //sys	resizePseudoConsole(pconsole Handle, size uint32) (hr error) = kernel32.ResizePseudoConsole
diff --git a/vendor/golang.org/x/sys/windows/types_windows.go b/vendor/golang.org/x/sys/windows/types_windows.go
index 7b97a154c..3f03b3d57 100644
--- a/vendor/golang.org/x/sys/windows/types_windows.go
+++ b/vendor/golang.org/x/sys/windows/types_windows.go
@@ -1060,7 +1060,6 @@ const (
 	SIO_GET_EXTENSION_FUNCTION_POINTER = IOC_INOUT | IOC_WS2 | 6
 	SIO_KEEPALIVE_VALS                 = IOC_IN | IOC_VENDOR | 4
 	SIO_UDP_CONNRESET                  = IOC_IN | IOC_VENDOR | 12
-	SIO_UDP_NETRESET                   = IOC_IN | IOC_VENDOR | 15
 
 	// cf. http://support.microsoft.com/default.aspx?scid=kb;en-us;257460
 
diff --git a/vendor/golang.org/x/sys/windows/zsyscall_windows.go b/vendor/golang.org/x/sys/windows/zsyscall_windows.go
index 4c2e1bdc0..9bb979a3e 100644
--- a/vendor/golang.org/x/sys/windows/zsyscall_windows.go
+++ b/vendor/golang.org/x/sys/windows/zsyscall_windows.go
@@ -247,9 +247,7 @@ var (
 	procGetCommandLineW                                      = modkernel32.NewProc("GetCommandLineW")
 	procGetComputerNameExW                                   = modkernel32.NewProc("GetComputerNameExW")
 	procGetComputerNameW                                     = modkernel32.NewProc("GetComputerNameW")
-	procGetConsoleCP                                         = modkernel32.NewProc("GetConsoleCP")
 	procGetConsoleMode                                       = modkernel32.NewProc("GetConsoleMode")
-	procGetConsoleOutputCP                                   = modkernel32.NewProc("GetConsoleOutputCP")
 	procGetConsoleScreenBufferInfo                           = modkernel32.NewProc("GetConsoleScreenBufferInfo")
 	procGetCurrentDirectoryW                                 = modkernel32.NewProc("GetCurrentDirectoryW")
 	procGetCurrentProcessId                                  = modkernel32.NewProc("GetCurrentProcessId")
@@ -349,10 +347,8 @@ var (
 	procSetCommMask                                          = modkernel32.NewProc("SetCommMask")
 	procSetCommState                                         = modkernel32.NewProc("SetCommState")
 	procSetCommTimeouts                                      = modkernel32.NewProc("SetCommTimeouts")
-	procSetConsoleCP                                         = modkernel32.NewProc("SetConsoleCP")
 	procSetConsoleCursorPosition                             = modkernel32.NewProc("SetConsoleCursorPosition")
 	procSetConsoleMode                                       = modkernel32.NewProc("SetConsoleMode")
-	procSetConsoleOutputCP                                   = modkernel32.NewProc("SetConsoleOutputCP")
 	procSetCurrentDirectoryW                                 = modkernel32.NewProc("SetCurrentDirectoryW")
 	procSetDefaultDllDirectories                             = modkernel32.NewProc("SetDefaultDllDirectories")
 	procSetDllDirectoryW                                     = modkernel32.NewProc("SetDllDirectoryW")
@@ -2166,15 +2162,6 @@ func GetComputerName(buf *uint16, n *uint32) (err error) {
 	return
 }
 
-func GetConsoleCP() (cp uint32, err error) {
-	r0, _, e1 := syscall.Syscall(procGetConsoleCP.Addr(), 0, 0, 0, 0)
-	cp = uint32(r0)
-	if cp == 0 {
-		err = errnoErr(e1)
-	}
-	return
-}
-
 func GetConsoleMode(console Handle, mode *uint32) (err error) {
 	r1, _, e1 := syscall.Syscall(procGetConsoleMode.Addr(), 2, uintptr(console), uintptr(unsafe.Pointer(mode)), 0)
 	if r1 == 0 {
@@ -2183,15 +2170,6 @@ func GetConsoleMode(console Handle, mode *uint32) (err error) {
 	return
 }
 
-func GetConsoleOutputCP() (cp uint32, err error) {
-	r0, _, e1 := syscall.Syscall(procGetConsoleOutputCP.Addr(), 0, 0, 0, 0)
-	cp = uint32(r0)
-	if cp == 0 {
-		err = errnoErr(e1)
-	}
-	return
-}
-
 func GetConsoleScreenBufferInfo(console Handle, info *ConsoleScreenBufferInfo) (err error) {
 	r1, _, e1 := syscall.Syscall(procGetConsoleScreenBufferInfo.Addr(), 2, uintptr(console), uintptr(unsafe.Pointer(info)), 0)
 	if r1 == 0 {
@@ -3060,14 +3038,6 @@ func SetCommTimeouts(handle Handle, timeouts *CommTimeouts) (err error) {
 	return
 }
 
-func SetConsoleCP(cp uint32) (err error) {
-	r1, _, e1 := syscall.Syscall(procSetConsoleCP.Addr(), 1, uintptr(cp), 0, 0)
-	if r1 == 0 {
-		err = errnoErr(e1)
-	}
-	return
-}
-
 func setConsoleCursorPosition(console Handle, position uint32) (err error) {
 	r1, _, e1 := syscall.Syscall(procSetConsoleCursorPosition.Addr(), 2, uintptr(console), uintptr(position), 0)
 	if r1 == 0 {
@@ -3084,14 +3054,6 @@ func SetConsoleMode(console Handle, mode uint32) (err error) {
 	return
 }
 
-func SetConsoleOutputCP(cp uint32) (err error) {
-	r1, _, e1 := syscall.Syscall(procSetConsoleOutputCP.Addr(), 1, uintptr(cp), 0, 0)
-	if r1 == 0 {
-		err = errnoErr(e1)
-	}
-	return
-}
-
 func SetCurrentDirectory(path *uint16) (err error) {
 	r1, _, e1 := syscall.Syscall(procSetCurrentDirectoryW.Addr(), 1, uintptr(unsafe.Pointer(path)), 0, 0)
 	if r1 == 0 {
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 0613b44ba..e52517e24 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -611,7 +611,7 @@ golang.org/x/oauth2/internal
 golang.org/x/sync/errgroup
 golang.org/x/sync/semaphore
 golang.org/x/sync/singleflight
-# golang.org/x/sys v0.25.0
+# golang.org/x/sys v0.24.0
 ## explicit; go 1.18
 golang.org/x/sys/cpu
 golang.org/x/sys/plan9


Test patch:
diff --git a/kubetest2-aks/go.mod b/kubetest2-aks/go.mod
index 99dfbeb91..933995083 100644
--- a/kubetest2-aks/go.mod
+++ b/kubetest2-aks/go.mod
@@ -1,7 +1,9 @@
 module sigs.k8s.io/cloud-provider-azure/kubetest2-aks
 
 // Bump GoTool golang version in .pipelines if you change this
-go 1.23.1
+go 1.22.0
+
+toolchain go1.22.2
 
 require (
 	github.com/Azure/azure-sdk-for-go/sdk/azcore v1.14.0
diff --git a/pkg/azclient/factory_test.go b/pkg/azclient/factory_test.go
index 2406237ef..1ce01e5db 100644
--- a/pkg/azclient/factory_test.go
+++ b/pkg/azclient/factory_test.go
@@ -73,6 +73,13 @@ var _ = ginkgo.Describe("Factory", func() {
 			client := factory.GetFileShareClient()
 			gomega.Expect(client).NotTo(gomega.BeNil())
 		})
+		ginkgo.It("should create factory instance without painc - Identity", func() {
+			factory, err := NewClientFactory(nil, nil, nil)
+			gomega.Expect(err).NotTo(gomega.HaveOccurred())
+			gomega.Expect(factory).NotTo(gomega.BeNil())
+			client := factory.GetIdentityClient()
+			gomega.Expect(client).NotTo(gomega.BeNil())
+		})
 		ginkgo.It("should create factory instance without painc - Interface", func() {
 			factory, err := NewClientFactory(nil, nil, nil)
 			gomega.Expect(err).NotTo(gomega.HaveOccurred())
diff --git a/pkg/azclient/identityclient/custom_test.go b/pkg/azclient/identityclient/custom_test.go
new file mode 100644
index 000000000..76776b167
--- /dev/null
+++ b/pkg/azclient/identityclient/custom_test.go
@@ -0,0 +1,60 @@
+// /*
+// Copyright 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.
+// */
+
+// Code generated by client-gen. DO NOT EDIT.
+package identityclient
+
+import (
+	"context"
+
+	"github.com/Azure/azure-sdk-for-go/sdk/azcore"
+	"github.com/Azure/azure-sdk-for-go/sdk/azcore/arm"
+	"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
+	"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/msi/armmsi"
+	"github.com/onsi/gomega"
+
+	"sigs.k8s.io/cloud-provider-azure/pkg/azclient/utils"
+)
+
+var msiClient *armmsi.UserAssignedIdentitiesClient
+var useridentity *armmsi.Identity
+func init() {
+	additionalTestCases = func() {
+	}
+
+	beforeAllFunc = func(ctx context.Context) {
+		var err error
+		msiClient,err = armmsi.NewUserAssignedIdentitiesClient(subscriptionID,recorder.TokenCredential(),&arm.ClientOptions{
+			ClientOptions: azcore.ClientOptions{
+				Transport:       recorder.HTTPClient(),
+				TracingProvider: utils.TracingProvider,
+			},
+		})
+		gomega.Expect(err).NotTo(gomega.HaveOccurred())
+
+		resp,err := msiClient.CreateOrUpdate(ctx,resourceGroupName,resourceName,armmsi.Identity{
+			Location: to.Ptr(location),
+			Name: to.Ptr(resourceName),
+		},nil)
+		useridentity = &resp.Identity
+		gomega.Expect(err).NotTo(gomega.HaveOccurred())
+
+	}
+	afterAllFunc = func(ctx context.Context) {
+		_,err := msiClient.Delete(ctx,resourceGroupName,resourceName,nil)
+		gomega.Expect(err).NotTo(gomega.HaveOccurred())
+	}
+}
diff --git a/pkg/azclient/identityclient/identityclient_suite_test.go b/pkg/azclient/identityclient/identityclient_suite_test.go
new file mode 100644
index 000000000..ff2d0f088
--- /dev/null
+++ b/pkg/azclient/identityclient/identityclient_suite_test.go
@@ -0,0 +1,87 @@
+// /*
+// Copyright 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.
+// */
+
+// Code generated by client-gen. DO NOT EDIT.
+package identityclient
+
+import (
+	"context"
+	"testing"
+
+	"github.com/Azure/azure-sdk-for-go/sdk/azcore"
+	"github.com/Azure/azure-sdk-for-go/sdk/azcore/arm"
+	"github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
+	"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources"
+	"github.com/onsi/ginkgo/v2"
+	"github.com/onsi/gomega"
+
+	"sigs.k8s.io/cloud-provider-azure/pkg/azclient/recording"
+	"sigs.k8s.io/cloud-provider-azure/pkg/azclient/utils"
+)
+
+func TestClient(t *testing.T) {
+	gomega.RegisterFailHandler(ginkgo.Fail)
+	ginkgo.RunSpecs(t, "Client Suite")
+}
+
+var resourceGroupName = "aks-cit-Identity"
+var resourceName = "testResource"
+
+var subscriptionID string
+var location = "eastus"
+var resourceGroupClient *armresources.ResourceGroupsClient
+var err error
+var recorder *recording.Recorder
+var realClient Interface
+
+var _ = ginkgo.BeforeSuite(func(ctx context.Context) {
+	recorder, err = recording.NewRecorder("testdata/Identity")
+	gomega.Expect(err).ToNot(gomega.HaveOccurred())
+	subscriptionID = recorder.SubscriptionID()
+	gomega.Expect(err).NotTo(gomega.HaveOccurred())
+	cred := recorder.TokenCredential()
+	resourceGroupClient, err = armresources.NewResourceGroupsClient(subscriptionID, cred, &arm.ClientOptions{
+		ClientOptions: azcore.ClientOptions{
+			Transport:       recorder.HTTPClient(),
+			TracingProvider: utils.TracingProvider,
+		},
+	})
+	gomega.Expect(err).NotTo(gomega.HaveOccurred())
+	realClient, err = New(subscriptionID, recorder.TokenCredential(), &arm.ClientOptions{
+		ClientOptions: azcore.ClientOptions{
+			Transport:       recorder.HTTPClient(),
+			TracingProvider: utils.TracingProvider,
+		},
+	})
+	gomega.Expect(err).NotTo(gomega.HaveOccurred())
+	_, err = resourceGroupClient.CreateOrUpdate(
+		ctx,
+		resourceGroupName,
+		armresources.ResourceGroup{
+			Location: to.Ptr(location),
+		},
+		nil)
+	gomega.Expect(err).NotTo(gomega.HaveOccurred())
+})
+
+var _ = ginkgo.AfterSuite(func(ctx context.Context) {
+	poller, err := resourceGroupClient.BeginDelete(ctx, resourceGroupName, nil)
+	gomega.Expect(err).NotTo(gomega.HaveOccurred())
+	_, err = poller.PollUntilDone(ctx, nil)
+	gomega.Expect(err).ToNot(gomega.HaveOccurred())
+	err = recorder.Stop()
+	gomega.Expect(err).ToNot(gomega.HaveOccurred())
+})
diff --git a/pkg/azclient/identityclient/identityclient_test.go b/pkg/azclient/identityclient/identityclient_test.go
new file mode 100644
index 000000000..61338931e
--- /dev/null
+++ b/pkg/azclient/identityclient/identityclient_test.go
@@ -0,0 +1,59 @@
+// /*
+// Copyright 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.
+// */
+
+// Code generated by client-gen. DO NOT EDIT.
+package identityclient
+
+import (
+	"context"
+
+	"github.com/onsi/ginkgo/v2"
+	"github.com/onsi/gomega"
+)
+
+var beforeAllFunc func(context.Context)
+var afterAllFunc func(context.Context)
+var additionalTestCases func()
+
+var _ = ginkgo.Describe("UserAssignedIdentitiesClient", ginkgo.Ordered, func() {
+
+	if beforeAllFunc != nil {
+		ginkgo.BeforeAll(beforeAllFunc)
+	}
+
+	if additionalTestCases != nil {
+		additionalTestCases()
+	}
+
+	ginkgo.When("get requests are raised", func() {
+		ginkgo.It("should not return error", func(ctx context.Context) {
+			newResource, err := realClient.Get(ctx, resourceGroupName, resourceName)
+			gomega.Expect(err).NotTo(gomega.HaveOccurred())
+			gomega.Expect(newResource).NotTo(gomega.BeNil())
+		})
+	})
+	ginkgo.When("invalid get requests are raised", func() {
+		ginkgo.It("should return 404 error", func(ctx context.Context) {
+			newResource, err := realClient.Get(ctx, resourceGroupName, resourceName+"notfound")
+			gomega.Expect(err).To(gomega.HaveOccurred())
+			gomega.Expect(newResource).To(gomega.BeNil())
+		})
+	})
+
+	if afterAllFunc != nil {
+		ginkgo.AfterAll(afterAllFunc)
+	}
+})
diff --git a/pkg/azclient/identityclient/testdata/Identity.yaml b/pkg/azclient/identityclient/testdata/Identity.yaml
new file mode 100644
index 000000000..1e01824a9
--- /dev/null
+++ b/pkg/azclient/identityclient/testdata/Identity.yaml
@@ -0,0 +1,338 @@
+---
+version: 2
+interactions:
+    - id: 0
+      request:
+        proto: HTTP/1.1
+        proto_major: 1
+        proto_minor: 1
+        content_length: 21
+        transfer_encoding: []
+        trailer: {}
+        host: management.azure.com
+        remote_addr: ""
+        request_uri: ""
+        body: '{"location":"eastus"}'
+        form: {}
+        headers:
+            Accept:
+                - application/json
+            Content-Length:
+                - "21"
+            Content-Type:
+                - application/json
+        url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/aks-cit-Identity?api-version=2021-04-01
+        method: PUT
+      response:
+        proto: HTTP/2.0
+        proto_major: 2
+        proto_minor: 0
+        transfer_encoding: []
+        trailer: {}
+        content_length: 229
+        uncompressed: false
+        body: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/aks-cit-Identity","name":"aks-cit-Identity","type":"Microsoft.Resources/resourceGroups","location":"eastus","properties":{"provisioningState":"Succeeded"}}'
+        headers:
+            Cache-Control:
+                - no-cache
+            Content-Length:
+                - "229"
+            Content-Type:
+                - application/json; charset=utf-8
+            Expires:
+                - "-1"
+            Pragma:
+                - no-cache
+            Strict-Transport-Security:
+                - max-age=31536000; includeSubDomains
+            X-Cache:
+                - CONFIG_NOCACHE
+            X-Content-Type-Options:
+                - nosniff
+        status: 201 Created
+        code: 201
+        duration: 200ms
+    - id: 1
+      request:
+        proto: HTTP/1.1
+        proto_major: 1
+        proto_minor: 1
+        content_length: 43
+        transfer_encoding: []
+        trailer: {}
+        host: management.azure.com
+        remote_addr: ""
+        request_uri: ""
+        body: '{"location":"eastus","name":"testResource"}'
+        form: {}
+        headers:
+            Accept:
+                - application/json
+            Content-Length:
+                - "43"
+            Content-Type:
+                - application/json
+        url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/aks-cit-Identity/providers/Microsoft.ManagedIdentity/userAssignedIdentities/testResource?api-version=2023-01-31
+        method: PUT
+      response:
+        proto: HTTP/2.0
+        proto_major: 2
+        proto_minor: 0
+        transfer_encoding: []
+        trailer: {}
+        content_length: 442
+        uncompressed: false
+        body: '{"location":"eastus","tags":{},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/aks-cit-Identity/providers/Microsoft.ManagedIdentity/userAssignedIdentities/testResource","name":"testResource","type":"Microsoft.ManagedIdentity/userAssignedIdentities","properties":{"tenantId":"tenantid","principalId":"00000000-0000-0000-0000-000000000000","clientId":"00000000-0000-0000-0000-000000000000"}}'
+        headers:
+            Cache-Control:
+                - no-cache
+            Content-Length:
+                - "442"
+            Content-Type:
+                - application/json; charset=utf-8
+            Expires:
+                - "-1"
+            Location:
+                - /subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/aks-cit-Identity/providers/Microsoft.ManagedIdentity/userAssignedIdentities/testResource?c=c&h=h&s=s&t=t
+            Pragma:
+                - no-cache
+            Strict-Transport-Security:
+                - max-age=31536000; includeSubDomains
+            X-Cache:
+                - CONFIG_NOCACHE
+            X-Content-Type-Options:
+                - nosniff
+        status: 201 Created
+        code: 201
+        duration: 200ms
+    - id: 2
+      request:
+        proto: HTTP/1.1
+        proto_major: 1
+        proto_minor: 1
+        content_length: 0
+        transfer_encoding: []
+        trailer: {}
+        host: management.azure.com
+        remote_addr: ""
+        request_uri: ""
+        body: ""
+        form: {}
+        headers:
+            Accept:
+                - application/json
+        url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/aks-cit-Identity/providers/Microsoft.ManagedIdentity/userAssignedIdentities/testResource?api-version=2023-01-31
+        method: GET
+      response:
+        proto: HTTP/2.0
+        proto_major: 2
+        proto_minor: 0
+        transfer_encoding: []
+        trailer: {}
+        content_length: 442
+        uncompressed: false
+        body: '{"location":"eastus","tags":{},"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/aks-cit-Identity/providers/Microsoft.ManagedIdentity/userAssignedIdentities/testResource","name":"testResource","type":"Microsoft.ManagedIdentity/userAssignedIdentities","properties":{"tenantId":"tenantid","principalId":"00000000-0000-0000-0000-000000000000","clientId":"00000000-0000-0000-0000-000000000000"}}'
+        headers:
+            Cache-Control:
+                - no-cache
+            Content-Length:
+                - "442"
+            Content-Type:
+                - application/json; charset=utf-8
+            Expires:
+                - "-1"
+            Pragma:
+                - no-cache
+            Strict-Transport-Security:
+                - max-age=31536000; includeSubDomains
+            X-Cache:
+                - CONFIG_NOCACHE
+            X-Content-Type-Options:
+                - nosniff
+        status: 200 OK
+        code: 200
+        duration: 200ms
+    - id: 3
+      request:
+        proto: HTTP/1.1
+        proto_major: 1
+        proto_minor: 1
+        content_length: 0
+        transfer_encoding: []
+        trailer: {}
+        host: management.azure.com
+        remote_addr: ""
+        request_uri: ""
+        body: ""
+        form: {}
+        headers:
+            Accept:
+                - application/json
+        url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/aks-cit-Identity/providers/Microsoft.ManagedIdentity/userAssignedIdentities/testResourcenotfound?api-version=2023-01-31
+        method: GET
+      response:
+        proto: HTTP/2.0
+        proto_major: 2
+        proto_minor: 0
+        transfer_encoding: []
+        trailer: {}
+        content_length: 257
+        uncompressed: false
+        body: '{"error":{"code":"ResourceNotFound","message":"The Resource ''Microsoft.ManagedIdentity/userAssignedIdentities/testResourcenotfound'' under resource group ''aks-cit-Identity'' was not found. For more details please go to https://aka.ms/ARMResourceNotFoundFix"}}'
+        headers:
+            Cache-Control:
+                - no-cache
+            Content-Length:
+                - "257"
+            Content-Type:
+                - application/json; charset=utf-8
+            Expires:
+                - "-1"
+            Pragma:
+                - no-cache
+            Strict-Transport-Security:
+                - max-age=31536000; includeSubDomains
+            X-Cache:
+                - CONFIG_NOCACHE
+            X-Content-Type-Options:
+                - nosniff
+            X-Ms-Failure-Cause:
+                - gateway
+        status: 404 Not Found
+        code: 404
+        duration: 200ms
+    - id: 4
+      request:
+        proto: HTTP/1.1
+        proto_major: 1
+        proto_minor: 1
+        content_length: 0
+        transfer_encoding: []
+        trailer: {}
+        host: management.azure.com
+        remote_addr: ""
+        request_uri: ""
+        body: ""
+        form: {}
+        headers:
+            Accept:
+                - application/json
+        url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/aks-cit-Identity/providers/Microsoft.ManagedIdentity/userAssignedIdentities/testResource?api-version=2023-01-31
+        method: DELETE
+      response:
+        proto: HTTP/2.0
+        proto_major: 2
+        proto_minor: 0
+        transfer_encoding: []
+        trailer: {}
+        content_length: 0
+        uncompressed: false
+        body: ""
+        headers:
+            Cache-Control:
+                - no-cache
+            Content-Length:
+                - "0"
+            Expires:
+                - "-1"
+            Pragma:
+                - no-cache
+            Strict-Transport-Security:
+                - max-age=31536000; includeSubDomains
+            X-Cache:
+                - CONFIG_NOCACHE
+            X-Content-Type-Options:
+                - nosniff
+        status: 200 OK
+        code: 200
+        duration: 200ms
+    - id: 5
+      request:
+        proto: HTTP/1.1
+        proto_major: 1
+        proto_minor: 1
+        content_length: 0
+        transfer_encoding: []
+        trailer: {}
+        host: management.azure.com
+        remote_addr: ""
+        request_uri: ""
+        body: ""
+        form: {}
+        headers:
+            Accept:
+                - application/json
+        url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/aks-cit-Identity?api-version=2021-04-01
+        method: DELETE
+      response:
+        proto: HTTP/2.0
+        proto_major: 2
+        proto_minor: 0
+        transfer_encoding: []
+        trailer: {}
+        content_length: 0
+        uncompressed: false
+        body: ""
+        headers:
+            Cache-Control:
+                - no-cache
+            Content-Length:
+                - "0"
+            Expires:
+                - "-1"
+            Location:
+                - https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BS1M6MkRDSVQ6MkRJREVOVElUWS1FQVNUVVMiLCJqb2JMb2NhdGlvbiI6ImVhc3R1cyJ9?api-version=2021-04-01&c=c&h=h&s=s&t=t
+            Pragma:
+                - no-cache
+            Strict-Transport-Security:
+                - max-age=31536000; includeSubDomains
+            X-Cache:
+                - CONFIG_NOCACHE
+            X-Content-Type-Options:
+                - nosniff
+        status: 202 Accepted
+        code: 202
+        duration: 200ms
+    - id: 6
+      request:
+        proto: HTTP/1.1
+        proto_major: 1
+        proto_minor: 1
+        content_length: 0
+        transfer_encoding: []
+        trailer: {}
+        host: management.azure.com
+        remote_addr: ""
+        request_uri: ""
+        body: ""
+        form: {}
+        headers: {}
+        url: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1BS1M6MkRDSVQ6MkRJREVOVElUWS1FQVNUVVMiLCJqb2JMb2NhdGlvbiI6ImVhc3R1cyJ9?api-version=2021-04-01&c=c&h=h&s=s&t=t
+        method: GET
+      response:
+        proto: HTTP/2.0
+        proto_major: 2
+        proto_minor: 0
+        transfer_encoding: []
+        trailer: {}
+        content_length: 0
+        uncompressed: false
+        body: ""
+        headers:
+            Cache-Control:
+                - no-cache
+            Content-Length:
+                - "0"
+            Expires:
+                - "-1"
+            Pragma:
+                - no-cache
+            Strict-Transport-Security:
+                - max-age=31536000; includeSubDomains
+            X-Cache:
+                - CONFIG_NOCACHE
+            X-Content-Type-Options:
+                - nosniff
+        status: 200 OK
+        code: 200
+        duration: 200ms
diff --git a/pkg/azclient/roledefinitionclient/roledefinitionclient_suite_test.go b/pkg/azclient/roledefinitionclient/roledefinitionclient_suite_test.go
index 470e649c7..f42cd7245 100644
--- a/pkg/azclient/roledefinitionclient/roledefinitionclient_suite_test.go
+++ b/pkg/azclient/roledefinitionclient/roledefinitionclient_suite_test.go
@@ -60,7 +60,7 @@ var _ = ginkgo.BeforeSuite(func(ctx context.Context) {
 		},
 	})
 	gomega.Expect(err).NotTo(gomega.HaveOccurred())
-	realClient, err = New(recorder.TokenCredential(), &arm.ClientOptions{
+	realClient, err = New(subscriptionID, recorder.TokenCredential(), &arm.ClientOptions{
 		ClientOptions: azcore.ClientOptions{
 			Transport:       recorder.HTTPClient(),
 			TracingProvider: utils.TracingProvider,
diff --git a/pkg/credentialprovider/azure_credentials_test.go b/pkg/credentialprovider/azure_credentials_test.go
index 2dd8d6918..5097e5ff3 100644
--- a/pkg/credentialprovider/azure_credentials_test.go
+++ b/pkg/credentialprovider/azure_credentials_test.go
@@ -21,7 +21,6 @@ import (
 	"net/http"
 	"net/http/httptest"
 	"os"
-	"reflect"
 	"testing"
 
 	"github.com/stretchr/testify/assert"
@@ -138,7 +137,7 @@ func TestGetCredentialsConfig(t *testing.T) {
 		if err != nil {
 			t.Fatalf("Unexpected error when closing temp file: %v", err)
 		}
-		provider, err := NewAcrProviderFromConfig(configFile.Name(), "")
+		provider, err := NewAcrProviderFromConfig(configFile.Name())
 		if err != nil && !test.expectError {
 			t.Fatalf("Unexpected error when creating new acr provider: %v", err)
 		}
@@ -164,53 +163,6 @@ func TestGetCredentialsConfig(t *testing.T) {
 	}
 }
 
-func TestProcessImageWithMirrorMapping(t *testing.T) {
-	configStr := `
-	{
-	    "aadClientId": "foo",
-	    "aadClientSecret": "bar"
-	}`
-
-	configFile, err := os.CreateTemp(".", "config.json")
-	assert.Nilf(t, err, "Unexpected error when creating temp file")
-	defer os.Remove(configFile.Name())
-	_, err = configFile.WriteString(configStr)
-	assert.Nilf(t, err, "Unexpected error when writing to temp file")
-	assert.Nilf(t, configFile.Close(), "Unexpected error when closing temp file")
-
-	provider, err := NewAcrProviderFromConfig(configFile.Name(), "mcr.microsoft.com:abc.azurecr.io")
-	assert.Nilf(t, err, "Unexpected error when creating new acr provider")
-	acrProvider := provider.(*acrProvider)
-
-	testcases := []struct {
-		description               string
-		image                     string
-		expectedLoginServer       string
-		expectedLoginServerMirror string
-	}{
-		{
-			description:               "image in registry mirror map",
-			image:                     "mcr.microsoft.com/bar/image:version",
-			expectedLoginServer:       "abc.azurecr.io",
-			expectedLoginServerMirror: "mcr.microsoft.com",
-		},
-		{
-			description:               "image not in registry mirror map",
-			image:                     "foo.azurecr.io/bar/image:version",
-			expectedLoginServer:       "foo.azurecr.io",
-			expectedLoginServerMirror: "",
-		},
-	}
-
-	for _, test := range testcases {
-		t.Run(test.description, func(t *testing.T) {
-			targetloginServer, sourceloginServer := acrProvider.parseACRLoginServerFromImage(test.image)
-			assert.Equal(t, targetloginServer, test.expectedLoginServer)
-			assert.Equal(t, sourceloginServer, test.expectedLoginServerMirror)
-		})
-	}
-}
-
 func TestParseACRLoginServerFromImage(t *testing.T) {
 
 	providerInterface := NewAcrProvider(&config.AzureAuthConfig{
@@ -263,48 +215,8 @@ func TestParseACRLoginServerFromImage(t *testing.T) {
 		},
 	}
 	for _, test := range tests {
-		t.Run(test.image, func(t *testing.T) {
-			targetloginServer, _ := provider.parseACRLoginServerFromImage(test.image)
-			assert.Equal(t, targetloginServer, test.expected)
-		})
-	}
-}
-
-func TestProcessMirrorMapping(t *testing.T) {
-	testcases := []struct {
-		description      string
-		mirrorMappingStr string
-		expected         map[string]string
-	}{
-		{
-			"multiple",
-			"aaa:bbb,ccc:ddd",
-			map[string]string{
-				"aaa": "bbb",
-				"ccc": "ddd",
-			},
-		},
-		{
-			"multiple with some spaces",
-			"aaa: bbb, ccc:ddd",
-			map[string]string{
-				"aaa": "bbb",
-				"ccc": "ddd",
-			},
-		},
-		{
-			"single",
-			"aaa:bbb",
-			map[string]string{
-				"aaa": "bbb",
-			},
-		},
-	}
-
-	for _, tc := range testcases {
-		t.Run(tc.description, func(t *testing.T) {
-			result := parseRegistryMirror(tc.mirrorMappingStr)
-			assert.True(t, reflect.DeepEqual(result, tc.expected))
-		})
+		if loginServer := provider.parseACRLoginServerFromImage(test.image); loginServer != test.expected {
+			t.Errorf("function parseACRLoginServerFromImage returns \"%s\" for image %s, expected \"%s\"", loginServer, test.image, test.expected)
+		}
 	}
 }
diff --git a/pkg/provider/azure_loadbalancer_test.go b/pkg/provider/azure_loadbalancer_test.go
index 0fb4d8a6f..3a116a426 100644
--- a/pkg/provider/azure_loadbalancer_test.go
+++ b/pkg/provider/azure_loadbalancer_test.go
@@ -7599,7 +7599,6 @@ func TestReconcileMultipleStandardLoadBalancerConfigurations(t *testing.T) {
 			}
 
 			if tc.useMultipleLB {
-				az.LoadBalancerBackendPool = newBackendPoolTypeNodeIP(az)
 				az.MultipleStandardLoadBalancerConfigurations = []MultipleStandardLoadBalancerConfiguration{
 					{Name: "lb1"},
 					{Name: "lb2"},
@@ -8077,7 +8076,6 @@ func TestReconcileMultipleStandardLoadBalancerNodes(t *testing.T) {
 	for _, tc := range []struct {
 		description          string
 		lbName               string
-		init                 bool
 		existingLBConfigs    []MultipleStandardLoadBalancerConfiguration
 		existingNodes        []*v1.Node
 		existingLBs          []network.LoadBalancer
@@ -8426,89 +8424,6 @@ func TestReconcileMultipleStandardLoadBalancerNodes(t *testing.T) {
 				"lb4": nil,
 			},
 		},
-		{
-			description: "should record current node distributions after restarting the controller",
-			init:        true,
-			existingLBConfigs: []MultipleStandardLoadBalancerConfiguration{
-				{
-					Name: "lb1",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
-						PrimaryVMSet: "vmss-1",
-					},
-				},
-				{
-					Name: "lb2",
-					MultipleStandardLoadBalancerConfigurationSpec: MultipleStandardLoadBalancerConfigurationSpec{
-						PrimaryVMSet: "vmss-2",
-					},
-				},
-			},
-			existingNodes: []*v1.Node{
-				getTestNodeWithMetadata("node1", "vmss-1", map[string]string{"k1": "v1"}, "10.1.0.1"),
-				getTestNodeWithMetadata("node2", "vmss-2", map[string]string{"k3": "v3"}, "10.1.0.2"),
-				getTestNodeWithMetadata("node3", "vmss-3", map[string]string{"k2": "v2"}, "10.1.0.3"),
-				getTestNodeWithMetadata("node5", "vmss-5", map[string]string{"k2": "v2"}, "10.1.0.5"),
-				getTestNodeWithMetadata("node6", "vmss-6", map[string]string{"k3": "v3"}, "10.1.0.6"),
-			},
-			existingLBs: []network.LoadBalancer{
-				{
-					Name: ptr.To("lb1-internal"),
-					LoadBalancerPropertiesFormat: &network.LoadBalancerPropertiesFormat{
-						BackendAddressPools: &[]network.BackendAddressPool{
-							{
-								Name: ptr.To("kubernetes"),
-								BackendAddressPoolPropertiesFormat: &network.BackendAddressPoolPropertiesFormat{
-									LoadBalancerBackendAddresses: &[]network.LoadBalancerBackendAddress{
-										{
-											Name: ptr.To("node2"),
-											LoadBalancerBackendAddressPropertiesFormat: &network.LoadBalancerBackendAddressPropertiesFormat{
-												IPAddress: ptr.To("10.1.0.2"),
-											},
-										},
-									},
-								},
-							},
-						},
-					},
-				},
-				{
-					Name: ptr.To("lb2"),
-					LoadBalancerPropertiesFormat: &network.LoadBalancerPropertiesFormat{
-						BackendAddressPools: &[]network.BackendAddressPool{
-							{
-								Name: ptr.To("kubernetes"),
-								BackendAddressPoolPropertiesFormat: &network.BackendAddressPoolPropertiesFormat{
-									LoadBalancerBackendAddresses: &[]network.LoadBalancerBackendAddress{
-										{
-											Name: ptr.To("node3"),
-											LoadBalancerBackendAddressPropertiesFormat: &network.LoadBalancerBackendAddressPropertiesFormat{
-												IPAddress: ptr.To("10.1.0.3"),
-											},
-										},
-										{
-											Name: ptr.To("node4"),
-											LoadBalancerBackendAddressPropertiesFormat: &network.LoadBalancerBackendAddressPropertiesFormat{
-												IPAddress: ptr.To("10.1.0.4"),
-											},
-										},
-										{
-											Name: ptr.To("node5"),
-											LoadBalancerBackendAddressPropertiesFormat: &network.LoadBalancerBackendAddressPropertiesFormat{
-												IPAddress: ptr.To("10.1.0.5"),
-											},
-										},
-									},
-								},
-							},
-						},
-					},
-				},
-			},
-			expectedLBToNodesMap: map[string]*utilsets.IgnoreCaseSet{
-				"lb1": utilsets.NewString("node1", "node6"),
-				"lb2": utilsets.NewString("node2", "node3", "node5"),
-			},
-		},
 	} {
 		tc := tc
 		t.Run(tc.description, func(t *testing.T) {
@@ -8516,18 +8431,9 @@ func TestReconcileMultipleStandardLoadBalancerNodes(t *testing.T) {
 			ss, _ := NewTestScaleSet(ctrl)
 			ss.DisableAvailabilitySetNodes = true
 			az.VMSet = ss
-			az.nodePrivateIPToNodeNameMap = map[string]string{
-				"10.1.0.1": "node1",
-				"10.1.0.2": "node2",
-				"10.1.0.3": "node3",
-				"10.1.0.4": "node4",
-				"10.1.0.5": "node5",
-				"10.1.0.6": "node6",
-			}
-			az.LoadBalancerBackendPool = newBackendPoolTypeNodeIP(az)
 			az.MultipleStandardLoadBalancerConfigurations = tc.existingLBConfigs
 			svc := getTestService("test", v1.ProtocolTCP, nil, false)
-			_ = az.reconcileMultipleStandardLoadBalancerBackendNodes("kubernetes", tc.lbName, &tc.existingLBs, &svc, tc.existingNodes, tc.init)
+			_ = az.reconcileMultipleStandardLoadBalancerBackendNodes(tc.lbName, &tc.existingLBs, &svc, tc.existingNodes)
 
 			expectedLBToNodesMap := make(map[string]*utilsets.IgnoreCaseSet)
 			for _, multiSLBConfig := range az.MultipleStandardLoadBalancerConfigurations {
diff --git a/pkg/provider/loadbalancer/iputil/prefix_test.go b/pkg/provider/loadbalancer/iputil/prefix_test.go
index 30661c4a4..d27fa91c6 100644
--- a/pkg/provider/loadbalancer/iputil/prefix_test.go
+++ b/pkg/provider/loadbalancer/iputil/prefix_test.go
@@ -203,7 +203,7 @@ func TestAggregatePrefixes(t *testing.T) {
 			Name: "Overlap IPv4",
 			Input: []netip.Prefix{
 				netip.MustParsePrefix("192.168.0.0/16"),
-				netip.MustParsePrefix("192.170.0.0/16"),
+				netip.MustParsePrefix("192.169.0.0/16"),
 				netip.MustParsePrefix("10.10.0.1/32"),
 
 				netip.MustParsePrefix("192.168.1.0/24"),
@@ -211,49 +211,10 @@ func TestAggregatePrefixes(t *testing.T) {
 			},
 			Output: []netip.Prefix{
 				netip.MustParsePrefix("192.168.0.0/16"),
-				netip.MustParsePrefix("192.170.0.0/16"),
+				netip.MustParsePrefix("192.169.0.0/16"),
 				netip.MustParsePrefix("10.10.0.1/32"),
 			},
 		},
-		{
-			Name: "Collapse IPv4",
-			Input: []netip.Prefix{
-				netip.MustParsePrefix("192.168.0.0/24"),
-				netip.MustParsePrefix("192.168.1.0/24"),
-				netip.MustParsePrefix("192.168.2.0/24"),
-				netip.MustParsePrefix("192.168.3.0/24"),
-				netip.MustParsePrefix("10.0.0.0/8"),
-				netip.MustParsePrefix("172.16.0.0/12"),
-				netip.MustParsePrefix("192.168.4.0/24"),
-				netip.MustParsePrefix("192.168.5.0/24"),
-			},
-			Output: []netip.Prefix{
-				netip.MustParsePrefix("10.0.0.0/8"),
-				netip.MustParsePrefix("172.16.0.0/12"),
-				netip.MustParsePrefix("192.168.0.0/22"),
-				netip.MustParsePrefix("192.168.4.0/23"),
-			},
-		},
-		{
-			Name: "Collapse IPv6",
-			Input: []netip.Prefix{
-				netip.MustParsePrefix("2001:db8::/32"),
-				netip.MustParsePrefix("2001:db8:1::/48"),
-				netip.MustParsePrefix("2001:db8:2::/48"),
-				netip.MustParsePrefix("2001:db8:3::/48"),
-				netip.MustParsePrefix("2001:db8:4::/48"),
-				netip.MustParsePrefix("2001:db8:5::/48"),
-				netip.MustParsePrefix("2001:db8:6::/48"),
-				netip.MustParsePrefix("2001:db8:7::/48"),
-				netip.MustParsePrefix("2001:dbf::/32"),
-				netip.MustParsePrefix("2001:dba::/32"),
-			},
-			Output: []netip.Prefix{
-				netip.MustParsePrefix("2001:db8::/32"),
-				netip.MustParsePrefix("2001:dbf::/32"),
-				netip.MustParsePrefix("2001:dba::/32"),
-			},
-		},
 	}
 
 	for _, tt := range tests {
diff --git a/pkg/provider/loadbalancer/iputil/prefix_tree_test.go b/pkg/provider/loadbalancer/iputil/prefix_tree_test.go
index fe3f3dddf..5a21a98ef 100644
--- a/pkg/provider/loadbalancer/iputil/prefix_tree_test.go
+++ b/pkg/provider/loadbalancer/iputil/prefix_tree_test.go
@@ -51,7 +51,7 @@ func TestPrefixTreeIPv4(t *testing.T) {
 			"Overlap",
 			[]string{
 				"192.168.0.0/16",
-				"192.170.0.0/16",
+				"192.169.0.0/16",
 				"10.10.0.1/32",
 
 				"192.168.1.0/24",
@@ -59,29 +59,10 @@ func TestPrefixTreeIPv4(t *testing.T) {
 			},
 			[]string{
 				"192.168.0.0/16",
-				"192.170.0.0/16",
+				"192.169.0.0/16",
 				"10.10.0.1/32",
 			},
 		},
-		{
-			"Collapse",
-			[]string{
-				"192.168.0.0/24",
-				"192.168.1.0/24",
-				"192.168.2.0/24",
-				"192.168.3.0/24",
-				"10.0.0.0/8",
-				"172.16.0.0/12",
-				"192.168.4.0/24",
-				"192.168.5.0/24",
-			},
-			[]string{
-				"10.0.0.0/8",
-				"172.16.0.0/12",
-				"192.168.0.0/22",
-				"192.168.4.0/23",
-			},
-		},
 	}
 
 	for _, tt := range tests {
@@ -120,13 +101,13 @@ func TestPrefixTreeIPv6(t *testing.T) {
 			"NoOverlap",
 			[]string{
 				"2001:db8:0:1::/64",
+				"2001:db8:0:2::/64",
 				"2001:db8:0:3::/64",
-				"2001:db8:0:5::/64",
 			},
 			[]string{
 				"2001:db8:0:1::/64",
+				"2001:db8:0:2::/64",
 				"2001:db8:0:3::/64",
-				"2001:db8:0:5::/64",
 			},
 		},
 		{
@@ -134,40 +115,13 @@ func TestPrefixTreeIPv6(t *testing.T) {
 			[]string{
 				"2001:db8::/32",
 				"2001:db8:0:1::/64",
+				"2001:db8:0:2::/64",
 				"2001:db8:0:3::/64",
 			},
 			[]string{
 				"2001:db8::/32",
 			},
 		},
-		{
-			"Collapse",
-			[]string{
-				"2001:db8::/32",
-				"2001:db8:1::/48",
-				"2001:db8:2::/48",
-				"2001:db8:3::/48",
-				"2001:db8:4::/48",
-				"2001:db8:5::/48",
-				"2001:db8:6::/48",
-				"2001:db8:7::/48",
-				"2001:db8:8::/48",
-				"2001:db8:9::/48",
-				"2001:db8:a::/48",
-				"2001:db8:b::/48",
-				"2001:db8:c::/48",
-				"2001:db8:d::/48",
-				"2001:db8:e::/48",
-				"2001:db8:f::/48",
-				"2001:dbf::/32", // Noise data
-				"2001:dba::/32", // Noise data
-			},
-			[]string{
-				"2001:db8::/32",
-				"2001:dbf::/32",
-				"2001:dba::/32",
-			},
-		},
 	}
 
 	for _, tt := range tests {