Repository: kubernetes-sigs/cloud-provider-azure
Pull request #2945 (2022-12-15 02:01:08)

[release 1.23] build: run golangci-lint in Github Action and enable errorlint
<!--  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 cleanup 
<!--
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:
cherry-pick #2868 and #2923 

#### 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/lint.yaml b/.github/workflows/lint.yaml
new file mode 100644
index 000000000..d68b3da4f
--- /dev/null
+++ b/.github/workflows/lint.yaml
@@ -0,0 +1,20 @@
+name: Code Lint
+
+on:
+  workflow_dispatch:
+  push:
+  pull_request:
+
+jobs:
+  Lint:
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout
+        uses: actions/checkout@v3
+      - name: Setup Golang
+        uses: actions/setup-go@v3
+        with:
+          go-version-file: go.mod
+      - name: Lint
+        run: |
+          make lint
diff --git a/.golangci.yml b/.golangci.yml
index e10f54519..34bd705e1 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -1,26 +1,45 @@
 run:
-  deadline: 30m
-  concurrency: 2
+  timeout: 30m
   go: '1.18'
-  allow-serial-runners: true
-skip-dirs:
+  tests: true
+  skip-dirs:
     - vendor
 linters:
   disable-all: true
   enable:
-    - LINTER_TO_RUN
-  # Run with --fast=false for more extensive checks
+    - errcheck
+    - goconst
+    - gofmt
+    - goimports
+    - revive
+    - gosec
+    - gosimple
+    - govet
+    - ineffassign
+    - misspell
+    - nakedret
+    - staticcheck
+    - typecheck
+    - unconvert
+    - unused
+    - asasalint
+    - asciicheck
+    - bidichk
+    - errorlint
+    - loggercheck
   fast: false
-  govet:
-    # Report about shadowed variables.
-    # Default: false
-    check-shadowing: true
 issues:
   exclude-rules:
     - path: tests/e2e
       linters:
         - revive
-  #include:
-  #  - EXC0002 # include "missing comments" issues from golint
   max-issues-per-linter: 0
   max-same-issues: 0
+linters-settings:
+  staticcheck:
+    checks: ["all", "-SA1019"]
+  gosec:
+    excludes:
+      - G114
+  goimports:
+    local-prefixes: sigs.k8s.io/cloud-provider-azure
diff --git a/Makefile b/Makefile
index 962e6b38d..2d7db24dd 100644
--- a/Makefile
+++ b/Makefile
@@ -308,11 +308,11 @@ ifdef JUNIT
 endif
 
 .PHONY: test-check
-test-check: test-lint test-boilerplate verify-vendor-licenses ## Run all static checks.
+test-check: test-boilerplate verify-vendor-licenses ## Run all static checks.
 
-.PHONY: test-lint
-test-lint: ## Run golint test.
-	hack/verify-golint.sh
+.PHONY: lint
+lint: golangci-lint ## Run golangci-lint against code.
+	$(LINTER) run -v
 
 .PHONY: test-boilerplate
 test-boilerplate: ## Run boilerplate test.
@@ -368,3 +368,12 @@ deploy: image push ## Build, push and deploy an aks-engine cluster.
 .PHONY: release-staging
 release-staging: ## Release the cloud provider images.
 	ENABLE_GIT_COMMAND=$(ENABLE_GIT_COMMAND) $(MAKE) image push
+
+##@ Tools
+
+LINTER = $(shell pwd)/bin/golangci-lint
+LINTER_VERSION = v1.50.1
+.PHONY: golangci-lint
+golangci-lint:  ## Download golangci-lint locally if necessary.
+	@echo "Installing golangci-lint"
+	@test -s $(LINTER) || curl -sfL https://raw.githubusercontent.com/golangci/golangci-lint/$(LINTER_VERSION)/install.sh | sh -s -- -b $(shell pwd)/bin $(LINTER_VERSION)
diff --git a/cmd/acr-credential-provider/main.go b/cmd/acr-credential-provider/main.go
index f19d141d5..12297be2f 100644
--- a/cmd/acr-credential-provider/main.go
+++ b/cmd/acr-credential-provider/main.go
@@ -27,6 +27,7 @@ import (
 	"github.com/spf13/cobra"
 	"k8s.io/component-base/logs"
 	"k8s.io/klog/v2"
+
 	"sigs.k8s.io/cloud-provider-azure/pkg/credentialprovider"
 )
 
diff --git a/cmd/acr-credential-provider/plugin.go b/cmd/acr-credential-provider/plugin.go
index 9005eac48..1a9a34bb0 100644
--- a/cmd/acr-credential-provider/plugin.go
+++ b/cmd/acr-credential-provider/plugin.go
@@ -30,6 +30,7 @@ import (
 	"k8s.io/apimachinery/pkg/runtime/serializer/json"
 	"k8s.io/kubelet/pkg/apis/credentialprovider/install"
 	"k8s.io/kubelet/pkg/apis/credentialprovider/v1alpha1"
+
 	"sigs.k8s.io/cloud-provider-azure/pkg/credentialprovider"
 )
 
