From d6ec78b53a243c601daf6f9dcee621d3e2034a10 Mon Sep 17 00:00:00 2001 From: odubajDT Date: Wed, 8 Nov 2023 14:16:00 +0100 Subject: [PATCH] add more tests Signed-off-by: odubajDT --- .github/workflows/pr-checks.yml | 4 +- apis/core/v1beta1/featureflag_types_test.go | 70 +++++ .../v1beta1/featureflagsource_types_test.go | 279 ++++++++++++++++++ common/common_test.go | 58 +++- common/constant/configuration.go | 3 + main.go | 7 +- webhooks/common.go | 19 +- webhooks/common_test.go | 5 +- webhooks/pod_webhook.go | 16 +- webhooks/pod_webhook_test.go | 67 +++-- 10 files changed, 468 insertions(+), 60 deletions(-) create mode 100644 apis/core/v1beta1/featureflag_types_test.go diff --git a/.github/workflows/pr-checks.yml b/.github/workflows/pr-checks.yml index 434615a07..eed3e37cd 100644 --- a/.github/workflows/pr-checks.yml +++ b/.github/workflows/pr-checks.yml @@ -141,12 +141,12 @@ jobs: IMG=open-feature-operator-local:${{ github.sha }} make deploy-operator IMG=open-feature-operator-local:${{ github.sha }} make e2e-test-kuttl - name: Create reports - if: always() + if: failure() working-directory: ./.github/scripts run: ./create-reports.sh - name: Upload cluster logs - if: always() + if: failure() uses: actions/upload-artifact@v3 with: name: e2e-tests diff --git a/apis/core/v1beta1/featureflag_types_test.go b/apis/core/v1beta1/featureflag_types_test.go new file mode 100644 index 000000000..fb7af9a37 --- /dev/null +++ b/apis/core/v1beta1/featureflag_types_test.go @@ -0,0 +1,70 @@ +package v1beta1 + +import ( + "testing" + + "github.com/open-feature/open-feature-operator/common/utils" + "github.com/stretchr/testify/require" + corev1 "k8s.io/api/core/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" +) + +func Test_FeatureFlag(t *testing.T) { + ff := FeatureFlag{ + ObjectMeta: v1.ObjectMeta{ + Name: "ffconf1", + Namespace: "test", + OwnerReferences: []v1.OwnerReference{ + { + APIVersion: "ver", + Kind: "kind", + Name: "ffconf1", + UID: types.UID("5"), + Controller: utils.TrueVal(), + }, + }, + }, + Spec: FeatureFlagSpec{ + FlagSpec: FlagSpec{ + Flags: map[string]Flag{}, + }, + }, + } + + require.Equal(t, v1.OwnerReference{ + APIVersion: ff.APIVersion, + Kind: ff.Kind, + Name: ff.Name, + UID: ff.UID, + Controller: utils.TrueVal(), + }, ff.GetReference()) + + name := "cmname" + namespace := "cmnamespace" + references := []v1.OwnerReference{ + { + APIVersion: "ver", + Kind: "kind", + Name: "ffconf1", + UID: types.UID("5"), + Controller: utils.TrueVal(), + }, + } + + cm, _ := ff.GenerateConfigMap(name, namespace, references) + + require.Equal(t, corev1.ConfigMap{ + ObjectMeta: v1.ObjectMeta{ + Name: name, + Namespace: namespace, + Annotations: map[string]string{ + "openfeature.dev/featureflag": name, + }, + OwnerReferences: references, + }, + Data: map[string]string{ + "cmnamespace_cmname.flagd.json": "{\"flags\":{}}", + }, + }, *cm) +} diff --git a/apis/core/v1beta1/featureflagsource_types_test.go b/apis/core/v1beta1/featureflagsource_types_test.go index a719871d4..dfb2decef 100644 --- a/apis/core/v1beta1/featureflagsource_types_test.go +++ b/apis/core/v1beta1/featureflagsource_types_test.go @@ -3,7 +3,9 @@ package v1beta1 import ( "testing" + "github.com/open-feature/open-feature-operator/common/utils" "github.com/stretchr/testify/require" + v1 "k8s.io/api/core/v1" ) func Test_FeatureFlagSource_SyncProvider(t *testing.T) { @@ -22,3 +24,280 @@ func Test_FeatureFlagSource_SyncProvider(t *testing.T) { require.False(t, k.IsGrpc()) require.False(t, g.IsHttp()) } + +func Test_FLagSourceConfiguration_envVarKey(t *testing.T) { + require.Equal(t, "pre_suf", envVarKey("pre", "suf")) +} + +func Test_FLagSourceConfiguration_ToEnvVars(t *testing.T) { + ff := FeatureFlagSource{ + Spec: FeatureFlagSourceSpec{ + EnvVars: []v1.EnvVar{ + { + Name: "env1", + Value: "val1", + }, + { + Name: "env2", + Value: "val2", + }, + }, + EnvVarPrefix: "PRE", + MetricsPort: 22, + Port: 33, + Evaluator: "evaluator", + SocketPath: "socket-path", + LogFormat: "log", + }, + } + expected := []v1.EnvVar{ + { + Name: "PRE_env1", + Value: "val1", + }, + { + Name: "PRE_env2", + Value: "val2", + }, + { + Name: "PRE_METRICS_PORT", + Value: "22", + }, + { + Name: "PRE_PORT", + Value: "33", + }, + { + Name: "PRE_EVALUATOR", + Value: "evaluator", + }, + { + Name: "PRE_SOCKET_PATH", + Value: "socket-path", + }, + { + Name: "PRE_LOG_FORMAT", + Value: "log", + }, + } + require.Equal(t, expected, ff.Spec.ToEnvVars()) +} + +func Test_FLagSourceConfiguration_Merge(t *testing.T) { + ff_old := &FeatureFlagSource{ + Spec: FeatureFlagSourceSpec{ + EnvVars: []v1.EnvVar{ + { + Name: "env1", + Value: "val1", + }, + { + Name: "env2", + Value: "val2", + }, + }, + EnvVarPrefix: "PRE", + MetricsPort: 22, + Port: 33, + Evaluator: "evaluator", + SocketPath: "socket-path", + LogFormat: "log", + Image: "img", + Tag: "tag", + Sources: []Source{ + { + Source: "src1", + Provider: SyncProviderGrpc, + TLS: true, + CertPath: "etc/cert.ca", + ProviderID: "app", + Selector: "source=database", + }, + }, + SyncProviderArgs: []string{"arg1", "arg2"}, + DefaultSyncProvider: SyncProviderKubernetes, + RolloutOnChange: utils.TrueVal(), + ProbesEnabled: utils.TrueVal(), + DebugLogging: utils.TrueVal(), + OtelCollectorUri: "", + }, + } + + ff_old.Spec.Merge(nil) + + require.Equal(t, &FeatureFlagSource{ + Spec: FeatureFlagSourceSpec{ + EnvVars: []v1.EnvVar{ + { + Name: "env1", + Value: "val1", + }, + { + Name: "env2", + Value: "val2", + }, + }, + EnvVarPrefix: "PRE", + MetricsPort: 22, + Port: 33, + Evaluator: "evaluator", + SocketPath: "socket-path", + LogFormat: "log", + Image: "img", + Tag: "tag", + Sources: []Source{ + { + Source: "src1", + Provider: SyncProviderGrpc, + TLS: true, + CertPath: "etc/cert.ca", + ProviderID: "app", + Selector: "source=database", + }, + }, + SyncProviderArgs: []string{"arg1", "arg2"}, + DefaultSyncProvider: SyncProviderKubernetes, + RolloutOnChange: utils.TrueVal(), + ProbesEnabled: utils.TrueVal(), + DebugLogging: utils.TrueVal(), + OtelCollectorUri: "", + }, + }, ff_old) + + ff_new := &FeatureFlagSource{ + Spec: FeatureFlagSourceSpec{ + EnvVars: []v1.EnvVar{ + { + Name: "env3", + Value: "val3", + }, + { + Name: "env4", + Value: "val4", + }, + }, + EnvVarPrefix: "PREFIX", + MetricsPort: 221, + Port: 331, + Evaluator: "evaluator1", + SocketPath: "socket-path1", + LogFormat: "log1", + Image: "img1", + Tag: "tag1", + Sources: []Source{ + { + Source: "src2", + Provider: SyncProviderFilepath, + }, + }, + SyncProviderArgs: []string{"arg3", "arg4"}, + DefaultSyncProvider: SyncProviderFilepath, + RolloutOnChange: utils.FalseVal(), + ProbesEnabled: utils.FalseVal(), + DebugLogging: utils.FalseVal(), + OtelCollectorUri: "", + }, + } + + ff_old.Spec.Merge(&ff_new.Spec) + + require.Equal(t, &FeatureFlagSource{ + Spec: FeatureFlagSourceSpec{ + EnvVars: []v1.EnvVar{ + { + Name: "env1", + Value: "val1", + }, + { + Name: "env2", + Value: "val2", + }, + { + Name: "env3", + Value: "val3", + }, + { + Name: "env4", + Value: "val4", + }, + }, + EnvVarPrefix: "PREFIX", + MetricsPort: 221, + Port: 331, + Evaluator: "evaluator1", + SocketPath: "socket-path1", + LogFormat: "log1", + Image: "img1", + Tag: "tag1", + Sources: []Source{ + { + Source: "src1", + Provider: SyncProviderGrpc, + TLS: true, + CertPath: "etc/cert.ca", + ProviderID: "app", + Selector: "source=database", + }, + { + Source: "src2", + Provider: SyncProviderFilepath, + }, + }, + SyncProviderArgs: []string{"arg1", "arg2", "arg3", "arg4"}, + DefaultSyncProvider: SyncProviderFilepath, + RolloutOnChange: utils.FalseVal(), + ProbesEnabled: utils.FalseVal(), + DebugLogging: utils.FalseVal(), + OtelCollectorUri: "", + }, + }, ff_old) +} + +func Test_FLagSourceConfiguration_NewFeatureFlagSourceSpec(t *testing.T) { + //happy path + t.Setenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarMetricPortEnvVar), "22") + t.Setenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarPortEnvVar), "33") + t.Setenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarSocketPathEnvVar), "val1") + t.Setenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarEvaluatorEnvVar), "val2") + t.Setenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarImageEnvVar), "val3") + t.Setenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarVersionEnvVar), "val4") + t.Setenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarProviderArgsEnvVar), "val11,val22") + t.Setenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarDefaultSyncProviderEnvVar), "kubernetes") + t.Setenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarLogFormatEnvVar), "val5") + t.Setenv(SidecarEnvVarPrefix, "val6") + t.Setenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarProbesEnabledVar), "true") + + fs, err := NewFeatureFlagSourceSpec() + + require.Nil(t, err) + require.Equal(t, &FeatureFlagSourceSpec{ + MetricsPort: 22, + Port: 33, + SocketPath: "val1", + Evaluator: "val2", + Image: "val3", + Tag: "val4", + Sources: []Source{}, + EnvVars: []v1.EnvVar{}, + SyncProviderArgs: []string{"val11", "val22"}, + DefaultSyncProvider: SyncProviderKubernetes, + EnvVarPrefix: "val6", + LogFormat: "val5", + ProbesEnabled: utils.TrueVal(), + DebugLogging: utils.FalseVal(), + OtelCollectorUri: "", + }, fs) + + //error paths + t.Setenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarProbesEnabledVar), "blah") + _, err = NewFeatureFlagSourceSpec() + require.NotNil(t, err) + + t.Setenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarPortEnvVar), "blah") + _, err = NewFeatureFlagSourceSpec() + require.NotNil(t, err) + + t.Setenv(envVarKey(InputConfigurationEnvVarPrefix, SidecarMetricPortEnvVar), "blah") + _, err = NewFeatureFlagSourceSpec() + require.NotNil(t, err) +} diff --git a/common/common_test.go b/common/common_test.go index a094edfdd..155955fbb 100644 --- a/common/common_test.go +++ b/common/common_test.go @@ -1,14 +1,18 @@ package common import ( + "context" "fmt" "testing" + api "github.com/open-feature/open-feature-operator/apis/core/v1beta1" "github.com/stretchr/testify/require" appsV1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/client-go/kubernetes/scheme" "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/client/fake" ) func TestFeatureFlagSourceIndex(t *testing.T) { @@ -102,8 +106,60 @@ func TestSharedOwnership(t *testing.T) { for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { if got := SharedOwnership(tt.owner1, tt.owner2); got != tt.want { - t.Errorf("podOwnerIsOwner() = %v, want %v", got, tt.want) + t.Errorf("SharedOwnership() = %v, want %v", got, tt.want) } }) } } + +func TestFindFlagConfig(t *testing.T) { + ff := &api.FeatureFlag{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test", + Namespace: "default", + }, + } + + tests := []struct { + name string + ns string + obj *api.FeatureFlag + want *api.FeatureFlag + wantErr bool + }{ + { + name: "test", + ns: "default", + obj: ff, + want: ff, + wantErr: false, + }, + { + name: "non-existing", + ns: "default", + obj: ff, + want: nil, + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + err := api.AddToScheme(scheme.Scheme) + require.Nil(t, err) + fakeClient := fake.NewClientBuilder().WithScheme(scheme.Scheme).WithObjects(tt.obj).Build() + + got, err := FindFlagConfig(context.TODO(), fakeClient, tt.ns, tt.name) + + if (err != nil) != tt.wantErr { + t.Errorf("FindFlagConfig() = expected error %t, got %v", tt.wantErr, err) + } + + if !tt.wantErr { + require.Equal(t, tt.want.Name, got.Name) + require.Equal(t, tt.want.Namespace, got.Namespace) + } + + }) + } +} diff --git a/common/constant/configuration.go b/common/constant/configuration.go index 3201eeb83..b3115d4ea 100644 --- a/common/constant/configuration.go +++ b/common/constant/configuration.go @@ -7,8 +7,11 @@ const ( ClusterRoleBindingName string = "open-feature-operator-flagd-kubernetes-sync" AllowKubernetesSyncAnnotation = "allowkubernetessync" OpenFeatureAnnotationPrefix = "openfeature.dev" + OpenFeatureAnnotationPath = "metadata.annotations.openfeature.dev" SourceConfigParam = "--sources" ProbeReadiness = "/readyz" ProbeLiveness = "/healthz" ProbeInitialDelay = 5 + FeatureFlagSourceAnnotation = "featureflagsource" + EnabledAnnotation = "enabled" ) diff --git a/main.go b/main.go index 8195bb938..bddfc025a 100644 --- a/main.go +++ b/main.go @@ -24,6 +24,7 @@ import ( corev1beta1 "github.com/open-feature/open-feature-operator/apis/core/v1beta1" "github.com/open-feature/open-feature-operator/common" + "github.com/open-feature/open-feature-operator/common/constant" "github.com/open-feature/open-feature-operator/common/flagdinjector" "github.com/open-feature/open-feature-operator/common/flagdproxy" "github.com/open-feature/open-feature-operator/controllers/core/featureflagsource" @@ -153,14 +154,14 @@ func main() { if err := mgr.GetFieldIndexer().IndexField( context.Background(), &corev1.Pod{}, - fmt.Sprintf("%s/%s", webhooks.OpenFeatureAnnotationPath, webhooks.AllowKubernetesSyncAnnotation), + fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPath, constant.AllowKubernetesSyncAnnotation), webhooks.OpenFeatureEnabledAnnotationIndex, ); err != nil { setupLog.Error( err, "unable to create indexer", "webhook", - fmt.Sprintf("%s/%s", webhooks.OpenFeatureAnnotationPath, webhooks.AllowKubernetesSyncAnnotation), + fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPath, constant.AllowKubernetesSyncAnnotation), ) os.Exit(1) } @@ -175,7 +176,7 @@ func main() { err, "unable to create indexer", "webhook", - fmt.Sprintf("%s/%s", webhooks.OpenFeatureAnnotationPath, common.FeatureFlagSourceAnnotation), + fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPath, common.FeatureFlagSourceAnnotation), ) os.Exit(1) } diff --git a/webhooks/common.go b/webhooks/common.go index b7e059ea3..1423fb991 100644 --- a/webhooks/common.go +++ b/webhooks/common.go @@ -5,24 +5,11 @@ import ( "strings" api "github.com/open-feature/open-feature-operator/apis/core/v1beta1" + "github.com/open-feature/open-feature-operator/common/constant" corev1 "k8s.io/api/core/v1" "sigs.k8s.io/controller-runtime/pkg/client" ) -// we likely want these to be configurable, eventually -const ( - FlagDImagePullPolicy corev1.PullPolicy = "Always" - clusterRoleBindingName string = "open-feature-operator-flagd-kubernetes-sync" - OpenFeatureAnnotationPath = "metadata.annotations.openfeature.dev" - OpenFeatureAnnotationPrefix = "openfeature.dev" - AllowKubernetesSyncAnnotation = "allowkubernetessync" - FeatureFlagSourceAnnotation = "featureflagsource" - EnabledAnnotation = "enabled" - ProbeReadiness = "/readyz" - ProbeLiveness = "/healthz" - SourceConfigParam = "--sources" -) - func OpenFeatureEnabledAnnotationIndex(o client.Object) []string { pod := o.(*corev1.Pod) if pod.ObjectMeta.Annotations == nil { @@ -30,7 +17,7 @@ func OpenFeatureEnabledAnnotationIndex(o client.Object) []string { "false", } } - val, ok := pod.ObjectMeta.Annotations[fmt.Sprintf("openfeature.dev/%s", AllowKubernetesSyncAnnotation)] + val, ok := pod.ObjectMeta.Annotations[fmt.Sprintf("openfeature.dev/%s", constant.AllowKubernetesSyncAnnotation)] if ok && val == "true" { return []string{ "true", @@ -63,6 +50,6 @@ func containsK8sProvider(sources []api.Source) bool { } func checkOFEnabled(annotations map[string]string) bool { - val, ok := annotations[fmt.Sprintf("%s/%s", OpenFeatureAnnotationPrefix, EnabledAnnotation)] + val, ok := annotations[fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPrefix, constant.EnabledAnnotation)] return ok && val == "true" } diff --git a/webhooks/common_test.go b/webhooks/common_test.go index 725d7d811..efb17e172 100644 --- a/webhooks/common_test.go +++ b/webhooks/common_test.go @@ -6,6 +6,7 @@ import ( "testing" api "github.com/open-feature/open-feature-operator/apis/core/v1beta1" + "github.com/open-feature/open-feature-operator/common/constant" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/client" @@ -50,11 +51,11 @@ func TestPodMutator_checkOFEnabled(t *testing.T) { }{ { name: "enabled", - annotations: map[string]string{fmt.Sprintf("%s/%s", OpenFeatureAnnotationPrefix, EnabledAnnotation): "true"}, + annotations: map[string]string{fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPrefix, constant.EnabledAnnotation): "true"}, want: true, }, { name: "disabled", - annotations: map[string]string{fmt.Sprintf("%s/%s", OpenFeatureAnnotationPrefix, EnabledAnnotation): "false"}, + annotations: map[string]string{fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPrefix, constant.EnabledAnnotation): "false"}, want: false, }, } diff --git a/webhooks/pod_webhook.go b/webhooks/pod_webhook.go index 0a88c4361..630972ec2 100644 --- a/webhooks/pod_webhook.go +++ b/webhooks/pod_webhook.go @@ -87,6 +87,7 @@ func (m *PodMutator) Handle(ctx context.Context, req admission.Request) admissio if errors.Is(err, constant.ErrFlagdProxyNotReady) { return admission.Denied(err.Error()) } + //test m.Log.Error(err, "unable to inject flagd sidecar") return admission.Errored(http.StatusInternalServerError, err) } @@ -102,23 +103,20 @@ func (m *PodMutator) Handle(ctx context.Context, req admission.Request) admissio func (m *PodMutator) createFSConfigSpec(ctx context.Context, req admission.Request, annotations map[string]string, pod *corev1.Pod) (*api.FeatureFlagSourceSpec, int32, error) { // Check configuration fscNames := []string{} - val, ok := annotations[fmt.Sprintf("%s/%s", OpenFeatureAnnotationPrefix, FeatureFlagSourceAnnotation)] + val, ok := annotations[fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPrefix, constant.FeatureFlagSourceAnnotation)] if ok { fscNames = parseList(val) } featureFlagSourceSpec, err := api.NewFeatureFlagSourceSpec() if err != nil { - m.Log.V(1).Error(err, "unable to parse env var configuration", "webhook", "handle") + m.Log.V(1).Error(err, "unable to create new FeatureFlagSourceSpec", "webhook", "handle") return nil, http.StatusBadRequest, err } for _, fscName := range fscNames { ns, name := utils.ParseAnnotation(fscName, req.Namespace) - if err != nil { - m.Log.V(1).Info(fmt.Sprintf("failed to parse annotation %s error: %s", fscName, err.Error())) - return nil, http.StatusBadRequest, err - } + fc, err := m.getFeatureFlagSource(ctx, ns, name) if err != nil { m.Log.V(1).Info(fmt.Sprintf("FeatureFlagSource could not be found for %s", fscName)) @@ -136,10 +134,10 @@ func (m *PodMutator) BackfillPermissions(ctx context.Context) error { m.ready = true }() for i := 0; i < 5; i++ { - // fetch all pods with the fmt.Sprintf("%s/%s", OpenFeatureAnnotationPrefix, EnabledAnnotation) annotation set to "true" + // fetch all pods with the fmt.Sprintf("%s/%s", OpenFeatureAnnotationPath, EnabledAnnotation) annotation set to "true" podList := &corev1.PodList{} err := m.Client.List(ctx, podList, client.MatchingFields{ - fmt.Sprintf("%s/%s", OpenFeatureAnnotationPath, AllowKubernetesSyncAnnotation): "true", + fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPath, constant.AllowKubernetesSyncAnnotation): "true", }) if err != nil { if !errors.Is(err, &cache.ErrCacheNotStarted{}) { @@ -157,7 +155,7 @@ func (m *PodMutator) BackfillPermissions(ctx context.Context) error { err, fmt.Sprintf("unable backfill permissions for pod %s/%s", pod.Namespace, pod.Name), "webhook", - fmt.Sprintf("%s/%s", OpenFeatureAnnotationPath, AllowKubernetesSyncAnnotation), + fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPath, constant.AllowKubernetesSyncAnnotation), ) } } diff --git a/webhooks/pod_webhook_test.go b/webhooks/pod_webhook_test.go index b2f3825a1..547652aa0 100644 --- a/webhooks/pod_webhook_test.go +++ b/webhooks/pod_webhook_test.go @@ -67,9 +67,9 @@ func TestPodMutator_BackfillPermissions(t *testing.T) { Name: pod, Namespace: ns, Annotations: map[string]string{ - fmt.Sprintf("%s/%s", OpenFeatureAnnotationPrefix, EnabledAnnotation): "true", - fmt.Sprintf("%s/%s", OpenFeatureAnnotationPrefix, FeatureFlagSourceAnnotation): fmt.Sprintf("%s/%s", mutatePodNamespace, featureFlagSourceName), - fmt.Sprintf("%s/%s", OpenFeatureAnnotationPrefix, AllowKubernetesSyncAnnotation): "true", + fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPrefix, constant.EnabledAnnotation): "true", + fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPrefix, constant.FeatureFlagSourceAnnotation): fmt.Sprintf("%s/%s", mutatePodNamespace, featureFlagSourceName), + fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPrefix, constant.AllowKubernetesSyncAnnotation): "true", }}, }, ), @@ -93,9 +93,9 @@ func TestPodMutator_BackfillPermissions(t *testing.T) { Name: pod + "-1", Namespace: ns, Annotations: map[string]string{ - fmt.Sprintf("%s/%s", OpenFeatureAnnotationPrefix, EnabledAnnotation): "true", - fmt.Sprintf("%s/%s", OpenFeatureAnnotationPrefix, FeatureFlagSourceAnnotation): fmt.Sprintf("%s/%s", mutatePodNamespace, featureFlagSourceName), - fmt.Sprintf("%s/%s", OpenFeatureAnnotationPrefix, AllowKubernetesSyncAnnotation): "true", + fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPrefix, constant.EnabledAnnotation): "true", + fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPrefix, constant.FeatureFlagSourceAnnotation): fmt.Sprintf("%s/%s", mutatePodNamespace, featureFlagSourceName), + fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPrefix, constant.AllowKubernetesSyncAnnotation): "true", }}, }, &corev1.Pod{ @@ -103,9 +103,9 @@ func TestPodMutator_BackfillPermissions(t *testing.T) { Name: pod + "-2", Namespace: ns, Annotations: map[string]string{ - fmt.Sprintf("%s/%s", OpenFeatureAnnotationPrefix, EnabledAnnotation): "true", - fmt.Sprintf("%s/%s", OpenFeatureAnnotationPrefix, FeatureFlagSourceAnnotation): fmt.Sprintf("%s/%s", mutatePodNamespace, featureFlagSourceName), - fmt.Sprintf("%s/%s", OpenFeatureAnnotationPrefix, AllowKubernetesSyncAnnotation): "true", + fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPrefix, constant.EnabledAnnotation): "true", + fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPrefix, constant.FeatureFlagSourceAnnotation): fmt.Sprintf("%s/%s", mutatePodNamespace, featureFlagSourceName), + fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPrefix, constant.AllowKubernetesSyncAnnotation): "true", }}, }, ), @@ -131,9 +131,9 @@ func TestPodMutator_BackfillPermissions(t *testing.T) { Name: pod, Namespace: ns, Annotations: map[string]string{ - fmt.Sprintf("%s/%s", OpenFeatureAnnotationPrefix, EnabledAnnotation): "true", - fmt.Sprintf("%s/%s", OpenFeatureAnnotationPrefix, FeatureFlagSourceAnnotation): fmt.Sprintf("%s/%s", mutatePodNamespace, featureFlagSourceName), - fmt.Sprintf("%s/%s", OpenFeatureAnnotationPrefix, AllowKubernetesSyncAnnotation): "true", + fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPrefix, constant.EnabledAnnotation): "true", + fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPrefix, constant.FeatureFlagSourceAnnotation): fmt.Sprintf("%s/%s", mutatePodNamespace, featureFlagSourceName), + fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPrefix, constant.AllowKubernetesSyncAnnotation): "true", }}, Spec: corev1.PodSpec{ServiceAccountName: "my-service-account"}, }, @@ -142,9 +142,9 @@ func TestPodMutator_BackfillPermissions(t *testing.T) { Name: name, Namespace: ns, Annotations: map[string]string{ - fmt.Sprintf("%s/%s", OpenFeatureAnnotationPrefix, EnabledAnnotation): "true", - fmt.Sprintf("%s/%s", OpenFeatureAnnotationPrefix, FeatureFlagSourceAnnotation): fmt.Sprintf("%s/%s", mutatePodNamespace, featureFlagSourceName), - fmt.Sprintf("%s/%s", OpenFeatureAnnotationPrefix, AllowKubernetesSyncAnnotation): "true", + fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPrefix, constant.EnabledAnnotation): "true", + fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPrefix, constant.FeatureFlagSourceAnnotation): fmt.Sprintf("%s/%s", mutatePodNamespace, featureFlagSourceName), + fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPrefix, constant.AllowKubernetesSyncAnnotation): "true", }}, }, &rbac.ClusterRoleBinding{ @@ -169,9 +169,9 @@ func TestPodMutator_BackfillPermissions(t *testing.T) { Name: pod, Namespace: ns, Annotations: map[string]string{ - fmt.Sprintf("%s/%s", OpenFeatureAnnotationPrefix, EnabledAnnotation): "true", - fmt.Sprintf("%s/%s", OpenFeatureAnnotationPrefix, FeatureFlagSourceAnnotation): fmt.Sprintf("%s/%s", mutatePodNamespace, featureFlagSourceName), - fmt.Sprintf("%s/%s", OpenFeatureAnnotationPrefix, AllowKubernetesSyncAnnotation): "true", + fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPrefix, constant.EnabledAnnotation): "true", + fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPrefix, constant.FeatureFlagSourceAnnotation): fmt.Sprintf("%s/%s", mutatePodNamespace, featureFlagSourceName), + fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPrefix, constant.AllowKubernetesSyncAnnotation): "true", }}, }, &corev1.ServiceAccount{ @@ -179,9 +179,9 @@ func TestPodMutator_BackfillPermissions(t *testing.T) { Name: name, Namespace: ns, Annotations: map[string]string{ - fmt.Sprintf("%s/%s", OpenFeatureAnnotationPrefix, EnabledAnnotation): "true", - fmt.Sprintf("%s/%s", OpenFeatureAnnotationPrefix, FeatureFlagSourceAnnotation): fmt.Sprintf("%s/%s", mutatePodNamespace, featureFlagSourceName), - fmt.Sprintf("%s/%s", OpenFeatureAnnotationPrefix, AllowKubernetesSyncAnnotation): "true", + fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPrefix, constant.EnabledAnnotation): "true", + fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPrefix, constant.FeatureFlagSourceAnnotation): fmt.Sprintf("%s/%s", mutatePodNamespace, featureFlagSourceName), + fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPrefix, constant.AllowKubernetesSyncAnnotation): "true", }}, }, &rbac.ClusterRoleBinding{ @@ -236,8 +236,8 @@ func TestPodMutator_Handle(t *testing.T) { ObjectMeta: metav1.ObjectMeta{ Name: "myAnnotatedPod", Annotations: map[string]string{ - fmt.Sprintf("%s/%s", OpenFeatureAnnotationPrefix, EnabledAnnotation): "true", - fmt.Sprintf("%s/%s", OpenFeatureAnnotationPrefix, FeatureFlagSourceAnnotation): fmt.Sprintf("%s/%s", mutatePodNamespace, featureFlagSourceName), + fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPrefix, constant.EnabledAnnotation): "true", + fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPrefix, constant.FeatureFlagSourceAnnotation): fmt.Sprintf("%s/%s", mutatePodNamespace, featureFlagSourceName), }, }, }) @@ -248,8 +248,8 @@ func TestPodMutator_Handle(t *testing.T) { Name: "myAnnotatedPod", Namespace: mutatePodNamespace, Annotations: map[string]string{ - fmt.Sprintf("%s/%s", OpenFeatureAnnotationPrefix, EnabledAnnotation): "true", - fmt.Sprintf("%s/%s", OpenFeatureAnnotationPrefix, FeatureFlagSourceAnnotation): fmt.Sprintf("%s/%s", mutatePodNamespace, featureFlagSourceName), + fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPrefix, constant.EnabledAnnotation): "true", + fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPrefix, constant.FeatureFlagSourceAnnotation): fmt.Sprintf("%s/%s", mutatePodNamespace, featureFlagSourceName), }, OwnerReferences: []metav1.OwnerReference{{UID: "123"}}, }, @@ -436,7 +436,7 @@ func TestPodMutator_Handle(t *testing.T) { }, }, &rbac.ClusterRoleBinding{ - ObjectMeta: metav1.ObjectMeta{Name: clusterRoleBindingName}, + ObjectMeta: metav1.ObjectMeta{Name: constant.ClusterRoleBindingName}, Subjects: nil, RoleRef: rbac.RoleRef{}, }, @@ -527,7 +527,7 @@ func NewClient(withIndexes bool, objs ...client.Object) client.Client { utilruntime.Must(api.AddToScheme(scheme.Scheme)) annotationsSyncIndexer := func(obj client.Object) []string { - res := obj.GetAnnotations()[fmt.Sprintf("%s/%s", OpenFeatureAnnotationPrefix, AllowKubernetesSyncAnnotation)] + res := obj.GetAnnotations()[fmt.Sprintf("%s/%s", constant.OpenFeatureAnnotationPrefix, constant.AllowKubernetesSyncAnnotation)] return []string{res} } @@ -554,3 +554,16 @@ func NewClient(withIndexes bool, objs ...client.Object) client.Client { } return fakeClient.Build() } + +func TestPodMutator_IsReady(t *testing.T) { + + podMutator := PodMutator{ + ready: true, + } + + require.Nil(t, podMutator.IsReady(nil)) + + podMutator.ready = false + + require.NotNil(t, podMutator.IsReady(nil)) +}