Skip to content

Commit 853e2fb

Browse files
refactor predefined cvi funcs
Signed-off-by: Nikita Korolev <nikita.korolev@flant.com>
1 parent 8db2b88 commit 853e2fb

5 files changed

Lines changed: 158 additions & 93 deletions

File tree

test/e2e/e2e_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,9 @@ var _ = SynchronizedBeforeSuite(func() {
4444
bootstrapPrecreatedCVIs()
4545
}, func() {})
4646

47-
var _ = SynchronizedAfterSuite(func() {}, func() {
48-
// cleanupPrecreatedCVIs()
47+
var _ = SynchronizedAfterSuite(func() {
48+
cleanupPrecreatedCVIs()
49+
}, func() {
4950
legacy.NewAfterAllProcessBody()
5051
controller.NewAfterAllProcessBody()
5152
})

test/e2e/internal/config/cleanup.go

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,28 @@ import (
2525
// PostCleanUpEnv defines an environment variable used to explicitly request the deletion of created/used resources.
2626
const PostCleanUpEnv = "POST_CLEANUP"
2727

28+
// PrecreatedCVICleanupEnv defines an environment variable to explicitly enable deletion of precreated CVIs after the suite.
29+
//
30+
// By default, precreated CVIs are not deleted: they are shared across runs and may be reused.
31+
// Set PRECREATED_CVI_CLEANUP=yes to delete them after the suite; unset, empty, or "no" means no deletion.
32+
const PrecreatedCVICleanupEnv = "PRECREATED_CVI_CLEANUP"
33+
34+
func CheckPrecreatedCVICleanupOption() error {
35+
env := os.Getenv(PrecreatedCVICleanupEnv)
36+
switch env {
37+
case "yes", "no", "":
38+
return nil
39+
default:
40+
return fmt.Errorf("invalid value for %s env: %q (allowed: \"\", \"yes\", \"no\")", PrecreatedCVICleanupEnv, env)
41+
}
42+
}
43+
44+
// IsPrecreatedCVICleanupNeeded returns true only when PRECREATED_CVI_CLEANUP is explicitly set to "yes".
45+
// Default (unset, empty, or "no"): precreated CVIs are not deleted after the suite.
46+
func IsPrecreatedCVICleanupNeeded() bool {
47+
return os.Getenv(PrecreatedCVICleanupEnv) == "yes"
48+
}
49+
2850
func CheckWithPostCleanUpOption() error {
2951
env := os.Getenv(PostCleanUpEnv)
3052
switch env {
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
/*
2+
Copyright 2026 Flant JSC
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
// Package precreatedcvi provides suite-level lifecycle (bootstrap and cleanup) for
18+
// precreated ClusterVirtualImages used by e2e tests.
19+
package precreatedcvi
20+
21+
import (
22+
"context"
23+
"fmt"
24+
25+
. "github.com/onsi/ginkgo/v2"
26+
. "github.com/onsi/gomega"
27+
k8serrors "k8s.io/apimachinery/pkg/api/errors"
28+
crclient "sigs.k8s.io/controller-runtime/pkg/client"
29+
30+
"github.com/deckhouse/virtualization/api/core/v1alpha2"
31+
"github.com/deckhouse/virtualization/test/e2e/internal/config"
32+
"github.com/deckhouse/virtualization/test/e2e/internal/framework"
33+
"github.com/deckhouse/virtualization/test/e2e/internal/object"
34+
"github.com/deckhouse/virtualization/test/e2e/internal/util"
35+
)
36+
37+
const labelKey = "v12n-e2e-precreated"
38+
39+
// PrecreatedCVIManager runs bootstrap and cleanup of precreated CVIs for the e2e suite.
40+
// The list of CVIs is loaded once during Bootstrap and reused in Cleanup.
41+
type PrecreatedCVIManager struct {
42+
cvis []*v1alpha2.ClusterVirtualImage
43+
}
44+
45+
// NewPrecreatedCVIManager returns a new precreated CVI manager.
46+
func NewPrecreatedCVIManager() *PrecreatedCVIManager {
47+
return &PrecreatedCVIManager{}
48+
}
49+
50+
// Bootstrap creates or reuses precreated CVIs in the cluster, then waits until all are ready.
51+
// Call once from SynchronizedBeforeSuite (process 1).
52+
func (m *PrecreatedCVIManager) Bootstrap(ctx context.Context) {
53+
GinkgoHelper()
54+
55+
m.cvis = object.PrecreatedClusterVirtualImages()
56+
57+
for _, cvi := range m.cvis {
58+
By(fmt.Sprintf("Create or reuse precreated CVI %q in the cluster", cvi.Name))
59+
created, err := m.createOrReuse(ctx, cvi)
60+
Expect(err).NotTo(HaveOccurred())
61+
if created {
62+
By(fmt.Sprintf("Precreated CVI %q has been created", cvi.Name))
63+
} else {
64+
By(fmt.Sprintf("Precreated CVI %q already exists and will be reused", cvi.Name))
65+
}
66+
}
67+
68+
By("Wait until all precreated CVIs are ready")
69+
util.UntilObjectPhase(string(v1alpha2.ImageReady), framework.LongTimeout, m.cvisAsObjects()...)
70+
71+
for _, cvi := range m.cvis {
72+
By(fmt.Sprintf("Precreated CVI %q is ready", cvi.Name))
73+
}
74+
}
75+
76+
// Cleanup deletes precreated CVIs when both POST_CLEANUP and PRECREATED_CVI_CLEANUP allow it.
77+
// Call from SynchronizedAfterSuite (process 1). Uses the same CVI list as Bootstrap; if Bootstrap
78+
// was not run, the list is loaded from object so that cleanup can still run.
79+
func (m *PrecreatedCVIManager) Cleanup(ctx context.Context) {
80+
GinkgoHelper()
81+
82+
if !config.IsCleanUpNeeded() {
83+
return
84+
}
85+
if !config.IsPrecreatedCVICleanupNeeded() {
86+
return
87+
}
88+
89+
if len(m.cvis) == 0 {
90+
m.cvis = object.PrecreatedClusterVirtualImages()
91+
}
92+
93+
f := framework.NewFramework("")
94+
err := f.Delete(ctx, m.cvisAsObjects()...)
95+
Expect(err).NotTo(HaveOccurred(), "Failed to delete precreated CVIs")
96+
}
97+
98+
func (m *PrecreatedCVIManager) createOrReuse(ctx context.Context, cvi *v1alpha2.ClusterVirtualImage) (bool, error) {
99+
applyLabel(cvi)
100+
101+
err := framework.GetClients().GenericClient().Create(ctx, cvi)
102+
if err == nil {
103+
return true, nil
104+
}
105+
if !k8serrors.IsAlreadyExists(err) {
106+
return false, err
107+
}
108+
return false, framework.GetClients().GenericClient().Get(ctx, crclient.ObjectKeyFromObject(cvi), cvi)
109+
}
110+
111+
func (m *PrecreatedCVIManager) cvisAsObjects() []crclient.Object {
112+
objs := make([]crclient.Object, 0, len(m.cvis))
113+
for _, cvi := range m.cvis {
114+
objs = append(objs, cvi)
115+
}
116+
return objs
117+
}
118+
119+
func applyLabel(cvi *v1alpha2.ClusterVirtualImage) {
120+
labels := cvi.GetLabels()
121+
if labels == nil {
122+
labels = make(map[string]string)
123+
}
124+
labels[labelKey] = "true"
125+
cvi.SetLabels(labels)
126+
}

test/e2e/legacy/legacy.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,9 @@ func configure() (err error) {
7272
if err = config.CheckWithPostCleanUpOption(); err != nil {
7373
return err
7474
}
75+
if err = config.CheckPrecreatedCVICleanupOption(); err != nil {
76+
return err
77+
}
7578

7679
conf = framework.GetConfig()
7780
defer framework.SetConfig(conf)

test/e2e/suite_cvi.go

Lines changed: 4 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -18,103 +18,16 @@ package e2e
1818

1919
import (
2020
"context"
21-
"fmt"
2221

23-
. "github.com/onsi/ginkgo/v2"
24-
. "github.com/onsi/gomega"
25-
k8serrors "k8s.io/apimachinery/pkg/api/errors"
26-
crclient "sigs.k8s.io/controller-runtime/pkg/client"
27-
28-
"github.com/deckhouse/virtualization/api/core/v1alpha2"
29-
"github.com/deckhouse/virtualization/test/e2e/internal/config"
30-
"github.com/deckhouse/virtualization/test/e2e/internal/framework"
31-
"github.com/deckhouse/virtualization/test/e2e/internal/object"
32-
"github.com/deckhouse/virtualization/test/e2e/internal/util"
22+
"github.com/deckhouse/virtualization/test/e2e/internal/precreatedcvi"
3323
)
3424

35-
const precreatedCVILabel = "v12n-e2e-precreated"
36-
37-
// Additional labels to add to precreated CVIs (e.g., for test discovery)
38-
var precreatedCVITestLabels = make(map[string]string)
25+
var precreatedCVIManager = precreatedcvi.NewPrecreatedCVIManager()
3926

4027
func bootstrapPrecreatedCVIs() {
41-
GinkgoHelper()
42-
43-
ctx := context.Background()
44-
for _, cvi := range object.PrecreatedClusterVirtualImages() {
45-
By(fmt.Sprintf("Create or reuse precreated CVI %q in the cluster", cvi.Name))
46-
created, err := createOrReusePrecreatedCVI(ctx, cvi)
47-
Expect(err).NotTo(HaveOccurred())
48-
if created {
49-
By(fmt.Sprintf("Precreated CVI %q has been created", cvi.Name))
50-
continue
51-
}
52-
By(fmt.Sprintf("Precreated CVI %q already exists and will be reused", cvi.Name))
53-
}
54-
55-
By("Wait until all precreated CVIs are ready")
56-
util.UntilObjectPhase(string(v1alpha2.ImageReady), framework.LongTimeout, precreatedClusterVirtualImagesAsObjects()...)
57-
for _, cvi := range object.PrecreatedClusterVirtualImages() {
58-
By(fmt.Sprintf("Precreated CVI %q is ready", cvi.Name))
59-
}
60-
}
61-
62-
// AddTestLabelsToPrecreatedCVI adds additional labels to precreated CVIs for test discovery.
63-
// Must be called before applying kustomize in tests that use precreated CVIs.
64-
func AddTestLabelsToPrecreatedCVI(labels map[string]string) {
65-
for k, v := range labels {
66-
precreatedCVITestLabels[k] = v
67-
}
28+
precreatedCVIManager.Bootstrap(context.Background())
6829
}
6930

7031
func cleanupPrecreatedCVIs() {
71-
GinkgoHelper()
72-
73-
if !config.IsCleanUpNeeded() {
74-
return
75-
}
76-
77-
ctx := context.Background()
78-
for _, cvi := range object.PrecreatedClusterVirtualImages() {
79-
err := framework.GetClients().GenericClient().Delete(ctx, cvi)
80-
Expect(err == nil || k8serrors.IsNotFound(err)).To(BeTrue(), "failed to delete precreated CVI %q: %v", cvi.Name, err)
81-
}
82-
}
83-
84-
func createOrReusePrecreatedCVI(ctx context.Context, cvi *v1alpha2.ClusterVirtualImage) (bool, error) {
85-
setPrecreatedCVILabel(cvi)
86-
87-
err := framework.GetClients().GenericClient().Create(ctx, cvi)
88-
if err == nil {
89-
return true, nil
90-
}
91-
92-
if !k8serrors.IsAlreadyExists(err) {
93-
return false, err
94-
}
95-
96-
return false, framework.GetClients().GenericClient().Get(ctx, crclient.ObjectKeyFromObject(cvi), cvi)
97-
}
98-
99-
func precreatedClusterVirtualImagesAsObjects() []crclient.Object {
100-
cvis := object.PrecreatedClusterVirtualImages()
101-
objs := make([]crclient.Object, 0, len(cvis))
102-
for _, cvi := range cvis {
103-
objs = append(objs, cvi)
104-
}
105-
106-
return objs
107-
}
108-
109-
func setPrecreatedCVILabel(cvi *v1alpha2.ClusterVirtualImage) {
110-
labels := cvi.GetLabels()
111-
if labels == nil {
112-
labels = make(map[string]string)
113-
}
114-
labels[precreatedCVILabel] = "true"
115-
// Add test-specific labels for test discovery
116-
for k, v := range precreatedCVITestLabels {
117-
labels[k] = v
118-
}
119-
cvi.SetLabels(labels)
32+
precreatedCVIManager.Cleanup(context.Background())
12033
}

0 commit comments

Comments
 (0)