diff --git a/.github/scripts/strip-kustomize-helm.sh b/.github/scripts/strip-kustomize-helm.sh index 7647a83f0..62e47a015 100755 --- a/.github/scripts/strip-kustomize-helm.sh +++ b/.github/scripts/strip-kustomize-helm.sh @@ -1,18 +1,26 @@ -#!/bin/bash +#!/usr/bin/env bash # This script is a hack to support helm flow control in kustomize overlays, which would otherwise break them. # It allows us to render helm template bindings and add newlines. # For instance, it transforms "___{{ .Value.myValue }}___" to {{ .Value.myValue }}. -# It also adds newlines wherever ___newline___ is found. - -CHARTS_DIR='./chart/open-feature-operator/templates'; +# It also adds newlines wherever ___newline___ is found, and other operations. See +# sed_expressions below. echo 'Running strip-kustomize-helm.sh script' -filenames=`find $CHARTS_DIR -name "*.yaml"` -for file in $filenames; do - sed -i "s/___newline___/\\n/g" $file - sed -i "s/\"___//g" $file - sed -i "s/___\"//g" $file - sed -i "s/___//g" $file +CHARTS_DIR='./chart/open-feature-operator/templates' +# Careful! Ordering of these expressions matter! +sed_expressions=( + "s/___newline___/\\n/g" + "s/___space___/ /g" + "s/\"___//g" + "s/___\"//g" + "/___delete_me___/d" + "s/___//g" +) +find $CHARTS_DIR -name "*.yaml" | while read file; do + for expr in "${sed_expressions[@]}"; do + sed -i "$expr" "$file" + done done -echo 'Done running strip-kustomize-helm.sh script' \ No newline at end of file + +echo 'Done running strip-kustomize-helm.sh script' diff --git a/Makefile b/Makefile index 01c8a213a..0d90223d1 100644 --- a/Makefile +++ b/Makefile @@ -252,7 +252,7 @@ set-helm-overlay: helm-package: set-helm-overlay generate release-manifests helm mkdir -p chart/open-feature-operator/templates/crds mv chart/open-feature-operator/templates/*customresourcedefinition* chart/open-feature-operator/templates/crds - sh .github/scripts/strip-kustomize-helm.sh + .github/scripts/strip-kustomize-helm.sh $(HELM) package --version $(CHART_VERSION) chart/open-feature-operator mkdir -p charts && mv open-feature-operator-*.tgz charts $(HELM) repo index --url https://open-feature.github.io/open-feature-operator/charts charts diff --git a/chart/open-feature-operator/README.md b/chart/open-feature-operator/README.md index 4d0a07cba..cf78aa601 100644 --- a/chart/open-feature-operator/README.md +++ b/chart/open-feature-operator/README.md @@ -97,6 +97,8 @@ The command removes all the Kubernetes components associated with the chart and | ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------ | | `defaultNamespace` | To override the namespace use the `--namespace` flag. This default is provided to ensure that the kustomize build charts in `/templates` deploy correctly when no `namespace` is provided via the `-n` flag. | `open-feature-operator-system` | | `imagePullSecrets` | Array of ImagePullSecret objects containing credentials for images pulled by the operator (flagdProxyConfiguration.image, flagdConfiguration.image, controllerManager.manager.image, controllerManager.kubeRbacProxy.image). Example: imagePullSecrets: [{"name": "my-secret"}] | `[]` | +| `labels` | Labels to apply to all of the pods in the operator. | `{}` | +| `annotations` | Annotations to apply to all of the pods in the operator. | `{}` | ### Sidecar configuration @@ -167,7 +169,7 @@ The command removes all the Kubernetes components associated with the chart and | `controllerManager.kubeRbacProxy.resources.requests.cpu` | Sets cpu resource requests for kube-rbac-proxy. | `5m` | | `controllerManager.kubeRbacProxy.resources.requests.memory` | Sets memory resource requests for kube-rbac-proxy. | `64Mi` | | `controllerManager.manager.image.repository` | Sets the image for the operator. | `ghcr.io/open-feature/open-feature-operator` | -| `controllerManager.manager.image.tag` | Sets the version tag for the operator. | `v0.6.1` | +| `controllerManager.manager.image.tag` | Sets the version tag for the operator. | `v0.7.0` | | `controllerManager.manager.resources.limits.cpu` | Sets cpu resource limits for operator. | `500m` | | `controllerManager.manager.resources.limits.memory` | Sets memory resource limits for operator. | `128Mi` | | `controllerManager.manager.resources.requests.cpu` | Sets cpu resource requests for operator. | `10m` | @@ -180,3 +182,4 @@ The command removes all the Kubernetes components associated with the chart and | `managerConfig.controllerManagerConfigYaml.metrics.bindAddress` | Sets the bind address for metrics (combined with bindPort). | `127.0.0.1` | | `managerConfig.controllerManagerConfigYaml.metrics.bindPort` | Sets the bind port for metrics. | `8080` | | `managerConfig.controllerManagerConfigYaml.webhook.port` | Sets the bind address for webhook. | `9443` | + diff --git a/chart/open-feature-operator/values.yaml b/chart/open-feature-operator/values.yaml index 42bec3d8d..8a6ef4002 100644 --- a/chart/open-feature-operator/values.yaml +++ b/chart/open-feature-operator/values.yaml @@ -4,6 +4,10 @@ defaultNamespace: open-feature-operator-system ## @param imagePullSecrets Array of ImagePullSecret objects containing credentials for images pulled by the operator (flagdProxyConfiguration.image, flagdConfiguration.image, controllerManager.manager.image, controllerManager.kubeRbacProxy.image). Example: imagePullSecrets: [{"name": "my-secret"}] imagePullSecrets: [] +## @param labels Labels to apply to all of the pods in the operator. +labels: {} +## @param annotations Annotations to apply to all of the pods in the operator. +annotations: {} ## @section Sidecar configuration sidecarConfiguration: diff --git a/common/flagdproxy/flagdproxy.go b/common/flagdproxy/flagdproxy.go index eefdb8abc..28131dd45 100644 --- a/common/flagdproxy/flagdproxy.go +++ b/common/flagdproxy/flagdproxy.go @@ -8,6 +8,7 @@ import ( "github.com/go-logr/logr" "github.com/open-feature/open-feature-operator/common" "github.com/open-feature/open-feature-operator/common/types" + "golang.org/x/exp/maps" appsV1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/api/errors" @@ -39,9 +40,11 @@ type FlagdProxyConfiguration struct { Namespace string OperatorDeploymentName string ImagePullSecrets []string + Labels map[string]string + Annotations map[string]string } -func NewFlagdProxyConfiguration(env types.EnvConfig, imagePullSecrets []string) *FlagdProxyConfiguration { +func NewFlagdProxyConfiguration(env types.EnvConfig, imagePullSecrets []string, labels map[string]string, annotations map[string]string) *FlagdProxyConfiguration { return &FlagdProxyConfiguration{ Image: env.FlagdProxyImage, Tag: env.FlagdProxyTag, @@ -51,6 +54,8 @@ func NewFlagdProxyConfiguration(env types.EnvConfig, imagePullSecrets []string) ManagementPort: env.FlagdProxyManagementPort, DebugLogging: env.FlagdProxyDebugLogging, ImagePullSecrets: imagePullSecrets, + Labels: labels, + Annotations: annotations, } } @@ -151,6 +156,21 @@ func (f *FlagdProxyHandler) newFlagdProxyManifest(ownerReference *metav1.OwnerRe Name: secret, }) } + flagdLabels := map[string]string{ + "app": FlagdProxyDeploymentName, + "app.kubernetes.io/name": FlagdProxyDeploymentName, + "app.kubernetes.io/managed-by": common.ManagedByAnnotationValue, + "app.kubernetes.io/version": f.config.Tag, + } + if len(f.config.Labels) > 0 { + maps.Copy(flagdLabels, f.config.Labels) + } + + // No "built-in" annotations to merge at this time. If adding them follow the same pattern as labels. + flagdAnnotations := map[string]string{} + if len(f.config.Annotations) > 0 { + maps.Copy(flagdAnnotations, f.config.Annotations) + } return &appsV1.Deployment{ ObjectMeta: metav1.ObjectMeta{ @@ -172,12 +192,8 @@ func (f *FlagdProxyHandler) newFlagdProxyManifest(ownerReference *metav1.OwnerRe }, Template: corev1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ - Labels: map[string]string{ - "app": FlagdProxyDeploymentName, - "app.kubernetes.io/name": FlagdProxyDeploymentName, - "app.kubernetes.io/managed-by": common.ManagedByAnnotationValue, - "app.kubernetes.io/version": f.config.Tag, - }, + Labels: flagdLabels, + Annotations: flagdAnnotations, }, Spec: corev1.PodSpec{ ServiceAccountName: FlagdProxyServiceAccountName, diff --git a/common/flagdproxy/flagdproxy_test.go b/common/flagdproxy/flagdproxy_test.go index ce324b2ed..8ab7d223c 100644 --- a/common/flagdproxy/flagdproxy_test.go +++ b/common/flagdproxy/flagdproxy_test.go @@ -21,12 +21,22 @@ import ( var pullSecrets = []string{"test-pullSecret"} +var labels = map[string]string{ + "label1": "labelValue1", + "label2": "labelValue2", +} + +var annotations = map[string]string{ + "annotation1": "annotationValue1", + "annotation2": "annotationValue2", +} + func TestNewFlagdProxyConfiguration(t *testing.T) { kpConfig := NewFlagdProxyConfiguration(types.EnvConfig{ FlagdProxyPort: 8015, FlagdProxyManagementPort: 8016, - }, pullSecrets) + }, pullSecrets, labels, annotations) require.NotNil(t, kpConfig) require.Equal(t, &FlagdProxyConfiguration{ @@ -35,6 +45,8 @@ func TestNewFlagdProxyConfiguration(t *testing.T) { DebugLogging: false, OperatorDeploymentName: common.OperatorDeploymentName, ImagePullSecrets: pullSecrets, + Labels: labels, + Annotations: annotations, }, kpConfig) } @@ -48,7 +60,7 @@ func TestNewFlagdProxyConfiguration_OverrideEnvVars(t *testing.T) { FlagdProxyDebugLogging: true, } - kpConfig := NewFlagdProxyConfiguration(env, pullSecrets) + kpConfig := NewFlagdProxyConfiguration(env, pullSecrets, labels, annotations) require.NotNil(t, kpConfig) require.Equal(t, &FlagdProxyConfiguration{ @@ -60,11 +72,13 @@ func TestNewFlagdProxyConfiguration_OverrideEnvVars(t *testing.T) { Namespace: "my-namespace", OperatorDeploymentName: common.OperatorDeploymentName, ImagePullSecrets: pullSecrets, + Labels: labels, + Annotations: annotations, }, kpConfig) } func TestNewFlagdProxyHandler(t *testing.T) { - kpConfig := NewFlagdProxyConfiguration(types.EnvConfig{}, pullSecrets) + kpConfig := NewFlagdProxyConfiguration(types.EnvConfig{}, pullSecrets, labels, annotations) require.NotNil(t, kpConfig) @@ -100,7 +114,7 @@ func TestDoesFlagdProxyExist(t *testing.T) { }, } - kpConfig := NewFlagdProxyConfiguration(env, pullSecrets) + kpConfig := NewFlagdProxyConfiguration(env, pullSecrets, labels, annotations) require.NotNil(t, kpConfig) @@ -128,7 +142,7 @@ func TestFlagdProxyHandler_HandleFlagdProxy_ProxyExistsWithBadVersion(t *testing env := types.EnvConfig{ PodNamespace: "ns", } - kpConfig := NewFlagdProxyConfiguration(env, pullSecrets) + kpConfig := NewFlagdProxyConfiguration(env, pullSecrets, labels, annotations) require.NotNil(t, kpConfig) @@ -187,7 +201,7 @@ func TestFlagdProxyHandler_HandleFlagdProxy_ProxyExistsWithoutLabel(t *testing.T env := types.EnvConfig{ PodNamespace: "ns", } - kpConfig := NewFlagdProxyConfiguration(env, pullSecrets) + kpConfig := NewFlagdProxyConfiguration(env, pullSecrets, labels, annotations) require.NotNil(t, kpConfig) @@ -236,7 +250,7 @@ func TestFlagdProxyHandler_HandleFlagdProxy_ProxyExistsWithNewestVersion(t *test env := types.EnvConfig{ PodNamespace: "ns", } - kpConfig := NewFlagdProxyConfiguration(env, pullSecrets) + kpConfig := NewFlagdProxyConfiguration(env, pullSecrets, labels, annotations) require.NotNil(t, kpConfig) @@ -280,7 +294,7 @@ func TestFlagdProxyHandler_HandleFlagdProxy_CreateProxy(t *testing.T) { FlagdProxyManagementPort: 90, FlagdProxyDebugLogging: true, } - kpConfig := NewFlagdProxyConfiguration(env, pullSecrets) + kpConfig := NewFlagdProxyConfiguration(env, pullSecrets, labels, annotations) require.NotNil(t, kpConfig) @@ -357,7 +371,10 @@ func TestFlagdProxyHandler_HandleFlagdProxy_CreateProxy(t *testing.T) { "app.kubernetes.io/name": FlagdProxyDeploymentName, "app.kubernetes.io/managed-by": common.ManagedByAnnotationValue, "app.kubernetes.io/version": "tag", + "label1": "labelValue1", + "label2": "labelValue2", }, + Annotations: annotations, }, Spec: corev1.PodSpec{ ServiceAccountName: FlagdProxyServiceAccountName, diff --git a/config/overlays/helm/manager.yaml b/config/overlays/helm/manager.yaml index e35ac993e..8f90f1fe2 100644 --- a/config/overlays/helm/manager.yaml +++ b/config/overlays/helm/manager.yaml @@ -6,12 +6,19 @@ metadata: spec: replicas: 0{{ .Values.controllerManager.replicas }} template: + metadata: + # this is transformed by .github/scripts/strip-kustomize-helm.sh + annotations: + ___delete_me___: "___ ___newline___{{ if .Values.annotations }}{{___space___toYaml___space___.Values.annotations___space___|___space___indent___space___8___space___}}{{ end }}___" + # this is transformed by .github/scripts/strip-kustomize-helm.sh + labels: + ___delete_me___: "___ ___newline___{{ if .Values.labels }}___newline___{{___space___toYaml___space___.Values.labels___space___|___space___indent___space___8___space___}}{{ end }}___" spec: # this is transformed by .github/scripts/strip-kustomize-helm.sh - ___imagePullSecrets___: "___ ___newline___{{ toYaml .Values.imagePullSecrets | indent 8 }}___" - dnsPolicy: "{{ .Values.controllerManager.manager.dnsPolicy }}" + ___imagePullSecrets___: "___ ___newline___ {{ toYaml .Values.imagePullSecrets___space___|___space___indent___space___8___space___}}___" # this is transformed by .github/scripts/strip-kustomize-helm.sh hostNetwork: "___{{ .Values.controllerManager.manager.hostNetwork }}___" + dnsPolicy: "{{ .Values.controllerManager.manager.dnsPolicy }}" containers: - name: manager image: "{{ .Values.controllerManager.manager.image.repository }}:{{ .Values.controllerManager.manager.image.tag }}" @@ -104,6 +111,8 @@ spec: - --sidecar-ram-request={{ .Values.sidecarConfiguration.resources.requests.memory }} - --image-pull-secrets={{ range .Values.imagePullSecrets }}{{ .name }},{{- end }} - --metrics-bind-address=:{{ .Values.managerConfig.controllerManagerConfigYaml.metrics.bindPort }} + - --labels={{ $labelKeys := keys .Values.labels -}}{{- $labelPairs := list -}}{{- range $key := $labelKeys -}}{{- $labelPairs = append $labelPairs (printf "%s:%s" $key (index $.Values.labels $key)) -}}{{- end -}}{{- join "," $labelPairs }} + - --annotations={{ $annotationKeys := keys .Values.annotations -}}{{- $annotationPairs := list -}}{{- range $key := $annotationKeys -}}{{- $annotationPairs = append $annotationPairs (printf "%s:%s" $key (index $.Values.annotations $key)) -}}{{- end -}}{{- join "," $annotationPairs }} - name: kube-rbac-proxy image: "{{ .Values.controllerManager.kubeRbacProxy.image.repository }}:{{ .Values.controllerManager.kubeRbacProxy.image.tag }}" resources: diff --git a/controllers/core/featureflagsource/controller_test.go b/controllers/core/featureflagsource/controller_test.go index e5f9b367e..6f2613b66 100644 --- a/controllers/core/featureflagsource/controller_test.go +++ b/controllers/core/featureflagsource/controller_test.go @@ -30,6 +30,16 @@ func TestFeatureFlagSourceReconciler_Reconcile(t *testing.T) { ) var pullSecrets = []string{"test-pullsecret"} + var labels = map[string]string{ + "label1": "labelValue1", + "label2": "labelValue2", + } + + var annotations = map[string]string{ + "annotation1": "annotationValue1", + "annotation2": "annotationValue2", + } + tests := []struct { name string fsConfig *api.FeatureFlagSource @@ -93,7 +103,7 @@ func TestFeatureFlagSourceReconciler_Reconcile(t *testing.T) { kpConfig := flagdproxy.NewFlagdProxyConfiguration(commontypes.EnvConfig{ FlagdProxyImage: "ghcr.io/open-feature/flagd-proxy", FlagdProxyTag: flagdProxyTag, - }, pullSecrets) + }, pullSecrets, labels, annotations) kpConfig.Namespace = testNamespace kph := flagdproxy.NewFlagdProxyHandler( @@ -169,6 +179,7 @@ func createTestDeployment(fsConfigName string, testNamespace string, deploymentN }, }, Spec: corev1.PodSpec{ + ImagePullSecrets: []corev1.LocalObjectReference{{Name: "test-pullSecret"}}, Containers: []corev1.Container{ { Name: "test", diff --git a/controllers/core/flagd/common/common.go b/controllers/core/flagd/common/common.go index fcdd61b74..fa88c55a9 100644 --- a/controllers/core/flagd/common/common.go +++ b/controllers/core/flagd/common/common.go @@ -9,6 +9,8 @@ type FlagdConfiguration struct { Image string Tag string ImagePullSecrets []string + Labels map[string]string + Annotations map[string]string OperatorNamespace string OperatorDeploymentName string diff --git a/controllers/core/flagd/config.go b/controllers/core/flagd/config.go index e4ce776b7..33a1c3434 100644 --- a/controllers/core/flagd/config.go +++ b/controllers/core/flagd/config.go @@ -6,7 +6,7 @@ import ( resources "github.com/open-feature/open-feature-operator/controllers/core/flagd/common" ) -func NewFlagdConfiguration(env types.EnvConfig, imagePullSecrets []string) resources.FlagdConfiguration { +func NewFlagdConfiguration(env types.EnvConfig, imagePullSecrets []string, labels map[string]string, annotations map[string]string) resources.FlagdConfiguration { return resources.FlagdConfiguration{ Image: env.FlagdImage, Tag: env.FlagdTag, @@ -17,5 +17,7 @@ func NewFlagdConfiguration(env types.EnvConfig, imagePullSecrets []string) resou ManagementPort: env.FlagdManagementPort, DebugLogging: env.FlagdDebugLogging, ImagePullSecrets: imagePullSecrets, + Labels: labels, + Annotations: annotations, } } diff --git a/controllers/core/flagd/resources/deployment.go b/controllers/core/flagd/resources/deployment.go index faedb5226..ba15567ce 100644 --- a/controllers/core/flagd/resources/deployment.go +++ b/controllers/core/flagd/resources/deployment.go @@ -11,6 +11,7 @@ import ( "github.com/open-feature/open-feature-operator/common" "github.com/open-feature/open-feature-operator/common/flagdinjector" resources "github.com/open-feature/open-feature-operator/controllers/core/flagd/common" + "golang.org/x/exp/maps" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -46,11 +47,20 @@ func (r *FlagdDeployment) GetResource(ctx context.Context, flagd *api.Flagd) (cl "app.kubernetes.io/managed-by": common.ManagedByAnnotationValue, "app.kubernetes.io/version": r.FlagdConfig.Tag, } + if len(r.FlagdConfig.Labels) > 0 { + maps.Copy(labels, r.FlagdConfig.Labels) + } + // No "built-in" annotations to merge at this time. If adding them follow the same pattern as labels. + annotations := map[string]string{} + if len(r.FlagdConfig.Annotations) > 0 { + maps.Copy(annotations, r.FlagdConfig.Annotations) + } deployment := &appsv1.Deployment{ ObjectMeta: metav1.ObjectMeta{ - Name: flagd.Name, - Namespace: flagd.Namespace, - Labels: labels, + Name: flagd.Name, + Namespace: flagd.Namespace, + Labels: labels, + Annotations: annotations, OwnerReferences: []metav1.OwnerReference{{ APIVersion: flagd.APIVersion, Kind: flagd.Kind, @@ -77,11 +87,9 @@ func (r *FlagdDeployment) GetResource(ctx context.Context, flagd *api.Flagd) (cl } featureFlagSource := &api.FeatureFlagSource{} - imagePullSecrets := []corev1.LocalObjectReference{} - for _, secret := range r.FlagdConfig.ImagePullSecrets { - imagePullSecrets = append(imagePullSecrets, corev1.LocalObjectReference{ - Name: secret, - }) + imagePullSecrets := make([]corev1.LocalObjectReference, len(r.FlagdConfig.ImagePullSecrets)) + for i, secret := range r.FlagdConfig.ImagePullSecrets { + imagePullSecrets[i] = corev1.LocalObjectReference{Name: secret} } if err := r.Client.Get(ctx, client.ObjectKey{ @@ -100,9 +108,14 @@ func (r *FlagdDeployment) GetResource(ctx context.Context, flagd *api.Flagd) (cl return nil, errors.New("no flagd container has been injected into deployment") } - deployment.Spec.Template.Spec.ImagePullSecrets = imagePullSecrets - // override settings for the injected container for flagd standalone deployment mode + deployment.Spec.Template.Spec.ImagePullSecrets = imagePullSecrets + if len(r.FlagdConfig.Labels) > 0 { + maps.Copy(deployment.Spec.Template.ObjectMeta.Labels, r.FlagdConfig.Labels) + } + if len(r.FlagdConfig.Annotations) > 0 { + maps.Copy(deployment.Spec.Template.ObjectMeta.Annotations, r.FlagdConfig.Annotations) + } deployment.Spec.Template.Spec.Containers[0].Image = fmt.Sprintf("%s:%s", r.FlagdConfig.Image, r.FlagdConfig.Tag) deployment.Spec.Template.Spec.Containers[0].Ports = []corev1.ContainerPort{ diff --git a/go.mod b/go.mod index 83ba65500..53892ec9e 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,7 @@ require ( github.com/open-feature/open-feature-operator/apis v0.2.41-0.20240506125212-c4831a3cdc00 github.com/stretchr/testify v1.8.4 go.uber.org/zap v1.27.0 + golang.org/x/exp v0.0.0-20240707233637-46b078467d37 k8s.io/api v0.28.10 k8s.io/apimachinery v0.28.10 k8s.io/client-go v0.28.10 @@ -31,7 +32,7 @@ require ( github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.4 // indirect github.com/google/gnostic-models v0.6.8 // indirect - github.com/google/go-cmp v0.5.9 // indirect + github.com/google/go-cmp v0.6.0 // indirect github.com/google/gofuzz v1.2.0 // indirect github.com/google/uuid v1.3.0 // indirect github.com/imdario/mergo v0.3.12 // indirect @@ -54,7 +55,6 @@ require ( github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect github.com/xeipuuv/gojsonschema v1.2.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect golang.org/x/net v0.23.0 // indirect golang.org/x/oauth2 v0.8.0 // indirect golang.org/x/sys v0.19.0 // indirect diff --git a/go.sum b/go.sum index ac9f436ce..c4bfb4b8d 100644 --- a/go.sum +++ b/go.sum @@ -1,6 +1,4 @@ github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= -github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A= -github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= @@ -18,7 +16,6 @@ github.com/evanphx/json-patch/v5 v5.6.0/go.mod h1:G79N1coSVB93tBe7j6PhzjmR3/2Vvl github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= @@ -44,8 +41,8 @@ github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= -github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= -github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= +github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -130,21 +127,19 @@ github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1 github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/goleak v1.1.11/go.mod h1:cwTWslyiVhfpKIDGSZEM2HlOvcqm+tG4zioyIeLoqMQ= -go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= -go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= +go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= +go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= -go.uber.org/zap v1.25.0 h1:4Hvk6GtkucQ790dqmj7l1eEnRdKm3k3ZUrUMS2d5+5c= -go.uber.org/zap v1.25.0/go.mod h1:JIAUzQIH94IC4fOJQm7gMmBJP5k7wQfdcnYdPoEXJYk= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= -golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= +golang.org/x/exp v0.0.0-20240707233637-46b078467d37 h1:uLDX+AfeFCct3a2C7uIWBKMJIR3CJMhcgfrUAqjRK6w= +golang.org/x/exp v0.0.0-20240707233637-46b078467d37/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= @@ -190,8 +185,8 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA= -golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0= +golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= +golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= diff --git a/main.go b/main.go index 779679648..c3902e062 100644 --- a/main.go +++ b/main.go @@ -58,16 +58,27 @@ const ( metricsBindAddressFlagName = "metrics-bind-address" verboseFlagName = "verbose" leaderElectFlagName = "leader-elect" - sidecarCpuLimitFlagName = "sidecar-cpu-limit" - sidecarRamLimitFlagName = "sidecar-ram-limit" - sidecarCpuRequestFlagName = "sidecar-cpu-request" - sidecarRamRequestFlagName = "sidecar-ram-request" - sidecarCpuLimitDefault = "0.5" - sidecarRamLimitDefault = "64M" - sidecarCpuRequestDefault = "0.2" - sidecarRamRequestDefault = "32M" - imagePullSecretFlagName = "image-pull-secrets" - imagePullSecretFlagDefault = "" + + sidecarCpuLimitFlagName = "sidecar-cpu-limit" + sidecarCpuLimitDefault = "0.5" + + sidecarRamLimitFlagName = "sidecar-ram-limit" + sidecarRamLimitDefault = "64M" + + sidecarCpuRequestFlagName = "sidecar-cpu-request" + sidecarCpuRequestDefault = "0.2" + + sidecarRamRequestFlagName = "sidecar-ram-request" + sidecarRamRequestDefault = "32M" + + imagePullSecretFlagName = "image-pull-secrets" + imagePullSecretFlagDefault = "" + + labelsFlagName = "labels" + labelsFlagDefault = "" + + annotationsFlagName = "annotations" + annotationsFlagDefault = "" ) var ( @@ -79,8 +90,22 @@ var ( verbose bool sidecarCpuLimit, sidecarRamLimit, sidecarCpuRequest, sidecarRamRequest string imagePullSecrets string + labels string + annotations string ) +// StringToMap transforms a string into a map[string]string +func StringToMap(s string) map[string]string { + m := map[string]string{} + for _, pair := range strings.Split(s, ",") { + kv := strings.SplitN(pair, ":", 2) + if len(kv) == 2 { + m[kv[0]] = kv[1] + } + } + return m +} + func init() { utilruntime.Must(clientgoscheme.AddToScheme(scheme)) utilruntime.Must(corev1beta1.AddToScheme(scheme)) @@ -107,6 +132,8 @@ func main() { flag.StringVar(&sidecarCpuRequest, sidecarCpuRequestFlagName, sidecarCpuRequestDefault, "sidecar CPU minimum, in cores. (500m = .5 cores)") flag.StringVar(&sidecarRamRequest, sidecarRamRequestFlagName, sidecarRamRequestDefault, "sidecar memory minimum, in bytes. (500Gi = 500GiB = 500 * 1024 * 1024 * 1024)") flag.StringVar(&imagePullSecrets, imagePullSecretFlagName, imagePullSecretFlagDefault, "Comma-delimited list of secrets containing credentials to pull images.") + flag.StringVar(&labels, labelsFlagName, labelsFlagDefault, "Map of labels to add to the deployed pods. Formatted like key1:value1,key2:value2,key3:value3") + flag.StringVar(&annotations, annotationsFlagName, annotationsFlagDefault, "Map of annotations to add to the deployed pods. Formatted like key1:value1,key2:value2,key3:value3") flag.Parse() @@ -182,8 +209,16 @@ func main() { os.Exit(1) } + labelsMap := StringToMap(labels) + annotationsMap := StringToMap(annotations) + kph := flagdproxy.NewFlagdProxyHandler( - flagdproxy.NewFlagdProxyConfiguration(env, strings.Split(imagePullSecrets, ",")), + flagdproxy.NewFlagdProxyConfiguration( + env, + strings.Split(imagePullSecrets, ","), + labelsMap, + annotationsMap, + ), mgr.GetClient(), ctrl.Log.WithName("FeatureFlagSource FlagdProxyHandler"), ) @@ -215,7 +250,12 @@ func main() { Scheme: mgr.GetScheme(), Log: flagdControllerLogger, } - flagdConfig := flagd.NewFlagdConfiguration(env, strings.Split(imagePullSecrets, ",")) + flagdConfig := flagd.NewFlagdConfiguration( + env, + strings.Split(imagePullSecrets, ","), + labelsMap, + annotationsMap, + ) if err = (&flagd.FlagdReconciler{ Client: mgr.GetClient(),