refactor: Move test helpers to testutil

This commit is contained in:
TheiLLeniumStudios
2025-12-28 08:47:59 +01:00
parent 172517512b
commit ced6ffabd1
10 changed files with 489 additions and 644 deletions
@@ -4,6 +4,7 @@ import (
"testing"
"github.com/stakater/Reloader/internal/pkg/config"
"github.com/stakater/Reloader/internal/pkg/testutil"
)
func TestConfigMapReconciler_NotFound(t *testing.T) {
@@ -16,7 +17,7 @@ func TestConfigMapReconciler_NotFound_ReloadOnDelete(t *testing.T) {
cfg := config.NewDefault()
cfg.ReloadOnDelete = true
deployment := testDeployment("test-deployment", "default", map[string]string{
deployment := testutil.NewDeployment("test-deployment", "default", map[string]string{
cfg.Annotations.ConfigmapReload: "deleted-cm",
})
reconciler := newConfigMapReconciler(t, cfg, deployment)
@@ -27,7 +28,7 @@ func TestConfigMapReconciler_IgnoredNamespace(t *testing.T) {
cfg := config.NewDefault()
cfg.IgnoredNamespaces = []string{"kube-system"}
cm := testConfigMap("test-cm", "kube-system")
cm := testutil.NewConfigMap("test-cm", "kube-system")
reconciler := newConfigMapReconciler(t, cfg, cm)
assertReconcileSuccess(t, reconciler, reconcileRequest("test-cm", "kube-system"))
}
@@ -35,8 +36,8 @@ func TestConfigMapReconciler_IgnoredNamespace(t *testing.T) {
func TestConfigMapReconciler_NoMatchingWorkloads(t *testing.T) {
cfg := config.NewDefault()
cm := testConfigMap("test-cm", "default")
deployment := testDeployment("test-deployment", "default", nil)
cm := testutil.NewConfigMap("test-cm", "default")
deployment := testutil.NewDeployment("test-deployment", "default", nil)
reconciler := newConfigMapReconciler(t, cfg, cm, deployment)
assertReconcileSuccess(t, reconciler, reconcileRequest("test-cm", "default"))
}
@@ -45,8 +46,8 @@ func TestConfigMapReconciler_MatchingDeployment_AutoAnnotation(t *testing.T) {
cfg := config.NewDefault()
cfg.AutoReloadAll = true
cm := testConfigMap("test-cm", "default")
deployment := testDeploymentWithEnvFrom("test-deployment", "default", "test-cm", "")
cm := testutil.NewConfigMap("test-cm", "default")
deployment := testutil.NewDeploymentWithEnvFrom("test-deployment", "default", "test-cm", "")
reconciler := newConfigMapReconciler(t, cfg, cm, deployment)
assertReconcileSuccess(t, reconciler, reconcileRequest("test-cm", "default"))
}
@@ -54,8 +55,8 @@ func TestConfigMapReconciler_MatchingDeployment_AutoAnnotation(t *testing.T) {
func TestConfigMapReconciler_MatchingDeployment_ExplicitAnnotation(t *testing.T) {
cfg := config.NewDefault()
cm := testConfigMap("test-cm", "default")
deployment := testDeployment("test-deployment", "default", map[string]string{
cm := testutil.NewConfigMap("test-cm", "default")
deployment := testutil.NewDeployment("test-deployment", "default", map[string]string{
cfg.Annotations.ConfigmapReload: "test-cm",
})
reconciler := newConfigMapReconciler(t, cfg, cm, deployment)
@@ -65,8 +66,8 @@ func TestConfigMapReconciler_MatchingDeployment_ExplicitAnnotation(t *testing.T)
func TestConfigMapReconciler_WorkloadInDifferentNamespace(t *testing.T) {
cfg := config.NewDefault()
cm := testConfigMap("test-cm", "namespace-a")
deployment := testDeployment("test-deployment", "namespace-b", map[string]string{
cm := testutil.NewConfigMap("test-cm", "namespace-a")
deployment := testutil.NewDeployment("test-deployment", "namespace-b", map[string]string{
cfg.Annotations.ConfigmapReload: "test-cm",
})
reconciler := newConfigMapReconciler(t, cfg, cm, deployment)
@@ -77,8 +78,8 @@ func TestConfigMapReconciler_IgnoredWorkloadType(t *testing.T) {
cfg := config.NewDefault()
cfg.IgnoredWorkloads = []string{"deployment"}
cm := testConfigMap("test-cm", "default")
deployment := testDeployment("test-deployment", "default", map[string]string{
cm := testutil.NewConfigMap("test-cm", "default")
deployment := testutil.NewDeployment("test-deployment", "default", map[string]string{
cfg.Annotations.ConfigmapReload: "test-cm",
})
reconciler := newConfigMapReconciler(t, cfg, cm, deployment)
@@ -88,8 +89,8 @@ func TestConfigMapReconciler_IgnoredWorkloadType(t *testing.T) {
func TestConfigMapReconciler_DaemonSet(t *testing.T) {
cfg := config.NewDefault()
cm := testConfigMap("test-cm", "default")
daemonset := testDaemonSet("test-daemonset", "default", map[string]string{
cm := testutil.NewConfigMap("test-cm", "default")
daemonset := testutil.NewDaemonSet("test-daemonset", "default", map[string]string{
cfg.Annotations.ConfigmapReload: "test-cm",
})
reconciler := newConfigMapReconciler(t, cfg, cm, daemonset)
@@ -99,8 +100,8 @@ func TestConfigMapReconciler_DaemonSet(t *testing.T) {
func TestConfigMapReconciler_StatefulSet(t *testing.T) {
cfg := config.NewDefault()
cm := testConfigMap("test-cm", "default")
statefulset := testStatefulSet("test-statefulset", "default", map[string]string{
cm := testutil.NewConfigMap("test-cm", "default")
statefulset := testutil.NewStatefulSet("test-statefulset", "default", map[string]string{
cfg.Annotations.ConfigmapReload: "test-cm",
})
reconciler := newConfigMapReconciler(t, cfg, cm, statefulset)
@@ -110,14 +111,14 @@ func TestConfigMapReconciler_StatefulSet(t *testing.T) {
func TestConfigMapReconciler_MultipleWorkloads(t *testing.T) {
cfg := config.NewDefault()
cm := testConfigMap("shared-cm", "default")
deployment1 := testDeployment("deployment-1", "default", map[string]string{
cm := testutil.NewConfigMap("shared-cm", "default")
deployment1 := testutil.NewDeployment("deployment-1", "default", map[string]string{
cfg.Annotations.ConfigmapReload: "shared-cm",
})
deployment2 := testDeployment("deployment-2", "default", map[string]string{
deployment2 := testutil.NewDeployment("deployment-2", "default", map[string]string{
cfg.Annotations.ConfigmapReload: "shared-cm",
})
daemonset := testDaemonSet("daemonset-1", "default", map[string]string{
daemonset := testutil.NewDaemonSet("daemonset-1", "default", map[string]string{
cfg.Annotations.ConfigmapReload: "shared-cm",
})
@@ -129,8 +130,8 @@ func TestConfigMapReconciler_VolumeMount(t *testing.T) {
cfg := config.NewDefault()
cfg.AutoReloadAll = true
cm := testConfigMap("volume-cm", "default")
deployment := testDeploymentWithVolume("test-deployment", "default", "volume-cm", "")
cm := testutil.NewConfigMap("volume-cm", "default")
deployment := testutil.NewDeploymentWithVolume("test-deployment", "default", "volume-cm", "")
reconciler := newConfigMapReconciler(t, cfg, cm, deployment)
assertReconcileSuccess(t, reconciler, reconcileRequest("volume-cm", "default"))
}
@@ -139,8 +140,8 @@ func TestConfigMapReconciler_ProjectedVolume(t *testing.T) {
cfg := config.NewDefault()
cfg.AutoReloadAll = true
cm := testConfigMap("projected-cm", "default")
deployment := testDeploymentWithProjectedVolume("test-deployment", "default", "projected-cm", "")
cm := testutil.NewConfigMap("projected-cm", "default")
deployment := testutil.NewDeploymentWithProjectedVolume("test-deployment", "default", "projected-cm", "")
reconciler := newConfigMapReconciler(t, cfg, cm, deployment)
assertReconcileSuccess(t, reconciler, reconcileRequest("projected-cm", "default"))
}
@@ -148,10 +149,10 @@ func TestConfigMapReconciler_ProjectedVolume(t *testing.T) {
func TestConfigMapReconciler_SearchAnnotation(t *testing.T) {
cfg := config.NewDefault()
cm := testConfigMapWithAnnotations("test-cm", "default", map[string]string{
cm := testutil.NewConfigMapWithAnnotations("test-cm", "default", map[string]string{
cfg.Annotations.Match: "true",
})
deployment := testDeployment("test-deployment", "default", map[string]string{
deployment := testutil.NewDeployment("test-deployment", "default", map[string]string{
cfg.Annotations.Search: "true",
})
reconciler := newConfigMapReconciler(t, cfg, cm, deployment)
@@ -5,6 +5,7 @@ import (
"github.com/stakater/Reloader/internal/pkg/config"
"github.com/stakater/Reloader/internal/pkg/controller"
"github.com/stakater/Reloader/internal/pkg/testutil"
"k8s.io/apimachinery/pkg/labels"
)
@@ -70,7 +71,7 @@ func TestNamespaceReconciler_Add(t *testing.T) {
cfg.NamespaceSelectors = []labels.Selector{selector}
cache := controller.NewNamespaceCache(true)
ns := testNamespace("test-ns", map[string]string{"env": "production"})
ns := testutil.NewNamespace("test-ns", map[string]string{"env": "production"})
reconciler := newNamespaceReconciler(t, cfg, cache, ns)
assertReconcileSuccess(t, reconciler, namespaceRequest("test-ns"))
@@ -88,7 +89,7 @@ func TestNamespaceReconciler_Remove_LabelChange(t *testing.T) {
cache := controller.NewNamespaceCache(true)
cache.Add("test-ns") // Pre-populate
ns := testNamespace("test-ns", map[string]string{"env": "staging"}) // Non-matching
ns := testutil.NewNamespace("test-ns", map[string]string{"env": "staging"}) // Non-matching
reconciler := newNamespaceReconciler(t, cfg, cache, ns)
assertReconcileSuccess(t, reconciler, namespaceRequest("test-ns"))
@@ -122,7 +123,7 @@ func TestNamespaceReconciler_MultipleSelectors(t *testing.T) {
cfg.NamespaceSelectors = []labels.Selector{selector1, selector2}
cache := controller.NewNamespaceCache(true)
ns := testNamespace("test-ns", map[string]string{"team": "platform"})
ns := testutil.NewNamespace("test-ns", map[string]string{"team": "platform"})
reconciler := newNamespaceReconciler(t, cfg, cache, ns)
assertReconcileSuccess(t, reconciler, namespaceRequest("test-ns"))
@@ -138,7 +139,7 @@ func TestNamespaceReconciler_NoLabels(t *testing.T) {
cfg.NamespaceSelectors = []labels.Selector{selector}
cache := controller.NewNamespaceCache(true)
ns := testNamespace("test-ns", nil) // No labels
ns := testutil.NewNamespace("test-ns", nil) // No labels
reconciler := newNamespaceReconciler(t, cfg, cache, ns)
assertReconcileSuccess(t, reconciler, namespaceRequest("test-ns"))
+11 -10
View File
@@ -7,6 +7,7 @@ import (
"github.com/stakater/Reloader/internal/pkg/config"
"github.com/stakater/Reloader/internal/pkg/controller"
"github.com/stakater/Reloader/internal/pkg/reload"
"github.com/stakater/Reloader/internal/pkg/testutil"
"github.com/stakater/Reloader/internal/pkg/workload"
appsv1 "k8s.io/api/apps/v1"
batchv1 "k8s.io/api/batch/v1"
@@ -27,7 +28,7 @@ func TestUpdateWorkloadWithRetry_WorkloadTypes(t *testing.T) {
}{
{
name: "Deployment",
object: testDeployment("test-deployment", "default", nil),
object: testutil.NewDeployment("test-deployment", "default", nil),
workload: func(o runtime.Object) workload.WorkloadAccessor {
return workload.NewDeploymentWorkload(o.(*appsv1.Deployment))
},
@@ -44,7 +45,7 @@ func TestUpdateWorkloadWithRetry_WorkloadTypes(t *testing.T) {
},
{
name: "DaemonSet",
object: testDaemonSet("test-daemonset", "default", nil),
object: testutil.NewDaemonSet("test-daemonset", "default", nil),
workload: func(o runtime.Object) workload.WorkloadAccessor {
return workload.NewDaemonSetWorkload(o.(*appsv1.DaemonSet))
},
@@ -61,7 +62,7 @@ func TestUpdateWorkloadWithRetry_WorkloadTypes(t *testing.T) {
},
{
name: "StatefulSet",
object: testStatefulSet("test-statefulset", "default", nil),
object: testutil.NewStatefulSet("test-statefulset", "default", nil),
workload: func(o runtime.Object) workload.WorkloadAccessor {
return workload.NewStatefulSetWorkload(o.(*appsv1.StatefulSet))
},
@@ -78,7 +79,7 @@ func TestUpdateWorkloadWithRetry_WorkloadTypes(t *testing.T) {
},
{
name: "Job",
object: testJob("test-job", "default"),
object: testutil.NewJob("test-job", "default"),
workload: func(o runtime.Object) workload.WorkloadAccessor {
return workload.NewJobWorkload(o.(*batchv1.Job))
},
@@ -95,7 +96,7 @@ func TestUpdateWorkloadWithRetry_WorkloadTypes(t *testing.T) {
},
{
name: "CronJob",
object: testCronJob("test-cronjob", "default"),
object: testutil.NewCronJob("test-cronjob", "default"),
workload: func(o runtime.Object) workload.WorkloadAccessor {
return workload.NewCronJobWorkload(o.(*batchv1.CronJob))
},
@@ -122,7 +123,7 @@ func TestUpdateWorkloadWithRetry_WorkloadTypes(t *testing.T) {
reloadService := reload.NewService(cfg)
fakeClient := fake.NewClientBuilder().
WithScheme(testScheme()).
WithScheme(testutil.NewScheme()).
WithRuntimeObjects(tt.object).
Build()
@@ -201,9 +202,9 @@ func TestUpdateWorkloadWithRetry_Strategies(t *testing.T) {
cfg.ReloadStrategy = tt.strategy
reloadService := reload.NewService(cfg)
deployment := testDeployment("test-deployment", "default", nil)
deployment := testutil.NewDeployment("test-deployment", "default", nil)
fakeClient := fake.NewClientBuilder().
WithScheme(testScheme()).
WithScheme(testutil.NewScheme()).
WithObjects(deployment).
Build()
@@ -245,7 +246,7 @@ func TestUpdateWorkloadWithRetry_NoUpdate(t *testing.T) {
cfg := config.NewDefault()
reloadService := reload.NewService(cfg)
deployment := testDeployment("test-deployment", "default", nil)
deployment := testutil.NewDeployment("test-deployment", "default", nil)
deployment.Spec.Template.Spec.Containers[0].Env = []corev1.EnvVar{
{
Name: "STAKATER_TEST_CM_CONFIGMAP",
@@ -254,7 +255,7 @@ func TestUpdateWorkloadWithRetry_NoUpdate(t *testing.T) {
}
fakeClient := fake.NewClientBuilder().
WithScheme(testScheme()).
WithScheme(testutil.NewScheme()).
WithObjects(deployment).
Build()
@@ -4,6 +4,7 @@ import (
"testing"
"github.com/stakater/Reloader/internal/pkg/config"
"github.com/stakater/Reloader/internal/pkg/testutil"
)
func TestSecretReconciler_NotFound(t *testing.T) {
@@ -16,7 +17,7 @@ func TestSecretReconciler_NotFound_ReloadOnDelete(t *testing.T) {
cfg := config.NewDefault()
cfg.ReloadOnDelete = true
deployment := testDeployment("test-deployment", "default", map[string]string{
deployment := testutil.NewDeployment("test-deployment", "default", map[string]string{
cfg.Annotations.SecretReload: "deleted-secret",
})
reconciler := newSecretReconciler(t, cfg, deployment)
@@ -27,7 +28,7 @@ func TestSecretReconciler_IgnoredNamespace(t *testing.T) {
cfg := config.NewDefault()
cfg.IgnoredNamespaces = []string{"kube-system"}
secret := testSecret("test-secret", "kube-system")
secret := testutil.NewSecret("test-secret", "kube-system")
reconciler := newSecretReconciler(t, cfg, secret)
assertReconcileSuccess(t, reconciler, reconcileRequest("test-secret", "kube-system"))
}
@@ -35,8 +36,8 @@ func TestSecretReconciler_IgnoredNamespace(t *testing.T) {
func TestSecretReconciler_NoMatchingWorkloads(t *testing.T) {
cfg := config.NewDefault()
secret := testSecret("test-secret", "default")
deployment := testDeployment("test-deployment", "default", nil)
secret := testutil.NewSecret("test-secret", "default")
deployment := testutil.NewDeployment("test-deployment", "default", nil)
reconciler := newSecretReconciler(t, cfg, secret, deployment)
assertReconcileSuccess(t, reconciler, reconcileRequest("test-secret", "default"))
}
@@ -45,8 +46,8 @@ func TestSecretReconciler_MatchingDeployment_AutoAnnotation(t *testing.T) {
cfg := config.NewDefault()
cfg.AutoReloadAll = true
secret := testSecret("test-secret", "default")
deployment := testDeploymentWithEnvFrom("test-deployment", "default", "", "test-secret")
secret := testutil.NewSecret("test-secret", "default")
deployment := testutil.NewDeploymentWithEnvFrom("test-deployment", "default", "", "test-secret")
reconciler := newSecretReconciler(t, cfg, secret, deployment)
assertReconcileSuccess(t, reconciler, reconcileRequest("test-secret", "default"))
}
@@ -54,8 +55,8 @@ func TestSecretReconciler_MatchingDeployment_AutoAnnotation(t *testing.T) {
func TestSecretReconciler_MatchingDeployment_ExplicitAnnotation(t *testing.T) {
cfg := config.NewDefault()
secret := testSecret("test-secret", "default")
deployment := testDeployment("test-deployment", "default", map[string]string{
secret := testutil.NewSecret("test-secret", "default")
deployment := testutil.NewDeployment("test-deployment", "default", map[string]string{
cfg.Annotations.SecretReload: "test-secret",
})
reconciler := newSecretReconciler(t, cfg, secret, deployment)
@@ -65,8 +66,8 @@ func TestSecretReconciler_MatchingDeployment_ExplicitAnnotation(t *testing.T) {
func TestSecretReconciler_WorkloadInDifferentNamespace(t *testing.T) {
cfg := config.NewDefault()
secret := testSecret("test-secret", "namespace-a")
deployment := testDeployment("test-deployment", "namespace-b", map[string]string{
secret := testutil.NewSecret("test-secret", "namespace-a")
deployment := testutil.NewDeployment("test-deployment", "namespace-b", map[string]string{
cfg.Annotations.SecretReload: "test-secret",
})
reconciler := newSecretReconciler(t, cfg, secret, deployment)
@@ -77,8 +78,8 @@ func TestSecretReconciler_IgnoredWorkloadType(t *testing.T) {
cfg := config.NewDefault()
cfg.IgnoredWorkloads = []string{"deployment"}
secret := testSecret("test-secret", "default")
deployment := testDeployment("test-deployment", "default", map[string]string{
secret := testutil.NewSecret("test-secret", "default")
deployment := testutil.NewDeployment("test-deployment", "default", map[string]string{
cfg.Annotations.SecretReload: "test-secret",
})
reconciler := newSecretReconciler(t, cfg, secret, deployment)
@@ -88,8 +89,8 @@ func TestSecretReconciler_IgnoredWorkloadType(t *testing.T) {
func TestSecretReconciler_DaemonSet(t *testing.T) {
cfg := config.NewDefault()
secret := testSecret("test-secret", "default")
daemonset := testDaemonSet("test-daemonset", "default", map[string]string{
secret := testutil.NewSecret("test-secret", "default")
daemonset := testutil.NewDaemonSet("test-daemonset", "default", map[string]string{
cfg.Annotations.SecretReload: "test-secret",
})
reconciler := newSecretReconciler(t, cfg, secret, daemonset)
@@ -99,8 +100,8 @@ func TestSecretReconciler_DaemonSet(t *testing.T) {
func TestSecretReconciler_StatefulSet(t *testing.T) {
cfg := config.NewDefault()
secret := testSecret("test-secret", "default")
statefulset := testStatefulSet("test-statefulset", "default", map[string]string{
secret := testutil.NewSecret("test-secret", "default")
statefulset := testutil.NewStatefulSet("test-statefulset", "default", map[string]string{
cfg.Annotations.SecretReload: "test-secret",
})
reconciler := newSecretReconciler(t, cfg, secret, statefulset)
@@ -110,14 +111,14 @@ func TestSecretReconciler_StatefulSet(t *testing.T) {
func TestSecretReconciler_MultipleWorkloads(t *testing.T) {
cfg := config.NewDefault()
secret := testSecret("shared-secret", "default")
deployment1 := testDeployment("deployment-1", "default", map[string]string{
secret := testutil.NewSecret("shared-secret", "default")
deployment1 := testutil.NewDeployment("deployment-1", "default", map[string]string{
cfg.Annotations.SecretReload: "shared-secret",
})
deployment2 := testDeployment("deployment-2", "default", map[string]string{
deployment2 := testutil.NewDeployment("deployment-2", "default", map[string]string{
cfg.Annotations.SecretReload: "shared-secret",
})
daemonset := testDaemonSet("daemonset-1", "default", map[string]string{
daemonset := testutil.NewDaemonSet("daemonset-1", "default", map[string]string{
cfg.Annotations.SecretReload: "shared-secret",
})
@@ -129,8 +130,8 @@ func TestSecretReconciler_VolumeMount(t *testing.T) {
cfg := config.NewDefault()
cfg.AutoReloadAll = true
secret := testSecret("volume-secret", "default")
deployment := testDeploymentWithVolume("test-deployment", "default", "", "volume-secret")
secret := testutil.NewSecret("volume-secret", "default")
deployment := testutil.NewDeploymentWithVolume("test-deployment", "default", "", "volume-secret")
reconciler := newSecretReconciler(t, cfg, secret, deployment)
assertReconcileSuccess(t, reconciler, reconcileRequest("volume-secret", "default"))
}
@@ -139,8 +140,8 @@ func TestSecretReconciler_ProjectedVolume(t *testing.T) {
cfg := config.NewDefault()
cfg.AutoReloadAll = true
secret := testSecret("projected-secret", "default")
deployment := testDeploymentWithProjectedVolume("test-deployment", "default", "", "projected-secret")
secret := testutil.NewSecret("projected-secret", "default")
deployment := testutil.NewDeploymentWithProjectedVolume("test-deployment", "default", "", "projected-secret")
reconciler := newSecretReconciler(t, cfg, secret, deployment)
assertReconcileSuccess(t, reconciler, reconcileRequest("projected-secret", "default"))
}
@@ -148,10 +149,10 @@ func TestSecretReconciler_ProjectedVolume(t *testing.T) {
func TestSecretReconciler_SearchAnnotation(t *testing.T) {
cfg := config.NewDefault()
secret := testSecretWithAnnotations("test-secret", "default", map[string]string{
secret := testutil.NewSecretWithAnnotations("test-secret", "default", map[string]string{
cfg.Annotations.Match: "true",
})
deployment := testDeployment("test-deployment", "default", map[string]string{
deployment := testutil.NewDeployment("test-deployment", "default", map[string]string{
cfg.Annotations.Search: "true",
})
reconciler := newSecretReconciler(t, cfg, secret, deployment)
@@ -163,10 +164,10 @@ func TestSecretReconciler_ServiceAccountTokenIgnored(t *testing.T) {
cfg.AutoReloadAll = true
// Service account tokens should be ignored
secret := testSecret("sa-token", "default")
secret := testutil.NewSecret("sa-token", "default")
secret.Type = "kubernetes.io/service-account-token"
deployment := testDeploymentWithEnvFrom("test-deployment", "default", "", "sa-token")
deployment := testutil.NewDeploymentWithEnvFrom("test-deployment", "default", "", "sa-token")
reconciler := newSecretReconciler(t, cfg, secret, deployment)
assertReconcileSuccess(t, reconciler, reconcileRequest("sa-token", "default"))
}
+20 -320
View File
@@ -11,32 +11,21 @@ import (
"github.com/stakater/Reloader/internal/pkg/events"
"github.com/stakater/Reloader/internal/pkg/metrics"
"github.com/stakater/Reloader/internal/pkg/reload"
"github.com/stakater/Reloader/internal/pkg/testutil"
"github.com/stakater/Reloader/internal/pkg/webhook"
"github.com/stakater/Reloader/internal/pkg/workload"
appsv1 "k8s.io/api/apps/v1"
batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
)
// testScheme is a shared scheme for all controller tests.
func testScheme() *runtime.Scheme {
scheme := runtime.NewScheme()
_ = corev1.AddToScheme(scheme)
_ = appsv1.AddToScheme(scheme)
_ = batchv1.AddToScheme(scheme)
return scheme
}
// newConfigMapReconciler creates a ConfigMapReconciler for testing.
func newConfigMapReconciler(t *testing.T, cfg *config.Config, objects ...runtime.Object) *controller.ConfigMapReconciler {
t.Helper()
fakeClient := fake.NewClientBuilder().
WithScheme(testScheme()).
WithScheme(testutil.NewScheme()).
WithRuntimeObjects(objects...).
Build()
@@ -59,7 +48,7 @@ func newConfigMapReconciler(t *testing.T, cfg *config.Config, objects ...runtime
func newSecretReconciler(t *testing.T, cfg *config.Config, objects ...runtime.Object) *controller.SecretReconciler {
t.Helper()
fakeClient := fake.NewClientBuilder().
WithScheme(testScheme()).
WithScheme(testutil.NewScheme()).
WithRuntimeObjects(objects...).
Build()
@@ -78,260 +67,6 @@ func newSecretReconciler(t *testing.T, cfg *config.Config, objects ...runtime.Ob
}
}
// testConfigMap creates a ConfigMap for testing.
func testConfigMap(name, namespace string) *corev1.ConfigMap {
return &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
Data: map[string]string{"key": "value"},
}
}
// testConfigMapWithAnnotations creates a ConfigMap with annotations.
func testConfigMapWithAnnotations(name, namespace string, annotations map[string]string) *corev1.ConfigMap {
cm := testConfigMap(name, namespace)
cm.Annotations = annotations
return cm
}
// testSecret creates a Secret for testing.
func testSecret(name, namespace string) *corev1.Secret {
return &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
Data: map[string][]byte{"key": []byte("value")},
}
}
// testSecretWithAnnotations creates a Secret with annotations.
func testSecretWithAnnotations(name, namespace string, annotations map[string]string) *corev1.Secret {
secret := testSecret(name, namespace)
secret.Annotations = annotations
return secret
}
// testDeployment creates a minimal Deployment for testing.
func testDeployment(name, namespace string, annotations map[string]string) *appsv1.Deployment {
return &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Annotations: annotations,
},
Spec: appsv1.DeploymentSpec{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"app": name},
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{"app": name},
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "main",
Image: "nginx",
},
},
},
},
},
}
}
// testDeploymentWithEnvFrom creates a Deployment with EnvFrom referencing a ConfigMap or Secret.
func testDeploymentWithEnvFrom(name, namespace string, configMapName, secretName string) *appsv1.Deployment {
d := testDeployment(name, namespace, nil)
if configMapName != "" {
d.Spec.Template.Spec.Containers[0].EnvFrom = append(
d.Spec.Template.Spec.Containers[0].EnvFrom,
corev1.EnvFromSource{
ConfigMapRef: &corev1.ConfigMapEnvSource{
LocalObjectReference: corev1.LocalObjectReference{Name: configMapName},
},
},
)
}
if secretName != "" {
d.Spec.Template.Spec.Containers[0].EnvFrom = append(
d.Spec.Template.Spec.Containers[0].EnvFrom,
corev1.EnvFromSource{
SecretRef: &corev1.SecretEnvSource{
LocalObjectReference: corev1.LocalObjectReference{Name: secretName},
},
},
)
}
return d
}
// testDeploymentWithVolume creates a Deployment with a volume from ConfigMap or Secret.
func testDeploymentWithVolume(name, namespace string, configMapName, secretName string) *appsv1.Deployment {
d := testDeployment(name, namespace, nil)
d.Spec.Template.Spec.Containers[0].VolumeMounts = []corev1.VolumeMount{
{
Name: "config",
MountPath: "/etc/config",
},
}
if configMapName != "" {
d.Spec.Template.Spec.Volumes = []corev1.Volume{
{
Name: "config",
VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{Name: configMapName},
},
},
},
}
}
if secretName != "" {
d.Spec.Template.Spec.Volumes = []corev1.Volume{
{
Name: "config",
VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
SecretName: secretName,
},
},
},
}
}
return d
}
// testDeploymentWithProjectedVolume creates a Deployment with a projected volume.
func testDeploymentWithProjectedVolume(name, namespace string, configMapName, secretName string) *appsv1.Deployment {
d := testDeployment(name, namespace, nil)
d.Spec.Template.Spec.Containers[0].VolumeMounts = []corev1.VolumeMount{
{
Name: "config",
MountPath: "/etc/config",
},
}
var sources []corev1.VolumeProjection
if configMapName != "" {
sources = append(
sources, corev1.VolumeProjection{
ConfigMap: &corev1.ConfigMapProjection{
LocalObjectReference: corev1.LocalObjectReference{Name: configMapName},
},
},
)
}
if secretName != "" {
sources = append(
sources, corev1.VolumeProjection{
Secret: &corev1.SecretProjection{
LocalObjectReference: corev1.LocalObjectReference{Name: secretName},
},
},
)
}
d.Spec.Template.Spec.Volumes = []corev1.Volume{
{
Name: "config",
VolumeSource: corev1.VolumeSource{
Projected: &corev1.ProjectedVolumeSource{Sources: sources},
},
},
}
return d
}
// testDaemonSet creates a minimal DaemonSet for testing.
func testDaemonSet(name, namespace string, annotations map[string]string) *appsv1.DaemonSet {
return &appsv1.DaemonSet{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Annotations: annotations,
},
Spec: appsv1.DaemonSetSpec{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"app": name},
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{"app": name},
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "main",
Image: "nginx",
},
},
},
},
},
}
}
// testStatefulSet creates a minimal StatefulSet for testing.
func testStatefulSet(name, namespace string, annotations map[string]string) *appsv1.StatefulSet {
return &appsv1.StatefulSet{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Annotations: annotations,
},
Spec: appsv1.StatefulSetSpec{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"app": name},
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{"app": name},
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "main",
Image: "nginx",
},
},
},
},
},
}
}
// reconcileRequest creates a ctrl.Request for the given name and namespace.
func reconcileRequest(name, namespace string) ctrl.Request {
return ctrl.Request{
NamespacedName: types.NamespacedName{
Name: name,
Namespace: namespace,
},
}
}
// namespaceRequest creates a ctrl.Request for a namespace (no namespace field needed).
func namespaceRequest(name string) ctrl.Request {
return ctrl.Request{
NamespacedName: types.NamespacedName{Name: name},
}
}
// testNamespace creates a Namespace with optional labels.
func testNamespace(name string, labels map[string]string) *corev1.Namespace {
return &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Labels: labels,
},
}
}
// newNamespaceReconciler creates a NamespaceReconciler for testing.
func newNamespaceReconciler(t *testing.T, cfg *config.Config, cache *controller.NamespaceCache, objects ...runtime.Object) *controller.NamespaceReconciler {
t.Helper()
@@ -351,6 +86,23 @@ func newNamespaceReconciler(t *testing.T, cfg *config.Config, cache *controller.
}
}
// reconcileRequest creates a ctrl.Request for the given name and namespace.
func reconcileRequest(name, namespace string) ctrl.Request {
return ctrl.Request{
NamespacedName: types.NamespacedName{
Name: name,
Namespace: namespace,
},
}
}
// namespaceRequest creates a ctrl.Request for a namespace (no namespace field needed).
func namespaceRequest(name string) ctrl.Request {
return ctrl.Request{
NamespacedName: types.NamespacedName{Name: name},
}
}
// assertReconcileSuccess runs reconcile and asserts no error and no requeue.
func assertReconcileSuccess(t *testing.T, reconciler interface {
Reconcile(context.Context, ctrl.Request) (ctrl.Result, error)
@@ -364,55 +116,3 @@ func assertReconcileSuccess(t *testing.T, reconciler interface {
t.Error("Should not requeue")
}
}
// testJob creates a minimal Job for testing.
func testJob(name, namespace string) *batchv1.Job {
return &batchv1.Job{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
Spec: batchv1.JobSpec{
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
RestartPolicy: corev1.RestartPolicyNever,
Containers: []corev1.Container{
{
Name: "main",
Image: "busybox",
},
},
},
},
},
}
}
// testCronJob creates a minimal CronJob for testing.
func testCronJob(name, namespace string) *batchv1.CronJob {
return &batchv1.CronJob{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
UID: "test-uid",
},
Spec: batchv1.CronJobSpec{
Schedule: "*/5 * * * *",
JobTemplate: batchv1.JobTemplateSpec{
Spec: batchv1.JobSpec{
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
RestartPolicy: corev1.RestartPolicyNever,
Containers: []corev1.Container{
{
Name: "main",
Image: "busybox",
},
},
},
},
},
},
},
}
}
+25 -57
View File
@@ -5,8 +5,8 @@ import (
"testing"
"github.com/stakater/Reloader/internal/pkg/config"
"github.com/stakater/Reloader/internal/pkg/testutil"
"github.com/stakater/Reloader/internal/pkg/workload"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
@@ -16,7 +16,7 @@ func TestService_ProcessConfigMap_AutoReload(t *testing.T) {
svc := NewService(cfg)
// Create a deployment with auto annotation that uses the configmap
deploy := createTestDeployment(
deploy := testutil.NewDeployment(
"test-deploy", "default", map[string]string{
"reloader.stakater.com/auto": "true",
},
@@ -76,7 +76,7 @@ func TestService_ProcessConfigMap_ExplicitAnnotation(t *testing.T) {
cfg := config.NewDefault()
svc := NewService(cfg)
deploy := createTestDeployment(
deploy := testutil.NewDeployment(
"test-deploy", "default", map[string]string{
"configmap.reloader.stakater.com/reload": "test-cm",
},
@@ -121,7 +121,7 @@ func TestService_ProcessConfigMap_IgnoredResource(t *testing.T) {
svc := NewService(cfg)
// Create a deployment with auto annotation
deploy := createTestDeployment(
deploy := testutil.NewDeployment(
"test-deploy", "default", map[string]string{
"reloader.stakater.com/auto": "true",
},
@@ -177,7 +177,7 @@ func TestService_ProcessSecret_AutoReload(t *testing.T) {
svc := NewService(cfg)
// Create a deployment with auto annotation that uses the secret
deploy := createTestDeployment(
deploy := testutil.NewDeployment(
"test-deploy", "default", map[string]string{
"reloader.stakater.com/auto": "true",
},
@@ -233,7 +233,7 @@ func TestService_ProcessConfigMap_DeleteEvent(t *testing.T) {
svc := NewService(cfg)
// Create a deployment with explicit configmap annotation
deploy := createTestDeployment(
deploy := testutil.NewDeployment(
"test-deploy", "default", map[string]string{
"configmap.reloader.stakater.com/reload": "test-cm",
},
@@ -276,7 +276,7 @@ func TestService_ProcessConfigMap_DeleteEventDisabled(t *testing.T) {
cfg.ReloadOnDelete = false // Disabled by default
svc := NewService(cfg)
deploy := createTestDeployment(
deploy := testutil.NewDeployment(
"test-deploy", "default", map[string]string{
"configmap.reloader.stakater.com/reload": "test-cm",
},
@@ -311,7 +311,7 @@ func TestService_ApplyReload_EnvVarStrategy(t *testing.T) {
cfg.ReloadStrategy = config.ReloadStrategyEnvVars
svc := NewService(cfg)
deploy := createTestDeployment("test-deploy", "default", nil)
deploy := testutil.NewDeployment("test-deploy", "default", nil)
accessor := workload.NewDeploymentWorkload(deploy)
ctx := context.Background()
@@ -355,7 +355,7 @@ func TestService_ApplyReload_AnnotationStrategy(t *testing.T) {
cfg.ReloadStrategy = config.ReloadStrategyAnnotations
svc := NewService(cfg)
deploy := createTestDeployment("test-deploy", "default", nil)
deploy := testutil.NewDeployment("test-deploy", "default", nil)
accessor := workload.NewDeploymentWorkload(deploy)
ctx := context.Background()
@@ -381,7 +381,7 @@ func TestService_ApplyReload_EnvVarDeletion(t *testing.T) {
cfg.ReloadStrategy = config.ReloadStrategyEnvVars
svc := NewService(cfg)
deploy := createTestDeployment("test-deploy", "default", nil)
deploy := testutil.NewDeployment("test-deploy", "default", nil)
// Pre-add an env var
deploy.Spec.Template.Spec.Containers[0].Env = []corev1.EnvVar{
{Name: "STAKATER_TEST_CM_CONFIGMAP", Value: "oldhash"},
@@ -427,7 +427,7 @@ func TestService_ApplyReload_NoChangeIfSameHash(t *testing.T) {
cfg.ReloadStrategy = config.ReloadStrategyEnvVars
svc := NewService(cfg)
deploy := createTestDeployment("test-deploy", "default", nil)
deploy := testutil.NewDeployment("test-deploy", "default", nil)
// Pre-add env var with same hash
deploy.Spec.Template.Spec.Containers[0].Env = []corev1.EnvVar{
{Name: "STAKATER_TEST_CM_CONFIGMAP", Value: "abc123hash"},
@@ -451,7 +451,7 @@ func TestService_ProcessConfigMap_MultipleWorkloads(t *testing.T) {
svc := NewService(cfg)
// Create multiple workloads
deploy1 := createTestDeployment(
deploy1 := testutil.NewDeployment(
"deploy1", "default", map[string]string{
"reloader.stakater.com/auto": "true",
},
@@ -469,7 +469,7 @@ func TestService_ProcessConfigMap_MultipleWorkloads(t *testing.T) {
},
}
deploy2 := createTestDeployment(
deploy2 := testutil.NewDeployment(
"deploy2", "default", map[string]string{
"reloader.stakater.com/auto": "true",
},
@@ -488,7 +488,7 @@ func TestService_ProcessConfigMap_MultipleWorkloads(t *testing.T) {
}
// Deploy3 doesn't use the configmap
deploy3 := createTestDeployment(
deploy3 := testutil.NewDeployment(
"deploy3", "default", map[string]string{
"reloader.stakater.com/auto": "true",
},
@@ -538,7 +538,7 @@ func TestService_ProcessConfigMap_DifferentNamespaces(t *testing.T) {
svc := NewService(cfg)
// Create deployments in different namespaces
deploy1 := createTestDeployment(
deploy1 := testutil.NewDeployment(
"deploy1", "namespace-a", map[string]string{
"reloader.stakater.com/auto": "true",
},
@@ -556,7 +556,7 @@ func TestService_ProcessConfigMap_DifferentNamespaces(t *testing.T) {
},
}
deploy2 := createTestDeployment(
deploy2 := testutil.NewDeployment(
"deploy2", "namespace-b", map[string]string{
"reloader.stakater.com/auto": "true",
},
@@ -1102,7 +1102,7 @@ func TestService_findTargetContainer_AutoReload(t *testing.T) {
svc := NewService(cfg)
// Test with autoReload=true and volume mount
deploy := createTestDeployment("test", "default", nil)
deploy := testutil.NewDeployment("test", "default", nil)
deploy.Spec.Template.Spec.Volumes = []corev1.Volume{
{
Name: "config-vol",
@@ -1138,7 +1138,7 @@ func TestService_findTargetContainer_AutoReload_EnvRef(t *testing.T) {
svc := NewService(cfg)
// Test with autoReload=true and env ref (no volume)
deploy := createTestDeployment("test", "default", nil)
deploy := testutil.NewDeployment("test", "default", nil)
deploy.Spec.Template.Spec.Containers = []corev1.Container{
{
Name: "sidecar",
@@ -1176,7 +1176,7 @@ func TestService_findTargetContainer_AutoReload_InitContainer(t *testing.T) {
svc := NewService(cfg)
// Test with autoReload=true where init container uses the volume
deploy := createTestDeployment("test", "default", nil)
deploy := testutil.NewDeployment("test", "default", nil)
deploy.Spec.Template.Spec.Volumes = []corev1.Volume{
{
Name: "config-vol",
@@ -1219,7 +1219,7 @@ func TestService_findTargetContainer_AutoReload_InitContainerEnvRef(t *testing.T
svc := NewService(cfg)
// Test with autoReload=true where init container has env ref
deploy := createTestDeployment("test", "default", nil)
deploy := testutil.NewDeployment("test", "default", nil)
deploy.Spec.Template.Spec.InitContainers = []corev1.Container{
{
Name: "init",
@@ -1259,7 +1259,7 @@ func TestService_findTargetContainer_NoContainers(t *testing.T) {
cfg := config.NewDefault()
svc := NewService(cfg)
deploy := createTestDeployment("test", "default", nil)
deploy := testutil.NewDeployment("test", "default", nil)
deploy.Spec.Template.Spec.Containers = []corev1.Container{}
accessor := workload.NewDeploymentWorkload(deploy)
@@ -1273,7 +1273,7 @@ func TestService_findTargetContainer_NonAutoReload(t *testing.T) {
cfg := config.NewDefault()
svc := NewService(cfg)
deploy := createTestDeployment("test", "default", nil)
deploy := testutil.NewDeployment("test", "default", nil)
deploy.Spec.Template.Spec.Containers = []corev1.Container{
{Name: "first", Image: "nginx"},
{Name: "second", Image: "busybox"},
@@ -1295,7 +1295,7 @@ func TestService_findTargetContainer_AutoReload_FallbackToFirst(t *testing.T) {
svc := NewService(cfg)
// autoReload=true but no matching volume or env ref - should fallback to first container
deploy := createTestDeployment("test", "default", nil)
deploy := testutil.NewDeployment("test", "default", nil)
deploy.Spec.Template.Spec.Containers = []corev1.Container{
{Name: "first", Image: "nginx"},
{Name: "second", Image: "busybox"},
@@ -1315,7 +1315,7 @@ func TestService_ProcessNilChange(t *testing.T) {
cfg := config.NewDefault()
svc := NewService(cfg)
deploy := createTestDeployment("test", "default", nil)
deploy := testutil.NewDeployment("test", "default", nil)
workloads := []workload.WorkloadAccessor{workload.NewDeploymentWorkload(deploy)}
// Test with nil ConfigMap
@@ -1335,7 +1335,7 @@ func TestService_ProcessCreateEventDisabled(t *testing.T) {
cfg.ReloadOnCreate = false
svc := NewService(cfg)
deploy := createTestDeployment(
deploy := testutil.NewDeployment(
"test", "default", map[string]string{
"reloader.stakater.com/auto": "true",
},
@@ -1357,35 +1357,3 @@ func TestService_ProcessCreateEventDisabled(t *testing.T) {
t.Errorf("Expected nil decisions when create events disabled, got %v", decisions)
}
}
// Helper function to create a test deployment
func createTestDeployment(name, namespace string, annotations map[string]string) *appsv1.Deployment {
replicas := int32(1)
return &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Annotations: annotations,
},
Spec: appsv1.DeploymentSpec{
Replicas: &replicas,
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"app": name},
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{"app": name},
Annotations: map[string]string{},
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "main",
Image: "nginx:latest",
},
},
},
},
},
}
}
+286
View File
@@ -0,0 +1,286 @@
package testutil
import (
appsv1 "k8s.io/api/apps/v1"
batchv1 "k8s.io/api/batch/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
)
// NewScheme creates a scheme with common types for testing.
func NewScheme() *runtime.Scheme {
scheme := runtime.NewScheme()
_ = corev1.AddToScheme(scheme)
_ = appsv1.AddToScheme(scheme)
_ = batchv1.AddToScheme(scheme)
return scheme
}
// NewDeployment creates a minimal Deployment for unit testing.
func NewDeployment(name, namespace string, annotations map[string]string) *appsv1.Deployment {
return &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Annotations: annotations,
},
Spec: appsv1.DeploymentSpec{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"app": name},
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{"app": name},
Annotations: map[string]string{},
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{{
Name: "main",
Image: "nginx",
}},
},
},
},
}
}
// NewDeploymentWithEnvFrom creates a Deployment with EnvFrom referencing a ConfigMap or Secret.
func NewDeploymentWithEnvFrom(name, namespace string, configMapName, secretName string) *appsv1.Deployment {
d := NewDeployment(name, namespace, nil)
if configMapName != "" {
d.Spec.Template.Spec.Containers[0].EnvFrom = append(
d.Spec.Template.Spec.Containers[0].EnvFrom,
corev1.EnvFromSource{
ConfigMapRef: &corev1.ConfigMapEnvSource{
LocalObjectReference: corev1.LocalObjectReference{Name: configMapName},
},
},
)
}
if secretName != "" {
d.Spec.Template.Spec.Containers[0].EnvFrom = append(
d.Spec.Template.Spec.Containers[0].EnvFrom,
corev1.EnvFromSource{
SecretRef: &corev1.SecretEnvSource{
LocalObjectReference: corev1.LocalObjectReference{Name: secretName},
},
},
)
}
return d
}
// NewDeploymentWithVolume creates a Deployment with a volume from ConfigMap or Secret.
func NewDeploymentWithVolume(name, namespace string, configMapName, secretName string) *appsv1.Deployment {
d := NewDeployment(name, namespace, nil)
d.Spec.Template.Spec.Containers[0].VolumeMounts = []corev1.VolumeMount{{
Name: "config",
MountPath: "/etc/config",
}}
if configMapName != "" {
d.Spec.Template.Spec.Volumes = []corev1.Volume{{
Name: "config",
VolumeSource: corev1.VolumeSource{
ConfigMap: &corev1.ConfigMapVolumeSource{
LocalObjectReference: corev1.LocalObjectReference{Name: configMapName},
},
},
}}
}
if secretName != "" {
d.Spec.Template.Spec.Volumes = []corev1.Volume{{
Name: "config",
VolumeSource: corev1.VolumeSource{
Secret: &corev1.SecretVolumeSource{
SecretName: secretName,
},
},
}}
}
return d
}
// NewDeploymentWithProjectedVolume creates a Deployment with a projected volume.
func NewDeploymentWithProjectedVolume(name, namespace string, configMapName, secretName string) *appsv1.Deployment {
d := NewDeployment(name, namespace, nil)
d.Spec.Template.Spec.Containers[0].VolumeMounts = []corev1.VolumeMount{{
Name: "config",
MountPath: "/etc/config",
}}
sources := []corev1.VolumeProjection{}
if configMapName != "" {
sources = append(sources, corev1.VolumeProjection{
ConfigMap: &corev1.ConfigMapProjection{
LocalObjectReference: corev1.LocalObjectReference{Name: configMapName},
},
})
}
if secretName != "" {
sources = append(sources, corev1.VolumeProjection{
Secret: &corev1.SecretProjection{
LocalObjectReference: corev1.LocalObjectReference{Name: secretName},
},
})
}
d.Spec.Template.Spec.Volumes = []corev1.Volume{{
Name: "config",
VolumeSource: corev1.VolumeSource{
Projected: &corev1.ProjectedVolumeSource{Sources: sources},
},
}}
return d
}
// NewDaemonSet creates a minimal DaemonSet for unit testing.
func NewDaemonSet(name, namespace string, annotations map[string]string) *appsv1.DaemonSet {
return &appsv1.DaemonSet{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Annotations: annotations,
},
Spec: appsv1.DaemonSetSpec{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"app": name},
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{"app": name},
Annotations: map[string]string{},
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{{
Name: "main",
Image: "nginx",
}},
},
},
},
}
}
// NewStatefulSet creates a minimal StatefulSet for unit testing.
func NewStatefulSet(name, namespace string, annotations map[string]string) *appsv1.StatefulSet {
return &appsv1.StatefulSet{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Annotations: annotations,
},
Spec: appsv1.StatefulSetSpec{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"app": name},
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{"app": name},
Annotations: map[string]string{},
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{{
Name: "main",
Image: "nginx",
}},
},
},
},
}
}
// NewJob creates a minimal Job for unit testing.
func NewJob(name, namespace string) *batchv1.Job {
return &batchv1.Job{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
Spec: batchv1.JobSpec{
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
RestartPolicy: corev1.RestartPolicyNever,
Containers: []corev1.Container{{
Name: "main",
Image: "busybox",
}},
},
},
},
}
}
// NewCronJob creates a minimal CronJob for unit testing.
func NewCronJob(name, namespace string) *batchv1.CronJob {
return &batchv1.CronJob{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
UID: "test-uid",
},
Spec: batchv1.CronJobSpec{
Schedule: "*/5 * * * *",
JobTemplate: batchv1.JobTemplateSpec{
Spec: batchv1.JobSpec{
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
RestartPolicy: corev1.RestartPolicyNever,
Containers: []corev1.Container{{
Name: "main",
Image: "busybox",
}},
},
},
},
},
},
}
}
// NewConfigMap creates a ConfigMap for unit testing.
func NewConfigMap(name, namespace string) *corev1.ConfigMap {
return &corev1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
Data: map[string]string{"key": "value"},
}
}
// NewConfigMapWithAnnotations creates a ConfigMap with annotations.
func NewConfigMapWithAnnotations(name, namespace string, annotations map[string]string) *corev1.ConfigMap {
cm := NewConfigMap(name, namespace)
cm.Annotations = annotations
return cm
}
// NewSecret creates a Secret for unit testing.
func NewSecret(name, namespace string) *corev1.Secret {
return &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
Data: map[string][]byte{"key": []byte("value")},
}
}
// NewSecretWithAnnotations creates a Secret with annotations.
func NewSecretWithAnnotations(name, namespace string, annotations map[string]string) *corev1.Secret {
secret := NewSecret(name, namespace)
secret.Annotations = annotations
return secret
}
// NewNamespace creates a Namespace with optional labels.
func NewNamespace(name string, labels map[string]string) *corev1.Namespace {
return &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Labels: labels,
},
}
}
+28 -146
View File
@@ -134,56 +134,16 @@ func DeleteSecret(client kubernetes.Interface, namespace, name string) error {
// CreateDeployment creates a Deployment that references a ConfigMap/Secret.
func CreateDeployment(client kubernetes.Interface, name, namespace string, useConfigMap bool, annotations map[string]string) (*appsv1.Deployment, error) {
replicas := int32(1)
deployment := &appsv1.Deployment{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Annotations: annotations,
},
Spec: appsv1.DeploymentSpec{
Replicas: &replicas,
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"app": name},
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{"app": name},
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "main",
Image: "busybox:1.36",
Command: []string{"sh", "-c", "while true; do sleep 3600; done"},
},
},
},
},
},
}
var deployment *appsv1.Deployment
if useConfigMap {
deployment.Spec.Template.Spec.Containers[0].EnvFrom = []corev1.EnvFromSource{
{
ConfigMapRef: &corev1.ConfigMapEnvSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: name,
},
},
},
}
deployment = NewDeploymentWithEnvFrom(name, namespace, name, "")
} else {
deployment.Spec.Template.Spec.Containers[0].EnvFrom = []corev1.EnvFromSource{
{
SecretRef: &corev1.SecretEnvSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: name,
},
},
},
}
deployment = NewDeploymentWithEnvFrom(name, namespace, "", name)
}
deployment.Annotations = annotations
// Override image for integration tests
deployment.Spec.Template.Spec.Containers[0].Image = "busybox:1.36"
deployment.Spec.Template.Spec.Containers[0].Command = []string{"sh", "-c", "while true; do sleep 3600; done"}
return client.AppsV1().Deployments(namespace).Create(context.Background(), deployment, metav1.CreateOptions{})
}
@@ -195,40 +155,16 @@ func DeleteDeployment(client kubernetes.Interface, namespace, name string) error
// CreateDaemonSet creates a DaemonSet that references a ConfigMap/Secret.
func CreateDaemonSet(client kubernetes.Interface, name, namespace string, useConfigMap bool, annotations map[string]string) (*appsv1.DaemonSet, error) {
daemonset := &appsv1.DaemonSet{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Annotations: annotations,
},
Spec: appsv1.DaemonSetSpec{
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"app": name},
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{"app": name},
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "main",
Image: "busybox:1.36",
Command: []string{"sh", "-c", "while true; do sleep 3600; done"},
},
},
},
},
},
}
daemonset := NewDaemonSet(name, namespace, annotations)
// Override image for integration tests
daemonset.Spec.Template.Spec.Containers[0].Image = "busybox:1.36"
daemonset.Spec.Template.Spec.Containers[0].Command = []string{"sh", "-c", "while true; do sleep 3600; done"}
if useConfigMap {
daemonset.Spec.Template.Spec.Containers[0].EnvFrom = []corev1.EnvFromSource{
{
ConfigMapRef: &corev1.ConfigMapEnvSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: name,
},
LocalObjectReference: corev1.LocalObjectReference{Name: name},
},
},
}
@@ -236,9 +172,7 @@ func CreateDaemonSet(client kubernetes.Interface, name, namespace string, useCon
daemonset.Spec.Template.Spec.Containers[0].EnvFrom = []corev1.EnvFromSource{
{
SecretRef: &corev1.SecretEnvSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: name,
},
LocalObjectReference: corev1.LocalObjectReference{Name: name},
},
},
}
@@ -254,43 +188,17 @@ func DeleteDaemonSet(client kubernetes.Interface, namespace, name string) error
// CreateStatefulSet creates a StatefulSet that references a ConfigMap/Secret.
func CreateStatefulSet(client kubernetes.Interface, name, namespace string, useConfigMap bool, annotations map[string]string) (*appsv1.StatefulSet, error) {
replicas := int32(1)
statefulset := &appsv1.StatefulSet{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Annotations: annotations,
},
Spec: appsv1.StatefulSetSpec{
Replicas: &replicas,
Selector: &metav1.LabelSelector{
MatchLabels: map[string]string{"app": name},
},
ServiceName: name,
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{"app": name},
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Name: "main",
Image: "busybox:1.36",
Command: []string{"sh", "-c", "while true; do sleep 3600; done"},
},
},
},
},
},
}
statefulset := NewStatefulSet(name, namespace, annotations)
statefulset.Spec.ServiceName = name
// Override image for integration tests
statefulset.Spec.Template.Spec.Containers[0].Image = "busybox:1.36"
statefulset.Spec.Template.Spec.Containers[0].Command = []string{"sh", "-c", "while true; do sleep 3600; done"}
if useConfigMap {
statefulset.Spec.Template.Spec.Containers[0].EnvFrom = []corev1.EnvFromSource{
{
ConfigMapRef: &corev1.ConfigMapEnvSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: name,
},
LocalObjectReference: corev1.LocalObjectReference{Name: name},
},
},
}
@@ -298,9 +206,7 @@ func CreateStatefulSet(client kubernetes.Interface, name, namespace string, useC
statefulset.Spec.Template.Spec.Containers[0].EnvFrom = []corev1.EnvFromSource{
{
SecretRef: &corev1.SecretEnvSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: name,
},
LocalObjectReference: corev1.LocalObjectReference{Name: name},
},
},
}
@@ -316,40 +222,18 @@ func DeleteStatefulSet(client kubernetes.Interface, namespace, name string) erro
// CreateCronJob creates a CronJob that references a ConfigMap/Secret.
func CreateCronJob(client kubernetes.Interface, name, namespace string, useConfigMap bool, annotations map[string]string) (*batchv1.CronJob, error) {
cronjob := &batchv1.CronJob{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Annotations: annotations,
},
Spec: batchv1.CronJobSpec{
Schedule: "*/5 * * * *",
JobTemplate: batchv1.JobTemplateSpec{
Spec: batchv1.JobSpec{
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
RestartPolicy: corev1.RestartPolicyOnFailure,
Containers: []corev1.Container{
{
Name: "main",
Image: "busybox:1.36",
Command: []string{"sh", "-c", "echo hello"},
},
},
},
},
},
},
},
}
cronjob := NewCronJob(name, namespace)
cronjob.Annotations = annotations
// Override image for integration tests
cronjob.Spec.JobTemplate.Spec.Template.Spec.Containers[0].Image = "busybox:1.36"
cronjob.Spec.JobTemplate.Spec.Template.Spec.Containers[0].Command = []string{"sh", "-c", "echo hello"}
cronjob.Spec.JobTemplate.Spec.Template.Spec.RestartPolicy = corev1.RestartPolicyOnFailure
if useConfigMap {
cronjob.Spec.JobTemplate.Spec.Template.Spec.Containers[0].EnvFrom = []corev1.EnvFromSource{
{
ConfigMapRef: &corev1.ConfigMapEnvSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: name,
},
LocalObjectReference: corev1.LocalObjectReference{Name: name},
},
},
}
@@ -357,9 +241,7 @@ func CreateCronJob(client kubernetes.Interface, name, namespace string, useConfi
cronjob.Spec.JobTemplate.Spec.Template.Spec.Containers[0].EnvFrom = []corev1.EnvFromSource{
{
SecretRef: &corev1.SecretEnvSource{
LocalObjectReference: corev1.LocalObjectReference{
Name: name,
},
LocalObjectReference: corev1.LocalObjectReference{Name: name},
},
},
}
-4
View File
@@ -18,14 +18,12 @@ func TestNewRegistry_WithoutArgoRollouts(t *testing.T) {
t.Errorf("SupportedKinds() = %d kinds, want 5", len(kinds))
}
// Should not include ArgoRollout
for _, k := range kinds {
if k == KindArgoRollout {
t.Error("SupportedKinds() should not include ArgoRollout when disabled")
}
}
// ListerFor should return nil for ArgoRollout
if r.ListerFor(KindArgoRollout) != nil {
t.Error("ListerFor(KindArgoRollout) should return nil when disabled")
}
@@ -39,7 +37,6 @@ func TestNewRegistry_WithArgoRollouts(t *testing.T) {
t.Errorf("SupportedKinds() = %d kinds, want 6", len(kinds))
}
// Should include ArgoRollout
found := false
for _, k := range kinds {
if k == KindArgoRollout {
@@ -51,7 +48,6 @@ func TestNewRegistry_WithArgoRollouts(t *testing.T) {
t.Error("SupportedKinds() should include ArgoRollout when enabled")
}
// ListerFor should return a function for ArgoRollout
if r.ListerFor(KindArgoRollout) == nil {
t.Error("ListerFor(KindArgoRollout) should return a function when enabled")
}