From 0ffffbc15c2f283d924584deee29f667803e7e24 Mon Sep 17 00:00:00 2001
From: Vasiliy Ulyanov <vulyanov@suse.de>
Date: Mon, 24 Jan 2022 10:36:24 +0100
Subject: [PATCH 1/2] Use semantic equality comparison in VMI controller

reflect.DeepEqual cannot be used to reliably compare k8s objects since
it may return unexpected results in certain scenarios. E.g. if one of
the objects contains an uninitialized slice (== nil) while the other has
it initialized but empty (!= nil), reflect.DeepEqual will return false.
However semantically the objects will be equal.

This may result in unwanted side effects like unnecessary update calls
which interfere with current expectations logic. To avoid such issues
semantic comparison is now used.

Signed-off-by: Vasiliy Ulyanov <vulyanov@suse.de>
---
 pkg/virt-handler/BUILD.bazel |  1 +
 pkg/virt-handler/vm.go       | 10 +++++-----
 pkg/virt-handler/vm_test.go  |  2 --
 3 files changed, 6 insertions(+), 7 deletions(-)

diff --git a/pkg/virt-handler/BUILD.bazel b/pkg/virt-handler/BUILD.bazel
index 0d1c88947..279203643 100644
--- a/pkg/virt-handler/BUILD.bazel
+++ b/pkg/virt-handler/BUILD.bazel
@@ -44,6 +44,7 @@ go_library(
         "//vendor/github.com/opencontainers/runc/libcontainer/cgroups:go_default_library",
         "//vendor/gopkg.in/yaml.v2:go_default_library",
         "//vendor/k8s.io/api/core/v1:go_default_library",
+        "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
diff --git a/pkg/virt-handler/vm.go b/pkg/virt-handler/vm.go
index 05083da08..9ef4810ed 100644
--- a/pkg/virt-handler/vm.go
+++ b/pkg/virt-handler/vm.go
@@ -28,7 +28,6 @@ import (
 	"os"
 	"path"
 	"path/filepath"
-	"reflect"
 	"regexp"
 	"sort"
 	"strings"
@@ -41,6 +40,7 @@ import (
 	nodelabellerapi "kubevirt.io/kubevirt/pkg/virt-handler/node-labeller/api"
 
 	k8sv1 "k8s.io/api/core/v1"
+	"k8s.io/apimachinery/pkg/api/equality"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/types"
 	"k8s.io/apimachinery/pkg/util/wait"
@@ -633,7 +633,7 @@ func (d *VirtualMachineController) migrationSourceUpdateVMIStatus(origVMI *v1.Vi
 		log.Log.Object(vmi).Infof("migration completed to node %s", migrationHost)
 	}
 
-	if !reflect.DeepEqual(oldStatus, vmi.Status) {
+	if !equality.Semantic.DeepEqual(oldStatus, vmi.Status) {
 		key := controller.VirtualMachineInstanceKey(vmi)
 		d.vmiExpectations.SetExpectations(key, 1, 0)
 		_, err := d.clientset.VirtualMachineInstance(vmi.ObjectMeta.Namespace).Update(vmi)
@@ -695,7 +695,7 @@ func (d *VirtualMachineController) migrationTargetUpdateVMIStatus(vmi *v1.Virtua
 	}
 
 	// update the VMI if necessary
-	if !reflect.DeepEqual(vmi.Status, vmiCopy.Status) {
+	if !equality.Semantic.DeepEqual(vmi.Status, vmiCopy.Status) {
 		key := controller.VirtualMachineInstanceKey(vmi)
 		d.vmiExpectations.SetExpectations(key, 1, 0)
 		_, err := d.clientset.VirtualMachineInstance(vmi.ObjectMeta.Namespace).Update(vmiCopy)
@@ -872,7 +872,7 @@ func (d *VirtualMachineController) updateLiveMigrationConditions(vmi *v1.Virtual
 		}
 	} else {
 		cond := condManager.GetCondition(vmi, v1.VirtualMachineInstanceIsMigratable)
-		if !reflect.DeepEqual(cond, liveMigrationCondition) {
+		if !equality.Semantic.DeepEqual(cond, liveMigrationCondition) {
 			condManager.RemoveCondition(vmi, v1.VirtualMachineInstanceIsMigratable)
 			vmi.Status.Conditions = append(vmi.Status.Conditions, *liveMigrationCondition)
 		}
@@ -1106,7 +1106,7 @@ func (d *VirtualMachineController) updateVMIStatus(origVMI *v1.VirtualMachineIns
 	controller.SetVMIPhaseTransitionTimestamp(origVMI, vmi)
 
 	// Only issue vmi update if status has changed
-	if !reflect.DeepEqual(oldStatus, vmi.Status) {
+	if !equality.Semantic.DeepEqual(oldStatus, vmi.Status) {
 		key := controller.VirtualMachineInstanceKey(vmi)
 		d.vmiExpectations.SetExpectations(key, 1, 0)
 		_, err = d.clientset.VirtualMachineInstance(vmi.ObjectMeta.Namespace).Update(vmi)
diff --git a/pkg/virt-handler/vm_test.go b/pkg/virt-handler/vm_test.go
index 82a3101f1..c8e86b41f 100644
--- a/pkg/virt-handler/vm_test.go
+++ b/pkg/virt-handler/vm_test.go
@@ -949,12 +949,10 @@ var _ = Describe("VirtualMachineInstance", func() {
 				Message:   "",
 			}
 
-			vmiCopy := vmi.DeepCopy()
 			vmiFeeder.Add(vmi)
 			domainFeeder.Add(domain)
 
 			client.EXPECT().SyncVirtualMachine(vmi, gomock.Any())
-			vmiInterface.EXPECT().Update(NewVMICondMatcher(*vmiCopy))
 			mockHotplugVolumeMounter.EXPECT().Unmount(gomock.Any()).Return(nil)
 			mockHotplugVolumeMounter.EXPECT().Mount(gomock.Any()).Return(nil)
 
-- 
2.35.1


From 27f6a36259ffc4386513d1d78ebf95aeee59d698 Mon Sep 17 00:00:00 2001
From: David Vossel <davidvossel@gmail.com>
Date: Mon, 24 Jan 2022 16:20:02 -0500
Subject: [PATCH 2/2] Switch to semantic DeepEquals()

Signed-off-by: David Vossel <davidvossel@gmail.com>
---
 pkg/controller/BUILD.bazel                    |  1 +
 pkg/controller/controller_ref_manager_test.go |  6 ++--
 pkg/hooks/BUILD.bazel                         |  1 +
 pkg/hooks/hooks_test.go                       |  5 ++-
 pkg/util/status/BUILD.bazel                   |  1 +
 pkg/util/status/status.go                     |  6 ++--
 pkg/virt-api/rest/BUILD.bazel                 |  1 +
 pkg/virt-api/rest/subresource.go              |  4 +--
 .../mutating-webhook/mutators/BUILD.bazel     |  2 ++
 .../mutating-webhook/mutators/preset.go       | 32 +++++++++----------
 .../mutating-webhook/mutators/vmi-mutator.go  |  4 +--
 .../mutators/vmi-mutator_test.go              | 10 +++---
 .../validating-webhook/admitters/BUILD.bazel  |  2 ++
 .../admitters/migration-update-admitter.go    |  5 ++-
 .../admitters/vmi-update-admitter.go          | 14 ++++----
 .../admitters/vmi-update-admitter_test.go     |  8 ++---
 .../admitters/vmpool-admitter.go              |  4 +--
 .../admitters/vmrestore-admitter.go           |  6 ++--
 .../admitters/vms-admitter.go                 | 10 +++---
 .../admitters/vmsnapshot-admitter.go          |  4 +--
 pkg/virt-controller/watch/BUILD.bazel         |  2 ++
 .../watch/drain/disruptionbudget/BUILD.bazel  |  1 +
 .../disruptionbudget/disruptionbudget.go      |  6 ++--
 pkg/virt-controller/watch/migration.go        | 18 +++++------
 pkg/virt-controller/watch/migration_test.go   |  2 ++
 pkg/virt-controller/watch/pool.go             |  8 ++---
 pkg/virt-controller/watch/replicaset.go       |  6 ++--
 .../watch/snapshot/BUILD.bazel                |  1 +
 pkg/virt-controller/watch/snapshot/restore.go |  8 ++---
 .../watch/snapshot/snapshot.go                |  6 ++--
 .../watch/topology/BUILD.bazel                |  1 +
 .../watch/topology/nodetopologyupdater.go     |  4 +--
 pkg/virt-controller/watch/vm.go               | 16 +++++-----
 pkg/virt-controller/watch/vmi.go              | 18 +++++------
 pkg/virt-controller/watch/vmi_test.go         | 12 +++----
 pkg/virt-handler/cache/BUILD.bazel            |  1 +
 pkg/virt-handler/cache/cache_test.go          |  4 +--
 pkg/virt-handler/container-disk/BUILD.bazel   |  1 +
 pkg/virt-handler/container-disk/mount.go      |  4 +--
 pkg/virt-handler/node-labeller/BUILD.bazel    |  1 +
 .../node-labeller/node_labeller.go            |  6 ++--
 pkg/virt-launcher/notify-client/BUILD.bazel   |  1 +
 .../notify-client/notify_test.go              | 10 +++---
 .../virtwrap/agent-poller/BUILD.bazel         |  1 +
 .../virtwrap/agent-poller/agent_poller.go     |  4 +--
 .../virtwrap/converter/BUILD.bazel            |  1 +
 .../virtwrap/converter/converter_test.go      |  6 ++--
 .../virtwrap/statsconv/BUILD.bazel            |  1 +
 .../virtwrap/statsconv/converter_test.go      |  4 +--
 pkg/virt-operator/BUILD.bazel                 |  1 +
 pkg/virt-operator/kubevirt.go                 |  6 ++--
 pkg/virt-operator/resource/apply/BUILD.bazel  |  1 +
 pkg/virt-operator/resource/apply/apps_test.go | 10 +++---
 pkg/virt-operator/resource/apply/core.go      |  3 +-
 .../resource/apply/reconcile_test.go          | 10 +++---
 .../resource/generate/install/BUILD.bazel     |  1 +
 .../generate/install/strategy_test.go         | 22 ++++++-------
 pkg/virt-operator/webhooks/BUILD.bazel        |  1 +
 .../webhooks/kubevirt-update-admitter.go      |  6 ++--
 tests/BUILD.bazel                             |  1 +
 tests/utils.go                                |  3 +-
 61 files changed, 185 insertions(+), 160 deletions(-)

diff --git a/pkg/controller/BUILD.bazel b/pkg/controller/BUILD.bazel
index 1fd084aed..e6f5e6634 100644
--- a/pkg/controller/BUILD.bazel
+++ b/pkg/controller/BUILD.bazel
@@ -76,6 +76,7 @@ go_test(
         "//vendor/github.com/onsi/gomega:go_default_library",
         "//vendor/k8s.io/api/core/v1:go_default_library",
         "//vendor/k8s.io/api/extensions/v1beta1:go_default_library",
+        "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
diff --git a/pkg/controller/controller_ref_manager_test.go b/pkg/controller/controller_ref_manager_test.go
index 132b3f80a..7864a8fe5 100644
--- a/pkg/controller/controller_ref_manager_test.go
+++ b/pkg/controller/controller_ref_manager_test.go
@@ -18,12 +18,12 @@ limitations under the License.
 package controller
 
 import (
-	"reflect"
 	"sync"
 	"testing"
 
 	v1 "k8s.io/api/core/v1"
 	"k8s.io/api/extensions/v1beta1"
+	"k8s.io/apimachinery/pkg/api/equality"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/labels"
 	"k8s.io/apimachinery/pkg/runtime/schema"
@@ -178,7 +178,7 @@ func TestClaimVirtualMachineInstance(t *testing.T) {
 		claimed, err := test.manager.ClaimVirtualMachineInstances(test.virtualmachines)
 		if test.expectError && err == nil {
 			t.Errorf("Test case `%s`, expected error but got nil", test.name)
-		} else if !reflect.DeepEqual(test.claimed, claimed) {
+		} else if !equality.Semantic.DeepEqual(test.claimed, claimed) {
 			t.Errorf("Test case `%s`, claimed wrong virtualmachines. Expected %v, got %v", test.name, virtualmachineToStringSlice(test.claimed), virtualmachineToStringSlice(claimed))
 		}
 
@@ -284,7 +284,7 @@ func TestClaimDataVolume(t *testing.T) {
 		claimed, err := test.manager.ClaimMatchedDataVolumes(test.datavolumes)
 		if test.expectError && err == nil {
 			t.Errorf("Test case `%s`, expected error but got nil", test.name)
-		} else if !reflect.DeepEqual(test.claimed, claimed) {
+		} else if !equality.Semantic.DeepEqual(test.claimed, claimed) {
 			t.Errorf("Test case `%s`, claimed wrong datavolumes. Expected %v, got %v", test.name, datavolumeToStringSlice(test.claimed), datavolumeToStringSlice(claimed))
 		}
 
diff --git a/pkg/hooks/BUILD.bazel b/pkg/hooks/BUILD.bazel
index 51c440c5e..903217ee7 100644
--- a/pkg/hooks/BUILD.bazel
+++ b/pkg/hooks/BUILD.bazel
@@ -36,6 +36,7 @@ go_test(
         "//staging/src/kubevirt.io/client-go/testutils:go_default_library",
         "//vendor/github.com/onsi/ginkgo:go_default_library",
         "//vendor/github.com/onsi/gomega:go_default_library",
+        "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
         "@org_golang_google_grpc//:go_default_library",
     ],
diff --git a/pkg/hooks/hooks_test.go b/pkg/hooks/hooks_test.go
index f52c2b21a..b964509a7 100644
--- a/pkg/hooks/hooks_test.go
+++ b/pkg/hooks/hooks_test.go
@@ -20,10 +20,9 @@
 package hooks_test
 
 import (
-	"reflect"
-
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
+	"k8s.io/apimachinery/pkg/api/equality"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 
 	v1 "kubevirt.io/api/core/v1"
@@ -63,7 +62,7 @@ var _ = Describe("HooksAPI", func() {
 			}
 			hookSidecarList, err := hooks.UnmarshalHookSidecarList(vmiHookObject)
 			Expect(err).ToNot(HaveOccurred())
-			Expect(reflect.DeepEqual(hookSidecarList, expectedHookSidecarList)).To(BeTrue())
+			Expect(equality.Semantic.DeepEqual(hookSidecarList, expectedHookSidecarList)).To(BeTrue())
 		})
 	})
 })
diff --git a/pkg/util/status/BUILD.bazel b/pkg/util/status/BUILD.bazel
index b434ee005..2ab558ac7 100644
--- a/pkg/util/status/BUILD.bazel
+++ b/pkg/util/status/BUILD.bazel
@@ -8,6 +8,7 @@ go_library(
     deps = [
         "//staging/src/kubevirt.io/api/core/v1:go_default_library",
         "//staging/src/kubevirt.io/client-go/kubecli:go_default_library",
+        "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
diff --git a/pkg/util/status/status.go b/pkg/util/status/status.go
index faacc50e4..dc86dd885 100644
--- a/pkg/util/status/status.go
+++ b/pkg/util/status/status.go
@@ -1,9 +1,9 @@
 package status
 
 import (
-	"reflect"
 	"sync"
 
+	"k8s.io/apimachinery/pkg/api/equality"
 	"k8s.io/apimachinery/pkg/api/errors"
 	"k8s.io/apimachinery/pkg/api/meta"
 	"k8s.io/apimachinery/pkg/runtime"
@@ -49,7 +49,7 @@ func (u *updater) updateWithoutSubresource(obj runtime.Object) (err error) {
 	if err != nil {
 		return err
 	}
-	if !reflect.DeepEqual(oldStatus, newStatus) {
+	if !equality.Semantic.DeepEqual(oldStatus, newStatus) {
 		u.setSubresource(true)
 		return u.updateStatusUnstructured(obj)
 	}
@@ -70,7 +70,7 @@ func (u *updater) updateWithSubresource(obj runtime.Object) (updateStatusErr err
 			// object does not exist
 			return err
 		}
-		if err == nil && reflect.DeepEqual(oldStatus, newStatus) {
+		if err == nil && equality.Semantic.DeepEqual(oldStatus, newStatus) {
 			u.setSubresource(false)
 		} else if err == nil {
 			return updateStatusErr
diff --git a/pkg/virt-api/rest/BUILD.bazel b/pkg/virt-api/rest/BUILD.bazel
index 52a65c90d..6fba3ea53 100644
--- a/pkg/virt-api/rest/BUILD.bazel
+++ b/pkg/virt-api/rest/BUILD.bazel
@@ -37,6 +37,7 @@ go_library(
         "//vendor/github.com/gorilla/websocket:go_default_library",
         "//vendor/k8s.io/api/authorization/v1:go_default_library",
         "//vendor/k8s.io/api/core/v1:go_default_library",
+        "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/fields:go_default_library",
diff --git a/pkg/virt-api/rest/subresource.go b/pkg/virt-api/rest/subresource.go
index e03d59b88..8d0e562bd 100644
--- a/pkg/virt-api/rest/subresource.go
+++ b/pkg/virt-api/rest/subresource.go
@@ -26,12 +26,12 @@ import (
 	"fmt"
 	"io"
 	"net/http"
-	"reflect"
 	"strings"
 	"sync"
 
 	"github.com/emicklei/go-restful"
 	v12 "k8s.io/api/core/v1"
+	"k8s.io/apimachinery/pkg/api/equality"
 	"k8s.io/apimachinery/pkg/api/errors"
 	k8smetav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/fields"
@@ -159,7 +159,7 @@ func getChangeRequestJson(vm *v1.VirtualMachine, changes ...v1.VirtualMachineSta
 	verb := "add"
 	// Special case: if there's no status field at all, add one.
 	newStatus := v1.VirtualMachineStatus{}
-	if reflect.DeepEqual(vm.Status, newStatus) {
+	if equality.Semantic.DeepEqual(vm.Status, newStatus) {
 		for _, change := range changes {
 			newStatus.StateChangeRequests = append(newStatus.StateChangeRequests, change)
 		}
diff --git a/pkg/virt-api/webhooks/mutating-webhook/mutators/BUILD.bazel b/pkg/virt-api/webhooks/mutating-webhook/mutators/BUILD.bazel
index 4b32a57a6..810abfa6a 100644
--- a/pkg/virt-api/webhooks/mutating-webhook/mutators/BUILD.bazel
+++ b/pkg/virt-api/webhooks/mutating-webhook/mutators/BUILD.bazel
@@ -22,6 +22,7 @@ go_library(
         "//staging/src/kubevirt.io/client-go/log:go_default_library",
         "//vendor/k8s.io/api/admission/v1:go_default_library",
         "//vendor/k8s.io/api/core/v1:go_default_library",
+        "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/labels:go_default_library",
@@ -58,6 +59,7 @@ go_test(
         "//vendor/k8s.io/api/admission/v1:go_default_library",
         "//vendor/k8s.io/api/authentication/v1:go_default_library",
         "//vendor/k8s.io/api/core/v1:go_default_library",
+        "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
diff --git a/pkg/virt-api/webhooks/mutating-webhook/mutators/preset.go b/pkg/virt-api/webhooks/mutating-webhook/mutators/preset.go
index 75dc3dc30..78d8bd5ef 100644
--- a/pkg/virt-api/webhooks/mutating-webhook/mutators/preset.go
+++ b/pkg/virt-api/webhooks/mutating-webhook/mutators/preset.go
@@ -21,9 +21,9 @@ package mutators
 
 import (
 	"fmt"
-	"reflect"
 
 	k8sv1 "k8s.io/api/core/v1"
+	"k8s.io/apimachinery/pkg/api/equality"
 	k8smetav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/labels"
 	utilerrors "k8s.io/apimachinery/pkg/util/errors"
@@ -78,37 +78,37 @@ func checkMergeConflicts(presetSpec *kubev1.DomainSpec, vmiSpec *kubev1.DomainSp
 		}
 	}
 	if presetSpec.CPU != nil && vmiSpec.CPU != nil {
-		if !reflect.DeepEqual(presetSpec.CPU, vmiSpec.CPU) {
+		if !equality.Semantic.DeepEqual(presetSpec.CPU, vmiSpec.CPU) {
 			errors = append(errors, fmt.Errorf("spec.cpu: %v != %v", presetSpec.CPU, vmiSpec.CPU))
 		}
 	}
 	if presetSpec.Firmware != nil && vmiSpec.Firmware != nil {
-		if !reflect.DeepEqual(presetSpec.Firmware, vmiSpec.Firmware) {
+		if !equality.Semantic.DeepEqual(presetSpec.Firmware, vmiSpec.Firmware) {
 			errors = append(errors, fmt.Errorf("spec.firmware: %v != %v", presetSpec.Firmware, vmiSpec.Firmware))
 		}
 	}
 	if presetSpec.Clock != nil && vmiSpec.Clock != nil {
-		if !reflect.DeepEqual(presetSpec.Clock.ClockOffset, vmiSpec.Clock.ClockOffset) {
+		if !equality.Semantic.DeepEqual(presetSpec.Clock.ClockOffset, vmiSpec.Clock.ClockOffset) {
 			errors = append(errors, fmt.Errorf("spec.clock.clockoffset: %v != %v", presetSpec.Clock.ClockOffset, vmiSpec.Clock.ClockOffset))
 		}
 		if presetSpec.Clock.Timer != nil && vmiSpec.Clock.Timer != nil {
-			if !reflect.DeepEqual(presetSpec.Clock.Timer, vmiSpec.Clock.Timer) {
+			if !equality.Semantic.DeepEqual(presetSpec.Clock.Timer, vmiSpec.Clock.Timer) {
 				errors = append(errors, fmt.Errorf("spec.clock.timer: %v != %v", presetSpec.Clock.Timer, vmiSpec.Clock.Timer))
 			}
 		}
 	}
 	if presetSpec.Features != nil && vmiSpec.Features != nil {
-		if !reflect.DeepEqual(presetSpec.Features, vmiSpec.Features) {
+		if !equality.Semantic.DeepEqual(presetSpec.Features, vmiSpec.Features) {
 			errors = append(errors, fmt.Errorf("spec.features: %v != %v", presetSpec.Features, vmiSpec.Features))
 		}
 	}
 	if presetSpec.Devices.Watchdog != nil && vmiSpec.Devices.Watchdog != nil {
-		if !reflect.DeepEqual(presetSpec.Devices.Watchdog, vmiSpec.Devices.Watchdog) {
+		if !equality.Semantic.DeepEqual(presetSpec.Devices.Watchdog, vmiSpec.Devices.Watchdog) {
 			errors = append(errors, fmt.Errorf("spec.devices.watchdog: %v != %v", presetSpec.Devices.Watchdog, vmiSpec.Devices.Watchdog))
 		}
 	}
 	if presetSpec.IOThreadsPolicy != nil && vmiSpec.IOThreadsPolicy != nil {
-		if !reflect.DeepEqual(presetSpec.IOThreadsPolicy, vmiSpec.IOThreadsPolicy) {
+		if !equality.Semantic.DeepEqual(presetSpec.IOThreadsPolicy, vmiSpec.IOThreadsPolicy) {
 			errors = append(errors, fmt.Errorf("spec.ioThreadsPolicy: %v != %v", presetSpec.IOThreadsPolicy, vmiSpec.IOThreadsPolicy))
 		}
 	}
@@ -130,7 +130,7 @@ func mergeDomainSpec(presetSpec *kubev1.DomainSpec, vmiSpec *kubev1.DomainSpec)
 				vmiSpec.Resources.Requests[key] = val
 			}
 		}
-		if reflect.DeepEqual(vmiSpec.Resources.Requests, presetSpec.Resources.Requests) {
+		if equality.Semantic.DeepEqual(vmiSpec.Resources.Requests, presetSpec.Resources.Requests) {
 			applied = true
 		}
 	}
@@ -139,7 +139,7 @@ func mergeDomainSpec(presetSpec *kubev1.DomainSpec, vmiSpec *kubev1.DomainSpec)
 			vmiSpec.CPU = &kubev1.CPU{}
 			presetSpec.CPU.DeepCopyInto(vmiSpec.CPU)
 		}
-		if reflect.DeepEqual(vmiSpec.CPU, presetSpec.CPU) {
+		if equality.Semantic.DeepEqual(vmiSpec.CPU, presetSpec.CPU) {
 			applied = true
 		}
 	}
@@ -148,7 +148,7 @@ func mergeDomainSpec(presetSpec *kubev1.DomainSpec, vmiSpec *kubev1.DomainSpec)
 			vmiSpec.Firmware = &kubev1.Firmware{}
 			presetSpec.Firmware.DeepCopyInto(vmiSpec.Firmware)
 		}
-		if reflect.DeepEqual(vmiSpec.Firmware, presetSpec.Firmware) {
+		if equality.Semantic.DeepEqual(vmiSpec.Firmware, presetSpec.Firmware) {
 			applied = true
 		}
 	}
@@ -157,7 +157,7 @@ func mergeDomainSpec(presetSpec *kubev1.DomainSpec, vmiSpec *kubev1.DomainSpec)
 			vmiSpec.Clock = &kubev1.Clock{}
 			vmiSpec.Clock.ClockOffset = presetSpec.Clock.ClockOffset
 		}
-		if reflect.DeepEqual(vmiSpec.Clock, presetSpec.Clock) {
+		if equality.Semantic.DeepEqual(vmiSpec.Clock, presetSpec.Clock) {
 			applied = true
 		}
 
@@ -166,7 +166,7 @@ func mergeDomainSpec(presetSpec *kubev1.DomainSpec, vmiSpec *kubev1.DomainSpec)
 				vmiSpec.Clock.Timer = &kubev1.Timer{}
 				presetSpec.Clock.Timer.DeepCopyInto(vmiSpec.Clock.Timer)
 			}
-			if reflect.DeepEqual(vmiSpec.Clock.Timer, presetSpec.Clock.Timer) {
+			if equality.Semantic.DeepEqual(vmiSpec.Clock.Timer, presetSpec.Clock.Timer) {
 				applied = true
 			}
 		}
@@ -176,7 +176,7 @@ func mergeDomainSpec(presetSpec *kubev1.DomainSpec, vmiSpec *kubev1.DomainSpec)
 			vmiSpec.Features = &kubev1.Features{}
 			presetSpec.Features.DeepCopyInto(vmiSpec.Features)
 		}
-		if reflect.DeepEqual(vmiSpec.Features, presetSpec.Features) {
+		if equality.Semantic.DeepEqual(vmiSpec.Features, presetSpec.Features) {
 			applied = true
 		}
 	}
@@ -185,7 +185,7 @@ func mergeDomainSpec(presetSpec *kubev1.DomainSpec, vmiSpec *kubev1.DomainSpec)
 			vmiSpec.Devices.Watchdog = &kubev1.Watchdog{}
 			presetSpec.Devices.Watchdog.DeepCopyInto(vmiSpec.Devices.Watchdog)
 		}
-		if reflect.DeepEqual(vmiSpec.Devices.Watchdog, presetSpec.Devices.Watchdog) {
+		if equality.Semantic.DeepEqual(vmiSpec.Devices.Watchdog, presetSpec.Devices.Watchdog) {
 			applied = true
 		}
 	}
@@ -194,7 +194,7 @@ func mergeDomainSpec(presetSpec *kubev1.DomainSpec, vmiSpec *kubev1.DomainSpec)
 			ioThreadsPolicy := *presetSpec.IOThreadsPolicy
 			vmiSpec.IOThreadsPolicy = &(ioThreadsPolicy)
 		}
-		if reflect.DeepEqual(vmiSpec.IOThreadsPolicy, presetSpec.IOThreadsPolicy) {
+		if equality.Semantic.DeepEqual(vmiSpec.IOThreadsPolicy, presetSpec.IOThreadsPolicy) {
 			applied = true
 		}
 	}
diff --git a/pkg/virt-api/webhooks/mutating-webhook/mutators/vmi-mutator.go b/pkg/virt-api/webhooks/mutating-webhook/mutators/vmi-mutator.go
index d036b22be..0aef56240 100644
--- a/pkg/virt-api/webhooks/mutating-webhook/mutators/vmi-mutator.go
+++ b/pkg/virt-api/webhooks/mutating-webhook/mutators/vmi-mutator.go
@@ -23,12 +23,12 @@ import (
 	"encoding/json"
 	"fmt"
 	"net/http"
-	"reflect"
 	"strings"
 	"time"
 
 	admissionv1 "k8s.io/api/admission/v1"
 	k8sv1 "k8s.io/api/core/v1"
+	"k8s.io/apimachinery/pkg/api/equality"
 	"k8s.io/apimachinery/pkg/api/resource"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/client-go/tools/cache"
@@ -180,7 +180,7 @@ func (mutator *VMIsMutator) Mutate(ar *admissionv1.AdmissionReview) *admissionv1
 		// Ignore status updates if they are not coming from our service accounts
 		// TODO: As soon as CRDs support field selectors we can remove this and just enable
 		// the status subresource. Until then we need to update Status and Metadata labels in parallel for e.g. Migrations.
-		if !reflect.DeepEqual(newVMI.Status, oldVMI.Status) {
+		if !equality.Semantic.DeepEqual(newVMI.Status, oldVMI.Status) {
 			if !webhooks.IsKubeVirtServiceAccount(ar.Request.UserInfo.Username) {
 				patch = append(patch, utiltypes.PatchOperation{
 					Op:    "replace",
diff --git a/pkg/virt-api/webhooks/mutating-webhook/mutators/vmi-mutator_test.go b/pkg/virt-api/webhooks/mutating-webhook/mutators/vmi-mutator_test.go
index 09179e576..05b974824 100644
--- a/pkg/virt-api/webhooks/mutating-webhook/mutators/vmi-mutator_test.go
+++ b/pkg/virt-api/webhooks/mutating-webhook/mutators/vmi-mutator_test.go
@@ -22,7 +22,6 @@ package mutators
 import (
 	"encoding/json"
 	"fmt"
-	"reflect"
 	rt "runtime"
 
 	. "github.com/onsi/ginkgo"
@@ -31,6 +30,7 @@ import (
 	admissionv1 "k8s.io/api/admission/v1"
 	v12 "k8s.io/api/authentication/v1"
 	k8sv1 "k8s.io/api/core/v1"
+	"k8s.io/apimachinery/pkg/api/equality"
 	"k8s.io/apimachinery/pkg/api/resource"
 	k8smetav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
@@ -612,7 +612,7 @@ var _ = Describe("VirtualMachineInstance Mutator", func() {
 		err := webhooks.SetVirtualMachineInstanceHypervFeatureDependencies(vmi)
 		Expect(err).To(BeNil())
 		hyperv := v1.FeatureHyperv{}
-		ok := reflect.DeepEqual(*vmi.Spec.Domain.Features.Hyperv, hyperv)
+		ok := equality.Semantic.DeepEqual(*vmi.Spec.Domain.Features.Hyperv, hyperv)
 		if !ok {
 			// debug aid
 			fmt.Fprintf(GinkgoWriter, "got: %#v\n", *vmi.Spec.Domain.Features.Hyperv)
@@ -651,7 +651,7 @@ var _ = Describe("VirtualMachineInstance Mutator", func() {
 			},
 		}
 
-		ok := reflect.DeepEqual(*vmi.Spec.Domain.Features.Hyperv, hyperv)
+		ok := equality.Semantic.DeepEqual(*vmi.Spec.Domain.Features.Hyperv, hyperv)
 		if !ok {
 			// debug aid
 			fmt.Fprintf(GinkgoWriter, "got: %#v\n", *vmi.Spec.Domain.Features.Hyperv)
@@ -690,7 +690,7 @@ var _ = Describe("VirtualMachineInstance Mutator", func() {
 			},
 		}
 
-		ok := reflect.DeepEqual(*vmi.Spec.Domain.Features.Hyperv, hyperv)
+		ok := equality.Semantic.DeepEqual(*vmi.Spec.Domain.Features.Hyperv, hyperv)
 		if !ok {
 			// debug aid
 			fmt.Fprintf(GinkgoWriter, "got: %#v\n", *vmi.Spec.Domain.Features.Hyperv)
@@ -739,7 +739,7 @@ var _ = Describe("VirtualMachineInstance Mutator", func() {
 			},
 		}
 
-		ok := reflect.DeepEqual(*vmi.Spec.Domain.Features.Hyperv, hyperv)
+		ok := equality.Semantic.DeepEqual(*vmi.Spec.Domain.Features.Hyperv, hyperv)
 		if !ok {
 			// debug aid
 			fmt.Fprintf(GinkgoWriter, "got: %#v\n", *vmi.Spec.Domain.Features.Hyperv)
diff --git a/pkg/virt-api/webhooks/validating-webhook/admitters/BUILD.bazel b/pkg/virt-api/webhooks/validating-webhook/admitters/BUILD.bazel
index d9031092b..9a1361db4 100644
--- a/pkg/virt-api/webhooks/validating-webhook/admitters/BUILD.bazel
+++ b/pkg/virt-api/webhooks/validating-webhook/admitters/BUILD.bazel
@@ -43,6 +43,7 @@ go_library(
         "//vendor/k8s.io/api/admission/v1:go_default_library",
         "//vendor/k8s.io/api/authorization/v1:go_default_library",
         "//vendor/k8s.io/api/core/v1:go_default_library",
+        "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
@@ -103,6 +104,7 @@ go_test(
         "//vendor/k8s.io/api/admission/v1:go_default_library",
         "//vendor/k8s.io/api/authentication/v1:go_default_library",
         "//vendor/k8s.io/api/core/v1:go_default_library",
+        "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
diff --git a/pkg/virt-api/webhooks/validating-webhook/admitters/migration-update-admitter.go b/pkg/virt-api/webhooks/validating-webhook/admitters/migration-update-admitter.go
index db3293960..ab8d409d3 100644
--- a/pkg/virt-api/webhooks/validating-webhook/admitters/migration-update-admitter.go
+++ b/pkg/virt-api/webhooks/validating-webhook/admitters/migration-update-admitter.go
@@ -20,9 +20,8 @@
 package admitters
 
 import (
-	"reflect"
-
 	admissionv1 "k8s.io/api/admission/v1"
+	"k8s.io/apimachinery/pkg/api/equality"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 
 	v1 "kubevirt.io/api/core/v1"
@@ -72,7 +71,7 @@ func (admitter *MigrationUpdateAdmitter) Admit(ar *admissionv1.AdmissionReview)
 	}
 
 	// Reject Migration update if spec changed
-	if !reflect.DeepEqual(newMigration.Spec, oldMigration.Spec) {
+	if !equality.Semantic.DeepEqual(newMigration.Spec, oldMigration.Spec) {
 		return webhookutils.ToAdmissionResponse([]metav1.StatusCause{
 			{
 				Type:    metav1.CauseTypeFieldValueNotSupported,
diff --git a/pkg/virt-api/webhooks/validating-webhook/admitters/vmi-update-admitter.go b/pkg/virt-api/webhooks/validating-webhook/admitters/vmi-update-admitter.go
index 28a239b1f..c50ce1e16 100644
--- a/pkg/virt-api/webhooks/validating-webhook/admitters/vmi-update-admitter.go
+++ b/pkg/virt-api/webhooks/validating-webhook/admitters/vmi-update-admitter.go
@@ -21,9 +21,9 @@ package admitters
 
 import (
 	"fmt"
-	"reflect"
 
 	admissionv1 "k8s.io/api/admission/v1"
+	"k8s.io/apimachinery/pkg/api/equality"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	k8sfield "k8s.io/apimachinery/pkg/util/validation/field"
 
@@ -50,7 +50,7 @@ func (admitter *VMIUpdateAdmitter) Admit(ar *admissionv1.AdmissionReview) *admis
 	}
 
 	// Reject VMI update if VMI spec changed
-	if !reflect.DeepEqual(newVMI.Spec, oldVMI.Spec) {
+	if !equality.Semantic.DeepEqual(newVMI.Spec, oldVMI.Spec) {
 		// Only allow the KubeVirt SA to modify the VMI spec, since that means it went through the sub resource.
 		if webhooks.IsKubeVirtServiceAccount(ar.Request.UserInfo.Username) {
 			hotplugResponse := admitHotplug(newVMI.Spec.Volumes, oldVMI.Spec.Volumes, newVMI.Spec.Domain.Devices.Disks, oldVMI.Spec.Domain.Devices.Disks, oldVMI.Status.VolumeStatus, newVMI, admitter.ClusterConfig)
@@ -116,7 +116,7 @@ func verifyHotplugVolumes(newHotplugVolumeMap, oldHotplugVolumeMap map[string]v1
 	for k, v := range newHotplugVolumeMap {
 		if _, ok := oldHotplugVolumeMap[k]; ok {
 			// New and old have same volume, ensure they are the same
-			if !reflect.DeepEqual(v, oldHotplugVolumeMap[k]) {
+			if !equality.Semantic.DeepEqual(v, oldHotplugVolumeMap[k]) {
 				return webhookutils.ToAdmissionResponse([]metav1.StatusCause{
 					{
 						Type:    metav1.CauseTypeFieldValueInvalid,
@@ -132,7 +132,7 @@ func verifyHotplugVolumes(newHotplugVolumeMap, oldHotplugVolumeMap map[string]v1
 					},
 				})
 			}
-			if !reflect.DeepEqual(newDisks[k], oldDisks[k]) {
+			if !equality.Semantic.DeepEqual(newDisks[k], oldDisks[k]) {
 				return webhookutils.ToAdmissionResponse([]metav1.StatusCause{
 					{
 						Type:    metav1.CauseTypeFieldValueInvalid,
@@ -196,7 +196,7 @@ func verifyPermanentVolumes(newPermanentVolumeMap, oldPermanentVolumeMap map[str
 				},
 			})
 		}
-		if !reflect.DeepEqual(v, oldPermanentVolumeMap[k]) {
+		if !equality.Semantic.DeepEqual(v, oldPermanentVolumeMap[k]) {
 			return webhookutils.ToAdmissionResponse([]metav1.StatusCause{
 				{
 					Type:    metav1.CauseTypeFieldValueInvalid,
@@ -204,7 +204,7 @@ func verifyPermanentVolumes(newPermanentVolumeMap, oldPermanentVolumeMap map[str
 				},
 			})
 		}
-		if !reflect.DeepEqual(newDisks[k], oldDisks[k]) {
+		if !equality.Semantic.DeepEqual(newDisks[k], oldDisks[k]) {
 			return webhookutils.ToAdmissionResponse([]metav1.StatusCause{
 				{
 					Type:    metav1.CauseTypeFieldValueInvalid,
@@ -270,7 +270,7 @@ func admitVMILabelsUpdate(
 	oldLabels := filterKubevirtLabels(oldVMI.ObjectMeta.Labels)
 	newLabels := filterKubevirtLabels(newVMI.ObjectMeta.Labels)
 
-	if !reflect.DeepEqual(oldLabels, newLabels) {
+	if !equality.Semantic.DeepEqual(oldLabels, newLabels) {
 		return webhookutils.ToAdmissionResponse([]metav1.StatusCause{
 			{
 				Type:    metav1.CauseTypeFieldValueNotSupported,
diff --git a/pkg/virt-api/webhooks/validating-webhook/admitters/vmi-update-admitter_test.go b/pkg/virt-api/webhooks/validating-webhook/admitters/vmi-update-admitter_test.go
index 896490c03..0b8cc1ff1 100644
--- a/pkg/virt-api/webhooks/validating-webhook/admitters/vmi-update-admitter_test.go
+++ b/pkg/virt-api/webhooks/validating-webhook/admitters/vmi-update-admitter_test.go
@@ -22,7 +22,6 @@ package admitters
 import (
 	"encoding/json"
 	"fmt"
-	"reflect"
 
 	. "github.com/onsi/ginkgo"
 	"github.com/onsi/ginkgo/extensions/table"
@@ -30,6 +29,7 @@ import (
 	"github.com/onsi/gomega/types"
 	admissionv1 "k8s.io/api/admission/v1"
 	authv1 "k8s.io/api/authentication/v1"
+	"k8s.io/apimachinery/pkg/api/equality"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
 
@@ -389,7 +389,7 @@ var _ = Describe("Validating VMIUpdate Admitter", func() {
 
 	table.DescribeTable("Should properly calculate the hotplugvolumes", func(volumes []v1.Volume, statuses []v1.VolumeStatus, expected map[string]v1.Volume) {
 		result := getHotplugVolumes(volumes, statuses)
-		Expect(reflect.DeepEqual(result, expected)).To(BeTrue(), "result: %v and expected: %v do not match", result, expected)
+		Expect(equality.Semantic.DeepEqual(result, expected)).To(BeTrue(), "result: %v and expected: %v do not match", result, expected)
 	},
 		table.Entry("Should be empty if statuses is empty", makeVolumes(), makeStatus(0, 0), emptyResult()),
 		table.Entry("Should be empty if statuses has multiple entries, but no hotplug", makeVolumes(), makeStatus(2, 0), emptyResult()),
@@ -400,7 +400,7 @@ var _ = Describe("Validating VMIUpdate Admitter", func() {
 
 	table.DescribeTable("Should properly calculate the permanent volumes", func(volumes []v1.Volume, statusVolumes []v1.VolumeStatus, expected map[string]v1.Volume) {
 		result := getPermanentVolumes(volumes, statusVolumes)
-		Expect(reflect.DeepEqual(result, expected)).To(BeTrue(), "result: %v and expected: %v do not match", result, expected)
+		Expect(equality.Semantic.DeepEqual(result, expected)).To(BeTrue(), "result: %v and expected: %v do not match", result, expected)
 	},
 		table.Entry("Should be empty if volume is empty", makeVolumes(), makeStatus(0, 0), emptyResult()),
 		table.Entry("Should be empty if all volumes are hotplugged", makeVolumes(0, 1, 2, 3), makeStatus(4, 4), emptyResult()),
@@ -415,7 +415,7 @@ var _ = Describe("Validating VMIUpdate Admitter", func() {
 		newVMI.Spec.Domain.Devices.Disks = newDisks
 
 		result := admitHotplug(newVolumes, oldVolumes, newDisks, oldDisks, volumeStatuses, newVMI, vmiUpdateAdmitter.ClusterConfig)
-		Expect(reflect.DeepEqual(result, expected)).To(BeTrue(), "result: %v and expected: %v do not match", result, expected)
+		Expect(equality.Semantic.DeepEqual(result, expected)).To(BeTrue(), "result: %v and expected: %v do not match", result, expected)
 	},
 		table.Entry("Should accept if no volumes are there or added",
 			makeVolumes(),
diff --git a/pkg/virt-api/webhooks/validating-webhook/admitters/vmpool-admitter.go b/pkg/virt-api/webhooks/validating-webhook/admitters/vmpool-admitter.go
index 0758c0813..1d9c8b2b0 100644
--- a/pkg/virt-api/webhooks/validating-webhook/admitters/vmpool-admitter.go
+++ b/pkg/virt-api/webhooks/validating-webhook/admitters/vmpool-admitter.go
@@ -22,9 +22,9 @@ package admitters
 import (
 	"encoding/json"
 	"fmt"
-	"reflect"
 
 	admissionv1 "k8s.io/api/admission/v1"
+	"k8s.io/apimachinery/pkg/api/equality"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/labels"
 	"k8s.io/apimachinery/pkg/runtime/schema"
@@ -124,7 +124,7 @@ func ValidateVMPoolSpec(ar *admissionv1.AdmissionReview, field *k8sfield.Path, p
 			})
 		}
 
-		if !reflect.DeepEqual(pool.Spec.Selector, oldPool.Spec.Selector) {
+		if !equality.Semantic.DeepEqual(pool.Spec.Selector, oldPool.Spec.Selector) {
 			causes = append(causes, metav1.StatusCause{
 				Type:    metav1.CauseTypeFieldValueInvalid,
 				Message: fmt.Sprintf("selector is immutable after creation."),
diff --git a/pkg/virt-api/webhooks/validating-webhook/admitters/vmrestore-admitter.go b/pkg/virt-api/webhooks/validating-webhook/admitters/vmrestore-admitter.go
index 8eb947aa8..34fa224b4 100644
--- a/pkg/virt-api/webhooks/validating-webhook/admitters/vmrestore-admitter.go
+++ b/pkg/virt-api/webhooks/validating-webhook/admitters/vmrestore-admitter.go
@@ -23,9 +23,9 @@ import (
 	"context"
 	"encoding/json"
 	"fmt"
-	"reflect"
 
 	admissionv1 "k8s.io/api/admission/v1"
+	"k8s.io/apimachinery/pkg/api/equality"
 	"k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/types"
@@ -136,7 +136,7 @@ func (admitter *VMRestoreAdmitter) Admit(ar *admissionv1.AdmissionReview) *admis
 
 		for _, obj := range objects {
 			r := obj.(*snapshotv1.VirtualMachineRestore)
-			if reflect.DeepEqual(r.Spec.Target, vmRestore.Spec.Target) &&
+			if equality.Semantic.DeepEqual(r.Spec.Target, vmRestore.Spec.Target) &&
 				(r.Status == nil || r.Status.Complete == nil || !*r.Status.Complete) {
 				cause := metav1.StatusCause{
 					Type:    metav1.CauseTypeFieldValueInvalid,
@@ -156,7 +156,7 @@ func (admitter *VMRestoreAdmitter) Admit(ar *admissionv1.AdmissionReview) *admis
 			return webhookutils.ToAdmissionResponseError(err)
 		}
 
-		if !reflect.DeepEqual(prevObj.Spec, vmRestore.Spec) {
+		if !equality.Semantic.DeepEqual(prevObj.Spec, vmRestore.Spec) {
 			causes = []metav1.StatusCause{
 				{
 					Type:    metav1.CauseTypeFieldValueInvalid,
diff --git a/pkg/virt-api/webhooks/validating-webhook/admitters/vms-admitter.go b/pkg/virt-api/webhooks/validating-webhook/admitters/vms-admitter.go
index d5ad90418..bd2463e56 100644
--- a/pkg/virt-api/webhooks/validating-webhook/admitters/vms-admitter.go
+++ b/pkg/virt-api/webhooks/validating-webhook/admitters/vms-admitter.go
@@ -23,10 +23,10 @@ import (
 	"context"
 	"encoding/json"
 	"fmt"
-	"reflect"
 
 	admissionv1 "k8s.io/api/admission/v1"
 	authv1 "k8s.io/api/authorization/v1"
+	"k8s.io/apimachinery/pkg/api/equality"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	k8sfield "k8s.io/apimachinery/pkg/util/validation/field"
 	"k8s.io/client-go/tools/cache"
@@ -437,7 +437,7 @@ func (admitter *VMsAdmitter) validateVolumeRequests(vm *v1.VirtualMachine) ([]me
 			}
 
 			vmVolume, ok := vmVolumeMap[name]
-			if ok && !reflect.DeepEqual(newVolume, vmVolume) {
+			if ok && !equality.Semantic.DeepEqual(newVolume, vmVolume) {
 				return []metav1.StatusCause{{
 					Type:    metav1.CauseTypeFieldValueInvalid,
 					Message: fmt.Sprintf("AddVolume request for [%s] conflicts with an existing volume of the same name on the vmi template.", name),
@@ -446,7 +446,7 @@ func (admitter *VMsAdmitter) validateVolumeRequests(vm *v1.VirtualMachine) ([]me
 			}
 
 			vmiVolume, ok := vmiVolumeMap[name]
-			if ok && !reflect.DeepEqual(newVolume, vmiVolume) {
+			if ok && !equality.Semantic.DeepEqual(newVolume, vmiVolume) {
 				return []metav1.StatusCause{{
 					Type:    metav1.CauseTypeFieldValueInvalid,
 					Message: fmt.Sprintf("AddVolume request for [%s] conflicts with an existing volume of the same name on currently running vmi", name),
@@ -521,7 +521,7 @@ func validateRestoreStatus(ar *admissionv1.AdmissionRequest, vm *v1.VirtualMachi
 		}}
 	}
 
-	if !reflect.DeepEqual(oldVM.Spec, vm.Spec) {
+	if !equality.Semantic.DeepEqual(oldVM.Spec, vm.Spec) {
 		strategy, _ := vm.RunStrategy()
 		if strategy != v1.RunStrategyHalted {
 			return []metav1.StatusCause{{
@@ -548,7 +548,7 @@ func validateSnapshotStatus(ar *admissionv1.AdmissionRequest, vm *v1.VirtualMach
 		}}
 	}
 
-	if !reflect.DeepEqual(oldVM.Spec, vm.Spec) {
+	if !equality.Semantic.DeepEqual(oldVM.Spec, vm.Spec) {
 		return []metav1.StatusCause{{
 			Type:    metav1.CauseTypeFieldValueNotSupported,
 			Message: fmt.Sprintf("Cannot update VM spec until snapshot %q completes", *vm.Status.SnapshotInProgress),
diff --git a/pkg/virt-api/webhooks/validating-webhook/admitters/vmsnapshot-admitter.go b/pkg/virt-api/webhooks/validating-webhook/admitters/vmsnapshot-admitter.go
index b3cdcd29d..17c284d0e 100644
--- a/pkg/virt-api/webhooks/validating-webhook/admitters/vmsnapshot-admitter.go
+++ b/pkg/virt-api/webhooks/validating-webhook/admitters/vmsnapshot-admitter.go
@@ -22,9 +22,9 @@ package admitters
 import (
 	"encoding/json"
 	"fmt"
-	"reflect"
 
 	admissionv1 "k8s.io/api/admission/v1"
+	"k8s.io/apimachinery/pkg/api/equality"
 	"k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	k8sfield "k8s.io/apimachinery/pkg/util/validation/field"
@@ -120,7 +120,7 @@ func (admitter *VMSnapshotAdmitter) Admit(ar *admissionv1.AdmissionReview) *admi
 			return webhookutils.ToAdmissionResponseError(err)
 		}
 
-		if !reflect.DeepEqual(prevObj.Spec, vmSnapshot.Spec) {
+		if !equality.Semantic.DeepEqual(prevObj.Spec, vmSnapshot.Spec) {
 			causes = []metav1.StatusCause{
 				{
 					Type:    metav1.CauseTypeFieldValueInvalid,
diff --git a/pkg/virt-controller/watch/BUILD.bazel b/pkg/virt-controller/watch/BUILD.bazel
index 74cb90c09..cabc2bf44 100644
--- a/pkg/virt-controller/watch/BUILD.bazel
+++ b/pkg/virt-controller/watch/BUILD.bazel
@@ -60,6 +60,7 @@ go_library(
         "//vendor/k8s.io/api/authorization/v1:go_default_library",
         "//vendor/k8s.io/api/core/v1:go_default_library",
         "//vendor/k8s.io/api/policy/v1beta1:go_default_library",
+        "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/fields:go_default_library",
@@ -140,6 +141,7 @@ go_test(
         "//vendor/k8s.io/api/policy/v1beta1:go_default_library",
         "//vendor/k8s.io/api/storage/v1:go_default_library",
         "//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1:go_default_library",
+        "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
diff --git a/pkg/virt-controller/watch/drain/disruptionbudget/BUILD.bazel b/pkg/virt-controller/watch/drain/disruptionbudget/BUILD.bazel
index 6e78f52aa..30f780a3b 100644
--- a/pkg/virt-controller/watch/drain/disruptionbudget/BUILD.bazel
+++ b/pkg/virt-controller/watch/drain/disruptionbudget/BUILD.bazel
@@ -14,6 +14,7 @@ go_library(
         "//staging/src/kubevirt.io/client-go/log:go_default_library",
         "//vendor/k8s.io/api/core/v1:go_default_library",
         "//vendor/k8s.io/api/policy/v1beta1:go_default_library",
+        "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
diff --git a/pkg/virt-controller/watch/drain/disruptionbudget/disruptionbudget.go b/pkg/virt-controller/watch/drain/disruptionbudget/disruptionbudget.go
index ef768640b..c5e144b32 100644
--- a/pkg/virt-controller/watch/drain/disruptionbudget/disruptionbudget.go
+++ b/pkg/virt-controller/watch/drain/disruptionbudget/disruptionbudget.go
@@ -3,11 +3,11 @@ package disruptionbudget
 import (
 	"context"
 	"fmt"
-	"reflect"
 	"time"
 
 	corev1 "k8s.io/api/core/v1"
 	"k8s.io/api/policy/v1beta1"
+	"k8s.io/apimachinery/pkg/api/equality"
 	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/types"
 	"k8s.io/apimachinery/pkg/util/intstr"
@@ -206,7 +206,7 @@ func (c *DisruptionBudgetController) updatePodDisruptionBudget(old, cur interfac
 	}
 
 	if curPodDisruptionBudget.DeletionTimestamp != nil {
-		labelChanged := !reflect.DeepEqual(curPodDisruptionBudget.Labels, oldPodDisruptionBudget.Labels)
+		labelChanged := !equality.Semantic.DeepEqual(curPodDisruptionBudget.Labels, oldPodDisruptionBudget.Labels)
 		// having a pdb marked for deletion is enough to count as a deletion expectation
 		c.deletePodDisruptionBudget(curPodDisruptionBudget)
 		if labelChanged {
@@ -218,7 +218,7 @@ func (c *DisruptionBudgetController) updatePodDisruptionBudget(old, cur interfac
 
 	curControllerRef := v1.GetControllerOf(curPodDisruptionBudget)
 	oldControllerRef := v1.GetControllerOf(oldPodDisruptionBudget)
-	controllerRefChanged := !reflect.DeepEqual(curControllerRef, oldControllerRef)
+	controllerRefChanged := !equality.Semantic.DeepEqual(curControllerRef, oldControllerRef)
 	if controllerRefChanged {
 		// The ControllerRef was changed. Sync the old controller, if any.
 		if vmi := c.resolveControllerRef(oldPodDisruptionBudget.Namespace, oldControllerRef); vmi != nil {
diff --git a/pkg/virt-controller/watch/migration.go b/pkg/virt-controller/watch/migration.go
index 496571bdf..096b80265 100644
--- a/pkg/virt-controller/watch/migration.go
+++ b/pkg/virt-controller/watch/migration.go
@@ -23,7 +23,6 @@ import (
 	"context"
 	"encoding/json"
 	"fmt"
-	"reflect"
 	"strconv"
 	"strings"
 	"sync"
@@ -33,6 +32,7 @@ import (
 
 	k8sv1 "k8s.io/api/core/v1"
 	"k8s.io/api/policy/v1beta1"
+	"k8s.io/apimachinery/pkg/api/equality"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/labels"
@@ -207,7 +207,7 @@ func ensureSelectorLabelPresent(migration *virtv1.VirtualMachineInstanceMigratio
 func (c *MigrationController) patchVMI(origVMI, newVMI *virtv1.VirtualMachineInstance) error {
 	var ops []string
 
-	if !reflect.DeepEqual(origVMI.Status.MigrationState, newVMI.Status.MigrationState) {
+	if !equality.Semantic.DeepEqual(origVMI.Status.MigrationState, newVMI.Status.MigrationState) {
 		newState, err := json.Marshal(newVMI.Status.MigrationState)
 		if err != nil {
 			return err
@@ -225,7 +225,7 @@ func (c *MigrationController) patchVMI(origVMI, newVMI *virtv1.VirtualMachineIns
 		}
 	}
 
-	if !reflect.DeepEqual(origVMI.Labels, newVMI.Labels) {
+	if !equality.Semantic.DeepEqual(origVMI.Labels, newVMI.Labels) {
 		newLabels, err := json.Marshal(newVMI.Labels)
 		if err != nil {
 			return err
@@ -490,12 +490,12 @@ func (c *MigrationController) updateStatus(migration *virtv1.VirtualMachineInsta
 		}
 	}
 
-	if !reflect.DeepEqual(migration.Status, migrationCopy.Status) {
+	if !equality.Semantic.DeepEqual(migration.Status, migrationCopy.Status) {
 		err := c.statusUpdater.UpdateStatus(migrationCopy)
 		if err != nil {
 			return err
 		}
-	} else if !reflect.DeepEqual(migration.Finalizers, migrationCopy.Finalizers) {
+	} else if !equality.Semantic.DeepEqual(migration.Finalizers, migrationCopy.Finalizers) {
 		_, err := c.clientset.VirtualMachineInstanceMigration(migrationCopy.Namespace).Update(migrationCopy)
 		if err != nil {
 			return err
@@ -676,7 +676,7 @@ func (c *MigrationController) handleSignalMigrationAbort(migration *virtv1.Virtu
 	vmiCopy := vmi.DeepCopy()
 
 	vmiCopy.Status.MigrationState.AbortRequested = true
-	if !reflect.DeepEqual(vmi.Status, vmiCopy.Status) {
+	if !equality.Semantic.DeepEqual(vmi.Status, vmiCopy.Status) {
 		newStatus, err := json.Marshal(vmiCopy.Status)
 		if err != nil {
 			return err
@@ -1167,7 +1167,7 @@ func (c *MigrationController) updatePod(old, cur interface{}) {
 		return
 	}
 
-	labelChanged := !reflect.DeepEqual(curPod.Labels, oldPod.Labels)
+	labelChanged := !equality.Semantic.DeepEqual(curPod.Labels, oldPod.Labels)
 	if curPod.DeletionTimestamp != nil {
 		// having a pod marked for deletion is enough to count as a deletion expectation
 		c.deletePod(curPod)
@@ -1180,7 +1180,7 @@ func (c *MigrationController) updatePod(old, cur interface{}) {
 
 	curControllerRef := c.getControllerOf(curPod)
 	oldControllerRef := c.getControllerOf(oldPod)
-	controllerRefChanged := !reflect.DeepEqual(curControllerRef, oldControllerRef)
+	controllerRefChanged := !equality.Semantic.DeepEqual(curControllerRef, oldControllerRef)
 	if controllerRefChanged && oldControllerRef != nil {
 		// The ControllerRef was changed. Sync the old controller, if any.
 		if migration := c.resolveControllerRef(oldPod.Namespace, oldControllerRef); migration != nil {
@@ -1302,7 +1302,7 @@ func (c *MigrationController) updateVMI(old, cur interface{}) {
 		// have different RVs.
 		return
 	}
-	labelChanged := !reflect.DeepEqual(curVMI.Labels, oldVMI.Labels)
+	labelChanged := !equality.Semantic.DeepEqual(curVMI.Labels, oldVMI.Labels)
 	if curVMI.DeletionTimestamp != nil {
 		// having a DataVOlume marked for deletion is enough
 		// to count as a deletion expectation
diff --git a/pkg/virt-controller/watch/migration_test.go b/pkg/virt-controller/watch/migration_test.go
index 54d14b34d..b85bfd533 100644
--- a/pkg/virt-controller/watch/migration_test.go
+++ b/pkg/virt-controller/watch/migration_test.go
@@ -1084,6 +1084,8 @@ var _ = Describe("Migration watcher", func() {
 			}
 
 			if phase == virtv1.MigrationFailed {
+				// This finalizer is added by the mutation webhook during creation
+				migration.Finalizers = append(migration.Finalizers, virtv1.VirtualMachineInstanceMigrationFinalizer)
 				shouldExpectMigrationFinalizerRemoval(migration)
 			} else {
 				shouldExpectMigrationFailedState(migration)
diff --git a/pkg/virt-controller/watch/pool.go b/pkg/virt-controller/watch/pool.go
index b029c15b5..9435a3787 100644
--- a/pkg/virt-controller/watch/pool.go
+++ b/pkg/virt-controller/watch/pool.go
@@ -5,12 +5,12 @@ import (
 	"fmt"
 	"hash/fnv"
 	"math/rand"
-	"reflect"
 	"strconv"
 	"strings"
 	"sync"
 	"time"
 
+	"k8s.io/apimachinery/pkg/api/equality"
 	randutil "k8s.io/apimachinery/pkg/util/rand"
 	"k8s.io/utils/pointer"
 	"k8s.io/utils/trace"
@@ -210,7 +210,7 @@ func (c *PoolController) updateVMHandler(old, cur interface{}) {
 		return
 	}
 
-	labelChanged := !reflect.DeepEqual(curVM.Labels, oldVM.Labels)
+	labelChanged := !equality.Semantic.DeepEqual(curVM.Labels, oldVM.Labels)
 	if curVM.DeletionTimestamp != nil {
 		c.deleteVMHandler(curVM)
 		if labelChanged {
@@ -221,7 +221,7 @@ func (c *PoolController) updateVMHandler(old, cur interface{}) {
 
 	curControllerRef := metav1.GetControllerOf(curVM)
 	oldControllerRef := metav1.GetControllerOf(oldVM)
-	controllerRefChanged := !reflect.DeepEqual(curControllerRef, oldControllerRef)
+	controllerRefChanged := !equality.Semantic.DeepEqual(curControllerRef, oldControllerRef)
 	if controllerRefChanged && oldControllerRef != nil {
 		// The ControllerRef was changed. Sync the old controller, if any.
 		if pool := c.resolveControllerRef(oldVM.Namespace, oldControllerRef); pool != nil {
@@ -907,7 +907,7 @@ func (c *PoolController) updateStatus(origPool *poolv1.VirtualMachinePool, vms [
 
 	pool.Status.Replicas = int32(len(vms))
 
-	if !reflect.DeepEqual(pool.Status, origPool.Status) {
+	if !equality.Semantic.DeepEqual(pool.Status, origPool.Status) {
 		_, err := c.clientset.VirtualMachinePool(pool.Namespace).Update(context.Background(), pool, metav1.UpdateOptions{})
 		if err != nil {
 			return err
diff --git a/pkg/virt-controller/watch/replicaset.go b/pkg/virt-controller/watch/replicaset.go
index 9bf290bf7..7913b87b5 100644
--- a/pkg/virt-controller/watch/replicaset.go
+++ b/pkg/virt-controller/watch/replicaset.go
@@ -21,11 +21,11 @@ package watch
 
 import (
 	"fmt"
-	"reflect"
 	"sync"
 	"time"
 
 	k8score "k8s.io/api/core/v1"
+	"k8s.io/apimachinery/pkg/api/equality"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/labels"
 	"k8s.io/apimachinery/pkg/util/wait"
@@ -468,7 +468,7 @@ func (c *VMIReplicaSet) updateVirtualMachine(old, cur interface{}) {
 		return
 	}
 
-	labelChanged := !reflect.DeepEqual(curVMI.Labels, oldVMI.Labels)
+	labelChanged := !equality.Semantic.DeepEqual(curVMI.Labels, oldVMI.Labels)
 	if curVMI.DeletionTimestamp != nil {
 		// when a vmi is deleted gracefully it's deletion timestamp is first modified to reflect a grace period,
 		// and after such time has passed, the virt-handler actually deletes it from the store. We receive an update
@@ -485,7 +485,7 @@ func (c *VMIReplicaSet) updateVirtualMachine(old, cur interface{}) {
 
 	curControllerRef := metav1.GetControllerOf(curVMI)
 	oldControllerRef := metav1.GetControllerOf(oldVMI)
-	controllerRefChanged := !reflect.DeepEqual(curControllerRef, oldControllerRef)
+	controllerRefChanged := !equality.Semantic.DeepEqual(curControllerRef, oldControllerRef)
 	if controllerRefChanged && oldControllerRef != nil {
 		// The ControllerRef was changed. Sync the old controller, if any.
 		if rs := c.resolveControllerRef(oldVMI.Namespace, oldControllerRef); rs != nil {
diff --git a/pkg/virt-controller/watch/snapshot/BUILD.bazel b/pkg/virt-controller/watch/snapshot/BUILD.bazel
index 65ba18b14..0220a520c 100644
--- a/pkg/virt-controller/watch/snapshot/BUILD.bazel
+++ b/pkg/virt-controller/watch/snapshot/BUILD.bazel
@@ -25,6 +25,7 @@ go_library(
         "//vendor/k8s.io/api/core/v1:go_default_library",
         "//vendor/k8s.io/api/storage/v1:go_default_library",
         "//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1:go_default_library",
+        "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
diff --git a/pkg/virt-controller/watch/snapshot/restore.go b/pkg/virt-controller/watch/snapshot/restore.go
index 71585f7d3..2f0535ecc 100644
--- a/pkg/virt-controller/watch/snapshot/restore.go
+++ b/pkg/virt-controller/watch/snapshot/restore.go
@@ -22,13 +22,13 @@ package snapshot
 import (
 	"context"
 	"fmt"
-	"reflect"
 	"strings"
 	"time"
 
 	vsv1beta1 "github.com/kubernetes-csi/external-snapshotter/v2/pkg/apis/volumesnapshot/v1beta1"
 	corev1 "k8s.io/api/core/v1"
 	storagev1 "k8s.io/api/storage/v1"
+	"k8s.io/apimachinery/pkg/api/equality"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/types"
 
@@ -126,7 +126,7 @@ func (ctrl *VMRestoreController) updateVMRestore(vmRestoreIn *snapshotv1.Virtual
 	}
 
 	// let's make sure everything is initialized properly before continuing
-	if !reflect.DeepEqual(vmRestoreIn, vmRestoreOut) {
+	if !equality.Semantic.DeepEqual(vmRestoreIn, vmRestoreOut) {
 		return 0, ctrl.doUpdate(vmRestoreIn, vmRestoreOut)
 	}
 
@@ -211,7 +211,7 @@ func (ctrl *VMRestoreController) doUpdateError(restore *snapshotv1.VirtualMachin
 }
 
 func (ctrl *VMRestoreController) doUpdate(original, updated *snapshotv1.VirtualMachineRestore) error {
-	if !reflect.DeepEqual(original, updated) {
+	if !equality.Semantic.DeepEqual(original, updated) {
 		if _, err := ctrl.Client.VirtualMachineRestore(updated.Namespace).Update(context.Background(), updated, metav1.UpdateOptions{}); err != nil {
 			return err
 		}
@@ -251,7 +251,7 @@ func (ctrl *VMRestoreController) reconcileVolumeRestores(vmRestore *snapshotv1.V
 		}
 	}
 
-	if !reflect.DeepEqual(vmRestore.Status.Restores, restores) {
+	if !equality.Semantic.DeepEqual(vmRestore.Status.Restores, restores) {
 		if len(vmRestore.Status.Restores) > 0 {
 			log.Log.Object(vmRestore).Warning("VMRestore in strange state")
 		}
diff --git a/pkg/virt-controller/watch/snapshot/snapshot.go b/pkg/virt-controller/watch/snapshot/snapshot.go
index a29147295..54d833f8a 100644
--- a/pkg/virt-controller/watch/snapshot/snapshot.go
+++ b/pkg/virt-controller/watch/snapshot/snapshot.go
@@ -22,13 +22,13 @@ package snapshot
 import (
 	"context"
 	"fmt"
-	"reflect"
 	"strings"
 	"time"
 
 	vsv1beta1 "github.com/kubernetes-csi/external-snapshotter/v2/pkg/apis/volumesnapshot/v1beta1"
 	corev1 "k8s.io/api/core/v1"
 	storagev1 "k8s.io/api/storage/v1"
+	"k8s.io/apimachinery/pkg/api/equality"
 	"k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 
@@ -348,7 +348,7 @@ func (ctrl *VMSnapshotController) updateVMSnapshotContent(content *snapshotv1.Vi
 	contentCpy.Status.ReadyToUse = &ready
 	contentCpy.Status.VolumeSnapshotStatus = volumeSnapshotStatus
 
-	if !reflect.DeepEqual(content, contentCpy) {
+	if !equality.Semantic.DeepEqual(content, contentCpy) {
 		if _, err := ctrl.Client.VirtualMachineSnapshotContent(contentCpy.Namespace).Update(context.Background(), contentCpy, metav1.UpdateOptions{}); err != nil {
 			return 0, err
 		}
@@ -662,7 +662,7 @@ func (ctrl *VMSnapshotController) updateSnapshotStatus(vmSnapshot *snapshotv1.Vi
 		updateSnapshotCondition(vmSnapshotCpy, newReadyCondition(corev1.ConditionUnknown, "Unknown state"))
 	}
 
-	if !reflect.DeepEqual(vmSnapshot, vmSnapshotCpy) {
+	if !equality.Semantic.DeepEqual(vmSnapshot, vmSnapshotCpy) {
 		if _, err := ctrl.Client.VirtualMachineSnapshot(vmSnapshotCpy.Namespace).Update(context.Background(), vmSnapshotCpy, metav1.UpdateOptions{}); err != nil {
 			return err
 		}
diff --git a/pkg/virt-controller/watch/topology/BUILD.bazel b/pkg/virt-controller/watch/topology/BUILD.bazel
index 339eb1f68..d64df1329 100644
--- a/pkg/virt-controller/watch/topology/BUILD.bazel
+++ b/pkg/virt-controller/watch/topology/BUILD.bazel
@@ -19,6 +19,7 @@ go_library(
         "//staging/src/kubevirt.io/client-go/log:go_default_library",
         "//vendor/github.com/golang/mock/gomock:go_default_library",
         "//vendor/k8s.io/api/core/v1:go_default_library",
+        "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/util/strategicpatch:go_default_library",
diff --git a/pkg/virt-controller/watch/topology/nodetopologyupdater.go b/pkg/virt-controller/watch/topology/nodetopologyupdater.go
index 90290c94f..28ab5a17f 100644
--- a/pkg/virt-controller/watch/topology/nodetopologyupdater.go
+++ b/pkg/virt-controller/watch/topology/nodetopologyupdater.go
@@ -6,10 +6,10 @@ import (
 	"context"
 	"encoding/json"
 	"fmt"
-	"reflect"
 	"time"
 
 	v1 "k8s.io/api/core/v1"
+	"k8s.io/apimachinery/pkg/api/equality"
 	v12 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/types"
 	"k8s.io/apimachinery/pkg/util/strategicpatch"
@@ -62,7 +62,7 @@ func (n *nodeTopologyUpdater) sync(nodes []*v1.Node) *updateStats {
 			log.DefaultLogger().Object(node).Reason(err).Error("Could not calculate TSC frequencies for node")
 			continue
 		}
-		if !reflect.DeepEqual(node.Labels, nodeCopy.Labels) {
+		if !equality.Semantic.DeepEqual(node.Labels, nodeCopy.Labels) {
 			if err := patchNode(n.client, node, nodeCopy); err != nil {
 				stats.error++
 				log.DefaultLogger().Object(node).Reason(err).Error("Could not patch TSC frequencies for node")
diff --git a/pkg/virt-controller/watch/vm.go b/pkg/virt-controller/watch/vm.go
index 3e19c5f95..a73aa8057 100644
--- a/pkg/virt-controller/watch/vm.go
+++ b/pkg/virt-controller/watch/vm.go
@@ -25,7 +25,6 @@ import (
 	"fmt"
 	"math"
 	"math/rand"
-	"reflect"
 	"strings"
 	"time"
 
@@ -33,6 +32,7 @@ import (
 	appsv1 "k8s.io/api/apps/v1"
 	authv1 "k8s.io/api/authorization/v1"
 	k8score "k8s.io/api/core/v1"
+	"k8s.io/apimachinery/pkg/api/equality"
 	"k8s.io/apimachinery/pkg/api/errors"
 	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
@@ -573,7 +573,7 @@ func (c *VMController) handleVolumeRequests(vm *virtv1.VirtualMachine, vmi *virt
 		}
 	}
 
-	if !reflect.DeepEqual(vm, vmCopy) {
+	if !equality.Semantic.DeepEqual(vm, vmCopy) {
 		_, err := c.clientset.VirtualMachine(vmCopy.Namespace).Update(vmCopy)
 		if err != nil {
 			return err
@@ -1304,7 +1304,7 @@ func (c *VMController) updateVirtualMachineInstance(old, cur interface{}) {
 		return
 	}
 
-	labelChanged := !reflect.DeepEqual(curVMI.Labels, oldVMI.Labels)
+	labelChanged := !equality.Semantic.DeepEqual(curVMI.Labels, oldVMI.Labels)
 	if curVMI.DeletionTimestamp != nil {
 		// when a vmi is deleted gracefully it's deletion timestamp is first modified to reflect a grace period,
 		// and after such time has passed, the virt-handler actually deletes it from the store. We receive an update
@@ -1321,7 +1321,7 @@ func (c *VMController) updateVirtualMachineInstance(old, cur interface{}) {
 
 	curControllerRef := v1.GetControllerOf(curVMI)
 	oldControllerRef := v1.GetControllerOf(oldVMI)
-	controllerRefChanged := !reflect.DeepEqual(curControllerRef, oldControllerRef)
+	controllerRefChanged := !equality.Semantic.DeepEqual(curControllerRef, oldControllerRef)
 	if controllerRefChanged && oldControllerRef != nil {
 		// The ControllerRef was changed. Sync the old controller, if any.
 		if vm := c.resolveControllerRef(oldVMI.Namespace, oldControllerRef); vm != nil {
@@ -1431,7 +1431,7 @@ func (c *VMController) updateDataVolume(old, cur interface{}) {
 		// have different RVs.
 		return
 	}
-	labelChanged := !reflect.DeepEqual(curDataVolume.Labels, oldDataVolume.Labels)
+	labelChanged := !equality.Semantic.DeepEqual(curDataVolume.Labels, oldDataVolume.Labels)
 	if curDataVolume.DeletionTimestamp != nil {
 		// having a DataVOlume marked for deletion is enough
 		// to count as a deletion expectation
@@ -1445,7 +1445,7 @@ func (c *VMController) updateDataVolume(old, cur interface{}) {
 	}
 	curControllerRef := v1.GetControllerOf(curDataVolume)
 	oldControllerRef := v1.GetControllerOf(oldDataVolume)
-	controllerRefChanged := !reflect.DeepEqual(curControllerRef, oldControllerRef)
+	controllerRefChanged := !equality.Semantic.DeepEqual(curControllerRef, oldControllerRef)
 	if controllerRefChanged && oldControllerRef != nil {
 		// The ControllerRef was changed. Sync the old controller, if any.
 		if vm := c.resolveControllerRef(oldDataVolume.Namespace, oldControllerRef); vm != nil {
@@ -1524,7 +1524,7 @@ func (c *VMController) removeVMIFinalizer(vmi *virtv1.VirtualMachineInstance) er
 	vmiCopy := vmi.DeepCopy()
 	controller.RemoveFinalizer(vmiCopy, virtv1.VirtualMachineControllerFinalizer)
 
-	if reflect.DeepEqual(vmi.Finalizers, vmiCopy.Finalizers) {
+	if equality.Semantic.DeepEqual(vmi.Finalizers, vmiCopy.Finalizers) {
 		return nil
 	}
 
@@ -1571,7 +1571,7 @@ func (c *VMController) updateStatus(vmOrig *virtv1.VirtualMachine, vmi *virtv1.V
 	c.setPrintableStatus(vm, vmi)
 
 	// only update if necessary
-	if !reflect.DeepEqual(vm.Status, vmOrig.Status) {
+	if !equality.Semantic.DeepEqual(vm.Status, vmOrig.Status) {
 		if err := c.statusUpdater.UpdateStatus(vm); err != nil {
 			return err
 		}
diff --git a/pkg/virt-controller/watch/vmi.go b/pkg/virt-controller/watch/vmi.go
index f69dcfc89..ba7b72a0c 100644
--- a/pkg/virt-controller/watch/vmi.go
+++ b/pkg/virt-controller/watch/vmi.go
@@ -23,12 +23,12 @@ import (
 	"encoding/json"
 	"errors"
 	"fmt"
-	"reflect"
 	"sort"
 	"strings"
 	"time"
 
 	k8sv1 "k8s.io/api/core/v1"
+	"k8s.io/apimachinery/pkg/api/equality"
 	k8serrors "k8s.io/apimachinery/pkg/api/errors"
 	v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/types"
@@ -625,7 +625,7 @@ func (c *VMIController) updateStatus(vmi *virtv1.VirtualMachineInstance, pod *k8
 	controller.SetVMIPhaseTransitionTimestamp(vmi, vmiCopy)
 
 	// If we detect a change on the vmi we update the vmi
-	vmiChanged := !reflect.DeepEqual(vmi.Status, vmiCopy.Status) || !reflect.DeepEqual(vmi.Finalizers, vmiCopy.Finalizers) || !reflect.DeepEqual(vmi.Annotations, vmiCopy.Annotations) || !reflect.DeepEqual(vmi.Labels, vmiCopy.Labels)
+	vmiChanged := !equality.Semantic.DeepEqual(vmi.Status, vmiCopy.Status) || !equality.Semantic.DeepEqual(vmi.Finalizers, vmiCopy.Finalizers) || !equality.Semantic.DeepEqual(vmi.Annotations, vmiCopy.Annotations) || !equality.Semantic.DeepEqual(vmi.Labels, vmiCopy.Labels)
 	if vmiChanged {
 		key := controller.VirtualMachineInstanceKey(vmi)
 		c.vmiExpectations.SetExpectations(key, 1, 0)
@@ -667,7 +667,7 @@ func preparePodPatch(oldPod, newPod *k8sv1.Pod) ([]byte, error) {
 func prepareVMIPatch(oldVMI, newVMI *virtv1.VirtualMachineInstance) ([]byte, error) {
 	var patchOps []string
 
-	if !reflect.DeepEqual(newVMI.Status.VolumeStatus, oldVMI.Status.VolumeStatus) {
+	if !equality.Semantic.DeepEqual(newVMI.Status.VolumeStatus, oldVMI.Status.VolumeStatus) {
 		// VolumeStatus changed which means either removed or added volumes.
 		newVolumeStatus, err := json.Marshal(newVMI.Status.VolumeStatus)
 		if err != nil {
@@ -704,7 +704,7 @@ func prepareVMIPatch(oldVMI, newVMI *virtv1.VirtualMachineInstance) ([]byte, err
 		log.Log.V(3).Object(oldVMI).Infof("Patching VMI conditions")
 	}
 
-	if !reflect.DeepEqual(newVMI.Status.ActivePods, oldVMI.Status.ActivePods) {
+	if !equality.Semantic.DeepEqual(newVMI.Status.ActivePods, oldVMI.Status.ActivePods) {
 		newPods, err := json.Marshal(newVMI.Status.ActivePods)
 		if err != nil {
 			return nil, err
@@ -729,7 +729,7 @@ func prepareVMIPatch(oldVMI, newVMI *virtv1.VirtualMachineInstance) ([]byte, err
 		}
 	}
 
-	if !reflect.DeepEqual(oldVMI.Labels, newVMI.Labels) {
+	if !equality.Semantic.DeepEqual(oldVMI.Labels, newVMI.Labels) {
 		newLabelBytes, err := json.Marshal(newVMI.Labels)
 		if err != nil {
 			return nil, err
@@ -1135,7 +1135,7 @@ func (c *VMIController) updatePVC(old, cur interface{}) {
 	if curPVC.DeletionTimestamp != nil {
 		return
 	}
-	if reflect.DeepEqual(curPVC.Status.Capacity, oldPVC.Status.Capacity) {
+	if equality.Semantic.DeepEqual(curPVC.Status.Capacity, oldPVC.Status.Capacity) {
 		// We only do something when the capacity changes
 		return
 	}
@@ -1177,7 +1177,7 @@ func (c *VMIController) updateDataVolume(old, cur interface{}) {
 		return
 	}
 	if curDataVolume.DeletionTimestamp != nil {
-		labelChanged := !reflect.DeepEqual(curDataVolume.Labels, oldDataVolume.Labels)
+		labelChanged := !equality.Semantic.DeepEqual(curDataVolume.Labels, oldDataVolume.Labels)
 		// having a DataVOlume marked for deletion is enough
 		// to count as a deletion expectation
 		c.deleteDataVolume(curDataVolume)
@@ -1265,7 +1265,7 @@ func (c *VMIController) updatePod(old, cur interface{}) {
 	}
 
 	if curPod.DeletionTimestamp != nil {
-		labelChanged := !reflect.DeepEqual(curPod.Labels, oldPod.Labels)
+		labelChanged := !equality.Semantic.DeepEqual(curPod.Labels, oldPod.Labels)
 		// having a pod marked for deletion is enough to count as a deletion expectation
 		c.deletePod(curPod)
 		if labelChanged {
@@ -1277,7 +1277,7 @@ func (c *VMIController) updatePod(old, cur interface{}) {
 
 	curControllerRef := controller.GetControllerOf(curPod)
 	oldControllerRef := controller.GetControllerOf(oldPod)
-	controllerRefChanged := !reflect.DeepEqual(curControllerRef, oldControllerRef)
+	controllerRefChanged := !equality.Semantic.DeepEqual(curControllerRef, oldControllerRef)
 	if controllerRefChanged {
 		// The ControllerRef was changed. Sync the old controller, if any.
 		if vmi := c.resolveControllerRef(oldPod.Namespace, oldControllerRef); vmi != nil {
diff --git a/pkg/virt-controller/watch/vmi_test.go b/pkg/virt-controller/watch/vmi_test.go
index a5c830be8..6b8b497ef 100644
--- a/pkg/virt-controller/watch/vmi_test.go
+++ b/pkg/virt-controller/watch/vmi_test.go
@@ -22,7 +22,6 @@ package watch
 import (
 	"encoding/json"
 	"fmt"
-	"reflect"
 	"strings"
 	"time"
 
@@ -34,6 +33,7 @@ import (
 	. "github.com/onsi/gomega/gstruct"
 	gomegaTypes "github.com/onsi/gomega/types"
 	k8sv1 "k8s.io/api/core/v1"
+	"k8s.io/apimachinery/pkg/api/equality"
 	k8serrors "k8s.io/apimachinery/pkg/api/errors"
 	"k8s.io/apimachinery/pkg/api/resource"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -1821,7 +1821,7 @@ var _ = Describe("VirtualMachineInstance watcher", func() {
 			addVirtualMachine(vmi)
 
 			result := controller.resolveControllerRef(k8sv1.NamespaceDefault, controllerRef)
-			Expect(reflect.DeepEqual(result, vmi)).To(BeTrue(), "result: %v, should equal %v", result, vmi)
+			Expect(equality.Semantic.DeepEqual(result, vmi)).To(BeTrue(), "result: %v, should equal %v", result, vmi)
 		})
 
 		It("Should find vmi, from attachment pod", func() {
@@ -1833,7 +1833,7 @@ var _ = Describe("VirtualMachineInstance watcher", func() {
 			podFeeder.Add(pod)
 
 			result := controller.resolveControllerRef(k8sv1.NamespaceDefault, controllerRef)
-			Expect(reflect.DeepEqual(result, vmi)).To(BeTrue(), "result: %v, should equal %v", result, vmi)
+			Expect(equality.Semantic.DeepEqual(result, vmi)).To(BeTrue(), "result: %v, should equal %v", result, vmi)
 		})
 
 		It("DeleteAllAttachmentPods should return success if no virt launcher pod exists", func() {
@@ -2138,7 +2138,7 @@ var _ = Describe("VirtualMachineInstance watcher", func() {
 			res := controller.getDeletedHotplugVolumes(hotplugPods, hotplugVolumes)
 			Expect(len(res)).To(Equal(len(expected)))
 			for i, volume := range res {
-				Expect(reflect.DeepEqual(volume, expected[i])).To(BeTrue(), "%v does not match %v", volume, expected[i])
+				Expect(equality.Semantic.DeepEqual(volume, expected[i])).To(BeTrue(), "%v does not match %v", volume, expected[i])
 			}
 		},
 			table.Entry("should return empty if pods and volumes is empty", make([]*k8sv1.Pod, 0), make([]*virtv1.Volume, 0), make([]k8sv1.Volume, 0)),
@@ -2150,7 +2150,7 @@ var _ = Describe("VirtualMachineInstance watcher", func() {
 			res := controller.getNewHotplugVolumes(hotplugPods, hotplugVolumes)
 			Expect(len(res)).To(Equal(len(expected)))
 			for i, volume := range res {
-				Expect(reflect.DeepEqual(volume, expected[i])).To(BeTrue(), "%v does not match %v", volume, expected[i])
+				Expect(equality.Semantic.DeepEqual(volume, expected[i])).To(BeTrue(), "%v does not match %v", volume, expected[i])
 			}
 		},
 			table.Entry("should return empty if pods and volumes is empty", make([]*k8sv1.Pod, 0), make([]*virtv1.Volume, 0), make([]*virtv1.Volume, 0)),
@@ -2401,7 +2401,7 @@ var _ = Describe("VirtualMachineInstance watcher", func() {
 			err := controller.updateVolumeStatus(vmi, virtlauncherPod)
 			testutils.ExpectEvents(recorder, expectedEvents...)
 			Expect(err).ToNot(HaveOccurred())
-			Expect(reflect.DeepEqual(expectedStatus, vmi.Status.VolumeStatus)).To(BeTrue(), "status: %v, expected: %v", vmi.Status.VolumeStatus, expectedStatus)
+			Expect(equality.Semantic.DeepEqual(expectedStatus, vmi.Status.VolumeStatus)).To(BeTrue(), "status: %v, expected: %v", vmi.Status.VolumeStatus, expectedStatus)
 		},
 			table.Entry("should not update volume status, if no volumes changed",
 				makeVolumeStatusesForUpdate(),
diff --git a/pkg/virt-handler/cache/BUILD.bazel b/pkg/virt-handler/cache/BUILD.bazel
index e91a3af0d..12e87072a 100644
--- a/pkg/virt-handler/cache/BUILD.bazel
+++ b/pkg/virt-handler/cache/BUILD.bazel
@@ -44,6 +44,7 @@ go_test(
         "//vendor/github.com/golang/mock/gomock:go_default_library",
         "//vendor/github.com/onsi/ginkgo:go_default_library",
         "//vendor/github.com/onsi/gomega:go_default_library",
+        "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
         "//vendor/k8s.io/client-go/tools/cache:go_default_library",
     ],
diff --git a/pkg/virt-handler/cache/cache_test.go b/pkg/virt-handler/cache/cache_test.go
index 20890f581..3138c4af2 100644
--- a/pkg/virt-handler/cache/cache_test.go
+++ b/pkg/virt-handler/cache/cache_test.go
@@ -25,7 +25,6 @@ import (
 	"net"
 	"os"
 	"path/filepath"
-	"reflect"
 	"sync"
 	"time"
 
@@ -33,6 +32,7 @@ import (
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
 
+	"k8s.io/apimachinery/pkg/api/equality"
 	"k8s.io/apimachinery/pkg/watch"
 	"k8s.io/client-go/tools/cache"
 
@@ -113,7 +113,7 @@ var _ = Describe("Domain informer", func() {
 
 			eventDomain := obj.(*api.Domain)
 			eventDomain.Spec.XMLName = xml.Name{}
-			Expect(reflect.DeepEqual(&domain.Spec, &eventDomain.Spec)).To(BeTrue())
+			Expect(equality.Semantic.DeepEqual(&domain.Spec, &eventDomain.Spec)).To(BeTrue())
 		} else {
 
 			Expect(exists).To(BeFalse())
diff --git a/pkg/virt-handler/container-disk/BUILD.bazel b/pkg/virt-handler/container-disk/BUILD.bazel
index 8e3c9f0f6..62a5f07bf 100644
--- a/pkg/virt-handler/container-disk/BUILD.bazel
+++ b/pkg/virt-handler/container-disk/BUILD.bazel
@@ -18,6 +18,7 @@ go_library(
         "//staging/src/kubevirt.io/api/core/v1:go_default_library",
         "//staging/src/kubevirt.io/client-go/log:go_default_library",
         "//vendor/github.com/golang/mock/gomock:go_default_library",
+        "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
     ],
 )
diff --git a/pkg/virt-handler/container-disk/mount.go b/pkg/virt-handler/container-disk/mount.go
index d831c8071..df018f687 100644
--- a/pkg/virt-handler/container-disk/mount.go
+++ b/pkg/virt-handler/container-disk/mount.go
@@ -5,7 +5,6 @@ import (
 	"fmt"
 	"os"
 	"path/filepath"
-	"reflect"
 	"strings"
 	"sync"
 	"time"
@@ -19,6 +18,7 @@ import (
 	diskutils "kubevirt.io/kubevirt/pkg/ephemeral-disk-utils"
 	"kubevirt.io/kubevirt/pkg/virt-handler/isolation"
 
+	"k8s.io/apimachinery/pkg/api/equality"
 	"k8s.io/apimachinery/pkg/types"
 
 	v1 "kubevirt.io/api/core/v1"
@@ -164,7 +164,7 @@ func (m *mounter) setMountTargetRecord(vmi *v1.VirtualMachineInstance, record *v
 	defer m.mountRecordsLock.Unlock()
 
 	existingRecord, ok := m.mountRecords[vmi.UID]
-	if ok && fileExists && reflect.DeepEqual(existingRecord, record) {
+	if ok && fileExists && equality.Semantic.DeepEqual(existingRecord, record) {
 		// already done
 		return nil
 	}
diff --git a/pkg/virt-handler/node-labeller/BUILD.bazel b/pkg/virt-handler/node-labeller/BUILD.bazel
index 00185ffb5..da5ff8f17 100644
--- a/pkg/virt-handler/node-labeller/BUILD.bazel
+++ b/pkg/virt-handler/node-labeller/BUILD.bazel
@@ -21,6 +21,7 @@ go_library(
         "//staging/src/kubevirt.io/client-go/kubecli:go_default_library",
         "//staging/src/kubevirt.io/client-go/log:go_default_library",
         "//vendor/k8s.io/api/core/v1:go_default_library",
+        "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/util/wait:go_default_library",
diff --git a/pkg/virt-handler/node-labeller/node_labeller.go b/pkg/virt-handler/node-labeller/node_labeller.go
index 1ae5beec7..ca283c26f 100644
--- a/pkg/virt-handler/node-labeller/node_labeller.go
+++ b/pkg/virt-handler/node-labeller/node_labeller.go
@@ -24,11 +24,11 @@ import (
 	"encoding/json"
 	"fmt"
 	"os/exec"
-	"reflect"
 	"strings"
 	"time"
 
 	v1 "k8s.io/api/core/v1"
+	"k8s.io/apimachinery/pkg/api/equality"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/types"
 	"k8s.io/apimachinery/pkg/util/wait"
@@ -194,7 +194,7 @@ func skipNode(node *v1.Node) bool {
 
 func (n *NodeLabeller) patchNode(originalNode, node *v1.Node) error {
 	p := make([]utiltype.PatchOperation, 0)
-	if !reflect.DeepEqual(originalNode.Labels, node.Labels) {
+	if !equality.Semantic.DeepEqual(originalNode.Labels, node.Labels) {
 		p = append(p, utiltype.PatchOperation{
 			Op:    "test",
 			Path:  "/metadata/labels",
@@ -206,7 +206,7 @@ func (n *NodeLabeller) patchNode(originalNode, node *v1.Node) error {
 		})
 	}
 
-	if !reflect.DeepEqual(originalNode.Annotations, node.Annotations) {
+	if !equality.Semantic.DeepEqual(originalNode.Annotations, node.Annotations) {
 		p = append(p, utiltype.PatchOperation{
 			Op:    "test",
 			Path:  "/metadata/annotations",
diff --git a/pkg/virt-launcher/notify-client/BUILD.bazel b/pkg/virt-launcher/notify-client/BUILD.bazel
index b48bf06ce..ae6d9766e 100644
--- a/pkg/virt-launcher/notify-client/BUILD.bazel
+++ b/pkg/virt-launcher/notify-client/BUILD.bazel
@@ -53,6 +53,7 @@ go_test(
         "//vendor/github.com/onsi/ginkgo:go_default_library",
         "//vendor/github.com/onsi/ginkgo/extensions/table:go_default_library",
         "//vendor/github.com/onsi/gomega:go_default_library",
+        "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
         "//vendor/k8s.io/client-go/tools/cache:go_default_library",
         "//vendor/k8s.io/client-go/tools/record:go_default_library",
diff --git a/pkg/virt-launcher/notify-client/notify_test.go b/pkg/virt-launcher/notify-client/notify_test.go
index 54f8b4857..3648fdfef 100644
--- a/pkg/virt-launcher/notify-client/notify_test.go
+++ b/pkg/virt-launcher/notify-client/notify_test.go
@@ -24,7 +24,6 @@ import (
 	"fmt"
 	"io/ioutil"
 	"os"
-	"reflect"
 	"time"
 
 	"github.com/golang/mock/gomock"
@@ -35,6 +34,7 @@ import (
 
 	api2 "kubevirt.io/client-go/api"
 
+	"k8s.io/apimachinery/pkg/api/equality"
 	"k8s.io/apimachinery/pkg/watch"
 	"k8s.io/client-go/tools/cache"
 	"k8s.io/client-go/tools/record"
@@ -118,7 +118,7 @@ var _ = Describe("Notify", func() {
 					newDomain, ok := event.Object.(*api.Domain)
 					newDomain.Spec.XMLName = xml.Name{}
 					Expect(ok).To(BeTrue(), "should typecase domain")
-					Expect(reflect.DeepEqual(domain.Spec, newDomain.Spec)).To(BeTrue())
+					Expect(equality.Semantic.DeepEqual(domain.Spec, newDomain.Spec)).To(BeTrue())
 					Expect(event.Type).To(Equal(kubeEventType))
 				}
 				Expect(timedOut).To(BeFalse(), "should not time out")
@@ -194,7 +194,7 @@ var _ = Describe("Notify", func() {
 					newDomain, _ := event.Object.(*api.Domain)
 					newInterfaceStatuses := newDomain.Status.Interfaces
 					Expect(len(newInterfaceStatuses)).To(Equal(2))
-					Expect(reflect.DeepEqual(interfaceStatus, newInterfaceStatuses)).To(BeTrue())
+					Expect(equality.Semantic.DeepEqual(interfaceStatus, newInterfaceStatuses)).To(BeTrue())
 				}
 				Expect(timedOut).To(BeFalse())
 			})
@@ -226,7 +226,7 @@ var _ = Describe("Notify", func() {
 				case event := <-eventChan:
 					newDomain, _ := event.Object.(*api.Domain)
 					newOSStatus := newDomain.Status.OSInfo
-					Expect(reflect.DeepEqual(osInfoStatus, newOSStatus)).To(BeTrue())
+					Expect(equality.Semantic.DeepEqual(osInfoStatus, newOSStatus)).To(BeTrue())
 				}
 				Expect(timedOut).To(BeFalse())
 			})
@@ -258,7 +258,7 @@ var _ = Describe("Notify", func() {
 				case event := <-eventChan:
 					newDomain, _ := event.Object.(*api.Domain)
 					newFSFreezeStatus := newDomain.Status.FSFreezeStatus
-					Expect(reflect.DeepEqual(fsFreezeStatus, newFSFreezeStatus)).To(BeTrue())
+					Expect(equality.Semantic.DeepEqual(fsFreezeStatus, newFSFreezeStatus)).To(BeTrue())
 				}
 				Expect(timedOut).To(BeFalse())
 			})
diff --git a/pkg/virt-launcher/virtwrap/agent-poller/BUILD.bazel b/pkg/virt-launcher/virtwrap/agent-poller/BUILD.bazel
index b22a04943..855d1ac88 100644
--- a/pkg/virt-launcher/virtwrap/agent-poller/BUILD.bazel
+++ b/pkg/virt-launcher/virtwrap/agent-poller/BUILD.bazel
@@ -13,6 +13,7 @@ go_library(
         "//pkg/virt-launcher/virtwrap/cli:go_default_library",
         "//staging/src/kubevirt.io/api/core/v1:go_default_library",
         "//staging/src/kubevirt.io/client-go/log:go_default_library",
+        "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
     ],
 )
diff --git a/pkg/virt-launcher/virtwrap/agent-poller/agent_poller.go b/pkg/virt-launcher/virtwrap/agent-poller/agent_poller.go
index cb7ed2f06..041a64e29 100644
--- a/pkg/virt-launcher/virtwrap/agent-poller/agent_poller.go
+++ b/pkg/virt-launcher/virtwrap/agent-poller/agent_poller.go
@@ -19,10 +19,10 @@
 package agentpoller
 
 import (
-	"reflect"
 	"sync"
 	"time"
 
+	"k8s.io/apimachinery/pkg/api/equality"
 	"k8s.io/apimachinery/pkg/types"
 
 	"kubevirt.io/client-go/log"
@@ -77,7 +77,7 @@ func NewAsyncAgentStore() AsyncAgentStore {
 func (s *AsyncAgentStore) Store(key AgentCommand, value interface{}) {
 
 	oldData, _ := s.store.Load(key)
-	updated := (oldData == nil) || !reflect.DeepEqual(oldData, value)
+	updated := (oldData == nil) || !equality.Semantic.DeepEqual(oldData, value)
 
 	s.store.Store(key, value)
 
diff --git a/pkg/virt-launcher/virtwrap/converter/BUILD.bazel b/pkg/virt-launcher/virtwrap/converter/BUILD.bazel
index 1297867b4..356bb8b81 100644
--- a/pkg/virt-launcher/virtwrap/converter/BUILD.bazel
+++ b/pkg/virt-launcher/virtwrap/converter/BUILD.bazel
@@ -60,6 +60,7 @@ go_test(
         "//vendor/github.com/onsi/ginkgo/extensions/table:go_default_library",
         "//vendor/github.com/onsi/gomega:go_default_library",
         "//vendor/k8s.io/api/core/v1:go_default_library",
+        "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
         "//vendor/k8s.io/utils/pointer:go_default_library",
diff --git a/pkg/virt-launcher/virtwrap/converter/converter_test.go b/pkg/virt-launcher/virtwrap/converter/converter_test.go
index d8ddfa841..f1c9e52e0 100644
--- a/pkg/virt-launcher/virtwrap/converter/converter_test.go
+++ b/pkg/virt-launcher/virtwrap/converter/converter_test.go
@@ -26,7 +26,6 @@ import (
 	"os"
 	"path"
 	"path/filepath"
-	"reflect"
 	"strconv"
 	"strings"
 
@@ -35,6 +34,7 @@ import (
 	"github.com/onsi/ginkgo/extensions/table"
 	. "github.com/onsi/gomega"
 	k8sv1 "k8s.io/api/core/v1"
+	"k8s.io/apimachinery/pkg/api/equality"
 	"k8s.io/apimachinery/pkg/api/resource"
 	k8smeta "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/utils/pointer"
@@ -2817,7 +2817,7 @@ var _ = Describe("Converter", func() {
 				{IOThread: 5, CPUSet: "17,18"},
 				{IOThread: 6, CPUSet: "19,20"},
 			}
-			isExpectedThreadsLayout := reflect.DeepEqual(expectedLayout, domain.Spec.CPUTune.IOThreadPin)
+			isExpectedThreadsLayout := equality.Semantic.DeepEqual(expectedLayout, domain.Spec.CPUTune.IOThreadPin)
 			Expect(isExpectedThreadsLayout).To(BeTrue())
 
 		})
@@ -2850,7 +2850,7 @@ var _ = Describe("Converter", func() {
 				{IOThread: 5, CPUSet: "6"},
 				{IOThread: 6, CPUSet: "5"},
 			}
-			isExpectedThreadsLayout := reflect.DeepEqual(expectedLayout, domain.Spec.CPUTune.IOThreadPin)
+			isExpectedThreadsLayout := equality.Semantic.DeepEqual(expectedLayout, domain.Spec.CPUTune.IOThreadPin)
 			Expect(isExpectedThreadsLayout).To(BeTrue())
 		})
 	})
diff --git a/pkg/virt-launcher/virtwrap/statsconv/BUILD.bazel b/pkg/virt-launcher/virtwrap/statsconv/BUILD.bazel
index 7a7f7914a..0b1ced992 100644
--- a/pkg/virt-launcher/virtwrap/statsconv/BUILD.bazel
+++ b/pkg/virt-launcher/virtwrap/statsconv/BUILD.bazel
@@ -29,6 +29,7 @@ go_test(
         "//vendor/github.com/golang/mock/gomock:go_default_library",
         "//vendor/github.com/onsi/ginkgo:go_default_library",
         "//vendor/github.com/onsi/gomega:go_default_library",
+        "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
         "//vendor/libvirt.org/go/libvirt:go_default_library",
     ],
 )
diff --git a/pkg/virt-launcher/virtwrap/statsconv/converter_test.go b/pkg/virt-launcher/virtwrap/statsconv/converter_test.go
index 1db9223eb..8249b50c0 100644
--- a/pkg/virt-launcher/virtwrap/statsconv/converter_test.go
+++ b/pkg/virt-launcher/virtwrap/statsconv/converter_test.go
@@ -24,12 +24,12 @@ import (
 	"encoding/json"
 	"io"
 	"os"
-	"reflect"
 	"strings"
 
 	"github.com/golang/mock/gomock"
 	. "github.com/onsi/ginkgo"
 	. "github.com/onsi/gomega"
+	"k8s.io/apimachinery/pkg/api/equality"
 	"libvirt.org/go/libvirt"
 
 	"kubevirt.io/kubevirt/pkg/virt-launcher/virtwrap/stats"
@@ -124,5 +124,5 @@ func JSONEqual(a, b io.Reader) (bool, error) {
 	if err := d.Decode(&j2); err != nil {
 		return false, err
 	}
-	return reflect.DeepEqual(j2, j), nil
+	return equality.Semantic.DeepEqual(j2, j), nil
 }
diff --git a/pkg/virt-operator/BUILD.bazel b/pkg/virt-operator/BUILD.bazel
index 7cc8ec253..9459913a1 100644
--- a/pkg/virt-operator/BUILD.bazel
+++ b/pkg/virt-operator/BUILD.bazel
@@ -37,6 +37,7 @@ go_library(
         "//vendor/k8s.io/api/apps/v1:go_default_library",
         "//vendor/k8s.io/api/batch/v1:go_default_library",
         "//vendor/k8s.io/api/core/v1:go_default_library",
+        "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
diff --git a/pkg/virt-operator/kubevirt.go b/pkg/virt-operator/kubevirt.go
index 4f6a5a3f7..fef45fcd7 100644
--- a/pkg/virt-operator/kubevirt.go
+++ b/pkg/virt-operator/kubevirt.go
@@ -23,7 +23,6 @@ import (
 	"context"
 	"encoding/json"
 	"fmt"
-	"reflect"
 	"sync"
 	"time"
 
@@ -33,6 +32,7 @@ import (
 	appsv1 "k8s.io/api/apps/v1"
 	batchv1 "k8s.io/api/batch/v1"
 	k8sv1 "k8s.io/api/core/v1"
+	"k8s.io/apimachinery/pkg/api/equality"
 	"k8s.io/apimachinery/pkg/api/errors"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/util/wait"
@@ -663,7 +663,7 @@ func (c *KubeVirtController) execute(key string) error {
 	operatorutil.SetConditionTimestamps(kv, kvCopy)
 
 	// If we detect a change on KubeVirt we update it
-	if !reflect.DeepEqual(kv.Status, kvCopy.Status) {
+	if !equality.Semantic.DeepEqual(kv.Status, kvCopy.Status) {
 		if err := c.statusUpdater.UpdateStatus(kvCopy); err != nil {
 			logger.Reason(err).Errorf("Could not update the KubeVirt resource status.")
 			return err
@@ -672,7 +672,7 @@ func (c *KubeVirtController) execute(key string) error {
 
 	// If we detect a change on KubeVirt finalizers we update them
 	// Note: we don't own the metadata section so we need to use Patch() and not Update()
-	if !reflect.DeepEqual(kv.Finalizers, kvCopy.Finalizers) {
+	if !equality.Semantic.DeepEqual(kv.Finalizers, kvCopy.Finalizers) {
 		finalizersJson, err := json.Marshal(kvCopy.Finalizers)
 		if err != nil {
 			return err
diff --git a/pkg/virt-operator/resource/apply/BUILD.bazel b/pkg/virt-operator/resource/apply/BUILD.bazel
index 7edab4088..4fcb0c30e 100644
--- a/pkg/virt-operator/resource/apply/BUILD.bazel
+++ b/pkg/virt-operator/resource/apply/BUILD.bazel
@@ -114,6 +114,7 @@ go_test(
         "//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1:go_default_library",
         "//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1:go_default_library",
         "//vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake:go_default_library",
+        "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
diff --git a/pkg/virt-operator/resource/apply/apps_test.go b/pkg/virt-operator/resource/apply/apps_test.go
index a8f314575..9a30f9427 100644
--- a/pkg/virt-operator/resource/apply/apps_test.go
+++ b/pkg/virt-operator/resource/apply/apps_test.go
@@ -22,7 +22,6 @@ package apply
 import (
 	"encoding/json"
 	"fmt"
-	"reflect"
 	"strings"
 
 	"kubevirt.io/kubevirt/pkg/testutils"
@@ -35,6 +34,7 @@ import (
 	appsv1 "k8s.io/api/apps/v1"
 	corev1 "k8s.io/api/core/v1"
 	"k8s.io/api/policy/v1beta1"
+	"k8s.io/apimachinery/pkg/api/equality"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	v12 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/apimachinery/pkg/runtime"
@@ -884,7 +884,7 @@ var _ = Describe("Apply Apps", func() {
 			orig := componentConfig.DeepCopy()
 			orig.NodePlacement.NodeSelector = map[string]string{kubernetesOSLabel: kubernetesOSLinux}
 			injectPlacementMetadata(componentConfig, nil)
-			Expect(reflect.DeepEqual(orig, componentConfig)).To(BeTrue())
+			Expect(equality.Semantic.DeepEqual(orig, componentConfig)).To(BeTrue())
 		})
 
 		It("should copy NodeSelectors when podSpec is empty", func() {
@@ -980,7 +980,7 @@ var _ = Describe("Apply Apps", func() {
 		It("It should copy NodePlacement if podSpec Affinity is empty", func() {
 			nodePlacement.Affinity = affinity
 			injectPlacementMetadata(componentConfig, podSpec)
-			Expect(reflect.DeepEqual(nodePlacement.Affinity, podSpec.Affinity)).To(BeTrue())
+			Expect(equality.Semantic.DeepEqual(nodePlacement.Affinity, podSpec.Affinity)).To(BeTrue())
 
 		})
 
@@ -988,7 +988,7 @@ var _ = Describe("Apply Apps", func() {
 			nodePlacement.Affinity = affinity
 			podSpec.Affinity = &corev1.Affinity{}
 			injectPlacementMetadata(componentConfig, podSpec)
-			Expect(reflect.DeepEqual(nodePlacement.Affinity, podSpec.Affinity)).To(BeTrue())
+			Expect(equality.Semantic.DeepEqual(nodePlacement.Affinity, podSpec.Affinity)).To(BeTrue())
 
 		})
 
@@ -1002,7 +1002,7 @@ var _ = Describe("Apply Apps", func() {
 			Expect(len(podSpec.Affinity.PodAffinity.PreferredDuringSchedulingIgnoredDuringExecution)).To(Equal(2))
 			Expect(len(podSpec.Affinity.PodAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution)).To(Equal(2))
 			Expect(len(podSpec.Affinity.PodAntiAffinity.PreferredDuringSchedulingIgnoredDuringExecution)).To(Equal(2))
-			Expect(reflect.DeepEqual(nodePlacement.Affinity, podSpec.Affinity)).To(BeFalse())
+			Expect(equality.Semantic.DeepEqual(nodePlacement.Affinity, podSpec.Affinity)).To(BeFalse())
 		})
 
 		It("It should copy Required NodeAffinity", func() {
diff --git a/pkg/virt-operator/resource/apply/core.go b/pkg/virt-operator/resource/apply/core.go
index cdaa52a49..000ebc83b 100644
--- a/pkg/virt-operator/resource/apply/core.go
+++ b/pkg/virt-operator/resource/apply/core.go
@@ -5,7 +5,6 @@ import (
 	"crypto/tls"
 	"encoding/json"
 	"fmt"
-	"reflect"
 	"time"
 
 	"github.com/openshift/library-go/pkg/operator/resource/resourcemerge"
@@ -549,7 +548,7 @@ func shouldUpdateBundle(required, existing *corev1.ConfigMap, key string, queue
 
 	updateBundle := false
 	required.Data = map[string]string{components.CABundleKey: string(bundle)}
-	if !reflect.DeepEqual(required.Data, existing.Data) {
+	if !equality.Semantic.DeepEqual(required.Data, existing.Data) {
 		updateBundle = true
 	}
 
diff --git a/pkg/virt-operator/resource/apply/reconcile_test.go b/pkg/virt-operator/resource/apply/reconcile_test.go
index 28821a5d2..10be20866 100644
--- a/pkg/virt-operator/resource/apply/reconcile_test.go
+++ b/pkg/virt-operator/resource/apply/reconcile_test.go
@@ -22,7 +22,6 @@ package apply
 import (
 	"bufio"
 	"bytes"
-	"reflect"
 
 	installstrategy "kubevirt.io/kubevirt/pkg/virt-operator/resource/generate/install"
 	marshalutil "kubevirt.io/kubevirt/tools/util"
@@ -32,6 +31,7 @@ import (
 	. "github.com/onsi/gomega"
 	appsv1 "k8s.io/api/apps/v1"
 	corev1 "k8s.io/api/core/v1"
+	"k8s.io/apimachinery/pkg/api/equality"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 
 	v1 "kubevirt.io/api/core/v1"
@@ -353,7 +353,7 @@ var _ = Describe("Apply", func() {
 			orig := componentConfig.DeepCopy()
 			orig.NodePlacement.NodeSelector = map[string]string{kubernetesOSLabel: kubernetesOSLinux}
 			injectPlacementMetadata(componentConfig, nil)
-			Expect(reflect.DeepEqual(orig, componentConfig)).To(BeTrue())
+			Expect(equality.Semantic.DeepEqual(orig, componentConfig)).To(BeTrue())
 		})
 
 		It("should copy NodeSelectors when podSpec is empty", func() {
@@ -449,7 +449,7 @@ var _ = Describe("Apply", func() {
 		It("It should copy NodePlacement if podSpec Affinity is empty", func() {
 			nodePlacement.Affinity = affinity
 			injectPlacementMetadata(componentConfig, podSpec)
-			Expect(reflect.DeepEqual(nodePlacement.Affinity, podSpec.Affinity)).To(BeTrue())
+			Expect(equality.Semantic.DeepEqual(nodePlacement.Affinity, podSpec.Affinity)).To(BeTrue())
 
 		})
 
@@ -457,7 +457,7 @@ var _ = Describe("Apply", func() {
 			nodePlacement.Affinity = affinity
 			podSpec.Affinity = &corev1.Affinity{}
 			injectPlacementMetadata(componentConfig, podSpec)
-			Expect(reflect.DeepEqual(nodePlacement.Affinity, podSpec.Affinity)).To(BeTrue())
+			Expect(equality.Semantic.DeepEqual(nodePlacement.Affinity, podSpec.Affinity)).To(BeTrue())
 
 		})
 
@@ -471,7 +471,7 @@ var _ = Describe("Apply", func() {
 			Expect(len(podSpec.Affinity.PodAffinity.PreferredDuringSchedulingIgnoredDuringExecution)).To(Equal(2))
 			Expect(len(podSpec.Affinity.PodAntiAffinity.RequiredDuringSchedulingIgnoredDuringExecution)).To(Equal(2))
 			Expect(len(podSpec.Affinity.PodAntiAffinity.PreferredDuringSchedulingIgnoredDuringExecution)).To(Equal(2))
-			Expect(reflect.DeepEqual(nodePlacement.Affinity, podSpec.Affinity)).To(BeFalse())
+			Expect(equality.Semantic.DeepEqual(nodePlacement.Affinity, podSpec.Affinity)).To(BeFalse())
 		})
 
 		It("It should copy Required NodeAffinity", func() {
diff --git a/pkg/virt-operator/resource/generate/install/BUILD.bazel b/pkg/virt-operator/resource/generate/install/BUILD.bazel
index a285a4e1a..407bb102b 100644
--- a/pkg/virt-operator/resource/generate/install/BUILD.bazel
+++ b/pkg/virt-operator/resource/generate/install/BUILD.bazel
@@ -56,6 +56,7 @@ go_test(
         "//vendor/k8s.io/api/core/v1:go_default_library",
         "//vendor/k8s.io/api/rbac/v1:go_default_library",
         "//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1:go_default_library",
+        "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
         "//vendor/k8s.io/client-go/kubernetes/fake:go_default_library",
diff --git a/pkg/virt-operator/resource/generate/install/strategy_test.go b/pkg/virt-operator/resource/generate/install/strategy_test.go
index 36347b9e1..86e59b232 100644
--- a/pkg/virt-operator/resource/generate/install/strategy_test.go
+++ b/pkg/virt-operator/resource/generate/install/strategy_test.go
@@ -20,10 +20,10 @@
 package install
 
 import (
-	"reflect"
 	"strings"
 
 	"github.com/onsi/ginkgo/extensions/table"
+	"k8s.io/apimachinery/pkg/api/equality"
 	"k8s.io/apimachinery/pkg/runtime"
 	"k8s.io/client-go/kubernetes/fake"
 	"k8s.io/client-go/tools/cache"
@@ -131,7 +131,7 @@ var _ = Describe("Install Strategy", func() {
 						break
 					}
 				}
-				Expect(reflect.DeepEqual(original, converted)).To(BeTrue())
+				Expect(equality.Semantic.DeepEqual(original, converted)).To(BeTrue())
 			}
 
 			for _, original := range strategy.clusterRoles {
@@ -141,7 +141,7 @@ var _ = Describe("Install Strategy", func() {
 						break
 					}
 				}
-				Expect(reflect.DeepEqual(original, converted)).To(BeTrue())
+				Expect(equality.Semantic.DeepEqual(original, converted)).To(BeTrue())
 			}
 
 			for _, original := range strategy.clusterRoleBindings {
@@ -151,7 +151,7 @@ var _ = Describe("Install Strategy", func() {
 						break
 					}
 				}
-				Expect(reflect.DeepEqual(original, converted)).To(BeTrue())
+				Expect(equality.Semantic.DeepEqual(original, converted)).To(BeTrue())
 			}
 
 			for _, original := range strategy.roles {
@@ -161,7 +161,7 @@ var _ = Describe("Install Strategy", func() {
 						break
 					}
 				}
-				Expect(reflect.DeepEqual(original, converted)).To(BeTrue())
+				Expect(equality.Semantic.DeepEqual(original, converted)).To(BeTrue())
 			}
 
 			for _, original := range strategy.roleBindings {
@@ -171,7 +171,7 @@ var _ = Describe("Install Strategy", func() {
 						break
 					}
 				}
-				Expect(reflect.DeepEqual(original, converted)).To(BeTrue())
+				Expect(equality.Semantic.DeepEqual(original, converted)).To(BeTrue())
 			}
 
 			for _, original := range strategy.crds {
@@ -181,7 +181,7 @@ var _ = Describe("Install Strategy", func() {
 						break
 					}
 				}
-				Expect(reflect.DeepEqual(original, converted)).To(BeTrue())
+				Expect(equality.Semantic.DeepEqual(original, converted)).To(BeTrue())
 			}
 
 			for _, original := range strategy.services {
@@ -191,7 +191,7 @@ var _ = Describe("Install Strategy", func() {
 						break
 					}
 				}
-				Expect(reflect.DeepEqual(original, converted)).To(BeTrue())
+				Expect(equality.Semantic.DeepEqual(original, converted)).To(BeTrue())
 			}
 
 			for _, original := range strategy.daemonSets {
@@ -201,7 +201,7 @@ var _ = Describe("Install Strategy", func() {
 						break
 					}
 				}
-				Expect(reflect.DeepEqual(original, converted)).To(BeTrue())
+				Expect(equality.Semantic.DeepEqual(original, converted)).To(BeTrue())
 			}
 
 			for _, original := range strategy.deployments {
@@ -211,7 +211,7 @@ var _ = Describe("Install Strategy", func() {
 						break
 					}
 				}
-				Expect(reflect.DeepEqual(original, converted)).To(BeTrue())
+				Expect(equality.Semantic.DeepEqual(original, converted)).To(BeTrue())
 			}
 
 			for _, original := range strategy.configMaps {
@@ -225,7 +225,7 @@ var _ = Describe("Install Strategy", func() {
 				//dumpInstallStrategyToBytes function deletes it, and then
 				//original and converted configmaps are not the same
 				delete(original.Labels, v1.ManagedByLabel)
-				Expect(reflect.DeepEqual(original, converted)).To(BeTrue())
+				Expect(equality.Semantic.DeepEqual(original, converted)).To(BeTrue())
 			}
 		})
 	})
diff --git a/pkg/virt-operator/webhooks/BUILD.bazel b/pkg/virt-operator/webhooks/BUILD.bazel
index 8076d9b93..a6fa3cc40 100644
--- a/pkg/virt-operator/webhooks/BUILD.bazel
+++ b/pkg/virt-operator/webhooks/BUILD.bazel
@@ -17,6 +17,7 @@ go_library(
         "//vendor/k8s.io/api/admission/v1:go_default_library",
         "//vendor/k8s.io/api/apps/v1:go_default_library",
         "//vendor/k8s.io/api/core/v1:go_default_library",
+        "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
         "//vendor/k8s.io/utils/pointer:go_default_library",
     ],
diff --git a/pkg/virt-operator/webhooks/kubevirt-update-admitter.go b/pkg/virt-operator/webhooks/kubevirt-update-admitter.go
index d7bc37f8d..86268dd81 100644
--- a/pkg/virt-operator/webhooks/kubevirt-update-admitter.go
+++ b/pkg/virt-operator/webhooks/kubevirt-update-admitter.go
@@ -23,13 +23,13 @@ import (
 	"context"
 	"encoding/json"
 	"fmt"
-	"reflect"
 
 	appsv1 "k8s.io/api/apps/v1"
 	corev1 "k8s.io/api/core/v1"
 	"k8s.io/utils/pointer"
 
 	admissionv1 "k8s.io/api/admission/v1"
+	"k8s.io/apimachinery/pkg/api/equality"
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 
 	v1 "kubevirt.io/api/core/v1"
@@ -67,14 +67,14 @@ func (admitter *KubeVirtUpdateAdmitter) Admit(ar *admissionv1.AdmissionReview) *
 	results = append(results, validateCustomizeComponents(newKV.Spec.CustomizeComponents)...)
 	results = append(results, validateCertificates(newKV.Spec.CertificateRotationStrategy.SelfSigned)...)
 
-	if !reflect.DeepEqual(currKV.Spec.Infra, newKV.Spec.Infra) {
+	if !equality.Semantic.DeepEqual(currKV.Spec.Infra, newKV.Spec.Infra) {
 		if newKV.Spec.Infra != nil && newKV.Spec.Infra.NodePlacement != nil {
 			results = append(results,
 				validateInfraPlacement(newKV.Namespace, newKV.Spec.Infra.NodePlacement, admitter.Client)...)
 		}
 	}
 
-	if !reflect.DeepEqual(currKV.Spec.Workloads, newKV.Spec.Workloads) {
+	if !equality.Semantic.DeepEqual(currKV.Spec.Workloads, newKV.Spec.Workloads) {
 		if newKV.Spec.Workloads != nil && newKV.Spec.Workloads.NodePlacement != nil {
 			results = append(results,
 				validateWorkloadPlacement(newKV.Namespace, newKV.Spec.Workloads.NodePlacement, admitter.Client)...)
diff --git a/tests/BUILD.bazel b/tests/BUILD.bazel
index a93f77aa0..a7501e0f6 100644
--- a/tests/BUILD.bazel
+++ b/tests/BUILD.bazel
@@ -58,6 +58,7 @@ go_library(
         "//vendor/k8s.io/api/rbac/v1:go_default_library",
         "//vendor/k8s.io/api/storage/v1:go_default_library",
         "//vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset:go_default_library",
+        "//vendor/k8s.io/apimachinery/pkg/api/equality:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/api/meta:go_default_library",
         "//vendor/k8s.io/apimachinery/pkg/api/resource:go_default_library",
diff --git a/tests/utils.go b/tests/utils.go
index ddda500bb..ecf66c7c4 100644
--- a/tests/utils.go
+++ b/tests/utils.go
@@ -61,6 +61,7 @@ import (
 	rbacv1 "k8s.io/api/rbac/v1"
 	storagev1 "k8s.io/api/storage/v1"
 	extclient "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
+	"k8s.io/apimachinery/pkg/api/equality"
 	"k8s.io/apimachinery/pkg/api/errors"
 	apierrors "k8s.io/apimachinery/pkg/api/errors"
 	"k8s.io/apimachinery/pkg/api/meta"
@@ -4516,7 +4517,7 @@ func UpdateKubeVirtConfigValueAndWait(kvConfig v1.KubeVirtConfiguration) *v1.Kub
 	old, err := json.Marshal(kv)
 	Expect(err).ToNot(HaveOccurred())
 
-	if reflect.DeepEqual(kv.Spec.Configuration, kvConfig) {
+	if equality.Semantic.DeepEqual(kv.Spec.Configuration, kvConfig) {
 		return kv
 	}
 
-- 
2.35.1