@@ -140,7 +141,7 @@ func encodeResponse(response *v1alpha1.CredentialProviderResponse) ([]byte, erro
 	encoder := codecs.EncoderForVersion(info.Serializer, v1alpha1.SchemeGroupVersion)
 	data, err := runtime.Encode(encoder, response)
 	if err != nil {
-		return nil, fmt.Errorf("failed to encode response: %v", err)
+		return nil, fmt.Errorf("failed to encode response: %w", err)
 	}
 
 	return data, nil
diff --git a/cmd/cloud-controller-manager/controller-manager.go b/cmd/cloud-controller-manager/controller-manager.go
index 6500b2eed..78af7b036 100644
--- a/cmd/cloud-controller-manager/controller-manager.go
+++ b/cmd/cloud-controller-manager/controller-manager.go
@@ -25,10 +25,9 @@ import (
 	"time"
 
 	"k8s.io/component-base/logs"
-	"sigs.k8s.io/cloud-provider-azure/cmd/cloud-controller-manager/app"
-
 	_ "k8s.io/component-base/metrics/prometheus/clientgo" // load all the prometheus client-go plugins
 
+	"sigs.k8s.io/cloud-provider-azure/cmd/cloud-controller-manager/app"
 	_ "sigs.k8s.io/cloud-provider-azure/pkg/provider"
 )
 
diff --git a/cmd/cloud-node-manager/node-manager.go b/cmd/cloud-node-manager/node-manager.go
index c132a8470..74c8c69e8 100644
--- a/cmd/cloud-node-manager/node-manager.go
+++ b/cmd/cloud-node-manager/node-manager.go
@@ -25,10 +25,9 @@ import (
 	"time"
 
 	"k8s.io/component-base/logs"
-	"sigs.k8s.io/cloud-provider-azure/cmd/cloud-node-manager/app"
-
 	_ "k8s.io/component-base/metrics/prometheus/clientgo" // load all the prometheus client-go plugins
 
+	"sigs.k8s.io/cloud-provider-azure/cmd/cloud-node-manager/app"
 	_ "sigs.k8s.io/cloud-provider-azure/pkg/provider"
 )
 
diff --git a/hack/verify-golint.sh b/hack/verify-golint.sh
deleted file mode 100755
index 1cf2c3a6e..000000000
--- a/hack/verify-golint.sh
+++ /dev/null
@@ -1,38 +0,0 @@
-#!/bin/bash
-
-# Copyright 2020 The Kubernetes Authors.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#     http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-set -euo pipefail
-
-if [[ -z "$(command -v golangci-lint)" ]]; then
-  echo "Cannot find golangci-lint. Installing golangci-lint..."
-  go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.45.0
-  export PATH=$PATH:$(go env GOPATH)/bin
-fi
-
-echo "Verifying golint"
-readonly PKG_ROOT="$(git rev-parse --show-toplevel)"
-
-LINTERS=("deadcode" "errcheck" "goconst" "gofmt" "goimports" "revive" "gosec" "gosimple" "govet" "ineffassign" "misspell" "nakedret" "staticcheck" "structcheck" "typecheck" "unconvert" "unused" "varcheck" )
-GOLANGCI_YML="${PKG_ROOT}/.golangci.yml"
-GOLANGCI_YML_TEST="${PKG_ROOT}/.golangci-test.yml"
-for LINTER in "${LINTERS[@]}"; do
-  cp -rf "${GOLANGCI_YML}" "${GOLANGCI_YML_TEST}"
-  sed -i "s|LINTER_TO_RUN|${LINTER}|g" "${GOLANGCI_YML_TEST}"
-  golangci-lint run -v --config "${GOLANGCI_YML_TEST}"
-  echo ""
-done
-
-echo "Congratulations! Lint check completed for all Go source files."
diff --git a/pkg/azureclients/armclient/azure_armclient.go b/pkg/azureclients/armclient/azure_armclient.go
index 224079e59..901ee39ba 100644
--- a/pkg/azureclients/armclient/azure_armclient.go
+++ b/pkg/azureclients/armclient/azure_armclient.go
@@ -34,13 +34,12 @@ import (
 	"time"
 	"unicode"
 
-	"sigs.k8s.io/cloud-provider-azure/pkg/azureclients"
-
 	"github.com/Azure/go-autorest/autorest"
 	"github.com/Azure/go-autorest/autorest/azure"
 	"github.com/Azure/go-autorest/tracing"
-
 	"k8s.io/klog/v2"
+
+	"sigs.k8s.io/cloud-provider-azure/pkg/azureclients"
 	"sigs.k8s.io/cloud-provider-azure/pkg/retry"
 	"sigs.k8s.io/cloud-provider-azure/pkg/version"
 )
diff --git a/pkg/azureclients/containerserviceclient/interface.go b/pkg/azureclients/containerserviceclient/interface.go
index 98ff18d8a..477b6b4fb 100644
--- a/pkg/azureclients/containerserviceclient/interface.go
+++ b/pkg/azureclients/containerserviceclient/interface.go
@@ -20,6 +20,7 @@ import (
 	"context"
 
 	"github.com/Azure/azure-sdk-for-go/services/containerservice/mgmt/2021-10-01/containerservice"
+
 	"sigs.k8s.io/cloud-provider-azure/pkg/retry"
 )
 
diff --git a/pkg/azureclients/virtualnetworklinksclient/azure_virtualnetworklinksclient.go b/pkg/azureclients/virtualnetworklinksclient/azure_virtualnetworklinksclient.go
index 46d9239b0..8436ff665 100644
--- a/pkg/azureclients/virtualnetworklinksclient/azure_virtualnetworklinksclient.go
+++ b/pkg/azureclients/virtualnetworklinksclient/azure_virtualnetworklinksclient.go
@@ -27,6 +27,7 @@ import (
 	"github.com/Azure/go-autorest/autorest/azure"
 	"k8s.io/client-go/util/flowcontrol"
 	"k8s.io/klog/v2"
+
 	azclients "sigs.k8s.io/cloud-provider-azure/pkg/azureclients"
 	"sigs.k8s.io/cloud-provider-azure/pkg/azureclients/armclient"
 	"sigs.k8s.io/cloud-provider-azure/pkg/metrics"
diff --git a/pkg/azureclients/virtualnetworklinksclient/interface.go b/pkg/azureclients/virtualnetworklinksclient/interface.go
index ff8c6c2df..5087bf601 100644
--- a/pkg/azureclients/virtualnetworklinksclient/interface.go
+++ b/pkg/azureclients/virtualnetworklinksclient/interface.go
@@ -20,6 +20,7 @@ import (
 	"context"
 
 	"github.com/Azure/azure-sdk-for-go/services/privatedns/mgmt/2018-09-01/privatedns"
+
 	"sigs.k8s.io/cloud-provider-azure/pkg/retry"
 )
 
diff --git a/pkg/azureclients/vmasclient/interface.go b/pkg/azureclients/vmasclient/interface.go
index 07ecb9ac1..4e303f16b 100644
--- a/pkg/azureclients/vmasclient/interface.go
+++ b/pkg/azureclients/vmasclient/interface.go
@@ -20,6 +20,7 @@ import (
 	"context"
 
 	"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2022-03-01/compute"
+
 	"sigs.k8s.io/cloud-provider-azure/pkg/retry"
 )
 
diff --git a/pkg/azureclients/vmsizeclient/interface.go b/pkg/azureclients/vmsizeclient/interface.go
index 119d55e9e..8c595d0f3 100644
--- a/pkg/azureclients/vmsizeclient/interface.go
+++ b/pkg/azureclients/vmsizeclient/interface.go
@@ -20,6 +20,7 @@ import (
 	"context"
 
 	"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2022-03-01/compute"
+
 	"sigs.k8s.io/cloud-provider-azure/pkg/retry"
 )
 
diff --git a/pkg/credentialprovider/azure_acr_helper.go b/pkg/credentialprovider/azure_acr_helper.go
index a7482f748..4fdf3a70a 100644
--- a/pkg/credentialprovider/azure_acr_helper.go
+++ b/pkg/credentialprovider/azure_acr_helper.go
@@ -91,13 +91,13 @@ func receiveChallengeFromLoginServer(serverAddress, scheme string) (*authDirecti
 	var r *http.Request
 	r, err = http.NewRequest("GET", challengeURL.String(), nil)
 	if err != nil {
-		return nil, fmt.Errorf("failed to construct request, got %v", err)
+		return nil, fmt.Errorf("failed to construct request, got %w", err)
 	}
 	r.Header.Add(userAgentHeader, userAgent)
 
 	var challenge *http.Response
 	if challenge, err = client.Do(r); err != nil {
-		return nil, fmt.Errorf("error reaching registry endpoint %s, error: %s", challengeURL.String(), err)
+		return nil, fmt.Errorf("error reaching registry endpoint %s, error: %w", challengeURL.String(), err)
 	}
 	defer challenge.Body.Close()
 
@@ -164,7 +164,7 @@ func performTokenExchange(
 	var r *http.Request
 	r, err = http.NewRequest("POST", authEndpoint, bytes.NewBufferString(datac))
 	if err != nil {
-		return "", fmt.Errorf("failed to construct request, got %v", err)
+		return "", fmt.Errorf("failed to construct request, got %w", err)
 	}
 	r.Header.Add(userAgentHeader, userAgent)
 	r.Header.Add("Content-Type", "application/x-www-form-urlencoded")
diff --git a/pkg/credentialprovider/azure_credentials.go b/pkg/credentialprovider/azure_credentials.go
index 593e3567b..7e4b7475e 100644
--- a/pkg/credentialprovider/azure_credentials.go
+++ b/pkg/credentialprovider/azure_credentials.go
@@ -29,12 +29,12 @@ import (
 
 	"github.com/Azure/go-autorest/autorest/adal"
 	"github.com/Azure/go-autorest/autorest/azure"
-
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/klog/v2"
 	"k8s.io/kubelet/pkg/apis/credentialprovider/v1alpha1"
-	"sigs.k8s.io/cloud-provider-azure/pkg/auth"
 	"sigs.k8s.io/yaml"
+
+	"sigs.k8s.io/cloud-provider-azure/pkg/auth"
 )
 
 // Refer: https://github.com/kubernetes/kubernetes/blob/master/pkg/credentialprovider/azure/azure_credentials.go
@@ -85,7 +85,7 @@ func newAcrProviderFromConfigReader(configReader io.Reader) (*acrProvider, error
 
 	servicePrincipalToken, err := auth.GetServicePrincipalToken(config, env, env.ServiceManagementEndpoint)
 	if err != nil {
-		return nil, fmt.Errorf("failed to create service principal token: %v", err)
+		return nil, fmt.Errorf("failed to create service principal token: %w", err)
 	}
 
 	return &acrProvider{
diff --git a/pkg/nodemanager/nodemanager.go b/pkg/nodemanager/nodemanager.go
index f7ba3abea..ec901f266 100644
--- a/pkg/nodemanager/nodemanager.go
+++ b/pkg/nodemanager/nodemanager.go
@@ -262,7 +262,7 @@ func (cnc *CloudNodeController) updateNodeAddress(ctx context.Context, node *v1.
 
 	nodeAddresses, err := cnc.getNodeAddressesByName(ctx, node)
 	if err != nil {
-		return fmt.Errorf("Error getting node addresses for node %q: %v", node.Name, err)
+		return fmt.Errorf("getting node addresses for node %q: %w", node.Name, err)
 	}
 
 	if len(nodeAddresses) == 0 {
@@ -302,7 +302,7 @@ func (cnc *CloudNodeController) updateNodeAddress(ctx context.Context, node *v1.
 	newNode.Status.Addresses = nodeAddresses
 	_, _, err = PatchNodeStatus(cnc.kubeClient.CoreV1(), types.NodeName(node.Name), node, newNode)
 	if err != nil {
-		return fmt.Errorf("Error patching node with cloud ip addresses = [%v]", err)
+		return fmt.Errorf("patching node with cloud ip addresses: %w", err)
 	}
 
 	return nil
diff --git a/pkg/provider/azure.go b/pkg/provider/azure.go
index 69de02af6..c7c2eb97c 100644
--- a/pkg/provider/azure.go
+++ b/pkg/provider/azure.go
@@ -392,7 +392,7 @@ func NewCloudFromConfigFile(configFilePath string, calFromCCM bool) (cloudprovid
 	}
 
 	if err != nil {
-		return nil, fmt.Errorf("could not init cloud provider azure: %v", err)
+		return nil, fmt.Errorf("could not init cloud provider azure: %w", err)
 	}
 	if cloud == nil {
 		return nil, fmt.Errorf("nil cloud")
@@ -436,7 +436,7 @@ func NewCloudFromSecret(clientBuilder cloudprovider.ControllerClientBuilder, sec
 
 	err := az.InitializeCloudFromSecret()
 	if err != nil {
-		return nil, fmt.Errorf("NewCloudFromSecret: failed to initialize cloud from secret %s/%s: %v", az.SecretNamespace, az.SecretName, err)
+		return nil, fmt.Errorf("NewCloudFromSecret: failed to initialize cloud from secret %s/%s: %w", az.SecretNamespace, az.SecretName, err)
 	}
 
 	az.ipv6DualStackEnabled = utilfeature.DefaultFeatureGate.Enabled(consts.IPv6DualStack)
diff --git a/pkg/provider/azure_controller_common.go b/pkg/provider/azure_controller_common.go
index ab69a95ef..175262a92 100644
--- a/pkg/provider/azure_controller_common.go
+++ b/pkg/provider/azure_controller_common.go
@@ -351,7 +351,7 @@ func (c *controllerCommon) DetachDisk(ctx context.Context, diskName, diskURI str
 	} else {
 		lun, _, errGetLun := c.GetDiskLun(diskName, diskURI, nodeName)
 		if errGetLun == nil || !strings.Contains(errGetLun.Error(), consts.CannotFindDiskLUN) {
-			return fmt.Errorf("disk(%s) is still attatched to node(%s) on lun(%d), error: %v", diskURI, nodeName, lun, errGetLun)
+			return fmt.Errorf("disk(%s) is still attached to node(%s) on lun(%d), error: %w", diskURI, nodeName, lun, errGetLun)
 		}
 	}
 
diff --git a/pkg/provider/azure_instance_metadata.go b/pkg/provider/azure_instance_metadata.go
index 708804a19..014f900fb 100644
--- a/pkg/provider/azure_instance_metadata.go
+++ b/pkg/provider/azure_instance_metadata.go
@@ -23,6 +23,7 @@ import (
 	"net/http"
 
 	"k8s.io/klog/v2"
+
 	azcache "sigs.k8s.io/cloud-provider-azure/pkg/cache"
 	"sigs.k8s.io/cloud-provider-azure/pkg/consts"
 )
diff --git a/pkg/provider/azure_instances.go b/pkg/provider/azure_instances.go
index 1acd8f908..2144795a5 100644
--- a/pkg/provider/azure_instances.go
+++ b/pkg/provider/azure_instances.go
@@ -29,6 +29,7 @@ import (
 	"k8s.io/klog/v2"
 
 	"github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2022-03-01/compute"
+
 	azcache "sigs.k8s.io/cloud-provider-azure/pkg/cache"
 	"sigs.k8s.io/cloud-provider-azure/pkg/consts"
 )
diff --git a/pkg/provider/azure_loadbalancer.go b/pkg/provider/azure_loadbalancer.go
index a56b275ed..1e884e7e2 100644
--- a/pkg/provider/azure_loadbalancer.go
+++ b/pkg/provider/azure_loadbalancer.go
@@ -2539,7 +2539,7 @@ func (az *Cloud) reconcileSecurityGroup(clusterName string, service *v1.Service,
 
 	additionalIPs, err := getServiceAdditionalPublicIPs(service)
 	if err != nil {
-		return nil, fmt.Errorf("unable to get additional public IPs, error=%v", err)
+		return nil, fmt.Errorf("unable to get additional public IPs, error=%w", err)
 	}
 
 	destinationIPAddresses := []string{destinationIPAddress}
diff --git a/pkg/provider/azure_mock_vmsets.go b/pkg/provider/azure_mock_vmsets.go
index 60980ad9b..470f96d04 100644
--- a/pkg/provider/azure_mock_vmsets.go
+++ b/pkg/provider/azure_mock_vmsets.go
@@ -27,6 +27,7 @@ import (
 	v1 "k8s.io/api/core/v1"
 	types "k8s.io/apimachinery/pkg/types"
 	cloud_provider "k8s.io/cloud-provider"
+
 	cache "sigs.k8s.io/cloud-provider-azure/pkg/cache"
 )
 
diff --git a/pkg/provider/azure_standard.go b/pkg/provider/azure_standard.go
index dd9a8ba9d..1c78f0b2b 100644
--- a/pkg/provider/azure_standard.go
+++ b/pkg/provider/azure_standard.go
@@ -1222,7 +1222,7 @@ func (as *availabilitySet) GetNodeNameByIPConfigurationID(ipConfigurationID stri
 
 	asName, err := getAvailabilitySetNameByID(asID)
 	if err != nil {
-		return "", "", fmt.Errorf("cannot get the availability set name by the availability set ID %s: %v", asID, err)
+		return "", "", fmt.Errorf("cannot get the availability set name by the availability set ID %s: %w", asID, err)
 	}
 	return vmName, strings.ToLower(asName), nil
 }
diff --git a/pkg/provider/azure_storageaccount.go b/pkg/provider/azure_storageaccount.go
index 7975418ad..c5366cccd 100644
--- a/pkg/provider/azure_storageaccount.go
+++ b/pkg/provider/azure_storageaccount.go
@@ -167,7 +167,7 @@ func (az *Cloud) EnsureStorageAccount(ctx context.Context, accountOptions *Accou
 	if accountOptions.CreatePrivateEndpoint {
 		// Create DNS zone first, this could make sure driver has write permission on vnetResourceGroup
 		if err := az.createPrivateDNSZone(ctx, vnetResourceGroup); err != nil {
-			return "", "", fmt.Errorf("Failed to create private DNS zone(%s) in resourceGroup(%s), error: %v", PrivateDNSZoneName, vnetResourceGroup, err)
+			return "", "", fmt.Errorf("Failed to create private DNS zone(%s) in resourceGroup(%s), error: %w", PrivateDNSZoneName, vnetResourceGroup, err)
 		}
 	}
 
@@ -271,19 +271,19 @@ func (az *Cloud) EnsureStorageAccount(ctx context.Context, accountOptions *Accou
 			// Create private endpoint
 			privateEndpointName := accountName + "-pvtendpoint"
 			if err := az.createPrivateEndpoint(ctx, accountName, storageAccount.ID, privateEndpointName, vnetResourceGroup); err != nil {
-				return "", "", fmt.Errorf("Failed to create private endpoint for storage account(%s), resourceGroup(%s), error: %v", accountName, vnetResourceGroup, err)
+				return "", "", fmt.Errorf("Failed to create private endpoint for storage account(%s), resourceGroup(%s), error: %w", accountName, vnetResourceGroup, err)
 			}
 
 			// Create virtual link to the zone private DNS zone
 			vNetLinkName := accountName + "-vnetlink"
 			if err := az.createVNetLink(ctx, vNetLinkName, vnetResourceGroup); err != nil {
-				return "", "", fmt.Errorf("Failed to create virtual link for vnet(%s) and DNS Zone(%s) in resourceGroup(%s), error: %v", az.VnetName, PrivateDNSZoneName, vnetResourceGroup, err)
+				return "", "", fmt.Errorf("Failed to create virtual link for vnet(%s) and DNS Zone(%s) in resourceGroup(%s), error: %w", az.VnetName, PrivateDNSZoneName, vnetResourceGroup, err)
 			}
 
 			// Create dns zone group
 			dnsZoneGroupName := accountName + "-dnszonegroup"
 			if err := az.createPrivateDNSZoneGroup(ctx, dnsZoneGroupName, privateEndpointName, vnetResourceGroup); err != nil {
-				return "", "", fmt.Errorf("Failed to create private DNS zone group - privateEndpoint(%s), vNetName(%s), resourceGroup(%s), error: %v", privateEndpointName, az.VnetName, vnetResourceGroup, err)
+				return "", "", fmt.Errorf("Failed to create private DNS zone group - privateEndpoint(%s), vNetName(%s), resourceGroup(%s), error: %w", privateEndpointName, az.VnetName, vnetResourceGroup, err)
 			}
 		}
 	}
diff --git a/pkg/provider/azure_vmss.go b/pkg/provider/azure_vmss.go
index f1b233a2d..21669d815 100644
--- a/pkg/provider/azure_vmss.go
+++ b/pkg/provider/azure_vmss.go
@@ -43,6 +43,7 @@ import (
 var (
 	// ErrorNotVmssInstance indicates an instance is not belonging to any vmss.
 	ErrorNotVmssInstance = errors.New("not a vmss instance")
+	ErrScaleSetNotFound  = errors.New("scale set not found")
 
 	scaleSetNameRE         = regexp.MustCompile(`.*/subscriptions/(?:.*)/Microsoft.Compute/virtualMachineScaleSets/(.+)/virtualMachines(?:.*)`)
 	resourceGroupRE        = regexp.MustCompile(`.*/subscriptions/(?:.*)/resourceGroups/(.+)/providers/Microsoft.Compute/virtualMachineScaleSets/(?:.*)/virtualMachines(?:.*)`)
@@ -816,7 +817,7 @@ func (ss *ScaleSet) GetVMSetNames(service *v1.Service, nodes []*v1.Node) (*[]str
 		}
 		if !found {
 			klog.Errorf("ss.GetVMSetNames - scale set (%s) in service annotation not found", serviceVMSetName)
-			return nil, fmt.Errorf("scale set (%s) - not found", serviceVMSetName)
+			return nil, ErrScaleSetNotFound
 		}
 		return &[]string{serviceVMSetName}, nil
 	}
diff --git a/pkg/retry/azure_error.go b/pkg/retry/azure_error.go
index 33e935591..751047264 100644
--- a/pkg/retry/azure_error.go
+++ b/pkg/retry/azure_error.go
@@ -339,7 +339,7 @@ func GetVMSSMetadataByRawError(err *Error) (string, string, error) {
 	reg := regexp.MustCompile(`.*/subscriptions/(?:.*)/resourceGroups/(.*)/providers/Microsoft.Compute/virtualMachineScaleSets/(.+).`)
 	matches := reg.FindStringSubmatch(err.ServiceErrorMessage())
 	if len(matches) != 3 {
-		return "", "", fmt.Errorf("GetVMSSMetadataByRawError: couldn't find a VMSS resource Id from error message %s", err.RawError)
+		return "", "", fmt.Errorf("GetVMSSMetadataByRawError: couldn't find a VMSS resource Id from error message %w", err.RawError)
 	}
 
 	return matches[1], matches[2], nil


Test patch:
diff --git a/cmd/cloud-controller-manager/app/options/options_test.go b/cmd/cloud-controller-manager/app/options/options_test.go
index ce705e78b..0bb3b7a47 100644
--- a/cmd/cloud-controller-manager/app/options/options_test.go
+++ b/cmd/cloud-controller-manager/app/options/options_test.go
@@ -22,10 +22,7 @@ import (
 	"testing"
 	"time"
 
-	"k8s.io/controller-manager/pkg/leadermigration/options"
-
 	"github.com/spf13/pflag"
-
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/util/diff"
 	"k8s.io/apimachinery/pkg/util/wait"
@@ -36,6 +33,8 @@ import (
 	componentbaseconfig "k8s.io/component-base/config"
 	kubectrlmgrconfig "k8s.io/controller-manager/config"
 	cmoptions "k8s.io/controller-manager/options"
+	"k8s.io/controller-manager/pkg/leadermigration/options"
+
 	"sigs.k8s.io/cloud-provider-azure/pkg/consts"
 	"sigs.k8s.io/cloud-provider-azure/pkg/nodeipam/config"
 )
diff --git a/cmd/cloud-controller-manager/app/testing/testserver.go b/cmd/cloud-controller-manager/app/testing/testserver.go
index a34a22df8..a59ac8aa5 100644
--- a/cmd/cloud-controller-manager/app/testing/testserver.go
+++ b/cmd/cloud-controller-manager/app/testing/testserver.go
@@ -29,6 +29,7 @@ import (
 	"k8s.io/apimachinery/pkg/util/wait"
 	"k8s.io/client-go/kubernetes"
 	restclient "k8s.io/client-go/rest"
+
 	"sigs.k8s.io/cloud-provider-azure/cmd/cloud-controller-manager/app"
 	cloudcontrollerconfig "sigs.k8s.io/cloud-provider-azure/cmd/cloud-controller-manager/app/config"
 	"sigs.k8s.io/cloud-provider-azure/cmd/cloud-controller-manager/app/options"
diff --git a/pkg/azureclients/privateendpointclient/azure_privateendpointclient_test.go b/pkg/azureclients/privateendpointclient/azure_privateendpointclient_test.go
index 2abb0003e..8b7e55c8a 100644
--- a/pkg/azureclients/privateendpointclient/azure_privateendpointclient_test.go
+++ b/pkg/azureclients/privateendpointclient/azure_privateendpointclient_test.go
@@ -26,12 +26,12 @@ import (
 	"testing"
 	"time"
 
-	"github.com/golang/mock/gomock"
-	"github.com/stretchr/testify/assert"
-
 	"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2021-08-01/network"
 	"github.com/Azure/go-autorest/autorest"
 	"github.com/Azure/go-autorest/autorest/to"
+	"github.com/golang/mock/gomock"
+	"github.com/stretchr/testify/assert"
+
 	azclients "sigs.k8s.io/cloud-provider-azure/pkg/azureclients"
 	"sigs.k8s.io/cloud-provider-azure/pkg/azureclients/armclient"
 	"sigs.k8s.io/cloud-provider-azure/pkg/azureclients/armclient/mockarmclient"
diff --git a/pkg/azureclients/privatelinkserviceclient/azure_privatelinkserviceclient_test.go b/pkg/azureclients/privatelinkserviceclient/azure_privatelinkserviceclient_test.go
index 6d9f1e74b..bb2a8bbc5 100644
--- a/pkg/azureclients/privatelinkserviceclient/azure_privatelinkserviceclient_test.go
+++ b/pkg/azureclients/privatelinkserviceclient/azure_privatelinkserviceclient_test.go
@@ -27,12 +27,12 @@ import (
 	"testing"
 	"time"
 
+	"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2021-08-01/network"
+	"github.com/Azure/go-autorest/autorest"
 	"github.com/Azure/go-autorest/autorest/to"
 	"github.com/golang/mock/gomock"
 	"github.com/stretchr/testify/assert"
 
-	"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2021-08-01/network"
-	"github.com/Azure/go-autorest/autorest"
 	azclients "sigs.k8s.io/cloud-provider-azure/pkg/azureclients"
 	"sigs.k8s.io/cloud-provider-azure/pkg/azureclients/armclient"
 	"sigs.k8s.io/cloud-provider-azure/pkg/azureclients/armclient/mockarmclient"
diff --git a/pkg/azureclients/snapshotclient/azure_snapshotclient_test.go b/pkg/azureclients/snapshotclient/azure_snapshotclient_test.go
index 25024c4f8..c6c1d1a0e 100644
--- a/pkg/azureclients/snapshotclient/azure_snapshotclient_test.go
+++ b/pkg/azureclients/snapshotclient/azure_snapshotclient_test.go
@@ -31,8 +31,8 @@ import (
 	"github.com/Azure/go-autorest/autorest/to"
 	"github.com/golang/mock/gomock"
 	"github.com/stretchr/testify/assert"
-
 	"k8s.io/client-go/util/flowcontrol"
+
 	azclients "sigs.k8s.io/cloud-provider-azure/pkg/azureclients"
 	"sigs.k8s.io/cloud-provider-azure/pkg/azureclients/armclient"
 	"sigs.k8s.io/cloud-provider-azure/pkg/azureclients/armclient/mockarmclient"
diff --git a/pkg/provider/azure_config_test.go b/pkg/provider/azure_config_test.go
index 3da00c653..f255c4bbc 100644
--- a/pkg/provider/azure_config_test.go
+++ b/pkg/provider/azure_config_test.go
@@ -23,6 +23,7 @@ import (
 	"sigs.k8s.io/cloud-provider-azure/pkg/consts"
 
 	"github.com/golang/mock/gomock"
+
 	"sigs.k8s.io/cloud-provider-azure/pkg/azureclients/zoneclient/mockzoneclient"
 
 	"github.com/Azure/go-autorest/autorest/to"
@@ -32,8 +33,9 @@ import (
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	fakeclient "k8s.io/client-go/kubernetes/fake"
 
-	"sigs.k8s.io/cloud-provider-azure/pkg/auth"
 	"sigs.k8s.io/yaml"
+
+	"sigs.k8s.io/cloud-provider-azure/pkg/auth"
 )
 
 func getTestConfig() *Config {
diff --git a/pkg/provider/azure_loadbalancer_backendpool_test.go b/pkg/provider/azure_loadbalancer_backendpool_test.go
index 0ebc64705..7b6c0bbfb 100644
--- a/pkg/provider/azure_loadbalancer_backendpool_test.go
+++ b/pkg/provider/azure_loadbalancer_backendpool_test.go
@@ -32,6 +32,7 @@ import (
 	"k8s.io/apimachinery/pkg/util/sets"
 	"k8s.io/client-go/kubernetes/fake"
 	cloudprovider "k8s.io/cloud-provider"
+
 	"sigs.k8s.io/cloud-provider-azure/pkg/azureclients/loadbalancerclient/mockloadbalancerclient"
 	"sigs.k8s.io/cloud-provider-azure/pkg/consts"
 	"sigs.k8s.io/cloud-provider-azure/pkg/retry"
diff --git a/pkg/provider/azure_vmss_test.go b/pkg/provider/azure_vmss_test.go
index 5bb18b3fa..40f767289 100644
--- a/pkg/provider/azure_vmss_test.go
+++ b/pkg/provider/azure_vmss_test.go
@@ -17,6 +17,7 @@ limitations under the License.
 package provider
 
 import (
+	"errors"
 	"fmt"
 	"strings"
 	"testing"
@@ -1543,7 +1544,7 @@ func TestGetVMSetNames(t *testing.T) {
 					},
 				},
 			},
-			expectedErr: fmt.Errorf("scale set (vmss-1) - not found"),
+			expectedErr: ErrScaleSetNotFound,
 		},
 		{
 			description: "GetVMSetNames should report an error if vm's network profile is nil",
@@ -1557,7 +1558,7 @@ func TestGetVMSetNames(t *testing.T) {
 					},
 				},
 			},
-			expectedErr: fmt.Errorf("instance not found"),
+			expectedErr: cloudprovider.InstanceNotFound,
 		},
 		{
 			description: "GetVMSetNames should return the correct vmss names",
@@ -1626,7 +1627,9 @@ func TestGetVMSetNames(t *testing.T) {
 		mockVMClient.EXPECT().List(gomock.Any(), gomock.Any()).Return(nil, nil).AnyTimes()
 
 		vmSetNames, err := ss.GetVMSetNames(test.service, test.nodes)
-		assert.Equal(t, test.expectedErr, err, test.description+", but an error occurs")
+		if test.expectedErr != nil {
+			assert.True(t, errors.Is(err, test.expectedErr), "expected error %v, got %v", test.expectedErr, err)
+		}
 		assert.Equal(t, test.expectedVMSetNames, vmSetNames, test.description)
 	}
 }
diff --git a/tests/e2e/autoscaling/autoscaler.go b/tests/e2e/autoscaling/autoscaler.go
index 31d331f33..18a3e3077 100644
--- a/tests/e2e/autoscaling/autoscaler.go
+++ b/tests/e2e/autoscaling/autoscaler.go
@@ -25,16 +25,16 @@ import (
 	"strings"
 	"time"
 
+	. "github.com/onsi/ginkgo/v2"
+	. "github.com/onsi/gomega"
 	appsv1 "k8s.io/api/apps/v1"
 	v1 "k8s.io/api/core/v1"
 	"k8s.io/apimachinery/pkg/api/resource"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/util/wait"
 	clientset "k8s.io/client-go/kubernetes"
-	"sigs.k8s.io/cloud-provider-azure/tests/e2e/utils"
 
-	. "github.com/onsi/ginkgo/v2"
-	. "github.com/onsi/gomega"
+	"sigs.k8s.io/cloud-provider-azure/tests/e2e/utils"
 )
 
 const (
diff --git a/tests/e2e/network/node.go b/tests/e2e/network/node.go
index 45e825b0b..88b7064e8 100644
--- a/tests/e2e/network/node.go
+++ b/tests/e2e/network/node.go
@@ -28,11 +28,11 @@ import (
 	"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2021-08-01/network"
 	. "github.com/onsi/ginkgo/v2"
 	. "github.com/onsi/gomega"
-
 	v1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/util/intstr"
 	clientset "k8s.io/client-go/kubernetes"
+
 	"sigs.k8s.io/cloud-provider-azure/tests/e2e/utils"
 )
 
diff --git a/tests/e2e/network/private_link_service.go b/tests/e2e/network/private_link_service.go
index 5278bfdfd..cbb1f60bb 100644
--- a/tests/e2e/network/private_link_service.go
+++ b/tests/e2e/network/private_link_service.go
@@ -24,18 +24,18 @@ import (
 	"strings"
 	"time"
 
+	"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2021-08-01/network"
+	"github.com/Azure/go-autorest/autorest/to"
+	. "github.com/onsi/ginkgo/v2"
+	. "github.com/onsi/gomega"
 	v1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/util/intstr"
 	"k8s.io/apimachinery/pkg/util/wait"
 	clientset "k8s.io/client-go/kubernetes"
+
 	"sigs.k8s.io/cloud-provider-azure/pkg/consts"
 	"sigs.k8s.io/cloud-provider-azure/tests/e2e/utils"
-
-	"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2021-08-01/network"
-	"github.com/Azure/go-autorest/autorest/to"
-	. "github.com/onsi/ginkgo/v2"
-	. "github.com/onsi/gomega"
 )
 
 var _ = Describe("Private link service", Label(utils.TestSuiteLabelPrivateLinkService), func() {
diff --git a/tests/e2e/network/service_annotations.go b/tests/e2e/network/service_annotations.go
index f5efb0f0e..73359eb06 100644
--- a/tests/e2e/network/service_annotations.go
+++ b/tests/e2e/network/service_annotations.go
@@ -643,10 +643,9 @@ var _ = Describe("Service with annotation", Label(utils.TestSuiteLabelServiceAnn
 		pipName := fmt.Sprintf("%s-public-IP%s", basename, string(uuid.NewUUID())[0:4])
 		By(fmt.Sprintf("Creating a public IP %q", pipName))
 		var pip network.PublicIPAddress
+		// TODO: dual-stack support
 		if tc.IPFamily != utils.DualStack {
 			pip = defaultPublicIPAddress(pipName, tc.IPFamily == utils.IPv6)
-		} else {
-			// TODO: dual-stack support
 		}
 		rg := tc.GetResourceGroup()
 		pip, err := utils.WaitCreatePIP(tc, pipName, rg, pip)
@@ -660,12 +659,11 @@ var _ = Describe("Service with annotation", Label(utils.TestSuiteLabelServiceAnn
 		utils.Logf("Created pip with address %s", pipAddr)
 
 		annotation := map[string]string{}
+		// TODO: dual-stack support
 		if tc.IPFamily == utils.IPv4 {
 			annotation[consts.ServiceAnnotationLoadBalancerIPDualStack[false]] = pipAddr
 		} else if tc.IPFamily == utils.IPv6 {
 			annotation[consts.ServiceAnnotationLoadBalancerIPDualStack[true]] = pipAddr
-		} else {
-			// TODO: dual-stack support
 		}
 
 		By("Creating a Service")
diff --git a/tests/e2e/network/standard_lb.go b/tests/e2e/network/standard_lb.go
index 6e2838e54..606d81ab2 100644
--- a/tests/e2e/network/standard_lb.go
+++ b/tests/e2e/network/standard_lb.go
@@ -23,14 +23,13 @@ import (
 
 	azcompute "github.com/Azure/azure-sdk-for-go/services/compute/mgmt/2022-03-01/compute"
 	"github.com/Azure/azure-sdk-for-go/services/network/mgmt/2021-08-01/network"
-
 	. "github.com/onsi/ginkgo/v2"
 	. "github.com/onsi/gomega"
-
 	v1 "k8s.io/api/core/v1"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/util/intstr"
 	clientset "k8s.io/client-go/kubernetes"
+
 	"sigs.k8s.io/cloud-provider-azure/tests/e2e/utils"
 )
 
diff --git a/tests/e2e/utils/ip_utils.go b/tests/e2e/utils/ip_utils.go
index 5d13fe111..0f79e32e9 100644
--- a/tests/e2e/utils/ip_utils.go
+++ b/tests/e2e/utils/ip_utils.go
@@ -89,13 +89,13 @@ func getNextSubnet(vnetCIDR string, existSubnets []string) (*net.IPNet, error) {
 	// IPv4
 	intIPArray, vNetMask, err := cidrString2intArray(vnetCIDR)
 	if err != nil {
-		return nil, fmt.Errorf("unexpected vnet address CIDR: %v", err)
+		return nil, fmt.Errorf("unexpected vnet address CIDR: %w", err)
 	}
 	root := initIPTreeRoot(vNetMask)
 	for _, subnet := range existSubnetsWithSameIPFamily {
 		subnetIPArray, subnetPrefix, err := cidrString2intArray(subnet)
 		if err != nil {
-			return nil, fmt.Errorf("unexpected subnet address prefix: %v", err)
+			return nil, fmt.Errorf("unexpected subnet address prefix: %w", err)
 		}
 		setOccupiedByPrefix(root, subnetIPArray, subnetPrefix)
 	}
diff --git a/tests/e2e/utils/kubectl.go b/tests/e2e/utils/kubectl.go
index 79303a5a5..906a3d1cb 100644
--- a/tests/e2e/utils/kubectl.go
+++ b/tests/e2e/utils/kubectl.go
@@ -18,6 +18,7 @@ package utils
 
 import (
 	"bytes"
+	"errors"
 	"fmt"
 	"net"
 	"net/url"
@@ -157,8 +158,9 @@ func (b KubectlBuilder) ExecWithFullOutput(print bool) (string, string, error) {
 	case err := <-errCh:
 		if err != nil {
 			var rc = 127
-			if ee, ok := err.(*exec.ExitError); ok {
-				rc = ee.Sys().(syscall.WaitStatus).ExitStatus()
+			var exitError *exec.ExitError
+			if errors.As(err, &exitError) {
+				rc = exitError.Sys().(syscall.WaitStatus).ExitStatus()
 				Logf("rc: %d", rc)
 			}
 			return stdout.String(), stderr.String(), uexec.CodeExitError{
@@ -178,16 +180,17 @@ func (b KubectlBuilder) ExecWithFullOutput(print bool) (string, string, error) {
 }
 
 func isTimeout(err error) bool {
-	switch err := err.(type) {
-	case *url.Error:
-		if err, ok := err.Err.(net.Error); ok && err.Timeout() {
-			return true
-		}
-	case net.Error:
-		if err.Timeout() {
-			return true
-		}
+	var (
+		urlError *url.Error
+		netError net.Error
+	)
+	if errors.As(err, &urlError) {
+		err = urlError.Err
 	}
+	if errors.As(err, &netError) {
+		return netError.Timeout()
+	}
+
 	return false
 }
 
diff --git a/tests/e2e/utils/network_utils.go b/tests/e2e/utils/network_utils.go
index a2b57bf57..4b5588704 100644
--- a/tests/e2e/utils/network_utils.go
+++ b/tests/e2e/utils/network_utils.go
@@ -18,6 +18,7 @@ package utils
 
 import (
 	"context"
+	"errors"
 	"fmt"
 	"net"
 	"os"
@@ -145,7 +146,7 @@ func GetNextSubnetCIDR(vnet aznetwork.VirtualNetwork, ipFamily IPFamily) (*net.I
 			addrPrefix := (*vnet.AddressSpace.AddressPrefixes)[i]
 			ip, _, err := net.ParseCIDR(addrPrefix)
 			if err != nil {
-				return nil, fmt.Errorf("failed to parse address prefix CIDR: %v", err)
+				return nil, fmt.Errorf("failed to parse address prefix CIDR: %w", err)
 			}
 			if ip.To4() == nil {
 				vnetCIDR = addrPrefix
@@ -211,7 +212,7 @@ func (azureTestClient *AzureTestClient) GetClusterSecurityGroups() (ret []aznetw
 		}
 		return false, nil
 	})
-	if err == wait.ErrWaitTimeout {
+	if errors.Is(err, wait.ErrWaitTimeout) {
 		err = fmt.Errorf("could not find the cluster security group in resource group %s", azureTestClient.GetResourceGroup())
 	}
 	return
@@ -327,7 +328,7 @@ func WaitGetPIPByPrefix(
 			}
 			Logf("prefix = [%s] not ready with error = [%v] and number of IP = [%d]", prefixName, err, numOfIPs)
 			if !untilPIPCreated {
-				return true, fmt.Errorf("get pip by prefix = [%s], err = [%v], number of IP = [%d]", prefixName, err, numOfIPs)
+				return true, fmt.Errorf("get pip by prefix = [%s], err = [%w], number of IP = [%d]", prefixName, err, numOfIPs)
 			}
 			return false, nil
 		}
@@ -548,7 +549,7 @@ func retrieveCIDRs(cmd string, reg string) ([]string, error) {
 	res := make([]string, 2)
 	stdout, err := RunKubectlNoPrint("", strings.Split(cmd, " ")...)
 	if err != nil {
-		return res, fmt.Errorf("error when running the following kubectl command %q: %v, %s", cmd, err, stdout)
+		return res, fmt.Errorf("error when running the following kubectl command %q: %w, %s", cmd, err, stdout)
 	}
 	re := regexp.MustCompile(reg)
 	matches := re.FindStringSubmatch(stdout)
diff --git a/tests/e2e/utils/pod_utils.go b/tests/e2e/utils/pod_utils.go
index d6be62acd..cc33d2ce3 100644
--- a/tests/e2e/utils/pod_utils.go
+++ b/tests/e2e/utils/pod_utils.go
@@ -18,6 +18,7 @@ package utils
 
 import (
 	"context"
+	"errors"
 	"fmt"
 	"regexp"
 	"time"
@@ -87,7 +88,7 @@ func WaitPodsToBeReady(cs clientset.Interface, ns string) error {
 		return pendingPodCount == 0, nil
 	})
 	if err != nil {
-		if err == wait.ErrWaitTimeout {
+		if errors.Is(err, wait.ErrWaitTimeout) {
 			for _, pod := range pods {
 				printPodInfo(cs, ns, pod.Name)
 			}
@@ -208,7 +209,7 @@ func GetPod(cs clientset.Interface, ns, name string) (pod *v1.Pod, err error) {
 			return false, err
 		}
 		return true, nil
-	}); pollErr == wait.ErrWaitTimeout {
+	}); errors.Is(pollErr, wait.ErrWaitTimeout) {
 		return nil, fmt.Errorf("failed to get Pod %q in namespace %q", name, ns)
 	}
 	return pod, err
@@ -291,7 +292,7 @@ func GetPodOutboundIP(cs clientset.Interface, podTemplate *v1.Pod, nsName string
 		return PodIPRE.MatchString(string(log)), nil
 	})
 	if err != nil {
-		if err == wait.ErrWaitTimeout {
+		if errors.Is(err, wait.ErrWaitTimeout) {
 			printPodInfo(cs, nsName, podTemplate.Name)
 		}
 		return "", err
diff --git a/tests/e2e/utils/service_utils.go b/tests/e2e/utils/service_utils.go
index 0783333b8..ba413b6e5 100644
--- a/tests/e2e/utils/service_utils.go
+++ b/tests/e2e/utils/service_utils.go
@@ -115,7 +115,7 @@ func WaitServiceExposureAndValidateConnectivity(cs clientset.Interface, namespac
 		}
 	}()
 	if !result || err != nil {
-		return "", fmt.Errorf("failed to create ExecAgnhostPod, result: %v, error: %v", result, err)
+		return "", fmt.Errorf("failed to create ExecAgnhostPod, result: %v, error: %w", result, err)
 	}
 
 	// TODO: Check if other WaitServiceExposureAndValidateConnectivity() callers with internal Service