From 183b99a5dc00d9078e54b61d4cbac62ba248e310 Mon Sep 17 00:00:00 2001 From: Arunesh Pandey Date: Sun, 15 Dec 2024 20:00:07 -0800 Subject: [PATCH] Introduce a new annotation to identify failed over VMs We need a new annotation for failed over VMs so we can skip some webhook checks. This is different from imported, or registered VMs since we will need to relax additional webhook checks such as allowing for network manipulation. Remove the test failover annotation since that is no longer needed. --- api/v1alpha3/virtualmachine_types.go | 18 ++-- pkg/backup/api/backup_types.go | 16 ---- pkg/util/annotations/helpers.go | 8 +- pkg/util/annotations/helpers_test.go | 25 +++++- .../validation/virtualmachine_validator.go | 25 +++--- .../virtualmachine_validator_unit_test.go | 83 +++++++++++-------- 6 files changed, 103 insertions(+), 72 deletions(-) diff --git a/api/v1alpha3/virtualmachine_types.go b/api/v1alpha3/virtualmachine_types.go index e6cd59ed9..c4aaa72d6 100644 --- a/api/v1alpha3/virtualmachine_types.go +++ b/api/v1alpha3/virtualmachine_types.go @@ -198,17 +198,25 @@ const ( // VMware vCenter (VC) that is managing this virtual machine. ManagerID = GroupName + "/manager-id" - // RegisteredVMAnnotation on a VirtualMachine represents that a virtual machine has - // been registered using the RegisterVM API after a restore, or a fail-over operation by - // a vendor. The presence of this annotation is used to bypass some validation checks - // that are otherwise applicable to all VirtualMachine create/update requests. - RegisteredVMAnnotation = GroupName + "/registered-vm" + // RestoredVMAnnotation on a VirtualMachine represents that a virtual + // machine has been restored using the RegisterVM API, typically by a + // VADP based data protection vendor. The presence of this annotation is + // used to bypass some validation checks that are otherwise + // applicable to all VirtualMachine create/update requests. + RestoredVMAnnotation = GroupName + "/restored-vm" // ImportedVMAnnotation on a VirtualMachine represents that a traditional virtual // machine has been imported into Supervisor using the ImportVM API. The presence of this // annotation is used to bypass some validation checks that are otherwise applicable // to all VirtualMachine create/update requests. ImportedVMAnnotation = GroupName + "/imported-vm" + + // FailedOverVMAnnotation on a VirtualMachine resource represents that a virtual + // machine has been failed over from one site to the other, typically as part of a + // disaster recovery workflow. The presence of this annotation is used to bypass + // some validation checks that are otherwise applicable to all VirtualMachine + // create/update requests. + FailedOverVMAnnotation = GroupName + "/failed-over-vm" ) const ( diff --git a/pkg/backup/api/backup_types.go b/pkg/backup/api/backup_types.go index 8e87dbf9f..19fe25672 100644 --- a/pkg/backup/api/backup_types.go +++ b/pkg/backup/api/backup_types.go @@ -108,20 +108,4 @@ const ( // specifying this key, backup/restore and/or disaster recovery solutions are // responsible to register the VM with Supervisor. DisableAutoRegistrationExtraConfigKey = "vmservice.virtualmachine.disableAutomaticRegistration" - - // TestFailoverLabelKey label signifies that a VirtualMachine is going through - // a test recovery plan scenario. Typically, this involves failing over a VM - // to a dedicated temporary network so as to not exhaust, and cause IP address - // collisions with the production network. This label on a VirtualMachine - // custom resource allows vendors to change the VM's network interface to - // connect to the test network after the VM is registered post a failover. - // - // VM operator does not support mutable networks, so this label allows only - // select vendors (e.g., SRM) to support recovery plan test workflows while we - // build support for true network mutability. - // - // The value of this label does not matter. Its presence is considered a - // sufficient evidence to indicate that the virtual machine is going through - // test fail-over. - TestFailoverLabelKey = "virtualmachine." + GroupName + "/test-failover" ) diff --git a/pkg/util/annotations/helpers.go b/pkg/util/annotations/helpers.go index 4079170dd..a03360850 100644 --- a/pkg/util/annotations/helpers.go +++ b/pkg/util/annotations/helpers.go @@ -9,8 +9,12 @@ import ( vmopv1 "github.com/vmware-tanzu/vm-operator/api/v1alpha3" ) -func HasRegisterVM(o metav1.Object) bool { - return hasAnnotation(o, vmopv1.RegisteredVMAnnotation) +func HasRestoredVM(o metav1.Object) bool { + return hasAnnotation(o, vmopv1.RestoredVMAnnotation) +} + +func HasFailOverVM(o metav1.Object) bool { + return hasAnnotation(o, vmopv1.FailedOverVMAnnotation) } func HasImportVM(o metav1.Object) bool { diff --git a/pkg/util/annotations/helpers_test.go b/pkg/util/annotations/helpers_test.go index 7ffe2ba8d..6c6565ddd 100644 --- a/pkg/util/annotations/helpers_test.go +++ b/pkg/util/annotations/helpers_test.go @@ -48,20 +48,20 @@ var _ = DescribeTable( ) var _ = DescribeTable( - "HasRegisterVM", + "HasRestoredVM", func(in map[string]string, out bool) { vm := &vmopv1.VirtualMachine{ ObjectMeta: metav1.ObjectMeta{ Annotations: in, }, } - actual := annotations.HasRegisterVM(vm) + actual := annotations.HasRestoredVM(vm) Expect(actual).To(Equal(out)) }, Entry("nil", nil, false), Entry("not present", map[string]string{"foo": "bar"}, false), - Entry("present but empty ", map[string]string{vmopv1.RegisteredVMAnnotation: ""}, true), - Entry("present and not empty ", map[string]string{vmopv1.RegisteredVMAnnotation: "true"}, true), + Entry("present but empty ", map[string]string{vmopv1.RestoredVMAnnotation: ""}, true), + Entry("present and not empty ", map[string]string{vmopv1.RestoredVMAnnotation: "true"}, true), ) var _ = DescribeTable( @@ -80,3 +80,20 @@ var _ = DescribeTable( Entry("present but empty ", map[string]string{vmopv1.ImportedVMAnnotation: ""}, true), Entry("present and not empty ", map[string]string{vmopv1.ImportedVMAnnotation: "true"}, true), ) + +var _ = DescribeTable( + "HasFailOverVM", + func(in map[string]string, out bool) { + vm := &vmopv1.VirtualMachine{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: in, + }, + } + actual := annotations.HasFailOverVM(vm) + Expect(actual).To(Equal(out)) + }, + Entry("nil", nil, false), + Entry("not present", map[string]string{"foo": "bar"}, false), + Entry("present but empty ", map[string]string{vmopv1.FailedOverVMAnnotation: ""}, true), + Entry("present and not empty ", map[string]string{vmopv1.FailedOverVMAnnotation: "true"}, true), +) diff --git a/webhooks/virtualmachine/validation/virtualmachine_validator.go b/webhooks/virtualmachine/validation/virtualmachine_validator.go index 7a6543d56..7610a75dd 100644 --- a/webhooks/virtualmachine/validation/virtualmachine_validator.go +++ b/webhooks/virtualmachine/validation/virtualmachine_validator.go @@ -33,7 +33,6 @@ import ( vmopv1 "github.com/vmware-tanzu/vm-operator/api/v1alpha3" "github.com/vmware-tanzu/vm-operator/api/v1alpha3/sysprep" - backupapi "github.com/vmware-tanzu/vm-operator/pkg/backup/api" "github.com/vmware-tanzu/vm-operator/pkg/builder" pkgcfg "github.com/vmware-tanzu/vm-operator/pkg/config" "github.com/vmware-tanzu/vm-operator/pkg/constants" @@ -154,13 +153,13 @@ func (v validator) ValidateDelete(*pkgctx.WebhookRequestContext) admission.Respo return admission.Allowed("") } -// Updates to VM's image are only allowed if it is a Registered VM (used for failover -// in disaster recovery). +// Updates to VM's image are only allowed if it is a failed over VM. func (v validator) validateImageOnUpdate(ctx *pkgctx.WebhookRequestContext, vm, oldVM *vmopv1.VirtualMachine) field.ErrorList { var allErrs field.ErrorList + // Allow resetting of image if this is a failover operation. if vmopv1util.IsImagelessVM(*vm) && pkgcfg.FromContext(ctx).Features.VMIncrementalRestore { - if annotations.HasRegisterVM(vm) { + if annotations.HasFailOverVM(vm) { if !vmopv1util.ImageRefsEqual(vm.Spec.Image, oldVM.Spec.Image) { if !ctx.IsPrivilegedAccount { allErrs = append(allErrs, field.Forbidden(field.NewPath("spec", "image"), restrictedToPrivUsers)) @@ -402,8 +401,8 @@ func (v validator) validateImageOnCreate(ctx *pkgctx.WebhookRequestContext, vm * (pkgcfg.FromContext(ctx).Features.VMImportNewNet || pkgcfg.FromContext(ctx).Features.VMIncrementalRestore): // TODO: Simplify this once mobility operator starts creating VMs with correct annotation. - // Skip validations on images if it is a VM created using ImportVM, or RegisterVM. - if annotations.HasImportVM(vm) || annotations.HasRegisterVM(vm) { + // Skip validations on images if it is a VM that is imported, registered, or failed over. + if annotations.HasImportVM(vm) || annotations.HasRestoredVM(vm) || annotations.HasFailOverVM(vm) { // Restrict creating imageless VM resources to privileged users. if !ctx.IsPrivilegedAccount { allErrs = append(allErrs, field.Forbidden(f, restrictedToPrivUsers)) @@ -1237,9 +1236,9 @@ func (v validator) validateImmutableNetwork(ctx *pkgctx.WebhookRequestContext, v return append(allErrs, field.Forbidden(p.Child("interfaces"), "network interfaces cannot be added or removed")) } - // Skip comparing interfaces if this is a test fail-over to allow vendors to - // connect network each interface to test network. - if _, ok := vm.Labels[backupapi.TestFailoverLabelKey]; ok { + // Skip comparing interfaces if this is a fail-over to allow vendors to + // connect network each interface to the test, or the production network. + if _, ok := vm.Annotations[vmopv1.FailedOverVMAnnotation]; ok { return allErrs } @@ -1337,8 +1336,12 @@ func (v validator) validateAnnotation(ctx *pkgctx.WebhookRequestContext, vm, old allErrs = append(allErrs, field.Forbidden(annotationPath.Key(vmopv1.FirstBootDoneAnnotation), modifyAnnotationNotAllowedForNonAdmin)) } - if vm.Annotations[vmopv1.RegisteredVMAnnotation] != oldVM.Annotations[vmopv1.RegisteredVMAnnotation] { - allErrs = append(allErrs, field.Forbidden(annotationPath.Key(vmopv1.RegisteredVMAnnotation), modifyAnnotationNotAllowedForNonAdmin)) + if vm.Annotations[vmopv1.RestoredVMAnnotation] != oldVM.Annotations[vmopv1.RestoredVMAnnotation] { + allErrs = append(allErrs, field.Forbidden(annotationPath.Key(vmopv1.RestoredVMAnnotation), modifyAnnotationNotAllowedForNonAdmin)) + } + + if vm.Annotations[vmopv1.FailedOverVMAnnotation] != oldVM.Annotations[vmopv1.FailedOverVMAnnotation] { + allErrs = append(allErrs, field.Forbidden(annotationPath.Key(vmopv1.FailedOverVMAnnotation), modifyAnnotationNotAllowedForNonAdmin)) } if vm.Annotations[vmopv1.ImportedVMAnnotation] != oldVM.Annotations[vmopv1.ImportedVMAnnotation] { diff --git a/webhooks/virtualmachine/validation/virtualmachine_validator_unit_test.go b/webhooks/virtualmachine/validation/virtualmachine_validator_unit_test.go index 4c8f9996f..570249c72 100644 --- a/webhooks/virtualmachine/validation/virtualmachine_validator_unit_test.go +++ b/webhooks/virtualmachine/validation/virtualmachine_validator_unit_test.go @@ -27,7 +27,6 @@ import ( "github.com/vmware-tanzu/vm-operator/api/v1alpha3/common" "github.com/vmware-tanzu/vm-operator/api/v1alpha3/sysprep" topologyv1 "github.com/vmware-tanzu/vm-operator/external/tanzu-topology/api/v1alpha1" - backupapi "github.com/vmware-tanzu/vm-operator/pkg/backup/api" pkgbuilder "github.com/vmware-tanzu/vm-operator/pkg/builder" pkgcfg "github.com/vmware-tanzu/vm-operator/pkg/config" "github.com/vmware-tanzu/vm-operator/pkg/constants" @@ -50,6 +49,7 @@ const ( dummyCreatedAtSchemaVersionVal = "dummy-created-at-schema-version" dummyRegisteredAnnVal = "dummy-registered-annotation" dummyImportedAnnVal = "dummy-imported-annotation" + dummyFailedOverAnnVal = "dummy-failedover-annotation" dummyPausedVMLabelVal = "dummy-devops" dummyVmiName = "vmi-dummy" dummyNamespaceName = "dummy-vm-namespace-for-webhook-validation" @@ -588,7 +588,7 @@ func unitTestsValidateCreate() { ctx.vm.Spec.ImageName = "" ctx.IsPrivilegedAccount = true ctx.vm.Annotations = map[string]string{ - vmopv1.RegisteredVMAnnotation: "", + vmopv1.RestoredVMAnnotation: "", } pkgcfg.SetContext(ctx, func(config *pkgcfg.Config) { config.Features.VMIncrementalRestore = true @@ -647,7 +647,7 @@ func unitTestsValidateCreate() { ctx.vm.Spec.ImageName = "" ctx.IsPrivilegedAccount = false ctx.vm.Annotations = map[string]string{ - vmopv1.RegisteredVMAnnotation: "", + vmopv1.RestoredVMAnnotation: "", } pkgcfg.SetContext(ctx, func(config *pkgcfg.Config) { config.Features.VMIncrementalRestore = true @@ -987,12 +987,14 @@ func unitTestsValidateCreate() { setup: func(ctx *unitValidatingWebhookContext) { ctx.vm.Annotations[vmopv1.InstanceIDAnnotation] = dummyInstanceIDVal ctx.vm.Annotations[vmopv1.FirstBootDoneAnnotation] = dummyFirstBootDoneVal - ctx.vm.Annotations[vmopv1.RegisteredVMAnnotation] = dummyFirstBootDoneVal - ctx.vm.Annotations[vmopv1.ImportedVMAnnotation] = dummyFirstBootDoneVal + ctx.vm.Annotations[vmopv1.RestoredVMAnnotation] = dummyRegisteredAnnVal + ctx.vm.Annotations[vmopv1.ImportedVMAnnotation] = dummyImportedAnnVal + ctx.vm.Annotations[vmopv1.FailedOverVMAnnotation] = dummyFailedOverAnnVal }, validate: doValidateWithMsg( - field.Forbidden(annotationPath.Key(vmopv1.RegisteredVMAnnotation), "modifying this annotation is not allowed for non-admin users").Error(), + field.Forbidden(annotationPath.Key(vmopv1.RestoredVMAnnotation), "modifying this annotation is not allowed for non-admin users").Error(), field.Forbidden(annotationPath.Key(vmopv1.ImportedVMAnnotation), "modifying this annotation is not allowed for non-admin users").Error(), + field.Forbidden(annotationPath.Key(vmopv1.FailedOverVMAnnotation), "modifying this annotation is not allowed for non-admin users").Error(), field.Forbidden(annotationPath.Key(vmopv1.InstanceIDAnnotation), "modifying this annotation is not allowed for non-admin users").Error(), field.Forbidden(annotationPath.Key(vmopv1.FirstBootDoneAnnotation), "modifying this annotation is not allowed for non-admin users").Error()), }, @@ -1004,8 +1006,9 @@ func unitTestsValidateCreate() { ctx.vm.Annotations[vmopv1.InstanceIDAnnotation] = dummyInstanceIDVal ctx.vm.Annotations[vmopv1.FirstBootDoneAnnotation] = dummyFirstBootDoneVal - ctx.vm.Annotations[vmopv1.RegisteredVMAnnotation] = dummyFirstBootDoneVal - ctx.vm.Annotations[vmopv1.ImportedVMAnnotation] = dummyFirstBootDoneVal + ctx.vm.Annotations[vmopv1.RestoredVMAnnotation] = dummyRegisteredAnnVal + ctx.vm.Annotations[vmopv1.ImportedVMAnnotation] = dummyImportedAnnVal + ctx.vm.Annotations[vmopv1.FailedOverVMAnnotation] = dummyFailedOverAnnVal }, expectAllowed: true, }, @@ -1023,8 +1026,9 @@ func unitTestsValidateCreate() { ctx.vm.Annotations[vmopv1.InstanceIDAnnotation] = dummyInstanceIDVal ctx.vm.Annotations[vmopv1.FirstBootDoneAnnotation] = dummyFirstBootDoneVal - ctx.vm.Annotations[vmopv1.RegisteredVMAnnotation] = dummyFirstBootDoneVal - ctx.vm.Annotations[vmopv1.ImportedVMAnnotation] = dummyFirstBootDoneVal + ctx.vm.Annotations[vmopv1.RestoredVMAnnotation] = dummyRegisteredAnnVal + ctx.vm.Annotations[vmopv1.ImportedVMAnnotation] = dummyImportedAnnVal + ctx.vm.Annotations[vmopv1.FailedOverVMAnnotation] = dummyFailedOverAnnVal }, expectAllowed: true, }, @@ -2787,23 +2791,26 @@ func unitTestsValidateUpdate() { ctx.oldVM.Annotations[vmopv1.FirstBootDoneAnnotation] = dummyFirstBootDoneVal ctx.oldVM.Annotations[constants.CreatedAtBuildVersionAnnotationKey] = dummyCreatedAtBuildVersionVal ctx.oldVM.Annotations[constants.CreatedAtSchemaVersionAnnotationKey] = dummyCreatedAtSchemaVersionVal - ctx.oldVM.Annotations[vmopv1.RegisteredVMAnnotation] = dummyRegisteredAnnVal + ctx.oldVM.Annotations[vmopv1.RestoredVMAnnotation] = dummyRegisteredAnnVal ctx.oldVM.Annotations[vmopv1.ImportedVMAnnotation] = dummyImportedAnnVal + ctx.oldVM.Annotations[vmopv1.FailedOverVMAnnotation] = dummyFailedOverAnnVal ctx.vm.Annotations[vmopv1.InstanceIDAnnotation] = dummyInstanceIDVal + updateSuffix ctx.vm.Annotations[vmopv1.FirstBootDoneAnnotation] = dummyFirstBootDoneVal + updateSuffix ctx.vm.Annotations[constants.CreatedAtBuildVersionAnnotationKey] = dummyCreatedAtBuildVersionVal + updateSuffix ctx.vm.Annotations[constants.CreatedAtSchemaVersionAnnotationKey] = dummyCreatedAtSchemaVersionVal + updateSuffix - ctx.vm.Annotations[vmopv1.RegisteredVMAnnotation] = dummyRegisteredAnnVal + updateSuffix + ctx.vm.Annotations[vmopv1.RestoredVMAnnotation] = dummyRegisteredAnnVal + updateSuffix ctx.vm.Annotations[vmopv1.ImportedVMAnnotation] = dummyImportedAnnVal + updateSuffix + ctx.vm.Annotations[vmopv1.FailedOverVMAnnotation] = dummyFailedOverAnnVal + updateSuffix }, validate: doValidateWithMsg( field.Forbidden(annotationPath.Key(vmopv1.InstanceIDAnnotation), "modifying this annotation is not allowed for non-admin users").Error(), field.Forbidden(annotationPath.Key(vmopv1.FirstBootDoneAnnotation), "modifying this annotation is not allowed for non-admin users").Error(), field.Forbidden(annotationPath.Key(constants.CreatedAtBuildVersionAnnotationKey), "modifying this annotation is not allowed for non-admin users").Error(), field.Forbidden(annotationPath.Key(constants.CreatedAtSchemaVersionAnnotationKey), "modifying this annotation is not allowed for non-admin users").Error(), - field.Forbidden(annotationPath.Key(vmopv1.RegisteredVMAnnotation), "modifying this annotation is not allowed for non-admin users").Error(), + field.Forbidden(annotationPath.Key(vmopv1.RestoredVMAnnotation), "modifying this annotation is not allowed for non-admin users").Error(), field.Forbidden(annotationPath.Key(vmopv1.ImportedVMAnnotation), "modifying this annotation is not allowed for non-admin users").Error(), + field.Forbidden(annotationPath.Key(vmopv1.FailedOverVMAnnotation), "modifying this annotation is not allowed for non-admin users").Error(), ), }, ), @@ -2814,16 +2821,18 @@ func unitTestsValidateUpdate() { ctx.oldVM.Annotations[vmopv1.FirstBootDoneAnnotation] = dummyFirstBootDoneVal ctx.oldVM.Annotations[constants.CreatedAtBuildVersionAnnotationKey] = dummyCreatedAtBuildVersionVal ctx.oldVM.Annotations[constants.CreatedAtSchemaVersionAnnotationKey] = dummyCreatedAtSchemaVersionVal - ctx.oldVM.Annotations[vmopv1.RegisteredVMAnnotation] = dummyRegisteredAnnVal + ctx.oldVM.Annotations[vmopv1.RestoredVMAnnotation] = dummyRegisteredAnnVal ctx.oldVM.Annotations[vmopv1.ImportedVMAnnotation] = dummyImportedAnnVal + ctx.oldVM.Annotations[vmopv1.FailedOverVMAnnotation] = dummyFailedOverAnnVal }, validate: doValidateWithMsg( field.Forbidden(annotationPath.Key(vmopv1.InstanceIDAnnotation), "modifying this annotation is not allowed for non-admin users").Error(), field.Forbidden(annotationPath.Key(vmopv1.FirstBootDoneAnnotation), "modifying this annotation is not allowed for non-admin users").Error(), field.Forbidden(annotationPath.Key(constants.CreatedAtBuildVersionAnnotationKey), "modifying this annotation is not allowed for non-admin users").Error(), field.Forbidden(annotationPath.Key(constants.CreatedAtSchemaVersionAnnotationKey), "modifying this annotation is not allowed for non-admin users").Error(), - field.Forbidden(annotationPath.Key(vmopv1.RegisteredVMAnnotation), "modifying this annotation is not allowed for non-admin users").Error(), + field.Forbidden(annotationPath.Key(vmopv1.RestoredVMAnnotation), "modifying this annotation is not allowed for non-admin users").Error(), field.Forbidden(annotationPath.Key(vmopv1.ImportedVMAnnotation), "modifying this annotation is not allowed for non-admin users").Error(), + field.Forbidden(annotationPath.Key(vmopv1.FailedOverVMAnnotation), "modifying this annotation is not allowed for non-admin users").Error(), ), }, ), @@ -2836,15 +2845,17 @@ func unitTestsValidateUpdate() { ctx.oldVM.Annotations[vmopv1.FirstBootDoneAnnotation] = dummyFirstBootDoneVal ctx.oldVM.Annotations[constants.CreatedAtBuildVersionAnnotationKey] = dummyCreatedAtBuildVersionVal ctx.oldVM.Annotations[constants.CreatedAtSchemaVersionAnnotationKey] = dummyCreatedAtSchemaVersionVal - ctx.oldVM.Annotations[vmopv1.RegisteredVMAnnotation] = dummyRegisteredAnnVal + ctx.oldVM.Annotations[vmopv1.RestoredVMAnnotation] = dummyRegisteredAnnVal ctx.oldVM.Annotations[vmopv1.ImportedVMAnnotation] = dummyImportedAnnVal + ctx.oldVM.Annotations[vmopv1.FailedOverVMAnnotation] = dummyFailedOverAnnVal ctx.vm.Annotations[vmopv1.InstanceIDAnnotation] = dummyInstanceIDVal + updateSuffix ctx.vm.Annotations[vmopv1.FirstBootDoneAnnotation] = dummyFirstBootDoneVal + updateSuffix ctx.vm.Annotations[constants.CreatedAtBuildVersionAnnotationKey] = dummyCreatedAtBuildVersionVal + updateSuffix ctx.vm.Annotations[constants.CreatedAtSchemaVersionAnnotationKey] = dummyCreatedAtSchemaVersionVal + updateSuffix - ctx.vm.Annotations[vmopv1.RegisteredVMAnnotation] = dummyRegisteredAnnVal + updateSuffix + ctx.vm.Annotations[vmopv1.RestoredVMAnnotation] = dummyRegisteredAnnVal + updateSuffix ctx.vm.Annotations[vmopv1.ImportedVMAnnotation] = dummyImportedAnnVal + updateSuffix + ctx.vm.Annotations[vmopv1.FailedOverVMAnnotation] = dummyFailedOverAnnVal + updateSuffix }, expectAllowed: true, }, @@ -2858,8 +2869,9 @@ func unitTestsValidateUpdate() { ctx.oldVM.Annotations[vmopv1.FirstBootDoneAnnotation] = dummyFirstBootDoneVal ctx.oldVM.Annotations[constants.CreatedAtBuildVersionAnnotationKey] = dummyCreatedAtBuildVersionVal ctx.oldVM.Annotations[constants.CreatedAtSchemaVersionAnnotationKey] = dummyCreatedAtSchemaVersionVal - ctx.oldVM.Annotations[vmopv1.RegisteredVMAnnotation] = dummyRegisteredAnnVal + ctx.oldVM.Annotations[vmopv1.RestoredVMAnnotation] = dummyRegisteredAnnVal ctx.oldVM.Annotations[vmopv1.ImportedVMAnnotation] = dummyImportedAnnVal + ctx.oldVM.Annotations[vmopv1.FailedOverVMAnnotation] = dummyFailedOverAnnVal }, expectAllowed: true, }, @@ -2881,15 +2893,17 @@ func unitTestsValidateUpdate() { ctx.oldVM.Annotations[vmopv1.FirstBootDoneAnnotation] = dummyFirstBootDoneVal ctx.oldVM.Annotations[constants.CreatedAtBuildVersionAnnotationKey] = dummyCreatedAtBuildVersionVal ctx.oldVM.Annotations[constants.CreatedAtSchemaVersionAnnotationKey] = dummyCreatedAtSchemaVersionVal - ctx.oldVM.Annotations[vmopv1.RegisteredVMAnnotation] = dummyRegisteredAnnVal + ctx.oldVM.Annotations[vmopv1.RestoredVMAnnotation] = dummyRegisteredAnnVal ctx.oldVM.Annotations[vmopv1.ImportedVMAnnotation] = dummyImportedAnnVal + ctx.oldVM.Annotations[vmopv1.FailedOverVMAnnotation] = dummyFailedOverAnnVal ctx.vm.Annotations[vmopv1.InstanceIDAnnotation] = dummyInstanceIDVal + updateSuffix ctx.vm.Annotations[vmopv1.FirstBootDoneAnnotation] = dummyFirstBootDoneVal + updateSuffix ctx.vm.Annotations[constants.CreatedAtBuildVersionAnnotationKey] = dummyCreatedAtBuildVersionVal + updateSuffix ctx.vm.Annotations[constants.CreatedAtSchemaVersionAnnotationKey] = dummyCreatedAtSchemaVersionVal + updateSuffix - ctx.vm.Annotations[vmopv1.RegisteredVMAnnotation] = dummyRegisteredAnnVal + updateSuffix + ctx.vm.Annotations[vmopv1.RestoredVMAnnotation] = dummyRegisteredAnnVal + updateSuffix ctx.vm.Annotations[vmopv1.ImportedVMAnnotation] = dummyImportedAnnVal + updateSuffix + ctx.vm.Annotations[vmopv1.FailedOverVMAnnotation] = dummyFailedOverAnnVal + updateSuffix }, expectAllowed: true, }, @@ -2911,8 +2925,9 @@ func unitTestsValidateUpdate() { ctx.oldVM.Annotations[vmopv1.FirstBootDoneAnnotation] = dummyFirstBootDoneVal ctx.oldVM.Annotations[constants.CreatedAtBuildVersionAnnotationKey] = dummyCreatedAtBuildVersionVal ctx.oldVM.Annotations[constants.CreatedAtSchemaVersionAnnotationKey] = dummyCreatedAtSchemaVersionVal - ctx.oldVM.Annotations[vmopv1.RegisteredVMAnnotation] = dummyRegisteredAnnVal + ctx.oldVM.Annotations[vmopv1.RestoredVMAnnotation] = dummyRegisteredAnnVal ctx.oldVM.Annotations[vmopv1.ImportedVMAnnotation] = dummyImportedAnnVal + ctx.oldVM.Annotations[vmopv1.FailedOverVMAnnotation] = dummyFailedOverAnnVal }, expectAllowed: true, }, @@ -3012,7 +3027,7 @@ func unitTestsValidateUpdate() { }, ), - Entry("forbid unset of imageName by unprivileged users if FSS_WCP_VMSERVICE_INCREMENTAL_RESTORE is enabled and registered annotation is present", + Entry("forbid unset of imageName by unprivileged users if FSS_WCP_VMSERVICE_INCREMENTAL_RESTORE is enabled and failover annotation is present", testParams{ setup: func(ctx *unitValidatingWebhookContext) { pkgcfg.SetContext(ctx, func(config *pkgcfg.Config) { @@ -3020,7 +3035,7 @@ func unitTestsValidateUpdate() { }) ctx.IsPrivilegedAccount = false ctx.oldVM.Annotations = map[string]string{ - vmopv1.RegisteredVMAnnotation: "foo", + vmopv1.FailedOverVMAnnotation: "foo", } ctx.oldVM.Spec.ImageName = dummyVmiName @@ -3033,7 +3048,7 @@ func unitTestsValidateUpdate() { }, ), - Entry("allow unset of imageName for privileged users when FSS_WCP_VMSERVICE_INCREMENTAL_RESTORE is enabled, and registered annotation is present", + Entry("allow unset of imageName for privileged users when FSS_WCP_VMSERVICE_INCREMENTAL_RESTORE is enabled, and failover annotation is present", testParams{ setup: func(ctx *unitValidatingWebhookContext) { pkgcfg.SetContext(ctx, func(config *pkgcfg.Config) { @@ -3044,7 +3059,7 @@ func unitTestsValidateUpdate() { ctx.oldVM.Spec.ImageName = dummyVmiName ctx.oldVM.Annotations = map[string]string{ - vmopv1.RegisteredVMAnnotation: "foo", + vmopv1.FailedOverVMAnnotation: "foo", } ctx.vm = ctx.oldVM.DeepCopy() ctx.vm.Spec.ImageName = "" @@ -3103,7 +3118,7 @@ func unitTestsValidateUpdate() { }, ), - Entry("forbid unset of image for privileged users when FSS_WCP_VMSERVICE_INCREMENTAL_RESTORE is enabled, but Registered annotation is not present", + Entry("forbid unset of image for privileged users when FSS_WCP_VMSERVICE_INCREMENTAL_RESTORE is enabled, but failover annotation is not present", testParams{ setup: func(ctx *unitValidatingWebhookContext) { pkgcfg.SetContext(ctx, func(config *pkgcfg.Config) { @@ -3124,7 +3139,7 @@ func unitTestsValidateUpdate() { }, ), - Entry("forbid unset of image by unprivileged users when FSS_WCP_VMSERVICE_INCREMENTAL_RESTORE is enabled and the Registered annotation is present", + Entry("forbid unset of image by unprivileged users when FSS_WCP_VMSERVICE_INCREMENTAL_RESTORE is enabled and the failover annotation is present", testParams{ setup: func(ctx *unitValidatingWebhookContext) { pkgcfg.SetContext(ctx, func(config *pkgcfg.Config) { @@ -3133,7 +3148,7 @@ func unitTestsValidateUpdate() { ctx.IsPrivilegedAccount = false ctx.oldVM.Annotations = map[string]string{ - vmopv1.RegisteredVMAnnotation: "bar", + vmopv1.FailedOverVMAnnotation: "bar", } ctx.oldVM.Spec.Image = &vmopv1.VirtualMachineImageRef{ @@ -3148,7 +3163,7 @@ func unitTestsValidateUpdate() { }, ), - Entry("alow changing image for privileged users when FSS_WCP_VMSERVICE_INCREMENTAL_RESTORE is enabled, and Registered annotation is present", + Entry("alow changing image for privileged users when FSS_WCP_VMSERVICE_INCREMENTAL_RESTORE is enabled, and failover annotation is present", testParams{ setup: func(ctx *unitValidatingWebhookContext) { pkgcfg.SetContext(ctx, func(config *pkgcfg.Config) { @@ -3157,7 +3172,7 @@ func unitTestsValidateUpdate() { ctx.IsPrivilegedAccount = true ctx.oldVM.Annotations = map[string]string{ - vmopv1.RegisteredVMAnnotation: "bar", + vmopv1.FailedOverVMAnnotation: "bar", } ctx.oldVM.Spec.Image = &vmopv1.VirtualMachineImageRef{ @@ -3329,13 +3344,13 @@ func unitTestsValidateUpdate() { }, ), - Entry("allow interface name change if VM has test failover label", + Entry("allow interface name change if VM has failover label", testParams{ setup: func(ctx *unitValidatingWebhookContext) { if ctx.oldVM.Labels == nil { ctx.oldVM.Labels = make(map[string]string) } - ctx.oldVM.Labels[backupapi.TestFailoverLabelKey] = "foo" + ctx.oldVM.Annotations[vmopv1.FailedOverVMAnnotation] = "foo" ctx.oldVM.Spec.Network = &vmopv1.VirtualMachineNetworkSpec{ Interfaces: []vmopv1.VirtualMachineNetworkInterfaceSpec{ @@ -3351,13 +3366,13 @@ func unitTestsValidateUpdate() { expectAllowed: true, }, ), - Entry("allow changing network interface network if VM has test failover label", + Entry("allow changing network interface network if VM has failover label", testParams{ setup: func(ctx *unitValidatingWebhookContext) { if ctx.oldVM.Labels == nil { ctx.oldVM.Labels = make(map[string]string) } - ctx.oldVM.Labels[backupapi.TestFailoverLabelKey] = "foo" + ctx.oldVM.Annotations[vmopv1.FailedOverVMAnnotation] = "foo" ctx.oldVM.Spec.Network = &vmopv1.VirtualMachineNetworkSpec{ Interfaces: []vmopv1.VirtualMachineNetworkInterfaceSpec{