Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions test/e2e/auto_provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,21 @@ func TestClusterAutoCertCreation(t *testing.T) {
_ = corev1.AddToScheme(client.Resources().GetScheme())
_ = apiextensionsV1.AddToScheme(client.Resources().GetScheme())

// Clean up existing EtcdCluster resource if it exists (for test idempotency)
var existingCluster ecv1alpha1.EtcdCluster
err := client.Resources().Get(ctx, etcdClusterName, namespace, &existingCluster)
if err == nil {
// Cluster exists, delete it first
t.Logf("Found existing EtcdCluster '%s', cleaning up before test", etcdClusterName)
if err := client.Resources().Delete(ctx, &existingCluster); err != nil && !k8serrors.IsNotFound(err) {
t.Logf("Warning: Failed to delete existing cluster: %v", err)
}
// Wait for deletion to complete
time.Sleep(10 * time.Second)
} else if !k8serrors.IsNotFound(err) {
t.Logf("Warning: Error checking for existing cluster: %v", err)
}

// create etcd cluster
if err := client.Resources().Create(ctx, etcdCluster); err != nil {
t.Fatalf("unable to create etcd cluster: %s", err)
Expand Down
15 changes: 15 additions & 0 deletions test/e2e/cert_manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,21 @@ func TestClusterCertCreation(t *testing.T) {
t.Logf("Created clusterIssuer: %s", cmIssuerName)
}

// Clean up existing EtcdCluster resource if it exists (for test idempotency)
var existingCluster ecv1alpha1.EtcdCluster
err := client.Resources().Get(ctx, etcdClusterName, namespace, &existingCluster)
if err == nil {
// Cluster exists, delete it first
t.Logf("Found existing EtcdCluster '%s', cleaning up before test", etcdClusterName)
if err := client.Resources().Delete(ctx, &existingCluster); err != nil && !k8serrors.IsNotFound(err) {
t.Logf("Warning: Failed to delete existing cluster: %v", err)
}
// Wait for deletion to complete
time.Sleep(10 * time.Second)
} else if !k8serrors.IsNotFound(err) {
t.Logf("Warning: Error checking for existing cluster: %v", err)
}

// create etcd cluster
if err := client.Resources().Create(ctx, etcdCluster); err != nil {
t.Fatalf("unable to create etcd cluster: %s", err)
Expand Down
71 changes: 50 additions & 21 deletions test/e2e/e2e_suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,28 +40,34 @@ import (
)

var (
testEnv env.Environment
imageName = "etcd-operator:v0.1"
namespace = "etcd-operator-system"
containerTool = os.Getenv("CONTAINER_TOOL")
skipTeardown = os.Getenv("ETCD_E2E_SKIP_TEARDOWN") == "true"
testEnv env.Environment
imageName = "etcd-operator:v0.1"
namespace = "etcd-operator-system"
containerTool = os.Getenv("CONTAINER_TOOL")
skipTeardown = os.Getenv("ETCD_E2E_SKIP_TEARDOWN") == "true"
kindClusterName, useExistingCluster = os.LookupEnv("TEST_KIND_CLUSTER")
)

func TestMain(m *testing.M) {
testEnv = env.New()
kindClusterName := "etcd-cluster"

if !useExistingCluster {
kindClusterName = "etcd-cluster"
}

kindCluster := kind.NewCluster(kindClusterName)
clusterVersion := kind.WithImage("kindest/node:v1.32.0")

log.Println("Creating KinD cluster...")
testEnv.Setup(
// create KinD cluster
func(ctx context.Context, cfg *envconf.Config) (context.Context, error) {
// create KinD cluster

// Kind's Cluster.Create() skips cluster creation internally if cluster already exists.
var err error
log.Println("Creating KinD cluster...")
ctx, err = envfuncs.CreateClusterWithOpts(kindCluster, kindClusterName, clusterVersion)(ctx, cfg)
if err != nil {
log.Printf("failed to create cluster: %s", err)
log.Printf("Failed to create cluster: %s", err)
return ctx, err
}

Expand All @@ -70,6 +76,12 @@ func TestMain(m *testing.M) {

// prepare the resources
func(ctx context.Context, cfg *envconf.Config) (context.Context, error) {
// Check if image already exists in the cluster (when using existing cluster)
if useExistingCluster && test_utils.IsImageLoadedInKindCluster(kindClusterName, imageName) {
log.Printf("Image %s already loaded in cluster %s, skipping build and load", imageName, kindClusterName)
return ctx, nil
}

// Build docker image
log.Println("Building docker image...")
cmd := exec.Command("make", "docker-build", fmt.Sprintf("IMG=%s", imageName))
Expand All @@ -90,6 +102,12 @@ func TestMain(m *testing.M) {

// install prometheus
func(ctx context.Context, cfg *envconf.Config) (context.Context, error) {
// Skip if using existing cluster and Prometheus is already installed
if useExistingCluster && test_utils.IsPrometheusCRDsInstalled() {
log.Println("Prometheus operator already installed in existing cluster, skipping installation")
return ctx, nil
}

log.Println("Installing prometheus operator...")
if err := test_utils.InstallPrometheusOperator(); err != nil {
log.Printf("Unable to install Prometheus operator: %s", err)
Expand All @@ -100,12 +118,16 @@ func TestMain(m *testing.M) {

// set up environment
func(ctx context.Context, cfg *envconf.Config) (context.Context, error) {
// create namespace
var err error
ctx, err = envfuncs.CreateNamespace(namespace)(ctx, cfg)
if err != nil {
log.Printf("failed to create namespace: %s", err)
return ctx, err
// Ensure namespace exists (skip creation if already exists in existing cluster)
if useExistingCluster && test_utils.NamespaceExists(namespace) {
log.Printf("Namespace %s already exists in existing cluster, skipping creation", namespace)
} else {
log.Printf("Creating namespace %s...", namespace)
ctx, err := envfuncs.CreateNamespace(namespace)(ctx, cfg)
if err != nil {
log.Printf("Failed to create namespace: %s", err)
return ctx, err
}
}

// install crd
Expand Down Expand Up @@ -174,19 +196,22 @@ func TestMain(m *testing.M) {
}

// remove namespace
var err error
if useExistingCluster {
log.Println("Skipping namespace cleanup")
return ctx, nil
}
log.Println("Destroying namespace...")
ctx, err = envfuncs.DeleteNamespace(namespace)(ctx, cfg)
ctx, err := envfuncs.DeleteNamespace(namespace)(ctx, cfg)
if err != nil {
log.Printf("failed to delete namespace: %s", err)
log.Printf("Warning: Failed to delete namespace (may not exist): %s", err)
}

return ctx, nil
},

// remove the installed dependencies
func(ctx context.Context, cfg *envconf.Config) (context.Context, error) {
if skipTeardown {
if skipTeardown || useExistingCluster {
log.Println("Skipping dependency cleanup")
return ctx, nil
}
Expand All @@ -203,8 +228,12 @@ func TestMain(m *testing.M) {

// Destroy environment
func(ctx context.Context, cfg *envconf.Config) (context.Context, error) {
if skipTeardown {
log.Println("Skipping KinD cluster destruction")
if skipTeardown || useExistingCluster {
if useExistingCluster {
log.Printf("Skipping cluster destruction, existing cluster could be in use: %s", kindClusterName)
} else {
log.Println("Skipping KinD cluster destruction")
}
return ctx, nil
}
var err error
Expand Down
38 changes: 38 additions & 0 deletions test/utils/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -326,3 +326,41 @@ func GetContainerByName(containers []corev1.Container, name string) (corev1.Cont
}
return container, fmt.Errorf("container named %s not found", name)
}

// NamespaceExists checks if a namespace exists in the cluster
func NamespaceExists(namespace string) bool {
cmd := exec.Command("kubectl", "get", "namespace", namespace)
output, err := cmd.CombinedOutput()
if err != nil {
log.Printf("Namespace check failed: %s", err)
return false
}

// If command succeeds and output contains the namespace name, it exists
exists := strings.Contains(string(output), namespace)
return exists
}

// IsImageLoadedInKindCluster checks if a Docker image is already loaded in a Kind cluster.
func IsImageLoadedInKindCluster(clusterName, imageName string) bool {
// Extract image name and tag (e.g., "etcd-operator:v0.1" -> ["etcd-operator", "v0.1"])
imageParts := strings.Split(imageName, ":")
imageNameOnly := imageParts[0]
imageTag := "latest"
if len(imageParts) > 1 {
imageTag = imageParts[1]
}

nodeContainerName := fmt.Sprintf("%s-control-plane", clusterName)
cmd := exec.Command("docker", "exec", nodeContainerName, "crictl", "images", "|", "grep", "-E", fmt.Sprintf("%s|%s", imageNameOnly, imageTag))
err := cmd.Run()
imageFound := err == nil

if imageFound {
log.Printf("✓ Image '%s:%s' found in cluster", imageNameOnly, imageTag)
} else {
log.Printf("✗ Image '%s:%s' not found in cluster", imageNameOnly, imageTag)
}

return imageFound
}