From 1562acb96a309bf5b9a461b8044f1d004a318a6e Mon Sep 17 00:00:00 2001 From: Ivan Mikheykin Date: Fri, 22 May 2026 11:28:02 +0300 Subject: [PATCH 1/4] chore(test): fix command to create generic-for-e2e vmclass Signed-off-by: Ivan Mikheykin --- test/e2e/internal/precheck/vmc.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/test/e2e/internal/precheck/vmc.go b/test/e2e/internal/precheck/vmc.go index c48aa8401a..05f6efd0a1 100644 --- a/test/e2e/internal/precheck/vmc.go +++ b/test/e2e/internal/precheck/vmc.go @@ -115,13 +115,17 @@ func (c *vmcPrecheck) Run(ctx context.Context, f *framework.Framework) error { return fmt.Errorf("%s=no to disable this precheck: cluster has no default class, e2e tests require %q to be default. Run: kubectl annotate vmclass/%s virtualmachineclass.virtualization.deckhouse.io/is-default-class=true", vmcModuleCheckEnvName, defaultVMClassName, defaultVMClassName) case e2eClass == nil && defaultClass == nil: - return fmt.Errorf("%s=no to disable this precheck: cluster has no default class and no %q class. Run: kubectl get vmclass/generic -o json | jq 'del(.status) | .metadata.annotations = {\"virtualmachineclass.virtualization.deckhouse.io/is-default-class\":\"true\"}' | kubectl create -f -", - vmcModuleCheckEnvName, defaultVMClassName) + return fmt.Errorf("%s=no to disable this precheck: cluster has no default class and no %q class. Run: %s", + vmcModuleCheckEnvName, defaultVMClassName, cmdCopyGenericAsDefaultClass(defaultVMClassName)) } return nil } +func cmdCopyGenericAsDefaultClass(targetVMClassName string) string { + return fmt.Sprintf(`kubectl get vmclass/generic -o json | jq 'del(.status) | del(.metadata) | .metadata = {"name":"%s","annotations":{"virtualmachineclass.virtualization.deckhouse.io/is-default-class":"true"}} ' | kubectl create -f -`, targetVMClassName) +} + // Register VMC precheck as common (runs for all tests). func init() { RegisterPrecheck(&vmcPrecheck{}, true) From e8c6d7dbeec326f65c2ded80ce72f148f10385d8 Mon Sep 17 00:00:00 2001 From: Ivan Mikheykin Date: Mon, 25 May 2026 11:25:10 +0300 Subject: [PATCH 2/4] ++ Signed-off-by: Ivan Mikheykin ++ split ifs Signed-off-by: Ivan Mikheykin --- test/e2e/internal/precheck/vmc.go | 52 +++++++++++++++++++++---------- 1 file changed, 35 insertions(+), 17 deletions(-) diff --git a/test/e2e/internal/precheck/vmc.go b/test/e2e/internal/precheck/vmc.go index 05f6efd0a1..d885a5e9e3 100644 --- a/test/e2e/internal/precheck/vmc.go +++ b/test/e2e/internal/precheck/vmc.go @@ -19,6 +19,7 @@ package precheck import ( "context" "fmt" + "strings" . "github.com/onsi/ginkgo/v2" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -101,31 +102,48 @@ func (c *vmcPrecheck) Run(ctx context.Context, f *framework.Framework) error { return name } - // Check if default VMClass exists and is correct - switch { - case e2eClass != nil && defaultClass != nil && getVMClassName(defaultClass) == defaultVMClassName: - // OK - case e2eClass != nil && defaultClass != nil: - return fmt.Errorf("%s=no to disable this precheck: cluster has wrong default class %q, e2e tests require %q to be default", - vmcModuleCheckEnvName, getVMClassName(defaultClass), defaultVMClassName) - case e2eClass == nil && defaultClass != nil: - return fmt.Errorf("%s=no to disable this precheck: cluster has wrong default class %q, e2e tests require %q to be default", - vmcModuleCheckEnvName, getVMClassName(defaultClass), defaultVMClassName) - case e2eClass != nil && defaultClass == nil: - return fmt.Errorf("%s=no to disable this precheck: cluster has no default class, e2e tests require %q to be default. Run: kubectl annotate vmclass/%s virtualmachineclass.virtualization.deckhouse.io/is-default-class=true", - vmcModuleCheckEnvName, defaultVMClassName, defaultVMClassName) - case e2eClass == nil && defaultClass == nil: - return fmt.Errorf("%s=no to disable this precheck: cluster has no default class and no %q class. Run: %s", - vmcModuleCheckEnvName, defaultVMClassName, cmdCopyGenericAsDefaultClass(defaultVMClassName)) + if e2eClass != nil && defaultClass != nil && getVMClassName(defaultClass) == defaultVMClassName { + // Everything is OK: correct default VMClass is present in the cluster. + return nil + } + + issues := make([]string, 0) + cmds := make([]string, 0) + + if defaultClass != nil { + issues = append(issues, fmt.Sprintf("cluster has wrong default vmclass %q", getVMClassName(defaultClass))) + cmds = append(cmds, cmdRemoveDefaultAnnotation(getVMClassName(defaultClass))) + } else { + issues = append(issues, "cluster has no default vmclass") + } + + if e2eClass != nil { + issues = append(issues, fmt.Sprintf("e2e tests require vmclass %q to be default", defaultVMClassName)) + cmds = append(cmds, cmdSetDefaultAnnotation(defaultVMClassName)) + } else { + issues = append(issues, fmt.Sprintf("e2e tests require vmclass %q to present and be default", defaultVMClassName)) + cmds = append(cmds, cmdCopyGenericAsDefaultClass(defaultVMClassName)) } - return nil + return fmt.Errorf("%s=no to disable this precheck: %s. Run command to fix cluster: %s", + vmcModuleCheckEnvName, + strings.Join(issues, "; "), + strings.Join(cmds, " && "), + ) } func cmdCopyGenericAsDefaultClass(targetVMClassName string) string { return fmt.Sprintf(`kubectl get vmclass/generic -o json | jq 'del(.status) | del(.metadata) | .metadata = {"name":"%s","annotations":{"virtualmachineclass.virtualization.deckhouse.io/is-default-class":"true"}} ' | kubectl create -f -`, targetVMClassName) } +func cmdRemoveDefaultAnnotation(targetVMClassName string) string { + return fmt.Sprintf(`kubectl annotate vmclass/%s virtualmachineclass.virtualization.deckhouse.io/is-default-class=-`, targetVMClassName) +} + +func cmdSetDefaultAnnotation(targetVMClassName string) string { + return fmt.Sprintf(`kubectl annotate vmclass/%s virtualmachineclass.virtualization.deckhouse.io/is-default-class=true`, targetVMClassName) +} + // Register VMC precheck as common (runs for all tests). func init() { RegisterPrecheck(&vmcPrecheck{}, true) From c29a83fc5654c6b6472d685a2d9572520fe20b31 Mon Sep 17 00:00:00 2001 From: Ivan Mikheykin Date: Tue, 26 May 2026 20:06:14 +0300 Subject: [PATCH 3/4] ++ Signed-off-by: Ivan Mikheykin --- test/e2e/internal/precheck/vmc.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/internal/precheck/vmc.go b/test/e2e/internal/precheck/vmc.go index d885a5e9e3..720690a4e8 100644 --- a/test/e2e/internal/precheck/vmc.go +++ b/test/e2e/internal/precheck/vmc.go @@ -125,7 +125,7 @@ func (c *vmcPrecheck) Run(ctx context.Context, f *framework.Framework) error { cmds = append(cmds, cmdCopyGenericAsDefaultClass(defaultVMClassName)) } - return fmt.Errorf("%s=no to disable this precheck: %s. Run command to fix cluster: %s", + return fmt.Errorf("%s=no to disable this precheck. Cluster has issues: %s. Run command to fix: %s", vmcModuleCheckEnvName, strings.Join(issues, "; "), strings.Join(cmds, " && "), From 8f8a11502580d339ae2f689305d91562151d2fe1 Mon Sep 17 00:00:00 2001 From: Roman Sysoev Date: Wed, 27 May 2026 13:22:18 +0300 Subject: [PATCH 4/4] refactor(test): optimize vmc precheck run method - rename defaultVMClassName to requiredVMClassName for clarity - extract defaultClassAnnotation as constant to avoid duplication - refactor loop to single pass through vmclasses - extract getVMClassName helper function to package level - add comments explaining variables purpose Signed-off-by: Roman Sysoev --- test/e2e/internal/precheck/vmc.go | 77 +++++++++++++++++-------------- 1 file changed, 43 insertions(+), 34 deletions(-) diff --git a/test/e2e/internal/precheck/vmc.go b/test/e2e/internal/precheck/vmc.go index 720690a4e8..6274da740f 100644 --- a/test/e2e/internal/precheck/vmc.go +++ b/test/e2e/internal/precheck/vmc.go @@ -30,9 +30,10 @@ import ( const ( vmcModuleCheckEnvName = "VMC_PRECHECK" - defaultVMClassName = "generic-for-e2e" + requiredVMClassName = "generic-for-e2e" - vmClassVersion = "v1alpha3" + vmClassVersion = "v1alpha3" + defaultClassAnnotation = "virtualmachineclass.virtualization.deckhouse.io/is-default-class" ) // vmcPrecheck implements Precheck interface for VMC/VMClass. @@ -61,55 +62,47 @@ func (c *vmcPrecheck) Run(ctx context.Context, f *framework.Framework) error { return fmt.Errorf("%s=no to disable this precheck: list VirtualMachineClasses: %w", vmcModuleCheckEnvName, err) } - var e2eClass map[string]interface{} - var defaultClass map[string]interface{} + var requiredClass map[string]interface{} // VMClass with requiredVMClassName + var defaultClass map[string]interface{} // VMClass with is-default-class annotation + // Single pass through all VMClasses for i := range vmClasses.Items { vmClass := vmClasses.Items[i].Object - name, ok := vmClass["metadata"].(map[string]interface{})["name"].(string) + + metadata, ok := vmClass["metadata"].(map[string]interface{}) if !ok { continue } - if name == defaultVMClassName { - e2eClass = vmClass - } - - // Check for default annotation - metadata, ok := vmClass["metadata"].(map[string]interface{}) + name, ok := metadata["name"].(string) if !ok { continue } + + // Check if this is the required e2e class + if name == requiredVMClassName { + requiredClass = vmClass + } + + // Check for default annotation annotations, ok := metadata["annotations"].(map[string]interface{}) if !ok { continue } - if _, ok := annotations["virtualmachineclass.virtualization.deckhouse.io/is-default-class"]; ok { + if _, isDefault := annotations[defaultClassAnnotation]; isDefault { defaultClass = vmClass } } - // Helper to get name from vmClass - getVMClassName := func(m map[string]interface{}) string { - if m == nil { - return "" - } - metadata, ok := m["metadata"].(map[string]interface{}) - if !ok { - return "" - } - name, _ := metadata["name"].(string) - return name - } - - if e2eClass != nil && defaultClass != nil && getVMClassName(defaultClass) == defaultVMClassName { - // Everything is OK: correct default VMClass is present in the cluster. + // Check if everything is OK: required class exists AND it is the default + if requiredClass != nil && defaultClass != nil && getVMClassName(defaultClass) == requiredVMClassName { return nil } - issues := make([]string, 0) - cmds := make([]string, 0) + // Build issues and fix commands + var issues, cmds []string + // Handle default class issue if defaultClass != nil { issues = append(issues, fmt.Sprintf("cluster has wrong default vmclass %q", getVMClassName(defaultClass))) cmds = append(cmds, cmdRemoveDefaultAnnotation(getVMClassName(defaultClass))) @@ -117,12 +110,15 @@ func (c *vmcPrecheck) Run(ctx context.Context, f *framework.Framework) error { issues = append(issues, "cluster has no default vmclass") } - if e2eClass != nil { - issues = append(issues, fmt.Sprintf("e2e tests require vmclass %q to be default", defaultVMClassName)) - cmds = append(cmds, cmdSetDefaultAnnotation(defaultVMClassName)) + // Handle required class issue + if requiredClass != nil { + // Required class exists but is not default - just need to set annotation + issues = append(issues, fmt.Sprintf("e2e tests require vmclass %q to be default", requiredVMClassName)) + cmds = append(cmds, cmdSetDefaultAnnotation(requiredVMClassName)) } else { - issues = append(issues, fmt.Sprintf("e2e tests require vmclass %q to present and be default", defaultVMClassName)) - cmds = append(cmds, cmdCopyGenericAsDefaultClass(defaultVMClassName)) + // Required class doesn't exist - need to create it + issues = append(issues, fmt.Sprintf("e2e tests require vmclass %q to present and be default", requiredVMClassName)) + cmds = append(cmds, cmdCopyGenericAsDefaultClass(requiredVMClassName)) } return fmt.Errorf("%s=no to disable this precheck. Cluster has issues: %s. Run command to fix: %s", @@ -132,6 +128,19 @@ func (c *vmcPrecheck) Run(ctx context.Context, f *framework.Framework) error { ) } +// getVMClassName extracts name from VMClass object +func getVMClassName(m map[string]interface{}) string { + if m == nil { + return "" + } + metadata, ok := m["metadata"].(map[string]interface{}) + if !ok { + return "" + } + name, _ := metadata["name"].(string) + return name +} + func cmdCopyGenericAsDefaultClass(targetVMClassName string) string { return fmt.Sprintf(`kubectl get vmclass/generic -o json | jq 'del(.status) | del(.metadata) | .metadata = {"name":"%s","annotations":{"virtualmachineclass.virtualization.deckhouse.io/is-default-class":"true"}} ' | kubectl create -f -`, targetVMClassName) }