diff --git a/tests/e2e/README.md b/tests/e2e/README.md index f84344c43..c95651140 100644 --- a/tests/e2e/README.md +++ b/tests/e2e/README.md @@ -74,6 +74,23 @@ For example, run only "Complex text" without cleanup on failure: FOCUS="Complex test" STOP_ON_FAILURE=yes task run ``` +### Reusable mode option + +The environment variable REUSABLE used to retain all resources created during e2e test after its completion (no cleanup). +When a test starts, it will reuse existing virtual machines created earlier, if they exist. +If no virtual machines were found, they will be created. + +For example, run test in reusable mode: +```bash +REUSABLE=yes task run +``` + +! Only the following e2e tests are supported in REUSABLE mode. All other tests will be skipped. +- "Virtual machine configuration" +- "Virtual machine migration" +- "VM connectivity" +- "Complex test" + ## Run tests in CI ```bash task run:ci diff --git a/tests/e2e/affinity_toleration_test.go b/tests/e2e/affinity_toleration_test.go index fd8736321..893509937 100644 --- a/tests/e2e/affinity_toleration_test.go +++ b/tests/e2e/affinity_toleration_test.go @@ -24,11 +24,18 @@ import ( v1 "k8s.io/api/core/v1" virtv2 "github.com/deckhouse/virtualization/api/core/v1alpha2" + "github.com/deckhouse/virtualization/tests/e2e/config" "github.com/deckhouse/virtualization/tests/e2e/ginkgoutil" kc "github.com/deckhouse/virtualization/tests/e2e/kubectl" ) var _ = Describe("Virtual machine affinity and toleration", ginkgoutil.CommonE2ETestDecorators(), func() { + BeforeEach(func() { + if config.IsReusable() { + Skip("Test not available in REUSABLE mode: not supported yet.") + } + }) + var ( testCaseLabel = map[string]string{"testcase": "affinity-toleration"} vmA = map[string]string{"vm": "vm-a"} diff --git a/tests/e2e/complex_test.go b/tests/e2e/complex_test.go index 8792b0783..b025acb5f 100644 --- a/tests/e2e/complex_test.go +++ b/tests/e2e/complex_test.go @@ -24,6 +24,7 @@ import ( . "github.com/onsi/gomega" virtv2 "github.com/deckhouse/virtualization/api/core/v1alpha2" + "github.com/deckhouse/virtualization/tests/e2e/config" "github.com/deckhouse/virtualization/tests/e2e/ginkgoutil" kc "github.com/deckhouse/virtualization/tests/e2e/kubectl" ) @@ -67,6 +68,19 @@ var _ = Describe("Complex test", ginkgoutil.CommonE2ETestDecorators(), func() { Context("When virtualization resources are applied", func() { It("result should be succeeded", func() { + if config.IsReusable() { + res := kubectl.List(kc.ResourceVM, kc.GetOptions{ + Labels: testCaseLabel, + Namespace: conf.Namespace, + Output: "jsonpath='{.items[*].metadata.name}'", + }) + Expect(res.Error()).NotTo(HaveOccurred(), res.StdErr()) + + if res.StdOut() != "" { + return + } + } + res := kubectl.Apply(kc.ApplyOptions{ Filename: []string{conf.TestData.ComplexTest}, FilenameOption: kc.Kustomize, @@ -231,15 +245,20 @@ var _ = Describe("Complex test", ginkgoutil.CommonE2ETestDecorators(), func() { Context("When test is completed", func() { It("deletes test case resources", func() { - DeleteTestCaseResources(ResourcesToDelete{ - KustomizationDir: conf.TestData.ComplexTest, + resourcesToDelete := ResourcesToDelete{ AdditionalResources: []AdditionalResource{ { kc.ResourceKubevirtVMIM, testCaseLabel, }, }, - }) + } + + if !config.IsReusable() { + resourcesToDelete.KustomizationDir = conf.TestData.ComplexTest + } + + DeleteTestCaseResources(resourcesToDelete) }) }) }) diff --git a/tests/e2e/config/config.go b/tests/e2e/config/config.go index 4c8cb4cb9..f4dc28f8d 100644 --- a/tests/e2e/config/config.go +++ b/tests/e2e/config/config.go @@ -31,12 +31,12 @@ import ( var ( conf *Config - err error git gt.Git kubectl kc.Kubectl ) func init() { + var err error if conf, err = GetConfig(); err != nil { log.Fatal(err) } diff --git a/tests/e2e/config/reusable.go b/tests/e2e/config/reusable.go new file mode 100644 index 000000000..f5626befc --- /dev/null +++ b/tests/e2e/config/reusable.go @@ -0,0 +1,48 @@ +/* +Copyright 2025 Flant JSC + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package config + +import ( + "fmt" + "os" +) + +// ReusableEnv defines an environment variable used to retain all resources created during e2e test after its completion (no cleanup). +// When a test starts, it will reuse existing virtual machines created earlier, if they exist. +// If no virtual machines were found, they will be created. +// Only the following e2e tests are supported in REUSABLE mode. All other tests will be skipped. +// - "Virtual machine configuration" +// - "Virtual machine migration" +// - "VM connectivity" +// - "Complex test" +const ReusableEnv = "REUSABLE" + +const reusableValue = "yes" + +func CheckReusableOption() error { + env := os.Getenv(ReusableEnv) + switch env { + case reusableValue, "": + return nil + default: + return fmt.Errorf("invalid value for the REUSABLE env: %q", env) + } +} + +func IsReusable() bool { + return os.Getenv(ReusableEnv) == reusableValue +} diff --git a/tests/e2e/sizing_policy_test.go b/tests/e2e/sizing_policy_test.go index eae1be27b..a57edcf3e 100644 --- a/tests/e2e/sizing_policy_test.go +++ b/tests/e2e/sizing_policy_test.go @@ -26,6 +26,7 @@ import ( . "github.com/onsi/gomega" virtv2 "github.com/deckhouse/virtualization/api/core/v1alpha2" + "github.com/deckhouse/virtualization/tests/e2e/config" "github.com/deckhouse/virtualization/tests/e2e/ginkgoutil" . "github.com/deckhouse/virtualization/tests/e2e/helper" kc "github.com/deckhouse/virtualization/tests/e2e/kubectl" @@ -67,6 +68,12 @@ func CompareVirtualMachineClassReadyStatus(vmName, expectedStatus string) { } var _ = Describe("Sizing policy", ginkgoutil.CommonE2ETestDecorators(), func() { + BeforeEach(func() { + if config.IsReusable() { + Skip("Test not available in REUSABLE mode: not supported yet.") + } + }) + var ( vmNotValidSizingPolicyChanging string vmNotValidSizingPolicyCreating string diff --git a/tests/e2e/tests_suite_test.go b/tests/e2e/tests_suite_test.go index 88ab8b608..9aba1d011 100644 --- a/tests/e2e/tests_suite_test.go +++ b/tests/e2e/tests_suite_test.go @@ -19,6 +19,7 @@ package e2e import ( "fmt" "log" + "strings" "testing" "time" @@ -64,7 +65,11 @@ var ( ) func init() { - var err error + err := config.CheckReusableOption() + if err != nil { + log.Println("To run tests in REUSABLE mode, set REUSABLE=yes. If you don't intend to use this mode, leave the variable unset.") + log.Fatal(err) + } if conf, err = config.GetConfig(); err != nil { log.Fatal(err) } @@ -108,13 +113,23 @@ func init() { log.Fatal(err) } } - err = Cleanup() - if err != nil { - log.Fatal(err) + + if !config.IsReusable() { + err = Cleanup() + if err != nil { + log.Fatal(err) + } + } else { + log.Printf("Run test in REUSABLE mode\n") } + res := kubectl.CreateResource(kc.ResourceNamespace, conf.Namespace, kc.CreateOptions{}) if !res.WasSuccess() { - log.Fatalf("err: %v\n%s", res.Error(), res.StdErr()) + if strings.Contains(res.StdErr(), "AlreadyExists") { + log.Printf("Namespace %q already exists: it will be reused", conf.Namespace) + } else { + log.Fatalf("err: %v\n%s", res.Error(), res.StdErr()) + } } } @@ -122,9 +137,12 @@ func TestTests(t *testing.T) { RegisterFailHandler(Fail) fmt.Fprintf(GinkgoWriter, "Starting test suite\n") RunSpecs(t, "Tests") - if !(ginkgoutil.FailureBehaviourEnvSwitcher{}).IsStopOnFailure() { - Cleanup() + + if (ginkgoutil.FailureBehaviourEnvSwitcher{}).IsStopOnFailure() || config.IsReusable() { + return } + + Cleanup() } func Cleanup() error { diff --git a/tests/e2e/util_test.go b/tests/e2e/util_test.go index f8313f43b..9439fa60a 100644 --- a/tests/e2e/util_test.go +++ b/tests/e2e/util_test.go @@ -454,12 +454,13 @@ type ResourcesToDelete struct { // This function checks that all resources in test case can be deleted correctly. func DeleteTestCaseResources(resources ResourcesToDelete) { By("Response on deletion request should be successful") - errMessage := "cannot delete test case resources" - kustimizationFile := fmt.Sprintf("%s/%s", resources.KustomizationDir, "kustomization.yaml") - err := kustomize.ExcludeResource(kustimizationFile, "ns.yaml") - Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("%s\nkustomizationDir: %s\nstderr: %s", errMessage, resources.KustomizationDir, err)) + const errMessage = "cannot delete test case resources" if resources.KustomizationDir != "" { + kustimizationFile := fmt.Sprintf("%s/%s", resources.KustomizationDir, "kustomization.yaml") + err := kustomize.ExcludeResource(kustimizationFile, "ns.yaml") + Expect(err).NotTo(HaveOccurred(), fmt.Sprintf("%s\nkustomizationDir: %s\nstderr: %s", errMessage, resources.KustomizationDir, err)) + res := kubectl.Delete(kc.DeleteOptions{ Filename: []string{resources.KustomizationDir}, FilenameOption: kc.Kustomize, diff --git a/tests/e2e/vd_snapshots_test.go b/tests/e2e/vd_snapshots_test.go index 6fef69136..d891ae4eb 100644 --- a/tests/e2e/vd_snapshots_test.go +++ b/tests/e2e/vd_snapshots_test.go @@ -23,14 +23,16 @@ import ( "sync" "time" - sdsrepvolv1 "github.com/deckhouse/sds-replicated-volume/api/v1alpha1" snapshotvolv1 "github.com/kubernetes-csi/external-snapshotter/client/v8/apis/volumesnapshot/v1" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" storagev1 "k8s.io/api/storage/v1" v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + sdsrepvolv1 "github.com/deckhouse/sds-replicated-volume/api/v1alpha1" + virtv2 "github.com/deckhouse/virtualization/api/core/v1alpha2" + "github.com/deckhouse/virtualization/tests/e2e/config" "github.com/deckhouse/virtualization/tests/e2e/ginkgoutil" . "github.com/deckhouse/virtualization/tests/e2e/helper" kc "github.com/deckhouse/virtualization/tests/e2e/kubectl" @@ -226,6 +228,12 @@ func CheckFilesystemReadyStatus(vmName string, status v1.ConditionStatus) (strin } var _ = Describe("Virtual disk snapshots", ginkgoutil.CommonE2ETestDecorators(), func() { + BeforeEach(func() { + if config.IsReusable() { + Skip("Test not available in REUSABLE mode: not supported yet.") + } + }) + var ( immediateStorageClassName string // require for unattached virtual disk snapshots defaultVolumeSnapshotClassName string diff --git a/tests/e2e/vm_configuration_test.go b/tests/e2e/vm_configuration_test.go index fad65bd4d..7f6eb7f1f 100644 --- a/tests/e2e/vm_configuration_test.go +++ b/tests/e2e/vm_configuration_test.go @@ -18,12 +18,14 @@ package e2e import ( "fmt" + "strconv" "strings" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" virtv2 "github.com/deckhouse/virtualization/api/core/v1alpha2" + "github.com/deckhouse/virtualization/tests/e2e/config" d8 "github.com/deckhouse/virtualization/tests/e2e/d8" "github.com/deckhouse/virtualization/tests/e2e/ginkgoutil" kc "github.com/deckhouse/virtualization/tests/e2e/kubectl" @@ -51,7 +53,7 @@ func ExecSshCommand(vmName, cmd string) { }).WithTimeout(Timeout).WithPolling(Interval).ShouldNot(HaveOccurred()) } -func ChangeCPUCoresNumber(namespace string, cpuNumber int, virtualMachines ...string) { +func ChangeCPUCoresNumber(cpuNumber int, virtualMachines ...string) { vms := strings.Join(virtualMachines, " ") cmd := fmt.Sprintf("patch %s --namespace %s %s --type merge --patch '{\"spec\":{\"cpu\":{\"cores\":%d}}}'", kc.ResourceVM, conf.Namespace, vms, cpuNumber) By("Patching virtual machine specification") @@ -92,6 +94,19 @@ var _ = Describe("Virtual machine configuration", ginkgoutil.CommonE2ETestDecora Context("When resources are applied", func() { It("result should be succeeded", func() { + if config.IsReusable() { + res := kubectl.List(kc.ResourceVM, kc.GetOptions{ + Labels: testCaseLabel, + Namespace: conf.Namespace, + Output: "jsonpath='{.items[*].metadata.name}'", + }) + Expect(res.Error()).NotTo(HaveOccurred(), res.StdErr()) + + if res.StdOut() != "" { + return + } + } + res := kubectl.Apply(kc.ApplyOptions{ Filename: []string{conf.TestData.VmConfiguration}, FilenameOption: kc.Kustomize, @@ -132,6 +147,9 @@ var _ = Describe("Virtual machine configuration", ginkgoutil.CommonE2ETestDecora }) Describe("Manual restart approval mode", func() { + var oldCpuCores int + var newCPUCores int + Context(fmt.Sprintf("When virtual machine is in %s phase", PhaseRunning), func() { It("changes the number of processor cores", func() { res := kubectl.List(kc.ResourceVM, kc.GetOptions{ @@ -142,8 +160,17 @@ var _ = Describe("Virtual machine configuration", ginkgoutil.CommonE2ETestDecora Expect(res.Error()).NotTo(HaveOccurred(), res.StdErr()) vms := strings.Split(res.StdOut(), " ") - CheckCPUCoresNumber(ManualMode, StageBefore, 1, vms...) - ChangeCPUCoresNumber(conf.Namespace, 2, vms...) + Expect(vms).NotTo(BeEmpty()) + + vmResource := virtv2.VirtualMachine{} + err := GetObject(kc.ResourceVM, vms[0], &vmResource, kc.GetOptions{Namespace: conf.Namespace}) + Expect(err).NotTo(HaveOccurred(), err) + + oldCpuCores = vmResource.Spec.CPU.Cores + newCPUCores = 1 + (vmResource.Spec.CPU.Cores & 1) + + CheckCPUCoresNumber(ManualMode, StageBefore, oldCpuCores, vms...) + ChangeCPUCoresNumber(newCPUCores, vms...) }) }) @@ -157,7 +184,7 @@ var _ = Describe("Virtual machine configuration", ginkgoutil.CommonE2ETestDecora Expect(res.WasSuccess()).To(Equal(true), res.StdErr()) vms := strings.Split(res.StdOut(), " ") - CheckCPUCoresNumber(ManualMode, StageAfter, 2, vms...) + CheckCPUCoresNumber(ManualMode, StageAfter, newCPUCores, vms...) }) }) @@ -193,12 +220,15 @@ var _ = Describe("Virtual machine configuration", ginkgoutil.CommonE2ETestDecora Expect(res.WasSuccess()).To(Equal(true), res.StdErr()) vms := strings.Split(res.StdOut(), " ") - CheckCPUCoresNumberFromVirtualMachine("2", vms...) + CheckCPUCoresNumberFromVirtualMachine(strconv.FormatInt(int64(newCPUCores), 10), vms...) }) }) }) Describe("Automatic restart approval mode", func() { + var oldCpuCores int + var newCPUCores int + Context(fmt.Sprintf("When virtual machine is in %s phase", PhaseRunning), func() { It("changes the number of processor cores", func() { res := kubectl.List(kc.ResourceVM, kc.GetOptions{ @@ -209,8 +239,17 @@ var _ = Describe("Virtual machine configuration", ginkgoutil.CommonE2ETestDecora Expect(res.WasSuccess()).To(Equal(true), res.StdErr()) vms := strings.Split(res.StdOut(), " ") - CheckCPUCoresNumber(AutomaticMode, StageBefore, 1, vms...) - ChangeCPUCoresNumber(conf.Namespace, 2, vms...) + Expect(vms).NotTo(BeEmpty()) + + vmResource := virtv2.VirtualMachine{} + err := GetObject(kc.ResourceVM, vms[0], &vmResource, kc.GetOptions{Namespace: conf.Namespace}) + Expect(err).NotTo(HaveOccurred(), err) + + oldCpuCores = vmResource.Spec.CPU.Cores + newCPUCores = 1 + (vmResource.Spec.CPU.Cores & 1) + + CheckCPUCoresNumber(AutomaticMode, StageBefore, oldCpuCores, vms...) + ChangeCPUCoresNumber(newCPUCores, vms...) }) }) @@ -224,7 +263,7 @@ var _ = Describe("Virtual machine configuration", ginkgoutil.CommonE2ETestDecora Expect(res.WasSuccess()).To(Equal(true), res.StdErr()) vms := strings.Split(res.StdOut(), " ") - CheckCPUCoresNumber(AutomaticMode, StageAfter, 2, vms...) + CheckCPUCoresNumber(AutomaticMode, StageAfter, newCPUCores, vms...) }) }) @@ -248,16 +287,20 @@ var _ = Describe("Virtual machine configuration", ginkgoutil.CommonE2ETestDecora Expect(res.Error()).NotTo(HaveOccurred(), res.StdErr()) vms := strings.Split(res.StdOut(), " ") - CheckCPUCoresNumberFromVirtualMachine("2", vms...) + CheckCPUCoresNumberFromVirtualMachine(strconv.FormatInt(int64(newCPUCores), 10), vms...) }) }) }) Context("When test is completed", func() { It("deletes test case resources", func() { - DeleteTestCaseResources(ResourcesToDelete{ - KustomizationDir: conf.TestData.VmConfiguration, - }) + var resourcesToDelete ResourcesToDelete + + if !config.IsReusable() { + resourcesToDelete.KustomizationDir = conf.TestData.VmConfiguration + } + + DeleteTestCaseResources(resourcesToDelete) }) }) }) diff --git a/tests/e2e/vm_connectivity_test.go b/tests/e2e/vm_connectivity_test.go index 8ad190982..eb5e2cd22 100644 --- a/tests/e2e/vm_connectivity_test.go +++ b/tests/e2e/vm_connectivity_test.go @@ -26,6 +26,7 @@ import ( corev1 "k8s.io/api/core/v1" virtv2 "github.com/deckhouse/virtualization/api/core/v1alpha2" + "github.com/deckhouse/virtualization/tests/e2e/config" d8 "github.com/deckhouse/virtualization/tests/e2e/d8" "github.com/deckhouse/virtualization/tests/e2e/executor" "github.com/deckhouse/virtualization/tests/e2e/ginkgoutil" @@ -100,10 +101,26 @@ var _ = Describe("VM connectivity", ginkgoutil.CommonE2ETestDecorators(), func() vmA, vmB virtv2.VirtualMachine svcA, svcB corev1.Service err error + + selectorA string + selectorB string ) Context("When resources are applied", func() { It("result should be succeeded", func() { + if config.IsReusable() { + res := kubectl.List(kc.ResourceVM, kc.GetOptions{ + Labels: testCaseLabel, + Namespace: conf.Namespace, + Output: "jsonpath='{.items[*].metadata.name}'", + }) + Expect(res.Error()).NotTo(HaveOccurred(), res.StdErr()) + + if res.StdOut() != "" { + return + } + } + res := kubectl.Apply(kc.ApplyOptions{ Filename: []string{conf.TestData.Connectivity}, FilenameOption: kc.Kustomize, @@ -226,18 +243,20 @@ var _ = Describe("VM connectivity", ginkgoutil.CommonE2ETestDecorators(), func() }) It(fmt.Sprintf("changes selector in service %s with selector from service %s", aObjName, bObjName), func() { + selectorA = svcA.Spec.Selector["service"] + selectorB = svcB.Spec.Selector["service"] + PatchResource(kc.ResourceService, svcA.Name, &kc.JsonPatch{ Op: "replace", Path: "/spec/selector/service", - Value: svcB.Spec.Selector["service"], + Value: selectorB, }) }) It(fmt.Sprintf("checks selector in service %s", aObjName), func() { - By(fmt.Sprintf("Selector should be %q", svcB.Spec.Selector["service"])) - label := svcB.Spec.Selector["service"] + By(fmt.Sprintf("Selector should be %q", selectorB)) output := "jsonpath={.spec.selector.service}" - CheckField(kc.ResourceService, svcA.Name, output, label) + CheckField(kc.ResourceService, svcA.Name, output, selectorB) }) It(fmt.Sprintf("gets page from service %s", aObjName), func() { @@ -251,19 +270,38 @@ var _ = Describe("VM connectivity", ginkgoutil.CommonE2ETestDecorators(), func() return strings.TrimSpace(res.StdOut()), nil }).WithTimeout(Timeout).WithPolling(Interval).Should(ContainSubstring(vmB.Name)) }) + + It(fmt.Sprintf("changes back selector in service %s", aObjName), func() { + PatchResource(kc.ResourceService, svcA.Name, &kc.JsonPatch{ + Op: "replace", + Path: "/spec/selector/service", + Value: selectorA, + }) + }) + + It(fmt.Sprintf("checks selector in service %s", aObjName), func() { + By(fmt.Sprintf("Selector should be %q", selectorA)) + output := "jsonpath={.spec.selector.service}" + CheckField(kc.ResourceService, svcA.Name, output, selectorA) + }) }) Context("When test is completed", func() { It("deletes test case resources", func() { - DeleteTestCaseResources(ResourcesToDelete{ - KustomizationDir: conf.TestData.Connectivity, + resourcesToDelete := ResourcesToDelete{ AdditionalResources: []AdditionalResource{ { Resource: kc.ResourcePod, Labels: map[string]string{"name": CurlPod}, }, }, - }) + } + + if !config.IsReusable() { + resourcesToDelete.KustomizationDir = conf.TestData.Connectivity + } + + DeleteTestCaseResources(resourcesToDelete) }) }) }) diff --git a/tests/e2e/vm_disk_attachment_test.go b/tests/e2e/vm_disk_attachment_test.go index 5e7a32914..f16e3cd9f 100644 --- a/tests/e2e/vm_disk_attachment_test.go +++ b/tests/e2e/vm_disk_attachment_test.go @@ -25,6 +25,7 @@ import ( v1 "k8s.io/apimachinery/pkg/apis/meta/v1" virtv2 "github.com/deckhouse/virtualization/api/core/v1alpha2" + "github.com/deckhouse/virtualization/tests/e2e/config" d8 "github.com/deckhouse/virtualization/tests/e2e/d8" "github.com/deckhouse/virtualization/tests/e2e/ginkgoutil" . "github.com/deckhouse/virtualization/tests/e2e/helper" @@ -105,6 +106,12 @@ func GetDisksMetadata(vmName string, disks *Disks) error { } var _ = Describe("Virtual disk attachment", ginkgoutil.CommonE2ETestDecorators(), func() { + BeforeEach(func() { + if config.IsReusable() { + Skip("Test not available in REUSABLE mode: not supported yet.") + } + }) + var ( testCaseLabel = map[string]string{"testcase": "vm-disk-attachment"} hasNoConsumerLabel = map[string]string{"hasNoConsumer": "vm-disk-attachment"} diff --git a/tests/e2e/vm_disk_resizing_test.go b/tests/e2e/vm_disk_resizing_test.go index faae2dc24..50539d866 100644 --- a/tests/e2e/vm_disk_resizing_test.go +++ b/tests/e2e/vm_disk_resizing_test.go @@ -159,6 +159,12 @@ func GetVirtualMachineDisks(vmName string, config *cfg.Config) (VirtualMachineDi } var _ = Describe("Virtual disk resizing", ginkgoutil.CommonE2ETestDecorators(), func() { + BeforeEach(func() { + if cfg.IsReusable() { + Skip("Test not available in REUSABLE mode: not supported yet.") + } + }) + testCaseLabel := map[string]string{"testcase": "disk-resizing"} Context("When resources are applied", func() { diff --git a/tests/e2e/vm_label_annotation_test.go b/tests/e2e/vm_label_annotation_test.go index e52e3087c..e01d5a68a 100644 --- a/tests/e2e/vm_label_annotation_test.go +++ b/tests/e2e/vm_label_annotation_test.go @@ -25,6 +25,7 @@ import ( v1 "k8s.io/api/core/v1" virtv2 "github.com/deckhouse/virtualization/api/core/v1alpha2" + "github.com/deckhouse/virtualization/tests/e2e/config" "github.com/deckhouse/virtualization/tests/e2e/ginkgoutil" kc "github.com/deckhouse/virtualization/tests/e2e/kubectl" ) @@ -99,6 +100,12 @@ func GetActiveVirtualMachinePod(vmObj *virtv2.VirtualMachine) string { } var _ = Describe("Virtual machine label and annotation", ginkgoutil.CommonE2ETestDecorators(), func() { + BeforeEach(func() { + if config.IsReusable() { + Skip("Test not available in REUSABLE mode: not supported yet.") + } + }) + testCaseLabel := map[string]string{"testcase": "vm-label-annotation"} specialKeyValue := map[string]string{"specialKey": "specialValue"} diff --git a/tests/e2e/vm_migration_test.go b/tests/e2e/vm_migration_test.go index b3887162c..aa526534b 100644 --- a/tests/e2e/vm_migration_test.go +++ b/tests/e2e/vm_migration_test.go @@ -25,6 +25,7 @@ import ( v1 "k8s.io/apimachinery/pkg/apis/meta/v1" virtv1 "kubevirt.io/api/core/v1" + "github.com/deckhouse/virtualization/tests/e2e/config" "github.com/deckhouse/virtualization/tests/e2e/ginkgoutil" . "github.com/deckhouse/virtualization/tests/e2e/helper" kc "github.com/deckhouse/virtualization/tests/e2e/kubectl" @@ -79,6 +80,19 @@ var _ = Describe("Virtual machine migration", ginkgoutil.CommonE2ETestDecorators Context("When resources are applied", func() { It("result should be succeeded", func() { + if config.IsReusable() { + res := kubectl.List(kc.ResourceVM, kc.GetOptions{ + Labels: testCaseLabel, + Namespace: conf.Namespace, + Output: "jsonpath='{.items[*].metadata.name}'", + }) + Expect(res.Error()).NotTo(HaveOccurred(), res.StdErr()) + + if res.StdOut() != "" { + return + } + } + res := kubectl.Apply(kc.ApplyOptions{ Filename: []string{conf.TestData.VmMigration}, FilenameOption: kc.Kustomize, @@ -165,15 +179,20 @@ var _ = Describe("Virtual machine migration", ginkgoutil.CommonE2ETestDecorators Context("When test is completed", func() { It("deletes test case resources", func() { - DeleteTestCaseResources(ResourcesToDelete{ - KustomizationDir: conf.TestData.VmMigration, + resourcesToDelete := ResourcesToDelete{ AdditionalResources: []AdditionalResource{ { Resource: kc.ResourceKubevirtVMIM, Labels: testCaseLabel, }, }, - }) + } + + if !config.IsReusable() { + resourcesToDelete.KustomizationDir = conf.TestData.VmMigration + } + + DeleteTestCaseResources(resourcesToDelete) }) }) })