diff --git a/tests/e2e/Taskfile.yaml b/tests/e2e/Taskfile.yaml index 4d8117e78..0bca43afd 100644 --- a/tests/e2e/Taskfile.yaml +++ b/tests/e2e/Taskfile.yaml @@ -15,6 +15,7 @@ tasks: mkdir /tmp/testdata cp -a testdata/virtualization-resources /tmp/testdata/virtualization-resources cp -a testdata/connectivity /tmp/testdata/connectivity + cp -a testdata/vm-configuration /tmp/testdata/vm-configuration cp -a testdata/sshkeys /tmp/testdata/sshkeys virtctl: cmds: diff --git a/tests/e2e/complex_test.go b/tests/e2e/complex_test.go index 7a6c51bd4..fdb9c341f 100644 --- a/tests/e2e/complex_test.go +++ b/tests/e2e/complex_test.go @@ -20,16 +20,17 @@ import ( "fmt" "strings" - kc "github.com/deckhouse/virtualization/tests/e2e/kubectl" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + + kc "github.com/deckhouse/virtualization/tests/e2e/kubectl" ) var _ = Describe("Complex test", Ordered, ContinueOnFailure, func() { Context("Virtualization resources", func() { When("Resources applied", func() { It("Result must have no error", func() { - res := kubectl.Kustomize(conf.VirtualizationResources, kc.KustomizeOptions{}) + res := kubectl.Kustomize(conf.TestData.VirtualizationResources, kc.KustomizeOptions{}) Expect(res.WasSuccess()).To(Equal(true), res.StdErr()) }) }) @@ -38,7 +39,21 @@ var _ = Describe("Complex test", Ordered, ContinueOnFailure, func() { Context("Virtual images", func() { When("VI applied", func() { It(fmt.Sprintf("Phase should be %s", PhaseReady), func() { - WaitPhase("vi", PhaseReady) + WaitPhase(kc.ResourceVI, PhaseReady, kc.GetOptions{ + Namespace: conf.Namespace, + Output: "jsonpath='{.items[*].metadata.name}'", + }) + }) + }) + }) + + Context("Cluster virtual images", func() { + When("CVI applied", func() { + It(fmt.Sprintf("Phase should be %s", PhaseReady), func() { + WaitPhase(kc.ResourceCVI, PhaseReady, kc.GetOptions{ + Namespace: conf.Namespace, + Output: "jsonpath='{.items[*].metadata.name}'", + }) }) }) }) @@ -46,7 +61,10 @@ var _ = Describe("Complex test", Ordered, ContinueOnFailure, func() { Context("Disks", func() { When("VD applied", func() { It(fmt.Sprintf("Phase should be %s", PhaseReady), func() { - WaitPhase("vd", PhaseReady) + WaitPhase(kc.ResourceVD, PhaseReady, kc.GetOptions{ + Namespace: conf.Namespace, + Output: "jsonpath='{.items[*].metadata.name}'", + }) }) }) }) @@ -61,7 +79,10 @@ var _ = Describe("Complex test", Ordered, ContinueOnFailure, func() { MergePatchResource(kc.ResourceVMIP, vmipMetadataName, mergePatch) }) It(fmt.Sprintf("Phase should be %s", PhaseBound), func() { - WaitPhase("vmip", PhaseBound) + WaitPhase(kc.ResourceVMIP, PhaseBound, kc.GetOptions{ + Namespace: conf.Namespace, + Output: "jsonpath='{.items[*].metadata.name}'", + }) }) }) }) @@ -69,7 +90,10 @@ var _ = Describe("Complex test", Ordered, ContinueOnFailure, func() { Context("Virtual machines", func() { When("VM applied", func() { It(fmt.Sprintf("Phase should be %s", PhaseRunning), func() { - WaitPhase("vm", PhaseRunning) + WaitPhase(kc.ResourceVM, PhaseRunning, kc.GetOptions{ + Namespace: conf.Namespace, + Output: "jsonpath='{.items[*].metadata.name}'", + }) }) }) }) @@ -77,7 +101,10 @@ var _ = Describe("Complex test", Ordered, ContinueOnFailure, func() { Context("Virtualmachine block device attachments", func() { When("VMBDA applied", func() { It(fmt.Sprintf("Phase should be %s", PhaseAttached), func() { - WaitPhase("vmbda", PhaseAttached) + WaitPhase(kc.ResourceVMBDA, PhaseAttached, kc.GetOptions{ + Namespace: conf.Namespace, + Output: "jsonpath='{.items[*].metadata.name}'", + }) }) }) }) @@ -85,14 +112,13 @@ var _ = Describe("Complex test", Ordered, ContinueOnFailure, func() { Context("External connection", func() { When("VMs are running", func() { It("All VMs must have to be connected to external network", func() { - sshKeyPath := fmt.Sprintf("%s/id_ed", conf.Sshkeys) - resourceType := kc.Resource("vm") + sshKeyPath := fmt.Sprintf("%s/id_ed", conf.TestData.Sshkeys) output := "jsonpath='{.items[*].metadata.name}'" - res := kubectl.List(resourceType, kc.GetOptions{ + res := kubectl.List(kc.ResourceVM, kc.GetOptions{ Namespace: conf.Namespace, Output: output, - Labels: map[string]string{"testcase": namePrefix}, + Labels: map[string]string{"id": namePrefix}, }) Expect(res.WasSuccess()).To(Equal(true), res.StdErr()) diff --git a/tests/e2e/config/config.go b/tests/e2e/config/config.go index cddce5baa..4411c92fd 100644 --- a/tests/e2e/config/config.go +++ b/tests/e2e/config/config.go @@ -22,9 +22,10 @@ import ( "os" "strconv" + yamlv3 "gopkg.in/yaml.v3" + gt "github.com/deckhouse/virtualization/tests/e2e/git" kc "github.com/deckhouse/virtualization/tests/e2e/kubectl" - yamlv3 "gopkg.in/yaml.v3" ) var ( @@ -115,15 +116,20 @@ type KustomizeLabel struct { } type Config struct { - ClusterTransport ClusterTransport `yaml:"clusterTransport"` - Disks DisksConf `yaml:"disks"` - VM VmConf `yaml:"vm"` - Ipam IpamConf `yaml:"ipam"` - HelperImages HelperImages `yaml:"helperImages"` - Namespace string `yaml:"namespaceSuffix"` - VirtualizationResources string `yaml:"virtualizationResources"` - Connectivity string `yaml:"connectivity"` - Sshkeys string `yaml:"sshKeys"` + ClusterTransport ClusterTransport `yaml:"clusterTransport"` + Disks DisksConf `yaml:"disks"` + VM VmConf `yaml:"vm"` + Ipam IpamConf `yaml:"ipam"` + HelperImages HelperImages `yaml:"helperImages"` + Namespace string `yaml:"namespaceSuffix"` + TestData TestData `yaml:"testData"` +} + +type TestData struct { + VirtualizationResources string `yaml:"virtualizationResources"` + Connectivity string `yaml:"connectivity"` + VmConfiguration string `yaml:"vmConfiguration"` + Sshkeys string `yaml:"sshKeys"` } type ClusterTransport struct { @@ -199,7 +205,6 @@ func (c *Config) setEnvs() error { c.Ipam.TestDataDir = e } return nil - } func GetNamePrefix() (string, error) { @@ -233,13 +238,13 @@ func (k *Kustomize) SetParams(filePath, namespace, namePrefix string) error { kustomizeFile.Namespace = namespace kustomizeFile.NamePrefix = namePrefix + "-" - kustomizeFile.Labels[0].Pairs["testcase"] = namePrefix + kustomizeFile.Labels[0].Pairs["id"] = namePrefix updatedKustomizeFile, marshalErr := yamlv3.Marshal(&kustomizeFile) if marshalErr != nil { return marshalErr } - writeErr := os.WriteFile(filePath, updatedKustomizeFile, 0644) + writeErr := os.WriteFile(filePath, updatedKustomizeFile, 0o644) if writeErr != nil { return writeErr } diff --git a/tests/e2e/default_config.yaml b/tests/e2e/default_config.yaml index ba77293e4..75e642f28 100644 --- a/tests/e2e/default_config.yaml +++ b/tests/e2e/default_config.yaml @@ -18,6 +18,8 @@ ipam: testDataDir: "./testdata/ipam" helperImages: curlImage: "curlimages/curl" -virtualizationResources: "/tmp/testdata/virtualization-resources" -connectivity: "/tmp/testdata/connectivity" -sshKeys: "/tmp/testdata/sshkeys" +testData: + virtualizationResources: "/tmp/testdata/virtualization-resources" + connectivity: "/tmp/testdata/connectivity" + vmConfiguration: "/tmp/testdata/vm-configuration" + sshKeys: "/tmp/testdata/sshkeys" diff --git a/tests/e2e/executor/executor.go b/tests/e2e/executor/executor.go index dc15d68ac..2b03ef4e4 100644 --- a/tests/e2e/executor/executor.go +++ b/tests/e2e/executor/executor.go @@ -32,7 +32,7 @@ type Executor interface { ExecContext(ctx context.Context, cmd string) *CMDResult ExecWithSudo(cmd string) *CMDResult ExecWithSudoContext(ctx context.Context, cmd string) *CMDResult - ExecuteContext(ctx context.Context, cmd string, stdout io.Writer, stderr io.Writer) error + ExecuteContext(ctx context.Context, cmd string, stdout, stderr io.Writer) error } func (e CMDExecutor) Exec(command string) *CMDResult { @@ -66,11 +66,12 @@ func (e CMDExecutor) ExecWithSudoContext(ctx context.Context, command string) *C return e.ExecContext(ctx, fmt.Sprintf("sudo %s", command)) } -func (e CMDExecutor) ExecuteContext(ctx context.Context, command string, stdout io.Writer, stderr io.Writer) error { +func (e CMDExecutor) ExecuteContext(ctx context.Context, command string, stdout, stderr io.Writer) error { cmd := e.makeCMD(ctx, command, stdout, stderr) return cmd.Run() } -func (e CMDExecutor) makeCMD(ctx context.Context, command string, stdout io.Writer, stderr io.Writer) *exec.Cmd { + +func (e CMDExecutor) makeCMD(ctx context.Context, command string, stdout, stderr io.Writer) *exec.Cmd { cmd := exec.CommandContext(ctx, "bash", "-c", command) cmd.Stdin = os.Stdin cmd.Stdout = stdout diff --git a/tests/e2e/helper/helper.go b/tests/e2e/helper/helper.go index 03cf5ca18..236109471 100644 --- a/tests/e2e/helper/helper.go +++ b/tests/e2e/helper/helper.go @@ -22,10 +22,11 @@ import ( "path/filepath" "strings" - "github.com/deckhouse/virtualization/tests/e2e/kubectl" . "github.com/onsi/ginkgo/v2" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/util/yaml" + + "github.com/deckhouse/virtualization/tests/e2e/kubectl" ) func GetFilesDir(yamlPath string) []string { diff --git a/tests/e2e/ipam_test.go b/tests/e2e/ipam_test.go index 643e1b440..c75859348 100644 --- a/tests/e2e/ipam_test.go +++ b/tests/e2e/ipam_test.go @@ -43,7 +43,6 @@ var _ = Describe("Ipam", func() { DeleteVMIP := func(manifest string) { res := kubectl.Delete(manifest, kc.DeleteOptions{}) Expect(res.Error()).NotTo(HaveOccurred(), "failed delete vmip from file %s.\n%s", manifest, res.StdErr()) - } When("reclaimPolicy Delete", func() { filepath := ipamPath("vmip-delete.yaml") @@ -56,7 +55,6 @@ var _ = Describe("Ipam", func() { Expect(res.Error()).To(HaveOccurred()) Expect(res.StdErr()).To(ContainSubstring("not found")) }) - }) When("reclaimPolicy Retain", func() { filepath := ipamPath("vmip-retain.yaml") diff --git a/tests/e2e/kubectl/resource.go b/tests/e2e/kubectl/resource.go index b8f69d250..97fdb262e 100644 --- a/tests/e2e/kubectl/resource.go +++ b/tests/e2e/kubectl/resource.go @@ -28,4 +28,6 @@ const ( ResourceVMIP Resource = "virtualmachineipaddresses.virtualization.deckhouse.io" ResourceVMIPLease Resource = "virtualmachineipaddressleases.virtualization.deckhouse.io" ResourceCVI Resource = "clustervirtualimages.virtualization.deckhouse.io" + ResourceVI Resource = "virtualimages.virtualization.deckhouse.io" + ResourceVMBDA Resource = "virtualmachineblockdeviceattachments.virtualization.deckhouse.io" ) diff --git a/tests/e2e/testdata/templates/kustomization.yaml b/tests/e2e/testdata/templates/kustomization.yaml index f31e51dba..25ef538ee 100644 --- a/tests/e2e/testdata/templates/kustomization.yaml +++ b/tests/e2e/testdata/templates/kustomization.yaml @@ -2,9 +2,11 @@ apiVersion: kustomize.config.k8s.io/v1beta1 kind: Kustomization namespace: testcases namePrefix: pr-number-or-commit-hash- -commonLabels: - testcase: pr-number-or-commit-hash resources: - ns.yaml configurations: - transformer.yaml +labels: + - includeSelectors: true + pairs: + id: pr-number-or-commit-hash diff --git a/tests/e2e/testdata/virtualization-resources/kustomization.yaml b/tests/e2e/testdata/virtualization-resources/kustomization.yaml index 68aa4c4d6..89382467c 100644 --- a/tests/e2e/testdata/virtualization-resources/kustomization.yaml +++ b/tests/e2e/testdata/virtualization-resources/kustomization.yaml @@ -13,4 +13,4 @@ configurations: labels: - includeSelectors: true pairs: - testcase: pr-number-or-commit-hash + id: pr-number-or-commit-hash diff --git a/tests/e2e/testdata/vm-configuration/base/cfg/cloudinit.yaml b/tests/e2e/testdata/vm-configuration/base/cfg/cloudinit.yaml new file mode 100644 index 000000000..e9ceb0454 --- /dev/null +++ b/tests/e2e/testdata/vm-configuration/base/cfg/cloudinit.yaml @@ -0,0 +1,12 @@ +#cloud-config +users: + - name: cloud + # passwd: cloud + passwd: $6$rounds=4096$vln/.aPHBOI7BMYR$bBMkqQvuGs5Gyd/1H5DP4m9HjQSy.kgrxpaGEHwkX7KEFV8BS.HZWPitAtZ2Vd8ZqIZRqmlykRCagTgPejt1i. + shell: /bin/bash + sudo: ALL=(ALL) NOPASSWD:ALL + chpasswd: { expire: False } + lock_passwd: false + ssh_authorized_keys: + # testcases + - ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFxcXHmwaGnJ8scJaEN5RzklBPZpVSic4GdaAsKjQoeA your_email@example.com diff --git a/tests/e2e/testdata/vm-configuration/base/kustomization.yaml b/tests/e2e/testdata/vm-configuration/base/kustomization.yaml new file mode 100644 index 000000000..894de6024 --- /dev/null +++ b/tests/e2e/testdata/vm-configuration/base/kustomization.yaml @@ -0,0 +1,15 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - ./vm.yaml + - ./vd-root.yaml + - ./vd-blank.yaml +configurations: + - transformer.yaml +generatorOptions: + disableNameSuffixHash: true +secretGenerator: + - files: + - userdata=cfg/cloudinit.yaml + name: cloud-init + type: Opaque diff --git a/tests/e2e/testdata/vm-configuration/base/transformer.yaml b/tests/e2e/testdata/vm-configuration/base/transformer.yaml new file mode 100644 index 000000000..c70c289af --- /dev/null +++ b/tests/e2e/testdata/vm-configuration/base/transformer.yaml @@ -0,0 +1,54 @@ +# https://github.com/kubernetes-sigs/kustomize/blob/master/examples/transformerconfigs/README.md#transformer-configurations + +namespace: + - kind: ClusterVirtualImage + path: spec/dataSource/objectRef/namespace +nameReference: + - kind: VirtualImage + version: v1alpha2 # optional + fieldSpecs: + - path: spec/dataSource/objectRef/name + kind: ClusterVirtualImage + - path: spec/dataSource/objectRef/name + kind: VirtualImage + - path: spec/dataSource/objectRef/name + kind: VirtualDisk + - path: spec/blockDeviceRefs/name + kind: VirtualMachine + - kind: ClusterVirtualImage + version: v1alpha2 # optional + fieldSpecs: + - path: spec/dataSource/objectRef/name + kind: ClusterVirtualImage + - path: spec/dataSource/objectRef/name + kind: VirtualImage + - path: spec/dataSource/objectRef/name + kind: VirtualDisk + - path: spec/blockDeviceRefs/name + kind: VirtualMachine + - kind: VirtualDisk + version: v1alpha2 # optional + fieldSpecs: + - path: spec/blockDeviceRefs/name + kind: VirtualMachine + - path: spec/blockDeviceRef/name + kind: VirtualMachineBlockDeviceAttachment + - kind: Secret + fieldSpecs: + - path: spec/provisioning/userDataRef/name + kind: VirtualMachine + - kind: VirtualMachineIPAddress + version: v1alpha2 + fieldSpecs: + - path: spec/virtualMachineIPAddressName + kind: VirtualMachine + - kind: VirtualMachine + version: v1alpha2 + fieldSpecs: + - path: spec/virtualMachineName + kind: VirtualMachineBlockDeviceAttachment + - kind: VirtualMachineClass + version: v1alpha2 + fieldSpecs: + - path: spec/virtualMachineClassName + kind: VirtualMachine diff --git a/tests/e2e/testdata/vm-configuration/base/vd-attach.yaml b/tests/e2e/testdata/vm-configuration/base/vd-attach.yaml new file mode 100644 index 000000000..a4862dd65 --- /dev/null +++ b/tests/e2e/testdata/vm-configuration/base/vd-attach.yaml @@ -0,0 +1,7 @@ +apiVersion: virtualization.deckhouse.io/v1alpha2 +kind: VirtualDisk +metadata: + name: vd-attach +spec: + persistentVolumeClaim: + size: 100Mi diff --git a/tests/e2e/testdata/vm-configuration/base/vd-blank.yaml b/tests/e2e/testdata/vm-configuration/base/vd-blank.yaml new file mode 100644 index 000000000..efe05d720 --- /dev/null +++ b/tests/e2e/testdata/vm-configuration/base/vd-blank.yaml @@ -0,0 +1,7 @@ +apiVersion: virtualization.deckhouse.io/v1alpha2 +kind: VirtualDisk +metadata: + name: vd-blank +spec: + persistentVolumeClaim: + size: 100Mi diff --git a/tests/e2e/testdata/vm-configuration/base/vd-root.yaml b/tests/e2e/testdata/vm-configuration/base/vd-root.yaml new file mode 100644 index 000000000..79dfd103e --- /dev/null +++ b/tests/e2e/testdata/vm-configuration/base/vd-root.yaml @@ -0,0 +1,12 @@ +apiVersion: virtualization.deckhouse.io/v1alpha2 +kind: VirtualDisk +metadata: + name: vd-root +spec: + persistentVolumeClaim: + size: 512Mi + dataSource: + type: ObjectRef + objectRef: + kind: VirtualImage + name: vi-alpine-http diff --git a/tests/e2e/testdata/vm-configuration/base/vm.yaml b/tests/e2e/testdata/vm-configuration/base/vm.yaml new file mode 100644 index 000000000..4c1d151f4 --- /dev/null +++ b/tests/e2e/testdata/vm-configuration/base/vm.yaml @@ -0,0 +1,23 @@ +apiVersion: virtualization.deckhouse.io/v1alpha2 +kind: VirtualMachine +metadata: + name: vm +spec: + virtualMachineClassName: generic + cpu: + cores: 1 + coreFraction: 5% + memory: + size: 256Mi + disruptions: + restartApprovalMode: Manual + provisioning: + type: UserDataRef + userDataRef: + kind: Secret + name: cloud-init + blockDeviceRefs: + - kind: VirtualDisk + name: vd-root + - kind: VirtualDisk + name: vd-blank diff --git a/tests/e2e/testdata/vm-configuration/kustomization.yaml b/tests/e2e/testdata/vm-configuration/kustomization.yaml new file mode 100644 index 000000000..e0cfe1dff --- /dev/null +++ b/tests/e2e/testdata/vm-configuration/kustomization.yaml @@ -0,0 +1,16 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +namespace: testcases +namePrefix: pr-number-or-commit-hash- +resources: + - ns.yaml + - vi + - overlays/automatic + - overlays/manual +configurations: + - transformer.yaml +labels: + - includeSelectors: true + pairs: + id: pr-number-or-commit-hash + testcase: vm-configuration diff --git a/tests/e2e/testdata/vm-configuration/ns.yaml b/tests/e2e/testdata/vm-configuration/ns.yaml new file mode 100644 index 000000000..5efde875b --- /dev/null +++ b/tests/e2e/testdata/vm-configuration/ns.yaml @@ -0,0 +1,4 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: default diff --git a/tests/e2e/testdata/vm-configuration/overlays/automatic/kustomization.yaml b/tests/e2e/testdata/vm-configuration/overlays/automatic/kustomization.yaml new file mode 100644 index 000000000..32ee399c6 --- /dev/null +++ b/tests/e2e/testdata/vm-configuration/overlays/automatic/kustomization.yaml @@ -0,0 +1,24 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +nameSuffix: -automatic-conf +resources: + - ../../base +patches: + - patch: |- + - op: replace + path: /spec/runPolicy + value: AlwaysOn + target: + kind: VirtualMachine + name: vm + - patch: |- + - op: replace + path: /spec/disruptions/restartApprovalMode + value: Automatic + target: + kind: VirtualMachine + name: vm +labels: + - includeSelectors: true + pairs: + vm: automatic-conf diff --git a/tests/e2e/testdata/vm-configuration/overlays/manual/kustomization.yaml b/tests/e2e/testdata/vm-configuration/overlays/manual/kustomization.yaml new file mode 100644 index 000000000..01ad7addb --- /dev/null +++ b/tests/e2e/testdata/vm-configuration/overlays/manual/kustomization.yaml @@ -0,0 +1,17 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +nameSuffix: -manual-conf +resources: + - ../../base +patches: + - patch: |- + - op: replace + path: /spec/runPolicy + value: AlwaysOn + target: + kind: VirtualMachine + name: vm +labels: + - includeSelectors: true + pairs: + vm: manual-conf diff --git a/tests/e2e/testdata/vm-configuration/transformer.yaml b/tests/e2e/testdata/vm-configuration/transformer.yaml new file mode 100644 index 000000000..e827a1923 --- /dev/null +++ b/tests/e2e/testdata/vm-configuration/transformer.yaml @@ -0,0 +1,52 @@ +namespace: + - kind: ClusterVirtualImage + path: spec/dataSource/objectRef/namespace +nameReference: + - kind: VirtualImage + version: v1alpha2 # optional + fieldSpecs: + - path: spec/dataSource/objectRef/name + kind: ClusterVirtualImage + - path: spec/dataSource/objectRef/name + kind: VirtualImage + - path: spec/dataSource/objectRef/name + kind: VirtualDisk + - path: spec/blockDeviceRefs/name + kind: VirtualMachine + - kind: ClusterVirtualImage + version: v1alpha2 # optional + fieldSpecs: + - path: spec/dataSource/objectRef/name + kind: ClusterVirtualImage + - path: spec/dataSource/objectRef/name + kind: VirtualImage + - path: spec/dataSource/objectRef/name + kind: VirtualDisk + - path: spec/blockDeviceRefs/name + kind: VirtualMachine + - kind: VirtualDisk + version: v1alpha2 # optional + fieldSpecs: + - path: spec/blockDeviceRefs/name + kind: VirtualMachine + - path: spec/blockDeviceRef/name + kind: VirtualMachineBlockDeviceAttachment + - kind: Secret + fieldSpecs: + - path: spec/provisioning/userDataRef/name + kind: VirtualMachine + - kind: VirtualMachineIPAddress + version: v1alpha2 + fieldSpecs: + - path: spec/virtualMachineIPAddressName + kind: VirtualMachine + - kind: VirtualMachine + version: v1alpha2 + fieldSpecs: + - path: spec/virtualMachineName + kind: VirtualMachineBlockDeviceAttachment + - kind: VirtualMachineClass + version: v1alpha2 + fieldSpecs: + - path: spec/virtualMachineClassName + kind: VirtualMachine diff --git a/tests/e2e/testdata/vm-configuration/vi/kustomization.yaml b/tests/e2e/testdata/vm-configuration/vi/kustomization.yaml new file mode 100644 index 000000000..b807d8e2d --- /dev/null +++ b/tests/e2e/testdata/vm-configuration/vi/kustomization.yaml @@ -0,0 +1,4 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - vi-alpine-http.yaml diff --git a/tests/e2e/testdata/vm-configuration/vi/vi-alpine-http.yaml b/tests/e2e/testdata/vm-configuration/vi/vi-alpine-http.yaml new file mode 100644 index 000000000..dab7aba67 --- /dev/null +++ b/tests/e2e/testdata/vm-configuration/vi/vi-alpine-http.yaml @@ -0,0 +1,11 @@ +--- +apiVersion: virtualization.deckhouse.io/v1alpha2 +kind: VirtualImage +metadata: + name: vi-alpine-http +spec: + storage: ContainerRegistry + dataSource: + type: HTTP + http: + url: https://0e773854-6b4e-4e76-a65b-d9d81675451a.selstorage.ru/alpine/alpine-3-20.qcow2 diff --git a/tests/e2e/tests_suite_test.go b/tests/e2e/tests_suite_test.go index 2211f1cf7..2d7bc0ede 100644 --- a/tests/e2e/tests_suite_test.go +++ b/tests/e2e/tests_suite_test.go @@ -22,13 +22,14 @@ import ( "testing" "time" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "github.com/deckhouse/virtualization/tests/e2e/config" d8 "github.com/deckhouse/virtualization/tests/e2e/d8" gt "github.com/deckhouse/virtualization/tests/e2e/git" kc "github.com/deckhouse/virtualization/tests/e2e/kubectl" virt "github.com/deckhouse/virtualization/tests/e2e/virtctl" - . "github.com/onsi/ginkgo/v2" - . "github.com/onsi/gomega" ) const ( @@ -83,8 +84,9 @@ func init() { conf.Namespace = fmt.Sprintf("%s-%s", namePrefix, conf.Namespace) // TODO: get kustomization files from testdata directory when all tests will be refactored kustomizationFiles := []string{ - fmt.Sprintf("%s/%s", conf.VirtualizationResources, "kustomization.yaml"), - fmt.Sprintf("%s/%s", conf.Connectivity, "kustomization.yaml"), + fmt.Sprintf("%s/%s", conf.TestData.VirtualizationResources, "kustomization.yaml"), + fmt.Sprintf("%s/%s", conf.TestData.Connectivity, "kustomization.yaml"), + fmt.Sprintf("%s/%s", conf.TestData.VmConfiguration, "kustomization.yaml"), } for _, filePath := range kustomizationFiles { if err = kustomize.SetParams(filePath, conf.Namespace, namePrefix); err != nil { @@ -108,6 +110,6 @@ func TestTests(t *testing.T) { func Cleanup() { kubectl.DeleteResource(kc.ResourceNamespace, conf.Namespace, kc.DeleteOptions{}) kubectl.DeleteResource(kc.ResourceCVI, "", kc.DeleteOptions{ - Labels: map[string]string{"testcase": namePrefix}, + Labels: map[string]string{"id": namePrefix}, }) } diff --git a/tests/e2e/util_test.go b/tests/e2e/util_test.go index 31656c668..3ea49e5fe 100644 --- a/tests/e2e/util_test.go +++ b/tests/e2e/util_test.go @@ -30,13 +30,12 @@ import ( corev1 "k8s.io/api/core/v1" storagev1 "k8s.io/api/storage/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" "github.com/deckhouse/virtualization/tests/e2e/executor" "github.com/deckhouse/virtualization/tests/e2e/helper" kc "github.com/deckhouse/virtualization/tests/e2e/kubectl" - - "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" ) type ApplyWaitGetOptions struct { @@ -57,7 +56,6 @@ func ItApplyWaitGet(filepath string, options ApplyWaitGetOptions) { ItApplyFromFile(filepath) ItWaitFromFile(filepath, phase, timeout) ItChekStatusPhaseFromFile(filepath, phase) - } func ItApplyFromFile(filepath string) { @@ -65,7 +63,6 @@ func ItApplyFromFile(filepath string) { It("Apply resource from file", func() { ApplyFromFile(filepath) }) - } func ApplyFromFile(filepath string) { @@ -81,6 +78,7 @@ func ItWaitFromFile(filepath, phase string, timeout time.Duration) { WaitFromFile(filepath, phase, timeout) }) } + func WaitFromFile(filepath, phase string, timeout time.Duration) { GinkgoHelper() For := "jsonpath={.status.phase}=" + phase @@ -111,7 +109,8 @@ func ItCheckStatusFromFile(filepath, output, compareField string) { } else { res = kubectl.GetResource(fullName, u.GetName(), kc.GetOptions{ Output: output, - Namespace: u.GetNamespace()}) + Namespace: u.GetNamespace(), + }) } Expect(res.Error()).NotTo(HaveOccurred(), "get failed resource %s %s/%s.\n%s", @@ -125,11 +124,11 @@ func ItCheckStatusFromFile(filepath, output, compareField string) { } } -func WaitResource(resource kc.Resource, name, For string, timeout time.Duration) { +func WaitResource(resource kc.Resource, name, waitFor string, timeout time.Duration) { GinkgoHelper() waitOpts := kc.WaitOptions{ Namespace: conf.Namespace, - For: For, + For: waitFor, Timeout: timeout, } res := kubectl.WaitResources(resource, waitOpts, name) @@ -146,7 +145,7 @@ func PatchResource(resource kc.Resource, name string, patch *kc.JsonPatch) { res.StdErr()) } -func MergePatchResource(resource kc.Resource, name string, patch string) { +func MergePatchResource(resource kc.Resource, name, patch string) { GinkgoHelper() res := kubectl.PatchResource(resource, name, kc.PatchOptions{ Namespace: conf.Namespace, @@ -169,10 +168,12 @@ func CheckField(resource kc.Resource, name, output, compareValue string) { type VirtualMachine struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` - Spec VirtualMachineSpec `json:"spec"` + Spec VirtualMachineSpec `json:"spec"` + Status VirtualMachineStatus `json:"status"` } type VirtualMachineSpec struct { + CPU CPUSpec `json:"cpu"` RunPolicy RunPolicy `json:"runPolicy"` VirtualMachineIPAddressClaimName string `json:"virtualMachineIPAddressClaimName,omitempty"` NodeSelector map[string]string `json:"nodeSelector,omitempty"` @@ -184,6 +185,20 @@ type VirtualMachineSpec struct { ApprovedChangeID string `json:"approvedChangeID,omitempty"` } +type CPUSpec struct { + CoreFraction string `json:"coreFraction"` + Cores int `json:"cores"` +} + +type VirtualMachineStatus struct { + RestartAwaitingChanges []RestartAwaitingChange `json:"restartAwaitingChanges,omitempty"` +} + +type RestartAwaitingChange struct { + Operation string `json:"operation"` + Path string `json:"path"` +} + type RunPolicy string func GetVMFromManifest(manifest string) (*VirtualMachine, error) { @@ -205,8 +220,21 @@ func GetVMFromManifest(manifest string) (*VirtualMachine, error) { return &vm, nil } -func ChmodFile(pathFile string, permission os.FileMode) { +func GetVirtualMachine(name, namespace string) (*VirtualMachine, error) { + GinkgoHelper() + getVmCmd := kubectl.GetResource(kc.ResourceVM, name, kc.GetOptions{Namespace: namespace, Output: "json"}) + if getVmCmd.Error() != nil { + return nil, fmt.Errorf(getVmCmd.StdErr()) + } + var vmResource VirtualMachine + unmarshalErr := json.Unmarshal(getVmCmd.StdOutBytes(), &vmResource) + if unmarshalErr != nil { + return nil, unmarshalErr + } + return &vmResource, nil +} +func ChmodFile(pathFile string, permission os.FileMode) { stats, err := os.Stat(pathFile) if err != nil { log.Fatal(err) @@ -220,24 +248,20 @@ func ChmodFile(pathFile string, permission os.FileMode) { } } -func WaitPhase(resource, phase string) { +func WaitPhase(resource kc.Resource, phase string, opts kc.GetOptions) { GinkgoHelper() - resourceType := kc.Resource(resource) jsonPath := fmt.Sprintf("'jsonpath={.status.phase}=%s'", phase) - res := kubectl.List(resourceType, kc.GetOptions{ - Namespace: conf.Namespace, - Output: "jsonpath='{.items[*].metadata.name}'", - }) + res := kubectl.List(resource, opts) Expect(res.WasSuccess()).To(Equal(true), res.StdErr()) resources := strings.Split(res.StdOut(), " ") waitOpts := kc.WaitOptions{ - Namespace: conf.Namespace, + Namespace: opts.Namespace, For: jsonPath, Timeout: 600, } - waitResult := kubectl.WaitResources(resourceType, waitOpts, resources...) + waitResult := kubectl.WaitResources(resource, waitOpts, resources...) Expect(waitResult.WasSuccess()).To(Equal(true), waitResult.StdErr()) } diff --git a/tests/e2e/vm_configuration_test.go b/tests/e2e/vm_configuration_test.go new file mode 100644 index 000000000..86ba9dace --- /dev/null +++ b/tests/e2e/vm_configuration_test.go @@ -0,0 +1,239 @@ +/* +Copyright 2024 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 e2e + +import ( + "fmt" + "strings" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + d8 "github.com/deckhouse/virtualization/tests/e2e/d8" + kc "github.com/deckhouse/virtualization/tests/e2e/kubectl" +) + +const ( + AutomaticMode = "automatic" + ManualMode = "manual" + StageBefore = "before" + StageAfter = "after" +) + +var ( + AutomaticLabel = map[string]string{"vm": "automatic-conf"} + ManualLabel = map[string]string{"vm": "manual-conf"} +) + +func ExecSshCommand(vmName, cmd, key string) { + GinkgoHelper() + Eventually(func(g Gomega) { + res := d8Virtualization.SshCommand(vmName, cmd, d8.SshOptions{ + Namespace: conf.Namespace, + Username: "cloud", + IdenityFile: key, + }) + g.Expect(res.Error()).NotTo(HaveOccurred(), "check ssh failed for %s/%s.\n%s\n%s", conf.Namespace, vmName, res.StdErr(), key) + }).WithTimeout(Timeout).WithPolling(Interval).Should(Succeed()) +} + +func ChangeCPUCoresNumber(namespace string, 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") + patchRes := kubectl.RawCommand(cmd, ShortWaitDuration) + Expect(patchRes.WasSuccess()).To(Equal(true), patchRes.StdErr()) +} + +func CheckCPUCoresNumber(approvalMode, stage string, requiredValue int, virtualMachines ...string) { + for _, vm := range virtualMachines { + By(fmt.Sprintf("Checking the number of processor cores %s changing", stage)) + vmResource, err := GetVirtualMachine(vm, conf.Namespace) + Expect(err).NotTo(HaveOccurred(), err) + Expect(vmResource.Spec.CPU.Cores).To(Equal(requiredValue)) + switch { + case approvalMode == ManualMode && stage == StageAfter: + Expect(vmResource.Status.RestartAwaitingChanges).ShouldNot(BeNil()) + case approvalMode == AutomaticMode && stage == StageAfter: + Expect(vmResource.Status.RestartAwaitingChanges).Should(BeNil()) + } + } +} + +func CheckCPUCoresNumberFromVirtualMachine(requiredValue, key string, virtualMachines ...string) { + By("Checking the number of processor cores after changing from virtual machine") + for _, vm := range virtualMachines { + cmd := "nproc --all" + CheckResultSshCommand(vm, cmd, requiredValue, key) + } +} + +var _ = Describe("Virtual machine configuration", Ordered, ContinueOnFailure, func() { + Context("When resources are applied:", func() { + It("must has no errors", func() { + res := kubectl.Kustomize(conf.TestData.VmConfiguration, kc.KustomizeOptions{}) + Expect(res.WasSuccess()).To(Equal(true), res.StdErr()) + }) + }) + + Context("When virtual disks are applied:", func() { + It(fmt.Sprintf("should be is in %s phase", PhaseReady), func() { + WaitPhase(kc.ResourceVD, PhaseReady, kc.GetOptions{ + Labels: map[string]string{"testcase": "vm-configuration"}, + Namespace: conf.Namespace, + Output: "jsonpath='{.items[*].metadata.name}'", + }) + }) + }) + + Context("When virtual machines are applied:", func() { + It(fmt.Sprintf("should be is in %s phase", PhaseRunning), func() { + WaitPhase(kc.ResourceVM, PhaseRunning, kc.GetOptions{ + Labels: map[string]string{"testcase": "vm-configuration"}, + Namespace: conf.Namespace, + Output: "jsonpath='{.items[*].metadata.name}'", + }) + }) + }) + + Describe("Manual restart approval mode", func() { + 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{ + Labels: ManualLabel, + Namespace: conf.Namespace, + Output: "jsonpath='{.items[*].metadata.name}'", + }) + Expect(res.WasSuccess()).To(Equal(true), res.StdErr()) + + vms := strings.Split(res.StdOut(), " ") + CheckCPUCoresNumber(ManualMode, StageBefore, 1, vms...) + ChangeCPUCoresNumber(conf.Namespace, 2, vms...) + }) + }) + + Context("When virtual machine is patched:", func() { + It("checks the number of processor cores in specification", func() { + res := kubectl.List(kc.ResourceVM, kc.GetOptions{ + Labels: ManualLabel, + Namespace: conf.Namespace, + Output: "jsonpath='{.items[*].metadata.name}'", + }) + Expect(res.WasSuccess()).To(Equal(true), res.StdErr()) + + vms := strings.Split(res.StdOut(), " ") + CheckCPUCoresNumber(ManualMode, StageAfter, 2, vms...) + }) + }) + + Context("When virtual machine is restarted:", func() { + sshKeyPath := fmt.Sprintf("%s/id_ed", conf.TestData.Sshkeys) + It(fmt.Sprintf("should be is in %s phase", PhaseRunning), func() { + res := kubectl.List(kc.ResourceVM, kc.GetOptions{ + Labels: ManualLabel, + Namespace: conf.Namespace, + Output: "jsonpath='{.items[*].metadata.name}'", + }) + Expect(res.WasSuccess()).To(Equal(true), res.StdErr()) + + vms := strings.Split(res.StdOut(), " ") + for _, vm := range vms { + cmd := "sudo reboot" + ExecSshCommand(vm, cmd, sshKeyPath) + } + WaitPhase(kc.ResourceVM, PhaseRunning, kc.GetOptions{ + Labels: ManualLabel, + Namespace: conf.Namespace, + Output: "jsonpath='{.items[*].metadata.name}'", + }) + }) + }) + + Context(fmt.Sprintf("When virtual machine is in %s phase:", PhaseRunning), func() { + sshKeyPath := fmt.Sprintf("%s/id_ed", conf.TestData.Sshkeys) + + It("checks that the number of processor cores was changed", func() { + res := kubectl.List(kc.ResourceVM, kc.GetOptions{ + Labels: ManualLabel, + Namespace: conf.Namespace, + Output: "jsonpath='{.items[*].metadata.name}'", + }) + Expect(res.WasSuccess()).To(Equal(true), res.StdErr()) + + vms := strings.Split(res.StdOut(), " ") + CheckCPUCoresNumberFromVirtualMachine("2", sshKeyPath, vms...) + }) + }) + }) + + Describe("Automatic restart approval mode", func() { + 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{ + Labels: AutomaticLabel, + Namespace: conf.Namespace, + Output: "jsonpath='{.items[*].metadata.name}'", + }) + Expect(res.WasSuccess()).To(Equal(true), res.StdErr()) + + vms := strings.Split(res.StdOut(), " ") + CheckCPUCoresNumber(AutomaticMode, StageBefore, 1, vms...) + ChangeCPUCoresNumber(conf.Namespace, 2, vms...) + }) + }) + + Context("When virtual machine is patched:", func() { + It("checks the number of processor cores in specification", func() { + res := kubectl.List(kc.ResourceVM, kc.GetOptions{ + Labels: AutomaticLabel, + Namespace: conf.Namespace, + Output: "jsonpath='{.items[*].metadata.name}'", + }) + Expect(res.WasSuccess()).To(Equal(true), res.StdErr()) + + vms := strings.Split(res.StdOut(), " ") + CheckCPUCoresNumber(AutomaticMode, StageAfter, 2, vms...) + }) + }) + + Context("When virtual machine is restarted:", func() { + It(fmt.Sprintf("should be is in %s phase", PhaseRunning), func() { + WaitPhase(kc.ResourceVM, PhaseRunning, kc.GetOptions{ + Labels: AutomaticLabel, + Namespace: conf.Namespace, + Output: "jsonpath='{.items[*].metadata.name}'", + }) + }) + }) + + Context(fmt.Sprintf("When virtual machine is in %s phase:", PhaseRunning), func() { + sshKeyPath := fmt.Sprintf("%s/id_ed", conf.TestData.Sshkeys) + + It("checks that the number of processor cores was changed", func() { + res := kubectl.List(kc.ResourceVM, kc.GetOptions{ + Labels: AutomaticLabel, + Namespace: conf.Namespace, + Output: "jsonpath='{.items[*].metadata.name}'", + }) + Expect(res.WasSuccess()).To(Equal(true), res.StdErr()) + + vms := strings.Split(res.StdOut(), " ") + CheckCPUCoresNumberFromVirtualMachine("2", sshKeyPath, vms...) + }) + }) + }) +}) diff --git a/tests/e2e/vm_connectivity_test.go b/tests/e2e/vm_connectivity_test.go index 627a69f00..77eae740b 100644 --- a/tests/e2e/vm_connectivity_test.go +++ b/tests/e2e/vm_connectivity_test.go @@ -24,28 +24,25 @@ import ( "strings" "time" - "github.com/deckhouse/virtualization/tests/e2e/executor" - "sigs.k8s.io/yaml" - . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" + "sigs.k8s.io/yaml" d8 "github.com/deckhouse/virtualization/tests/e2e/d8" + "github.com/deckhouse/virtualization/tests/e2e/executor" kc "github.com/deckhouse/virtualization/tests/e2e/kubectl" - corev1 "k8s.io/api/core/v1" ) const ( CurlPod = "curl-helper" - Timeout = 40 * time.Second + Timeout = 90 * time.Second Interval = 5 * time.Second externalHost = "https://flant.com" nginxActiveStatus = "active" ) -var ( - httpStatusOk = fmt.Sprintf("%v", http.StatusOK) -) +var httpStatusOk = fmt.Sprintf("%v", http.StatusOK) type PodEntrypoint struct { Command string @@ -117,7 +114,7 @@ var _ = Describe("VM connectivity", Ordered, ContinueOnFailure, func() { Context("Resources", func() { When("Resources applied", func() { It("Result must have no error", func() { - res := kubectl.Kustomize(conf.Connectivity, kc.KustomizeOptions{}) + res := kubectl.Kustomize(conf.TestData.Connectivity, kc.KustomizeOptions{}) Expect(res.WasSuccess()).To(Equal(true), res.StdErr()) }) }) @@ -153,11 +150,11 @@ var _ = Describe("VM connectivity", Ordered, ContinueOnFailure, func() { vm1Name := fmt.Sprintf("%s-vm1", namePrefix) vm2Name := fmt.Sprintf("%s-vm2", namePrefix) - svc1Path := fmt.Sprintf("%s/resources/vm1-svc.yaml", conf.Connectivity) - svc2Path := fmt.Sprintf("%s/resources/vm2-svc.yaml", conf.Connectivity) + svc1Path := fmt.Sprintf("%s/resources/vm1-svc.yaml", conf.TestData.Connectivity) + svc2Path := fmt.Sprintf("%s/resources/vm2-svc.yaml", conf.TestData.Connectivity) - sshKeyPath := fmt.Sprintf("%s/id_ed", conf.Sshkeys) - ChmodFile(sshKeyPath, 0600) + sshKeyPath := fmt.Sprintf("%s/id_ed", conf.TestData.Sshkeys) + ChmodFile(sshKeyPath, 0o600) svc1, err := getSVC(svc1Path) Expect(err).NotTo(HaveOccurred(), err) diff --git a/tests/e2e/vm_label_annotation_test.go b/tests/e2e/vm_label_annotation_test.go index a6c2f2004..95368ff12 100644 --- a/tests/e2e/vm_label_annotation_test.go +++ b/tests/e2e/vm_label_annotation_test.go @@ -122,7 +122,6 @@ var _ = Describe("Label and Annotation", Ordered, ContinueOnFailure, func() { }) Describe("Check label on resource", func() { - It("VM", func() { res := getRecourseLabel(kc.ResourceVM, vm.Name) Expect(res.Error()).NotTo(HaveOccurred(), "failed to get VM %s.\n%s", vm.Name, res.StdErr()) @@ -147,7 +146,6 @@ var _ = Describe("Label and Annotation", Ordered, ContinueOnFailure, func() { }) Describe(fmt.Sprintf("Remove label %s=%s", labelName, labelValue), func() { - It("Label was removed", func() { subCMD := fmt.Sprintf("-n %s label vm %s %s-", conf.Namespace, vm.Name, labelName) res := kubectl.RawCommand(subCMD, ShortWaitDuration) @@ -156,7 +154,6 @@ var _ = Describe("Label and Annotation", Ordered, ContinueOnFailure, func() { }) Describe("Label must be removed from resource", func() { - It("VM", func() { res := getRecourseLabel(kc.ResourceVM, vm.Name) Expect(res.Error()).NotTo(HaveOccurred(), "failed to get VM %s.\n%s", vm.Name, res.StdErr()) @@ -232,7 +229,6 @@ var _ = Describe("Label and Annotation", Ordered, ContinueOnFailure, func() { }) Describe("Remove annotation test-annotation=true", func() { - It("Was removed", func() { subCMD := fmt.Sprintf("-n %s annotate vm %s %s-", conf.Namespace, vm.Name, annotationName) res := kubectl.RawCommand(subCMD, ShortWaitDuration) diff --git a/tests/e2e/vm_test.go b/tests/e2e/vm_test.go index e584e9c71..53bb00350 100644 --- a/tests/e2e/vm_test.go +++ b/tests/e2e/vm_test.go @@ -193,12 +193,11 @@ var _ = Describe("VM", Ordered, ContinueOnFailure, func() { GetKubevirtRunStrategy(name, KubeVirtRunStrategyAlways) }) }) - }) Context("Provisioning", func() { BeforeAll(func() { - ChmodFile(vmPath("provisioning/id_ed"), 0600) + ChmodFile(vmPath("provisioning/id_ed"), 0o600) }) CheckSsh := func(vmName string) { GinkgoHelper() @@ -218,7 +217,6 @@ var _ = Describe("VM", Ordered, ContinueOnFailure, func() { vm, err := GetVMFromManifest(manifest) Expect(err).To(BeNil()) name = vm.Name - }) ItApplyFromFile(manifest) It("Wait vm running", func() { @@ -243,7 +241,6 @@ var _ = Describe("VM", Ordered, ContinueOnFailure, func() { }) Context("Network", func() { - }) Context("Resources", func() { @@ -267,7 +264,7 @@ var _ = Describe("VM", Ordered, ContinueOnFailure, func() { Expect(resKubevirt.Limits.Cpu().String()).To(Equal("1")) Expect(resKubevirt.Limits.Memory().String()).To(Equal("1Gi")) } - CompareRequrest := func(resKubevirt *corev1.ResourceRequirements, cpu string, mem string) { + CompareRequrest := func(resKubevirt *corev1.ResourceRequirements, cpu, mem string) { GinkgoHelper() Expect(resKubevirt.Requests.Cpu().String()).To(Equal(cpu)) Expect(resKubevirt.Requests.Memory().String()).To(Equal(mem)) @@ -312,7 +309,6 @@ var _ = Describe("VM", Ordered, ContinueOnFailure, func() { }) Context("NodePlacement", func() { - }) Context("PriorityClassName", func() { @@ -396,5 +392,4 @@ var _ = Describe("VM", Ordered, ContinueOnFailure, func() { }) }) }) - })