diff --git a/Taskfile.yaml b/Taskfile.yaml index ea795554e7..87d630defd 100644 --- a/Taskfile.yaml +++ b/Taskfile.yaml @@ -324,16 +324,6 @@ tasks: "readinessProbe": null, "livenessProbe": null, "command": null - }, - { - "name": "proxy", - "readinessProbe": null, - "livenessProbe": null - }, - { - "name": "kube-rbac-proxy", - "readinessProbe": null, - "livenessProbe": null } ] } diff --git a/build/components/versions.yml b/build/components/versions.yml index 2c203a7eaf..379d07f0ea 100644 --- a/build/components/versions.yml +++ b/build/components/versions.yml @@ -3,7 +3,7 @@ firmware: libvirt: v10.9.0 edk2: stable202411 core: - 3p-kubevirt: v1.6.2-v12n.43 + 3p-kubevirt: v1.6.2-v12n.44 3p-containerized-data-importer: v1.60.3-v12n.19 distribution: 2.8.3 package: diff --git a/images/virtualization-artifact/pkg/controller/vd/internal/migration.go b/images/virtualization-artifact/pkg/controller/vd/internal/migration.go index c2484af2b8..1077e9be01 100644 --- a/images/virtualization-artifact/pkg/controller/vd/internal/migration.go +++ b/images/virtualization-artifact/pkg/controller/vd/internal/migration.go @@ -717,9 +717,7 @@ func deletePersistentVolumeClaim(ctx context.Context, pvc *corev1.PersistentVolu var shouldPatch bool for _, finalizer := range pvc.Finalizers { switch finalizer { - // When pod completed, we cannot remove pvc, because Kubernetes protects pvc until pod is removed. - // https://github.com/kubernetes/kubernetes/issues/120756 - case v1alpha2.FinalizerVDProtection, "kubernetes.io/pvc-protection": // remove + case v1alpha2.FinalizerVDProtection: // remove shouldPatch = true default: newFinalizers = append(newFinalizers, finalizer) diff --git a/test/e2e/Taskfile.yaml b/test/e2e/Taskfile.yaml index 43c54742bd..13a8d95c41 100644 --- a/test/e2e/Taskfile.yaml +++ b/test/e2e/Taskfile.yaml @@ -87,6 +87,7 @@ tasks: - copy - kubectl - d8 + - precheck:prepare cmds: - | go tool ginkgo -v \ diff --git a/test/e2e/internal/config/storageclass.go b/test/e2e/internal/config/storageclass.go index ed4e7af0e0..91790fbc1e 100644 --- a/test/e2e/internal/config/storageclass.go +++ b/test/e2e/internal/config/storageclass.go @@ -19,13 +19,19 @@ package config import ( "context" "fmt" + "os" "sort" storagev1 "k8s.io/api/storage/v1" "sigs.k8s.io/controller-runtime/pkg/client" ) -const NFS = "nfs.csi.k8s.io" +const ( + NFS = "nfs.csi.k8s.io" + + // StorageClassNameEnv overrides TemplateStorageClass for tests (see README). + StorageClassNameEnv = "STORAGE_CLASS_NAME" +) // FindDefaultStorageClass returns the default StorageClass from the list. // It selects the most recently created default StorageClass (by creationTimestamp). @@ -85,25 +91,55 @@ func FindImmediateStorageClass(defaultSC *storagev1.StorageClass, scList *storag return nil } -// SetImmediateStorageClass finds and sets ImmediateStorageClass in Config. -// It searches for a StorageClass with VolumeBindingMode=Immediate and same provisioner as default StorageClass. -// If default StorageClass already has Immediate binding mode, it will be used. -func (c *Config) SetImmediateStorageClass(ctx context.Context, k8sClient client.Client) error { - if c.StorageClass.DefaultStorageClass == nil { - return fmt.Errorf("default StorageClass is not set") - } - +// SetStorageClasses discovers cluster StorageClasses and populates Config.StorageClass fields. +// TemplateStorageClass is taken from StorageClassNameEnv when set, otherwise DefaultStorageClass is used. +func (c *Config) SetStorageClasses(ctx context.Context, k8sClient client.Client) error { var scList storagev1.StorageClassList if err := k8sClient.List(ctx, &scList); err != nil { return fmt.Errorf("failed to list StorageClasses: %w", err) } - immediateSC := FindImmediateStorageClass(c.StorageClass.DefaultStorageClass, &scList) - if immediateSC == nil { - return fmt.Errorf("immediate StorageClass not found for provisioner %q", - c.StorageClass.DefaultStorageClass.Provisioner) + c.StorageClass.DefaultStorageClass = FindDefaultStorageClass(&scList) + if c.StorageClass.DefaultStorageClass == nil { + return fmt.Errorf("default StorageClass not found in the cluster") + } + + c.StorageClass.ImmediateStorageClass = FindImmediateStorageClass(c.StorageClass.DefaultStorageClass, &scList) + + templateSC, err := findStorageClassFromEnv(ctx, k8sClient, StorageClassNameEnv, &scList) + if err != nil { + return err + } + if templateSC != nil { + c.StorageClass.TemplateStorageClass = templateSC + } else { + c.StorageClass.TemplateStorageClass = c.StorageClass.DefaultStorageClass } - c.StorageClass.ImmediateStorageClass = immediateSC return nil } + +func findStorageClassFromEnv( + ctx context.Context, + k8sClient client.Client, + envName string, + scList *storagev1.StorageClassList, +) (*storagev1.StorageClass, error) { + scName, ok := os.LookupEnv(envName) + if !ok { + return nil, nil + } + + for i := range scList.Items { + if scList.Items[i].Name == scName { + return &scList.Items[i], nil + } + } + + sc := &storagev1.StorageClass{} + if err := k8sClient.Get(ctx, client.ObjectKey{Name: scName}, sc); err != nil { + return nil, fmt.Errorf("failed to get StorageClass %q from %s env: %w", scName, envName, err) + } + + return sc, nil +} diff --git a/test/e2e/internal/framework/client.go b/test/e2e/internal/framework/client.go index 29e08c5db7..078bcdd6aa 100644 --- a/test/e2e/internal/framework/client.go +++ b/test/e2e/internal/framework/client.go @@ -17,6 +17,8 @@ limitations under the License. package framework import ( + "sync" + apiruntime "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/dynamic" "k8s.io/client-go/kubernetes" @@ -39,9 +41,12 @@ import ( var clients = Clients{} +var clientsOnce sync.Once + func GetClients() Clients { onceLoadConfig() InitClients() + initStorageClasses() return clients } @@ -93,7 +98,7 @@ func (c Clients) Git() gt.Git { // This should be called before using framework clients. func InitClients() { clientsOnce.Do(func() { - _ = GetConfig() + onceLoadConfig() restConfig, err := conf.ClusterTransport.RestConfig() if err != nil { diff --git a/test/e2e/internal/framework/config.go b/test/e2e/internal/framework/config.go index fa00c5ce50..e5edb7dbcb 100644 --- a/test/e2e/internal/framework/config.go +++ b/test/e2e/internal/framework/config.go @@ -17,15 +17,17 @@ limitations under the License. package framework import ( + "context" "sync" "github.com/deckhouse/virtualization/test/e2e/internal/config" ) var ( - conf *config.Config - once sync.Once - clientsOnce sync.Once + conf *config.Config + confMu sync.RWMutex + once sync.Once + storageClassesOnce sync.Once ) func onceLoadConfig() { @@ -34,20 +36,44 @@ func onceLoadConfig() { if err != nil { panic(err) } - SetConfig(c) + setConfig(c) + }) +} + +func initStorageClasses() { + storageClassesOnce.Do(func() { + onceLoadConfig() + InitClients() + + confMu.Lock() + defer confMu.Unlock() + + if err := conf.SetStorageClasses(context.Background(), clients.client); err != nil { + panic(err) + } }) } func GetConfig() *config.Config { onceLoadConfig() + initStorageClasses() + confMu.RLock() copied := *conf + confMu.RUnlock() + return &copied } // SetConfig sets the config. -// this needs because we have some legacy, config mutating in the main test suite -// should be refactored in the future +// +// Deprecated: config is populated by framework initialization; legacy should not mutate it. func SetConfig(c *config.Config) { + setConfig(c) +} + +func setConfig(c *config.Config) { + confMu.Lock() conf = c + confMu.Unlock() } diff --git a/test/e2e/legacy/legacy.go b/test/e2e/legacy/legacy.go index 0472c21ace..87c9023194 100644 --- a/test/e2e/legacy/legacy.go +++ b/test/e2e/legacy/legacy.go @@ -26,7 +26,6 @@ import ( . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" - storagev1 "k8s.io/api/storage/v1" k8serrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" crclient "sigs.k8s.io/controller-runtime/pkg/client" @@ -48,7 +47,6 @@ const ( PhaseReady = "Ready" PhasePending = "Pending" PhaseRunning = "Running" - storageClassName = "STORAGE_CLASS_NAME" testDataDir = "/tmp/testdata" ) @@ -67,35 +65,16 @@ func Init() error { func configure() (err error) { conf = framework.GetConfig() - defer framework.SetConfig(conf) - clients := framework.GetClients() - kubectl = clients.Kubectl() + kubectl = framework.GetClients().Kubectl() - var scList storagev1.StorageClassList - if err := clients.GenericClient().List(context.Background(), &scList); err != nil { - return fmt.Errorf("failed to list StorageClasses: %w", err) + if conf.StorageClass.TemplateStorageClass == nil { + return fmt.Errorf("TemplateStorageClass is not set") } - conf.StorageClass.DefaultStorageClass = config.FindDefaultStorageClass(&scList) - if conf.StorageClass.DefaultStorageClass == nil { - return fmt.Errorf("default StorageClass not found in the cluster") - } - - conf.StorageClass.ImmediateStorageClass = config.FindImmediateStorageClass(conf.StorageClass.DefaultStorageClass, &scList) - - scFromEnv, err := GetStorageClassFromEnv(storageClassName) - if err != nil { - return err - } - - if scFromEnv != nil { - conf.StorageClass.TemplateStorageClass = scFromEnv - } else { - conf.StorageClass.TemplateStorageClass = conf.StorageClass.DefaultStorageClass - } - - if err = SetStorageClass(testDataDir, map[string]string{storageClassName: conf.StorageClass.TemplateStorageClass.Name}); err != nil { + if err = SetStorageClass(testDataDir, map[string]string{ + config.StorageClassNameEnv: conf.StorageClass.TemplateStorageClass.Name, + }); err != nil { return err } diff --git a/test/e2e/legacy/util.go b/test/e2e/legacy/util.go index d7d3632339..6f4d75d50f 100644 --- a/test/e2e/legacy/util.go +++ b/test/e2e/legacy/util.go @@ -245,20 +245,6 @@ func WaitResources(resources []string, resource kc.Resource, opts kc.WaitOptions Expect(waitErr).To(BeEmpty(), "should observe resources in '%s' state before %s timeout", opts.For, opts.Timeout.String()) } -func GetStorageClassFromEnv(envName string) (*storagev1.StorageClass, error) { - sc := &storagev1.StorageClass{} - scName, ok := os.LookupEnv(envName) - if ok { - err := GetObject(kc.ResourceStorageClass, scName, sc, kc.GetOptions{}) - if err != nil { - return nil, err - } - return sc, nil - } - - return nil, nil -} - func SetStorageClass(tmplRoot string, storageClasse map[string]string) error { return filepath.Walk(tmplRoot, func(path string, info os.FileInfo, err error) error { if err != nil {