diff --git a/tests/e2e/affinity_toleration_test.go b/tests/e2e/affinity_toleration_test.go index 893509937..798736502 100644 --- a/tests/e2e/affinity_toleration_test.go +++ b/tests/e2e/affinity_toleration_test.go @@ -44,6 +44,15 @@ var _ = Describe("Virtual machine affinity and toleration", ginkgoutil.CommonE2E vmD = map[string]string{"vm": "vm-d"} ) + Context("Preparing the environment", func() { + It("sets the namespace", func() { + kustomization := fmt.Sprintf("%s/%s", conf.TestData.AffinityToleration, "kustomization.yaml") + ns, err := kustomize.GetNamespace(kustomization) + Expect(err).NotTo(HaveOccurred(), "%w", err) + conf.SetNamespace(ns) + }) + }) + Context("When virtualization resources are applied:", func() { It("result should be succeeded", func() { res := kubectl.Apply(kc.ApplyOptions{ diff --git a/tests/e2e/complex_test.go b/tests/e2e/complex_test.go index b025acb5f..07bfee4f5 100644 --- a/tests/e2e/complex_test.go +++ b/tests/e2e/complex_test.go @@ -66,6 +66,15 @@ var _ = Describe("Complex test", ginkgoutil.CommonE2ETestDecorators(), func() { hasNoConsumerLabel = map[string]string{"hasNoConsumer": "complex-test"} ) + Context("Preparing the environment", func() { + It("sets the namespace", func() { + kustomization := fmt.Sprintf("%s/%s", conf.TestData.ComplexTest, "kustomization.yaml") + ns, err := kustomize.GetNamespace(kustomization) + Expect(err).NotTo(HaveOccurred(), "%w", err) + conf.SetNamespace(ns) + }) + }) + Context("When virtualization resources are applied", func() { It("result should be succeeded", func() { if config.IsReusable() { diff --git a/tests/e2e/config/config.go b/tests/e2e/config/config.go index f4dc28f8d..d633adcc4 100644 --- a/tests/e2e/config/config.go +++ b/tests/e2e/config/config.go @@ -17,9 +17,13 @@ limitations under the License. package config import ( + "errors" "fmt" "log" "os" + "path/filepath" + "reflect" + "slices" "strconv" yamlv3 "gopkg.in/yaml.v3" @@ -221,6 +225,26 @@ func (c *Config) setEnvs() error { return nil } +func (c *Config) GetTestCases() ([]string, error) { + testDataValue := reflect.ValueOf(c.TestData) + testDataType := reflect.TypeOf(c.TestData) + excludedData := []string{"Sshkey", "SshUser"} + testCases := make([]string, 0, testDataType.NumField()-len(excludedData)) + + if testDataType.Kind() == reflect.Struct { + for i := 0; i < testDataType.NumField(); i++ { + field := testDataType.Field(i) + value := testDataValue.Field(i) + if !slices.Contains(excludedData, field.Name) { + testCases = append(testCases, fmt.Sprintf("%v", value.Interface())) + } + } + return testCases, nil + } else { + return nil, errors.New("`config.TestData` it is not a structure") + } +} + func GetNamePrefix() (string, error) { if prNumber, ok := os.LookupEnv("MODULES_MODULE_TAG"); ok && prNumber != "" { return prNumber, nil @@ -228,7 +252,7 @@ func GetNamePrefix() (string, error) { res := git.GetHeadHash() if !res.WasSuccess() { - return "", fmt.Errorf(res.StdErr()) + return "", errors.New(res.StdErr()) } commitHash := res.StdOut() @@ -237,6 +261,10 @@ func GetNamePrefix() (string, error) { return commitHash, nil } +func (c *Config) SetNamespace(name string) { + c.Namespace = name +} + func (k *Kustomize) SetParams(filePath, namespace, namePrefix string) error { var kustomizeFile Kustomize @@ -250,7 +278,10 @@ func (k *Kustomize) SetParams(filePath, namespace, namePrefix string) error { return unmarshalErr } - kustomizeFile.Namespace = namespace + fileDir := filepath.Dir(filePath) + testCaseName := filepath.Base(fileDir) + + kustomizeFile.Namespace = namespace + "-" + testCaseName kustomizeFile.NamePrefix = namePrefix + "-" kustomizeFile.Labels[0].Pairs["id"] = namePrefix updatedKustomizeFile, marshalErr := yamlv3.Marshal(&kustomizeFile) @@ -266,6 +297,22 @@ func (k *Kustomize) SetParams(filePath, namespace, namePrefix string) error { return nil } +func (k *Kustomize) GetNamespace(filePath string) (string, error) { + var kustomizeFile Kustomize + + data, readErr := os.ReadFile(filePath) + if readErr != nil { + return "", fmt.Errorf("cannot get namespace from %s: %w", filePath, readErr) + } + + unmarshalErr := yamlv3.Unmarshal([]byte(data), &kustomizeFile) + if unmarshalErr != nil { + return "", fmt.Errorf("cannot get namespace from %s: %w", filePath, unmarshalErr) + } + + return kustomizeFile.Namespace, nil +} + func (k *Kustomize) ExcludeResource(filePath, resourceName string) error { var kustomizeFile Kustomize @@ -302,7 +349,7 @@ func (k *Kustomize) ExcludeResource(filePath, resourceName string) error { func GetModuleConfig() (*ModuleConfig, error) { res := kubectl.GetResource(kc.ResourceModuleConfig, "virtualization", kc.GetOptions{Output: "yaml"}) if !res.WasSuccess() { - return nil, fmt.Errorf(res.StdErr()) + return nil, errors.New(res.StdErr()) } var mc ModuleConfig diff --git a/tests/e2e/sizing_policy_test.go b/tests/e2e/sizing_policy_test.go index a57edcf3e..0bc14bb0f 100644 --- a/tests/e2e/sizing_policy_test.go +++ b/tests/e2e/sizing_policy_test.go @@ -92,6 +92,13 @@ var _ = Describe("Sizing policy", ginkgoutil.CommonE2ETestDecorators(), func() { vmClassDiscovery = fmt.Sprintf("%s-discovery", namePrefix) vmClassDiscoveryCopy = fmt.Sprintf("%s-discovery-copy", namePrefix) newVmClassFilePath = fmt.Sprintf("%s/vmc-copy.yaml", conf.TestData.SizingPolicy) + + It("sets the namespace", func() { + kustomization := fmt.Sprintf("%s/%s", conf.TestData.SizingPolicy, "kustomization.yaml") + ns, err := kustomize.GetNamespace(kustomization) + Expect(err).NotTo(HaveOccurred(), "%w", err) + conf.SetNamespace(ns) + }) }) Context("When resources are applied", func() { diff --git a/tests/e2e/tests_suite_test.go b/tests/e2e/tests_suite_test.go index 9aba1d011..c848f5040 100644 --- a/tests/e2e/tests_suite_test.go +++ b/tests/e2e/tests_suite_test.go @@ -19,7 +19,6 @@ package e2e import ( "fmt" "log" - "strings" "testing" "time" @@ -115,21 +114,12 @@ func init() { } if !config.IsReusable() { - err = Cleanup() - if err != nil { + err := Cleanup() + if len(err) != 0 { log.Fatal(err) } } else { - log.Printf("Run test in REUSABLE mode\n") - } - - res := kubectl.CreateResource(kc.ResourceNamespace, conf.Namespace, kc.CreateOptions{}) - if !res.WasSuccess() { - 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()) - } + log.Println("Run test in REUSABLE mode") } } @@ -142,31 +132,60 @@ func TestTests(t *testing.T) { return } - Cleanup() + err := Cleanup() + if len(err) != 0 { + log.Fatal(err) + } } -func Cleanup() error { - res := kubectl.Delete(kc.DeleteOptions{ - Filename: []string{conf.Namespace}, - IgnoreNotFound: true, - Resource: kc.ResourceNamespace, - }) - if res.Error() != nil { - return fmt.Errorf("cmd: %s\nstderr: %s", res.GetCmd(), res.StdErr()) +func Cleanup() []error { + cleanupErrs := make([]error, 0) + testCases, err := conf.GetTestCases() + if err != nil { + cleanupErrs = append(cleanupErrs, err) + return cleanupErrs } - res = kubectl.Delete(kc.DeleteOptions{ + + for _, tc := range testCases { + kustomizeFilePath := fmt.Sprintf("%s/kustomization.yaml", tc) + namespace, err := kustomize.GetNamespace(kustomizeFilePath) + if err != nil { + cleanupErrs = append( + cleanupErrs, fmt.Errorf("cannot cleanup namespace %q: %w", namespace, err), + ) + continue + } + res := kubectl.Delete(kc.DeleteOptions{ + Filename: []string{conf.Namespace}, + IgnoreNotFound: true, + Resource: kc.ResourceNamespace, + }) + if res.Error() != nil { + cleanupErrs = append( + cleanupErrs, fmt.Errorf("cmd: %s\nstderr: %s", res.GetCmd(), res.StdErr()), + ) + continue + } + } + + res := kubectl.Delete(kc.DeleteOptions{ Labels: map[string]string{"id": namePrefix}, Resource: kc.ResourceCVI, }) if res.Error() != nil { - return fmt.Errorf("cmd: %s\nstderr: %s", res.GetCmd(), res.StdErr()) + cleanupErrs = append( + cleanupErrs, fmt.Errorf("cmd: %s\nstderr: %s", res.GetCmd(), res.StdErr()), + ) } res = kubectl.Delete(kc.DeleteOptions{ Labels: map[string]string{"id": namePrefix}, Resource: kc.ResourceVMClass, }) if res.Error() != nil { - return fmt.Errorf("cmd: %s\nstderr: %s", res.GetCmd(), res.StdErr()) + cleanupErrs = append( + cleanupErrs, fmt.Errorf("cmd: %s\nstderr: %s", res.GetCmd(), res.StdErr()), + ) } - return nil + + return cleanupErrs } diff --git a/tests/e2e/util_test.go b/tests/e2e/util_test.go index 9439fa60a..415af6348 100644 --- a/tests/e2e/util_test.go +++ b/tests/e2e/util_test.go @@ -457,10 +457,6 @@ func DeleteTestCaseResources(resources ResourcesToDelete) { 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 d891ae4eb..ac22fd3d1 100644 --- a/tests/e2e/vd_snapshots_test.go +++ b/tests/e2e/vd_snapshots_test.go @@ -243,7 +243,14 @@ var _ = Describe("Virtual disk snapshots", ginkgoutil.CommonE2ETestDecorators(), vmAutomaticWithHotplug = map[string]string{"vm": "automatic-with-hotplug"} ) - Context("Environment preparing", func() { + Context("Preparing the environment", func() { + It("sets the namespace", func() { + kustomization := fmt.Sprintf("%s/%s", conf.TestData.VdSnapshots, "kustomization.yaml") + ns, err := kustomize.GetNamespace(kustomization) + Expect(err).NotTo(HaveOccurred(), "%w", err) + conf.SetNamespace(ns) + }) + It("prepares `Immediate` storage class and virtual disk that use it", func() { sc, err := GetDefaultStorageClass() Expect(err).NotTo(HaveOccurred(), "cannot get default storage class\nstderr: %s", err) diff --git a/tests/e2e/vm_configuration_test.go b/tests/e2e/vm_configuration_test.go index 7f6eb7f1f..4ae7e73c0 100644 --- a/tests/e2e/vm_configuration_test.go +++ b/tests/e2e/vm_configuration_test.go @@ -92,6 +92,15 @@ var _ = Describe("Virtual machine configuration", ginkgoutil.CommonE2ETestDecora manualLabel = map[string]string{"vm": "manual-conf"} ) + Context("Preparing the environment", func() { + It("sets the namespace", func() { + kustomization := fmt.Sprintf("%s/%s", conf.TestData.VmConfiguration, "kustomization.yaml") + ns, err := kustomize.GetNamespace(kustomization) + Expect(err).NotTo(HaveOccurred(), "%w", err) + conf.SetNamespace(ns) + }) + }) + Context("When resources are applied", func() { It("result should be succeeded", func() { if config.IsReusable() { diff --git a/tests/e2e/vm_connectivity_test.go b/tests/e2e/vm_connectivity_test.go index eb5e2cd22..f9fe0724a 100644 --- a/tests/e2e/vm_connectivity_test.go +++ b/tests/e2e/vm_connectivity_test.go @@ -106,6 +106,15 @@ var _ = Describe("VM connectivity", ginkgoutil.CommonE2ETestDecorators(), func() selectorB string ) + Context("Preparing the environment", func() { + It("sets the namespace", func() { + kustomization := fmt.Sprintf("%s/%s", conf.TestData.Connectivity, "kustomization.yaml") + ns, err := kustomize.GetNamespace(kustomization) + Expect(err).NotTo(HaveOccurred(), "%w", err) + conf.SetNamespace(ns) + }) + }) + Context("When resources are applied", func() { It("result should be succeeded", func() { if config.IsReusable() { diff --git a/tests/e2e/vm_disk_attachment_test.go b/tests/e2e/vm_disk_attachment_test.go index f16e3cd9f..cf4f65b02 100644 --- a/tests/e2e/vm_disk_attachment_test.go +++ b/tests/e2e/vm_disk_attachment_test.go @@ -127,6 +127,13 @@ var _ = Describe("Virtual disk attachment", ginkgoutil.CommonE2ETestDecorators() vdAttach = fmt.Sprintf("%s-vd-attach-%s", namePrefix, nameSuffix) vmName = fmt.Sprintf("%s-vm-%s", namePrefix, nameSuffix) vmbdaName = fmt.Sprintf("%s-vm-%s", namePrefix, nameSuffix) + + It("sets the namespace", func() { + kustomization := fmt.Sprintf("%s/%s", conf.TestData.VmDiskAttachment, "kustomization.yaml") + ns, err := kustomize.GetNamespace(kustomization) + Expect(err).NotTo(HaveOccurred(), "%w", err) + conf.SetNamespace(ns) + }) }) Context("When resources are applied", func() { diff --git a/tests/e2e/vm_disk_resizing_test.go b/tests/e2e/vm_disk_resizing_test.go index 50539d866..9890b8fb5 100644 --- a/tests/e2e/vm_disk_resizing_test.go +++ b/tests/e2e/vm_disk_resizing_test.go @@ -18,6 +18,7 @@ package e2e import ( "encoding/json" + "errors" "fmt" "strings" @@ -26,6 +27,7 @@ import ( "k8s.io/apimachinery/pkg/api/resource" virtv2 "github.com/deckhouse/virtualization/api/core/v1alpha2" + "github.com/deckhouse/virtualization/tests/e2e/config" cfg "github.com/deckhouse/virtualization/tests/e2e/config" d8 "github.com/deckhouse/virtualization/tests/e2e/d8" "github.com/deckhouse/virtualization/tests/e2e/ginkgoutil" @@ -97,7 +99,7 @@ func GetSizeByLsblk(vmName, diskId string) (*resource.Quantity, error) { IdenityFile: conf.TestData.Sshkey, }) if res.Error() != nil { - return nil, fmt.Errorf(res.StdErr()) + return nil, errors.New(res.StdErr()) } err := json.Unmarshal(res.StdOutBytes(), &blockDevice) if err != nil { @@ -160,13 +162,22 @@ func GetVirtualMachineDisks(vmName string, config *cfg.Config) (VirtualMachineDi var _ = Describe("Virtual disk resizing", ginkgoutil.CommonE2ETestDecorators(), func() { BeforeEach(func() { - if cfg.IsReusable() { + if config.IsReusable() { Skip("Test not available in REUSABLE mode: not supported yet.") } }) testCaseLabel := map[string]string{"testcase": "disk-resizing"} + Context("Preparing the environment", func() { + It("sets the namespace", func() { + kustomization := fmt.Sprintf("%s/%s", conf.TestData.DiskResizing, "kustomization.yaml") + ns, err := kustomize.GetNamespace(kustomization) + Expect(err).NotTo(HaveOccurred(), "%w", err) + conf.SetNamespace(ns) + }) + }) + Context("When resources are applied", func() { It("result should be succeeded", func() { res := kubectl.Apply(kc.ApplyOptions{ diff --git a/tests/e2e/vm_label_annotation_test.go b/tests/e2e/vm_label_annotation_test.go index e01d5a68a..f57f7d890 100644 --- a/tests/e2e/vm_label_annotation_test.go +++ b/tests/e2e/vm_label_annotation_test.go @@ -109,6 +109,15 @@ var _ = Describe("Virtual machine label and annotation", ginkgoutil.CommonE2ETes testCaseLabel := map[string]string{"testcase": "vm-label-annotation"} specialKeyValue := map[string]string{"specialKey": "specialValue"} + Context("Preparing the environment", func() { + It("sets the namespace", func() { + kustomization := fmt.Sprintf("%s/%s", conf.TestData.VmLabelAnnotation, "kustomization.yaml") + ns, err := kustomize.GetNamespace(kustomization) + Expect(err).NotTo(HaveOccurred(), "%w", err) + conf.SetNamespace(ns) + }) + }) + Context("When resources are applied", func() { It("result should be succeeded", func() { res := kubectl.Apply(kc.ApplyOptions{ diff --git a/tests/e2e/vm_migration_test.go b/tests/e2e/vm_migration_test.go index aa526534b..bfca2fe92 100644 --- a/tests/e2e/vm_migration_test.go +++ b/tests/e2e/vm_migration_test.go @@ -78,6 +78,15 @@ func CreateMigrationManifest(vmName, filePath string, labels map[string]string) var _ = Describe("Virtual machine migration", ginkgoutil.CommonE2ETestDecorators(), func() { testCaseLabel := map[string]string{"testcase": "vm-migration"} + Context("Preparing the environment", func() { + It("sets the namespace", func() { + kustomization := fmt.Sprintf("%s/%s", conf.TestData.VmMigration, "kustomization.yaml") + ns, err := kustomize.GetNamespace(kustomization) + Expect(err).NotTo(HaveOccurred(), "%w", err) + conf.SetNamespace(ns) + }) + }) + Context("When resources are applied", func() { It("result should be succeeded", func() { if config.IsReusable() {