diff --git a/api/core/v1alpha2/events.go b/api/core/v1alpha2/events.go index 124da0509..d8c7e98cb 100644 --- a/api/core/v1alpha2/events.go +++ b/api/core/v1alpha2/events.go @@ -95,4 +95,25 @@ const ( // ReasonDataSourceDiskProvisioningFailed is event reason that DataSource disk provisioning is failed. ReasonDataSourceDiskProvisioningFailed = "DataSourceImportDiskProvisioningFailed" + + // ReasonVMSnapshottingStarted is event reason that VirtualMachine snapshotting is started. + ReasonVMSnapshottingStarted = "VirtualMachineSnapshottingStarted" + + // ReasonVMSnapshottingFrozen is event reason that the file system of VirtualMachine is frozen. + ReasonVMSnapshottingFrozen = "VirtualMachineSnapshottingFrozen" + + // ReasonVMSnapshottingInProgress is event reason that VirtualMachine snapshotting is in progress. + ReasonVMSnapshottingInProgress = "VirtualMachineSnapshottingInProgress" + + // ReasonVMSnapshottingThawed is event reason that the file system of VirtualMachine is thawed. + ReasonVMSnapshottingThawed = "VirtualMachineSnapshottingThawed" + + // ReasonVMSnapshottingPending is event reason that VirtualMachine is not ready for snapshotting. + ReasonVMSnapshottingPending = "VirtualMachineSnapshottingPending" + + // ReasonVMSnapshottingCompleted is event reason that VirtualMachine snapshotting is completed. + ReasonVMSnapshottingCompleted = "VirtualMachineSnapshottingCompleted" + + // ReasonVMSnapshottingFailed is event reason that VirtualMachine snapshotting is failed. + ReasonVMSnapshottingFailed = "VirtualMachineSnapshottingFailed" ) diff --git a/images/virtualization-artifact/pkg/controller/vmsnapshot/internal/life_cycle.go b/images/virtualization-artifact/pkg/controller/vmsnapshot/internal/life_cycle.go index 853d0fb6e..88ae8a3fa 100644 --- a/images/virtualization-artifact/pkg/controller/vmsnapshot/internal/life_cycle.go +++ b/images/virtualization-artifact/pkg/controller/vmsnapshot/internal/life_cycle.go @@ -29,6 +29,7 @@ import ( "github.com/deckhouse/virtualization-controller/pkg/controller/conditions" "github.com/deckhouse/virtualization-controller/pkg/controller/service" + "github.com/deckhouse/virtualization-controller/pkg/eventrecord" "github.com/deckhouse/virtualization-controller/pkg/logger" virtv2 "github.com/deckhouse/virtualization/api/core/v1alpha2" "github.com/deckhouse/virtualization/api/core/v1alpha2/vdcondition" @@ -38,12 +39,14 @@ import ( ) type LifeCycleHandler struct { + recorder eventrecord.EventRecorderLogger snapshotter Snapshotter storer Storer } -func NewLifeCycleHandler(snapshotter Snapshotter, storer Storer) *LifeCycleHandler { +func NewLifeCycleHandler(recorder eventrecord.EventRecorderLogger, snapshotter Snapshotter, storer Storer) *LifeCycleHandler { return &LifeCycleHandler{ + recorder: recorder, snapshotter: snapshotter, storer: storer, } @@ -61,7 +64,7 @@ func (h LifeCycleHandler) Handle(ctx context.Context, vmSnapshot *virtv2.Virtual vm, err := h.snapshotter.GetVirtualMachine(ctx, vmSnapshot.Spec.VirtualMachineName, vmSnapshot.Namespace) if err != nil { - setPhaseConditionToFailed(cb, &vmSnapshot.Status.Phase, err) + h.setPhaseConditionToFailed(cb, vmSnapshot, err) return reconcile.Result{}, err } @@ -74,7 +77,7 @@ func (h LifeCycleHandler) Handle(ctx context.Context, vmSnapshot *virtv2.Virtual _, err = h.unfreezeVirtualMachineIfCan(ctx, vmSnapshot, vm) if err != nil { - setPhaseConditionToFailed(cb, &vmSnapshot.Status.Phase, err) + h.setPhaseConditionToFailed(cb, vmSnapshot, err) return reconcile.Result{}, err } @@ -97,7 +100,7 @@ func (h LifeCycleHandler) Handle(ctx context.Context, vmSnapshot *virtv2.Virtual for _, vdSnapshotName := range vmSnapshot.Status.VirtualDiskSnapshotNames { vdSnapshot, err := h.snapshotter.GetVirtualDiskSnapshot(ctx, vdSnapshotName, vmSnapshot.Namespace) if err != nil { - setPhaseConditionToFailed(cb, &vmSnapshot.Status.Phase, err) + h.setPhaseConditionToFailed(cb, vmSnapshot, err) return reconcile.Result{}, err } @@ -113,9 +116,23 @@ func (h LifeCycleHandler) Handle(ctx context.Context, vmSnapshot *virtv2.Virtual vmSnapshot.Status.Phase = virtv2.VirtualMachineSnapshotPhaseFailed cb.Status(metav1.ConditionFalse).Reason(vmscondition.VirtualDiskSnapshotLost) if len(lostVDSnapshots) == 1 { - cb.Message(fmt.Sprintf("The underlieng virtual disk snapshot (%s) is lost.", lostVDSnapshots[0])) + msg := fmt.Sprintf("The underlieng virtual disk snapshot (%s) is lost.", lostVDSnapshots[0]) + h.recorder.Event( + vmSnapshot, + corev1.EventTypeWarning, + virtv2.ReasonVMSnapshottingFailed, + msg, + ) + cb.Message(msg) } else { - cb.Message(fmt.Sprintf("The underlieng virtual disk snapshots (%s) are lost.", strings.Join(lostVDSnapshots, ", "))) + msg := fmt.Sprintf("The underlieng virtual disk snapshots (%s) are lost.", strings.Join(lostVDSnapshots, ", ")) + h.recorder.Event( + vmSnapshot, + corev1.EventTypeWarning, + virtv2.ReasonVMSnapshottingFailed, + msg, + ) + cb.Message(msg) } return reconcile.Result{}, nil } @@ -131,10 +148,17 @@ func (h LifeCycleHandler) Handle(ctx context.Context, vmSnapshot *virtv2.Virtual virtualMachineReadyCondition, _ := conditions.GetCondition(vmscondition.VirtualMachineReadyType, vmSnapshot.Status.Conditions) if vm == nil || virtualMachineReadyCondition.Status != metav1.ConditionTrue { vmSnapshot.Status.Phase = virtv2.VirtualMachineSnapshotPhasePending + msg := fmt.Sprintf("Waiting for the virtual machine %q to be ready for snapshotting.", vmSnapshot.Spec.VirtualMachineName) + h.recorder.Event( + vmSnapshot, + corev1.EventTypeNormal, + virtv2.ReasonVMSnapshottingPending, + msg, + ) cb. Status(metav1.ConditionFalse). Reason(vmscondition.WaitingForTheVirtualMachine). - Message(fmt.Sprintf("Waiting for the virtual machine %q to be ready for snapshotting.", vmSnapshot.Spec.VirtualMachineName)) + Message(msg) return reconcile.Result{}, nil } @@ -144,26 +168,39 @@ func (h LifeCycleHandler) Handle(ctx context.Context, vmSnapshot *virtv2.Virtual case err == nil: case errors.Is(err, ErrBlockDevicesNotReady), errors.Is(err, ErrVirtualDiskNotReady), errors.Is(err, ErrVirtualDiskResizing): vmSnapshot.Status.Phase = virtv2.VirtualMachineSnapshotPhasePending + msg := service.CapitalizeFirstLetter(err.Error() + ".") + h.recorder.Event( + vmSnapshot, + corev1.EventTypeNormal, + virtv2.ReasonVMSnapshottingPending, + msg, + ) cb. Status(metav1.ConditionFalse). Reason(vmscondition.BlockDevicesNotReady). - Message(service.CapitalizeFirstLetter(err.Error() + ".")) + Message(msg) return reconcile.Result{}, nil default: - setPhaseConditionToFailed(cb, &vmSnapshot.Status.Phase, err) + h.setPhaseConditionToFailed(cb, vmSnapshot, err) return reconcile.Result{}, err } // 2. Ensure there are no RestartAwaitingChanges. if len(vm.Status.RestartAwaitingChanges) > 0 { vmSnapshot.Status.Phase = virtv2.VirtualMachineSnapshotPhasePending + msg := fmt.Sprintf( + "Waiting for the restart and approval of changes to virtual machine %q before taking the snapshot.", + vm.Name, + ) + h.recorder.Event( + vmSnapshot, + corev1.EventTypeNormal, + virtv2.ReasonVMSnapshottingPending, + msg, + ) cb. Status(metav1.ConditionFalse). - Reason(vmscondition.RestartAwaitingChanges).Message( - fmt.Sprintf( - "Waiting for the restart and approval of changes to virtual machine %q before taking the snapshot.", - vm.Name, - )) + Reason(vmscondition.RestartAwaitingChanges).Message(msg) return reconcile.Result{}, nil } @@ -172,19 +209,32 @@ func (h LifeCycleHandler) Handle(ctx context.Context, vmSnapshot *virtv2.Virtual isAwaitingConsistency := needToFreeze && !h.snapshotter.CanFreeze(vm) && vmSnapshot.Spec.RequiredConsistency if isAwaitingConsistency { vmSnapshot.Status.Phase = virtv2.VirtualMachineSnapshotPhasePending + msg := fmt.Sprintf( + "The snapshotting of virtual machine %q might result in an inconsistent snapshot: "+ + "waiting for the virtual machine to be %s", + vm.Name, virtv2.MachineStopped, + ) + h.recorder.Event( + vmSnapshot, + corev1.EventTypeNormal, + virtv2.ReasonVMSnapshottingPending, + msg, + ) cb. Status(metav1.ConditionFalse). Reason(vmscondition.PotentiallyInconsistent). - Message(fmt.Sprintf( - "The snapshotting of virtual machine %q might result in an inconsistent snapshot: "+ - "waiting for the virtual machine to be %s", - vm.Name, virtv2.MachineStopped, - )) + Message(msg) return reconcile.Result{}, nil } if vmSnapshot.Status.Phase == virtv2.VirtualMachineSnapshotPhasePending { vmSnapshot.Status.Phase = virtv2.VirtualMachineSnapshotPhaseInProgress + h.recorder.Event( + vmSnapshot, + corev1.EventTypeNormal, + virtv2.ReasonVMSnapshottingStarted, + "Virtual machine snapshotting process is started.", + ) cb. Status(metav1.ConditionFalse). Reason(vmscondition.FileSystemFreezing). @@ -196,9 +246,9 @@ func (h LifeCycleHandler) Handle(ctx context.Context, vmSnapshot *virtv2.Virtual // 3. Ensure the virtual machine is consistent for snapshotting. if needToFreeze { - hasFrozen, err = h.freezeVirtualMachine(ctx, vm) + hasFrozen, err = h.freezeVirtualMachine(ctx, vm, vmSnapshot) if err != nil { - setPhaseConditionToFailed(cb, &vmSnapshot.Status.Phase, err) + h.setPhaseConditionToFailed(cb, vmSnapshot, err) return reconcile.Result{}, err } } @@ -215,7 +265,7 @@ func (h LifeCycleHandler) Handle(ctx context.Context, vmSnapshot *virtv2.Virtual // 4. Create secret. err = h.ensureSecret(ctx, vm, vmSnapshot) if err != nil { - setPhaseConditionToFailed(cb, &vmSnapshot.Status.Phase, err) + h.setPhaseConditionToFailed(cb, vmSnapshot, err) return reconcile.Result{}, err } @@ -229,6 +279,12 @@ func (h LifeCycleHandler) Handle(ctx context.Context, vmSnapshot *virtv2.Virtual case errors.Is(err, ErrVolumeSnapshotClassNotFound), errors.Is(err, ErrCannotTakeSnapshot): vmSnapshot.Status.Phase = virtv2.VirtualMachineSnapshotPhaseFailed msg := service.CapitalizeFirstLetter(err.Error()) + h.recorder.Event( + vmSnapshot, + corev1.EventTypeWarning, + virtv2.ReasonVMSnapshottingFailed, + msg, + ) if !strings.HasSuffix(msg, ".") { msg += "." } @@ -238,26 +294,40 @@ func (h LifeCycleHandler) Handle(ctx context.Context, vmSnapshot *virtv2.Virtual Message(msg) return reconcile.Result{}, nil default: - setPhaseConditionToFailed(cb, &vmSnapshot.Status.Phase, err) + h.setPhaseConditionToFailed(cb, vmSnapshot, err) return reconcile.Result{}, err } // 7. Wait for VirtualDiskSnapshots to be Ready. readyCount := h.countReadyVirtualDiskSnapshots(vdSnapshots) + msg := fmt.Sprintf( + "Waiting for the virtual disk snapshots to be taken for "+ + "the block devices of the virtual machine %q (%d/%d).", + vm.Name, readyCount, len(vdSnapshots), + ) if readyCount != len(vdSnapshots) { log.Debug("Waiting for the virtual disk snapshots to be taken for the block devices of the virtual machine") vmSnapshot.Status.Phase = virtv2.VirtualMachineSnapshotPhaseInProgress + h.recorder.Event( + vmSnapshot, + corev1.EventTypeNormal, + virtv2.ReasonVMSnapshottingInProgress, + msg, + ) cb. Status(metav1.ConditionFalse). Reason(vmscondition.Snapshotting). - Message(fmt.Sprintf( - "Waiting for the virtual disk snapshots to be taken for "+ - "the block devices of the virtual machine %q (%d/%d).", - vm.Name, readyCount, len(vdSnapshots), - )) + Message(msg) return reconcile.Result{}, nil + } else { + h.recorder.Event( + vmSnapshot, + corev1.EventTypeNormal, + virtv2.ReasonVMSnapshottingInProgress, + msg, + ) } vmSnapshot.Status.Consistent = ptr.To(true) @@ -268,7 +338,7 @@ func (h LifeCycleHandler) Handle(ctx context.Context, vmSnapshot *virtv2.Virtual // 8. Unfreeze VirtualMachine if can. unfrozen, err := h.unfreezeVirtualMachineIfCan(ctx, vmSnapshot, vm) if err != nil { - setPhaseConditionToFailed(cb, &vmSnapshot.Status.Phase, err) + h.setPhaseConditionToFailed(cb, vmSnapshot, err) return reconcile.Result{}, err } @@ -276,6 +346,12 @@ func (h LifeCycleHandler) Handle(ctx context.Context, vmSnapshot *virtv2.Virtual log.Debug("The virtual disk snapshots are taken: the virtual machine snapshot is Ready now", "unfrozen", unfrozen) vmSnapshot.Status.Phase = virtv2.VirtualMachineSnapshotPhaseReady + h.recorder.Event( + vmSnapshot, + corev1.EventTypeNormal, + virtv2.ReasonVMSnapshottingCompleted, + "Virtual machine snapshotting process is completed.", + ) cb. Status(metav1.ConditionTrue). Reason(vmscondition.VirtualMachineReady). @@ -284,8 +360,14 @@ func (h LifeCycleHandler) Handle(ctx context.Context, vmSnapshot *virtv2.Virtual return reconcile.Result{}, nil } -func setPhaseConditionToFailed(cb *conditions.ConditionBuilder, phase *virtv2.VirtualMachineSnapshotPhase, err error) { - *phase = virtv2.VirtualMachineSnapshotPhaseFailed +func (h LifeCycleHandler) setPhaseConditionToFailed(cb *conditions.ConditionBuilder, vmSnapshot *virtv2.VirtualMachineSnapshot, err error) { + vmSnapshot.Status.Phase = virtv2.VirtualMachineSnapshotPhaseFailed + h.recorder.Event( + vmSnapshot, + corev1.EventTypeWarning, + virtv2.ReasonVMSnapshottingFailed, + err.Error()+".", + ) cb. Status(metav1.ConditionFalse). Reason(vmscondition.VirtualMachineSnapshotFailed). @@ -423,7 +505,7 @@ func (h LifeCycleHandler) needToFreeze(vm *virtv2.VirtualMachine) bool { return true } -func (h LifeCycleHandler) freezeVirtualMachine(ctx context.Context, vm *virtv2.VirtualMachine) (bool, error) { +func (h LifeCycleHandler) freezeVirtualMachine(ctx context.Context, vm *virtv2.VirtualMachine, vmSnapshot *virtv2.VirtualMachineSnapshot) (bool, error) { if vm.Status.Phase != virtv2.MachineRunning { return false, errors.New("cannot freeze not Running virtual machine") } @@ -433,6 +515,13 @@ func (h LifeCycleHandler) freezeVirtualMachine(ctx context.Context, vm *virtv2.V return false, fmt.Errorf("freeze the virtual machine %q: %w", vm.Name, err) } + h.recorder.Event( + vmSnapshot, + corev1.EventTypeNormal, + virtv2.ReasonVMSnapshottingFrozen, + fmt.Sprintf("The file system of the virtual machine %q is frozen.", vm.Name), + ) + return true, nil } @@ -455,6 +544,13 @@ func (h LifeCycleHandler) unfreezeVirtualMachineIfCan(ctx context.Context, vmSna return false, fmt.Errorf("unfreeze the virtual machine %q: %w", vm.Name, err) } + h.recorder.Event( + vmSnapshot, + corev1.EventTypeNormal, + virtv2.ReasonVMSnapshottingThawed, + fmt.Sprintf("The file system of the virtual machine %q is thawed.", vm.Name), + ) + return true, nil } diff --git a/images/virtualization-artifact/pkg/controller/vmsnapshot/internal/life_cycle_test.go b/images/virtualization-artifact/pkg/controller/vmsnapshot/internal/life_cycle_test.go index 1d8acebca..dbbee1f4d 100644 --- a/images/virtualization-artifact/pkg/controller/vmsnapshot/internal/life_cycle_test.go +++ b/images/virtualization-artifact/pkg/controller/vmsnapshot/internal/life_cycle_test.go @@ -25,8 +25,10 @@ import ( apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/utils/ptr" + "sigs.k8s.io/controller-runtime/pkg/client" "github.com/deckhouse/virtualization-controller/pkg/controller/conditions" + "github.com/deckhouse/virtualization-controller/pkg/eventrecord" virtv2 "github.com/deckhouse/virtualization/api/core/v1alpha2" "github.com/deckhouse/virtualization/api/core/v1alpha2/vdcondition" "github.com/deckhouse/virtualization/api/core/v1alpha2/vmcondition" @@ -34,6 +36,7 @@ import ( ) var _ = Describe("LifeCycle handler", func() { + var recorder eventrecord.EventRecorderLogger var snapshotter *SnapshotterMock var storer *StorerMock var vd *virtv2.VirtualDisk @@ -143,6 +146,10 @@ var _ = Describe("LifeCycle handler", func() { return vdSnapshot, nil }, } + + recorder = &eventrecord.EventRecorderLoggerMock{ + EventFunc: func(_ client.Object, _, _, _ string) {}, + } }) Context("The block devices of the virtual machine are not in the consistent state", func() { @@ -154,7 +161,7 @@ var _ = Describe("LifeCycle handler", func() { conditions.SetCondition(cb, &vm.Status.Conditions) return vm, nil } - h := NewLifeCycleHandler(snapshotter, storer) + h := NewLifeCycleHandler(recorder, snapshotter, storer) _, err := h.Handle(testContext(), vmSnapshot) Expect(err).To(BeNil()) @@ -170,7 +177,7 @@ var _ = Describe("LifeCycle handler", func() { vd.Status.Phase = virtv2.DiskPending return vd, nil } - h := NewLifeCycleHandler(snapshotter, storer) + h := NewLifeCycleHandler(recorder, snapshotter, storer) _, err := h.Handle(testContext(), vmSnapshot) Expect(err).To(BeNil()) @@ -189,7 +196,7 @@ var _ = Describe("LifeCycle handler", func() { conditions.SetCondition(cb, &vd.Status.Conditions) return vd, nil } - h := NewLifeCycleHandler(snapshotter, storer) + h := NewLifeCycleHandler(recorder, snapshotter, storer) _, err := h.Handle(testContext(), vmSnapshot) Expect(err).To(BeNil()) @@ -209,7 +216,7 @@ var _ = Describe("LifeCycle handler", func() { conditions.SetCondition(cb, &vd.Status.Conditions) return vd, nil } - h := NewLifeCycleHandler(snapshotter, storer) + h := NewLifeCycleHandler(recorder, snapshotter, storer) _, err := h.Handle(testContext(), vmSnapshot) Expect(err).To(BeNil()) @@ -228,7 +235,7 @@ var _ = Describe("LifeCycle handler", func() { return vm, nil } - h := NewLifeCycleHandler(snapshotter, storer) + h := NewLifeCycleHandler(recorder, snapshotter, storer) _, err := h.Handle(testContext(), vmSnapshot) Expect(err).To(BeNil()) @@ -247,7 +254,7 @@ var _ = Describe("LifeCycle handler", func() { return false } - h := NewLifeCycleHandler(snapshotter, storer) + h := NewLifeCycleHandler(recorder, snapshotter, storer) _, err := h.Handle(testContext(), vmSnapshot) Expect(err).To(BeNil()) @@ -269,7 +276,7 @@ var _ = Describe("LifeCycle handler", func() { return nil } - h := NewLifeCycleHandler(snapshotter, storer) + h := NewLifeCycleHandler(recorder, snapshotter, storer) _, err := h.Handle(testContext(), vmSnapshot) Expect(err).To(BeNil()) @@ -287,7 +294,7 @@ var _ = Describe("LifeCycle handler", func() { }) It("The snapshot of virtual machine is Ready", func() { - h := NewLifeCycleHandler(snapshotter, storer) + h := NewLifeCycleHandler(recorder, snapshotter, storer) _, err := h.Handle(testContext(), vmSnapshot) Expect(err).To(BeNil()) @@ -301,7 +308,7 @@ var _ = Describe("LifeCycle handler", func() { }) It("The snapshot of running virtual machine is consistent", func() { - h := NewLifeCycleHandler(snapshotter, storer) + h := NewLifeCycleHandler(recorder, snapshotter, storer) _, err := h.Handle(testContext(), vmSnapshot) Expect(err).To(BeNil()) @@ -313,7 +320,7 @@ var _ = Describe("LifeCycle handler", func() { vm.Status.Phase = virtv2.MachineStopped return vm, nil } - h := NewLifeCycleHandler(snapshotter, storer) + h := NewLifeCycleHandler(recorder, snapshotter, storer) _, err := h.Handle(testContext(), vmSnapshot) Expect(err).To(BeNil()) @@ -326,7 +333,7 @@ var _ = Describe("LifeCycle handler", func() { vdSnapshot.Status.Consistent = nil return vdSnapshot, nil } - h := NewLifeCycleHandler(snapshotter, storer) + h := NewLifeCycleHandler(recorder, snapshotter, storer) _, err := h.Handle(testContext(), vmSnapshot) Expect(err).To(BeNil()) diff --git a/images/virtualization-artifact/pkg/controller/vmsnapshot/vmsnapshot_controller.go b/images/virtualization-artifact/pkg/controller/vmsnapshot/vmsnapshot_controller.go index 052ef353b..9ddaaea50 100644 --- a/images/virtualization-artifact/pkg/controller/vmsnapshot/vmsnapshot_controller.go +++ b/images/virtualization-artifact/pkg/controller/vmsnapshot/vmsnapshot_controller.go @@ -29,6 +29,7 @@ import ( "github.com/deckhouse/virtualization-controller/pkg/controller/service" "github.com/deckhouse/virtualization-controller/pkg/controller/service/restorer" "github.com/deckhouse/virtualization-controller/pkg/controller/vmsnapshot/internal" + "github.com/deckhouse/virtualization-controller/pkg/eventrecord" "github.com/deckhouse/virtualization-controller/pkg/logger" "github.com/deckhouse/virtualization/api/client/kubeclient" virtv2 "github.com/deckhouse/virtualization/api/core/v1alpha2" @@ -43,12 +44,13 @@ func NewController( virtClient kubeclient.Client, ) error { protection := service.NewProtectionService(mgr.GetClient(), virtv2.FinalizerVMSnapshotProtection) + recorder := eventrecord.NewEventRecorderLogger(mgr, ControllerName) snapshotter := service.NewSnapshotService(virtClient, mgr.GetClient(), protection) reconciler := NewReconciler( mgr.GetClient(), internal.NewVirtualMachineReadyHandler(snapshotter), - internal.NewLifeCycleHandler(snapshotter, restorer.NewSecretRestorer(mgr.GetClient())), + internal.NewLifeCycleHandler(recorder, snapshotter, restorer.NewSecretRestorer(mgr.GetClient())), ) vmSnapshotController, err := controller.New(ControllerName, mgr, controller.Options{ diff --git a/images/virtualization-artifact/pkg/controller/vmsnapshot/vmsnapshot_reconciler.go b/images/virtualization-artifact/pkg/controller/vmsnapshot/vmsnapshot_reconciler.go index 647091807..6a0f49078 100644 --- a/images/virtualization-artifact/pkg/controller/vmsnapshot/vmsnapshot_reconciler.go +++ b/images/virtualization-artifact/pkg/controller/vmsnapshot/vmsnapshot_reconciler.go @@ -105,7 +105,7 @@ func (r *Reconciler) SetupController(_ context.Context, mgr manager.Manager, ctr } { err := w.Watch(mgr, ctr) if err != nil { - return fmt.Errorf("faield to run watcher %s: %w", reflect.TypeOf(w).Elem().Name(), err) + return fmt.Errorf("failed to run watcher %s: %w", reflect.TypeOf(w).Elem().Name(), err) } }