From 5067160b32dab0e6f9133e111f2281ab50a7d240 Mon Sep 17 00:00:00 2001 From: realanna Date: Thu, 16 Feb 2023 11:42:07 +0100 Subject: [PATCH 1/9] feat: introduce topologyConstraints, node selectors and tolerations Signed-off-by: RealAnna feat: added constraints Signed-off-by: RealAnna feat: introduce topologyConstraints, node selectors and tolerations Signed-off-by: RealAnna feat: added node selector and tolerations Signed-off-by: RealAnna feat: added node selector and tolerations Signed-off-by: RealAnna feat: added topologyConstraint Signed-off-by: RealAnna feat: introduce topologyConstraints Signed-off-by: RealAnna --- examples/operator/templates/_helpers.tpl | 13 ++++ examples/operator/templates/deployment.yaml | 11 ++- examples/operator/values.yaml | 6 ++ pkg/processor/constraints/constraint.go | 46 ++++++++++++ pkg/processor/constraints/constraint_test.go | 74 ++++++++++++++++++++ pkg/processor/deployment/deployment.go | 6 +- test_data/k8s-operator-kustomize.output | 7 ++ 7 files changed, 158 insertions(+), 5 deletions(-) create mode 100644 pkg/processor/constraints/constraint.go create mode 100644 pkg/processor/constraints/constraint_test.go diff --git a/examples/operator/templates/_helpers.tpl b/examples/operator/templates/_helpers.tpl index c57b744..18be40f 100644 --- a/examples/operator/templates/_helpers.tpl +++ b/examples/operator/templates/_helpers.tpl @@ -60,3 +60,16 @@ Create the name of the service account to use {{- default "default" .Values.serviceAccount.name }} {{- end }} {{- end }} + +{{/* +Renders a value that contains template. +Usage: +{{ include "tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $) }} +*/}} +{{- define "tplvalues.render" -}} + {{- if typeIs "string" .value }} + {{- tpl .value .context }} + {{- else }} + {{- tpl (.value | toYaml) .context }} + {{- end }} +{{- end -}} diff --git a/examples/operator/templates/deployment.yaml b/examples/operator/templates/deployment.yaml index cda4bfa..283407a 100644 --- a/examples/operator/templates/deployment.yaml +++ b/examples/operator/templates/deployment.yaml @@ -110,4 +110,13 @@ spec: name: manager-config - name: secret-volume secret: - secretName: {{ include "operator.fullname" . }}-secret-ca \ No newline at end of file + secretName: {{ include "operator.fullname" . }}-secret-ca +{{- if .Values.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "tplvalues.render" (dict "value" .Values.topologySpreadConstraints "context" $) | nindent 8 }} +{{- end }} +{{- if .Values.nodeSelector }} + nodeSelector: {{- include "tplvalues.render" ( dict "value" .Values.nodeSelector "context" $) | nindent 8 }} +{{- end }} +{{- if .Values.tolerations }} + tolerations: {{- include "tplvalues.render" (dict "value" .Values.tolerations "context" .) | nindent 8 }} +{{- end }} diff --git a/examples/operator/values.yaml b/examples/operator/values.yaml index 8095684..f61710a 100644 --- a/examples/operator/values.yaml +++ b/examples/operator/values.yaml @@ -43,6 +43,7 @@ metricsService: port: 8443 targetPort: https type: ClusterIP +nodeSelector: {} pvc: pvcLim: storageClass: cust1-mypool-lim @@ -54,6 +55,11 @@ secretRegistryCredentials: secretVars: var1: "" var2: "" +tolerations: [] +topologySpreadConstraints: +- maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: DoNotSchedule webhookService: ports: - port: 443 diff --git a/pkg/processor/constraints/constraint.go b/pkg/processor/constraints/constraint.go new file mode 100644 index 0000000..7e490d3 --- /dev/null +++ b/pkg/processor/constraints/constraint.go @@ -0,0 +1,46 @@ +package constraints + +import ( + "github.com/arttor/helmify/pkg/helmify" + yamlformat "github.com/arttor/helmify/pkg/yaml" +) + +const tolerations = "tolerations" +const topology = "topologySpreadConstraints" +const nodeSelector = "nodeSelector" + +const topologyExpression = "\n{{- if .Values.topologySpreadConstraints }}\n" + + " topologySpreadConstraints: {{- include \"tplvalues.render\" (dict \"value\" .Values.topologySpreadConstraints \"context\" $) | nindent 8 }}\n" + + "{{- end }}\n" + +const nodeSelectorExpression = "{{- if .Values.nodeSelector }}\n" + + " nodeSelector: {{- include \"tplvalues.render\" ( dict \"value\" .Values.nodeSelector \"context\" $) | nindent 8 }}\n" + + "{{- end }}\n" + +const tolerationsExpression = "{{- if .Values.tolerations }}\n" + + " tolerations: {{- include \"tplvalues.render\" (dict \"value\" .Values.tolerations \"context\" .) | nindent 8 }}\n" + + "{{- end }}\n" + +// ProcessSpecMap adds 'topologyConstraints' to the podSpec in specMap, if it doesn't +// already has one defined. +func ProcessSpecMap(specMap map[string]interface{}, values *helmify.Values) string { + + mapConstraint(specMap, topology, []interface{}{}, values) + mapConstraint(specMap, tolerations, []interface{}{}, values) + mapConstraint(specMap, nodeSelector, map[string]string{}, values) + + spec, err := yamlformat.Marshal(specMap, 6) + if err != nil { + return "" + } + return spec + topologyExpression + nodeSelectorExpression + tolerationsExpression +} + +func mapConstraint(specMap map[string]interface{}, constraint string, override interface{}, values *helmify.Values) { + if specMap[constraint] != nil { + (*values)[constraint] = specMap[constraint].(interface{}) + } else { + (*values)[constraint] = override + } + delete(specMap, constraint) +} diff --git a/pkg/processor/constraints/constraint_test.go b/pkg/processor/constraints/constraint_test.go new file mode 100644 index 0000000..f67d63b --- /dev/null +++ b/pkg/processor/constraints/constraint_test.go @@ -0,0 +1,74 @@ +package constraints + +import ( + "testing" + + "github.com/arttor/helmify/pkg/helmify" + "github.com/stretchr/testify/require" + v1 "k8s.io/api/core/v1" +) + +const templatedResult = "{{- if .Values.topologySpreadConstraints }}\n" + + " topologySpreadConstraints: {{- include \"tplvalues.render\" (dict \"value\" .Values.topologySpreadConstraints \"context\" $) | nindent 8 }}\n" + + "{{- end }}\n" + + "{{- if .Values.nodeSelector }}\n" + + " nodeSelector: {{- include \"tplvalues.render\" ( dict \"value\" .Values.nodeSelector \"context\" $) | nindent 8 }}\n" + + "{{- end }}\n" + + "{{- if .Values.tolerations }}\n" + + " tolerations: {{- include \"tplvalues.render\" (dict \"value\" .Values.tolerations \"context\" .) | nindent 8 }}\n" + + "{{- end }}\n" + +func TestProcessSpecMap(t *testing.T) { + + tests := []struct { + name string + specMap map[string]interface{} + values *helmify.Values + podspec v1.PodSpec + want string + wantValues *helmify.Values + }{ + {name: "no predefined resource returns still a template and to fill in values", + specMap: make(map[string]interface{}, 4), + values: &helmify.Values{}, + want: templatedResult, + wantValues: &helmify.Values{ + "nodeSelector": map[string]string{}, + "tolerations": []interface{}{}, + "topologySpreadConstraints": []interface{}{}, + }, + }, + {name: "predefined resource are added to values, template is the same", + values: &helmify.Values{}, + specMap: map[string]interface{}{ + "topologySpreadConstraints": []v1.TopologySpreadConstraint{ + { + MaxSkew: 0, + TopologyKey: "trtr", + WhenUnsatisfiable: "test", + LabelSelector: nil, + }, + }, + }, + want: templatedResult, + wantValues: &helmify.Values{ + "nodeSelector": map[string]string{}, + "tolerations": []interface{}{}, + "topologySpreadConstraints": []v1.TopologySpreadConstraint{ + { + MaxSkew: 0, + TopologyKey: "trtr", + WhenUnsatisfiable: "test", + }, + }, + }, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got := ProcessSpecMap(tt.specMap, tt.values) + require.Contains(t, got, tt.want) + require.Equal(t, tt.wantValues, tt.values) + }) + } +} diff --git a/pkg/processor/deployment/deployment.go b/pkg/processor/deployment/deployment.go index 4a4daa6..25c5865 100644 --- a/pkg/processor/deployment/deployment.go +++ b/pkg/processor/deployment/deployment.go @@ -8,6 +8,7 @@ import ( "github.com/arttor/helmify/pkg/cluster" "github.com/arttor/helmify/pkg/processor" + "github.com/arttor/helmify/pkg/processor/constraints" "github.com/arttor/helmify/pkg/processor/imagePullSecrets" "github.com/arttor/helmify/pkg/helmify" @@ -164,10 +165,7 @@ func (d deployment) Process(appMeta helmify.AppMetadata, obj *unstructured.Unstr imagePullSecrets.ProcessSpecMap(specMap, &values) } - spec, err := yamlformat.Marshal(specMap, 6) - if err != nil { - return true, nil, err - } + spec := constraints.ProcessSpecMap(specMap, &values) spec = strings.ReplaceAll(spec, "'", "") return true, &result{ diff --git a/test_data/k8s-operator-kustomize.output b/test_data/k8s-operator-kustomize.output index dc3c123..fe62270 100644 --- a/test_data/k8s-operator-kustomize.output +++ b/test_data/k8s-operator-kustomize.output @@ -586,6 +586,13 @@ spec: labels: control-plane: controller-manager spec: + topologySpreadConstraints: + - maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: DoNotSchedule + matchLabelKeys: + - app + - pod-template-hash imagePullSecrets: - name: my-operator-secret-registry-credentials containers: From c071c5655ec0e12b9dd39797b8af87563414695e Mon Sep 17 00:00:00 2001 From: RealAnna Date: Mon, 20 Feb 2023 11:18:37 +0100 Subject: [PATCH 2/9] feat: added constraints Signed-off-by: RealAnna --- pkg/helm/init.go | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/pkg/helm/init.go b/pkg/helm/init.go index a8d77dd..4a9b0b7 100644 --- a/pkg/helm/init.go +++ b/pkg/helm/init.go @@ -99,6 +99,19 @@ Create the name of the service account to use {{- default "default" .Values.serviceAccount.name }} {{- end }} {{- end }} + +{{/* +Renders a value that contains template. +Usage: +{{ include "tplvalues.render" ( dict "value" .Values.path.to.the.Value "context" $) }} +*/}} +{{- define "tplvalues.render" -}} + {{- if typeIs "string" .value }} + {{- tpl .value .context }} + {{- else }} + {{- tpl (.value | toYaml) .context }} + {{- end }} +{{- end -}} ` const defaultChartfile = `apiVersion: v2 From 12d38e79bcc357f8853074af487db5e6bf2075ca Mon Sep 17 00:00:00 2001 From: RealAnna Date: Tue, 21 Feb 2023 14:57:20 +0100 Subject: [PATCH 3/9] fix: tolerations and other constraint under deployment name Signed-off-by: RealAnna --- examples/operator/values.yaml | 12 ++++++------ pkg/processor/constraints/constraint.go | 14 +++++++------- pkg/processor/deployment/deployment.go | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/examples/operator/values.yaml b/examples/operator/values.yaml index f61710a..4d35e50 100644 --- a/examples/operator/values.yaml +++ b/examples/operator/values.yaml @@ -20,7 +20,13 @@ controllerManager: requests: cpu: 100m memory: 20Mi + nodeSelector: {} replicas: 1 + tolerations: [] + topologySpreadConstraints: + - maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: DoNotSchedule kubernetesClusterDomain: cluster.local managerConfig: controllerManagerConfigYaml: @@ -43,7 +49,6 @@ metricsService: port: 8443 targetPort: https type: ClusterIP -nodeSelector: {} pvc: pvcLim: storageClass: cust1-mypool-lim @@ -55,11 +60,6 @@ secretRegistryCredentials: secretVars: var1: "" var2: "" -tolerations: [] -topologySpreadConstraints: -- maxSkew: 1 - topologyKey: kubernetes.io/hostname - whenUnsatisfiable: DoNotSchedule webhookService: ports: - port: 443 diff --git a/pkg/processor/constraints/constraint.go b/pkg/processor/constraints/constraint.go index 7e490d3..431c8fd 100644 --- a/pkg/processor/constraints/constraint.go +++ b/pkg/processor/constraints/constraint.go @@ -23,11 +23,11 @@ const tolerationsExpression = "{{- if .Values.tolerations }}\n" + // ProcessSpecMap adds 'topologyConstraints' to the podSpec in specMap, if it doesn't // already has one defined. -func ProcessSpecMap(specMap map[string]interface{}, values *helmify.Values) string { +func ProcessSpecMap(name string, specMap map[string]interface{}, values *helmify.Values) string { - mapConstraint(specMap, topology, []interface{}{}, values) - mapConstraint(specMap, tolerations, []interface{}{}, values) - mapConstraint(specMap, nodeSelector, map[string]string{}, values) + mapConstraint(name, specMap, topology, []interface{}{}, values) + mapConstraint(name, specMap, tolerations, []interface{}{}, values) + mapConstraint(name, specMap, nodeSelector, map[string]string{}, values) spec, err := yamlformat.Marshal(specMap, 6) if err != nil { @@ -36,11 +36,11 @@ func ProcessSpecMap(specMap map[string]interface{}, values *helmify.Values) stri return spec + topologyExpression + nodeSelectorExpression + tolerationsExpression } -func mapConstraint(specMap map[string]interface{}, constraint string, override interface{}, values *helmify.Values) { +func mapConstraint(name string, specMap map[string]interface{}, constraint string, override interface{}, values *helmify.Values) { if specMap[constraint] != nil { - (*values)[constraint] = specMap[constraint].(interface{}) + (*values)[name].(map[string]interface{})[constraint] = specMap[constraint].(interface{}) } else { - (*values)[constraint] = override + (*values)[name].(map[string]interface{})[constraint] = override } delete(specMap, constraint) } diff --git a/pkg/processor/deployment/deployment.go b/pkg/processor/deployment/deployment.go index 25c5865..84488dc 100644 --- a/pkg/processor/deployment/deployment.go +++ b/pkg/processor/deployment/deployment.go @@ -165,7 +165,7 @@ func (d deployment) Process(appMeta helmify.AppMetadata, obj *unstructured.Unstr imagePullSecrets.ProcessSpecMap(specMap, &values) } - spec := constraints.ProcessSpecMap(specMap, &values) + spec := constraints.ProcessSpecMap(nameCamel, specMap, &values) spec = strings.ReplaceAll(spec, "'", "") return true, &result{ From e4d3d6e3a864d0c3cb90367d86c4693866d88e43 Mon Sep 17 00:00:00 2001 From: RealAnna Date: Tue, 21 Feb 2023 15:48:40 +0100 Subject: [PATCH 4/9] fix: tolerations and other constraint under deployment name Signed-off-by: RealAnna --- pkg/processor/constraints/constraint_test.go | 39 ++++++++++++-------- 1 file changed, 24 insertions(+), 15 deletions(-) diff --git a/pkg/processor/constraints/constraint_test.go b/pkg/processor/constraints/constraint_test.go index f67d63b..60f6a67 100644 --- a/pkg/processor/constraints/constraint_test.go +++ b/pkg/processor/constraints/constraint_test.go @@ -30,17 +30,24 @@ func TestProcessSpecMap(t *testing.T) { }{ {name: "no predefined resource returns still a template and to fill in values", specMap: make(map[string]interface{}, 4), - values: &helmify.Values{}, - want: templatedResult, + values: &helmify.Values{ + "mydep": map[string]interface{}{}, + }, + want: templatedResult, wantValues: &helmify.Values{ - "nodeSelector": map[string]string{}, - "tolerations": []interface{}{}, - "topologySpreadConstraints": []interface{}{}, + "mydep": map[string]interface{}{ + "nodeSelector": map[string]string{}, + "tolerations": []interface{}{}, + "topologySpreadConstraints": []interface{}{}, + }, }, }, {name: "predefined resource are added to values, template is the same", - values: &helmify.Values{}, + values: &helmify.Values{ + "mydep": map[string]interface{}{}, + }, specMap: map[string]interface{}{ + "topologySpreadConstraints": []v1.TopologySpreadConstraint{ { MaxSkew: 0, @@ -52,13 +59,15 @@ func TestProcessSpecMap(t *testing.T) { }, want: templatedResult, wantValues: &helmify.Values{ - "nodeSelector": map[string]string{}, - "tolerations": []interface{}{}, - "topologySpreadConstraints": []v1.TopologySpreadConstraint{ - { - MaxSkew: 0, - TopologyKey: "trtr", - WhenUnsatisfiable: "test", + "mydep": map[string]interface{}{ + "nodeSelector": map[string]string{}, + "tolerations": []interface{}{}, + "topologySpreadConstraints": []v1.TopologySpreadConstraint{ + { + MaxSkew: 0, + TopologyKey: "trtr", + WhenUnsatisfiable: "test", + }, }, }, }, @@ -66,9 +75,9 @@ func TestProcessSpecMap(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got := ProcessSpecMap(tt.specMap, tt.values) + got := ProcessSpecMap("mydep", tt.specMap, tt.values) require.Contains(t, got, tt.want) - require.Equal(t, tt.wantValues, tt.values) + require.Equal(t, *tt.wantValues, *tt.values) }) } } From 764a7de78160e0ec26294b7bd2a7506d09ea90a9 Mon Sep 17 00:00:00 2001 From: RealAnna Date: Mon, 13 Mar 2023 09:47:49 +0100 Subject: [PATCH 5/9] hide autofill behind CLI flag Signed-off-by: RealAnna --- cmd/helmify/flags.go | 1 + examples/operator/values.yaml | 2 -- pkg/config/config.go | 3 +++ pkg/processor/constraints/constraint.go | 25 ++++++++++++++++++------- pkg/processor/deployment/deployment.go | 2 +- 5 files changed, 23 insertions(+), 10 deletions(-) diff --git a/cmd/helmify/flags.go b/cmd/helmify/flags.go index b33579d..67efc96 100644 --- a/cmd/helmify/flags.go +++ b/cmd/helmify/flags.go @@ -37,6 +37,7 @@ func ReadFlags() config.Config { flag.BoolVar(&result.VeryVerbose, "vv", false, "Enable very verbose output. Same as verbose but with DEBUG. Example: helmify -vv") flag.BoolVar(&crd, "crd-dir", false, "Enable crd install into 'crds' directory.\nWarning: CRDs placed in 'crds' directory will not be templated by Helm.\nSee https://helm.sh/docs/chart_best_practices/custom_resource_definitions/#some-caveats-and-explanations\nExample: helmify -crd-dir") flag.BoolVar(&result.ImagePullSecrets, "image-pull-secrets", false, "Allows the user to use existing secrets as imagePullSecrets in values.yaml") + flag.BoolVar(&result.GenerateDefault, "default", false, "Allows the user to add empty placeholders for tipical customization options in values.yaml. Currently covers: topology constraints, node selectors, tolerances") flag.Parse() if h || help { diff --git a/examples/operator/values.yaml b/examples/operator/values.yaml index 4d35e50..51c1515 100644 --- a/examples/operator/values.yaml +++ b/examples/operator/values.yaml @@ -20,9 +20,7 @@ controllerManager: requests: cpu: 100m memory: 20Mi - nodeSelector: {} replicas: 1 - tolerations: [] topologySpreadConstraints: - maxSkew: 1 topologyKey: kubernetes.io/hostname diff --git a/pkg/config/config.go b/pkg/config/config.go index b7d3c68..c648333 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -23,6 +23,9 @@ type Config struct { Crd bool // ImagePullSecrets flag ImagePullSecrets bool + // GenerateDefault enables the generation of empty values placeholders for common customization options of helm chart + // current generated values: tolerances, node selectors, topology constraints + GenerateDefault bool } func (c *Config) Validate() error { diff --git a/pkg/processor/constraints/constraint.go b/pkg/processor/constraints/constraint.go index 431c8fd..cdca392 100644 --- a/pkg/processor/constraints/constraint.go +++ b/pkg/processor/constraints/constraint.go @@ -23,11 +23,17 @@ const tolerationsExpression = "{{- if .Values.tolerations }}\n" + // ProcessSpecMap adds 'topologyConstraints' to the podSpec in specMap, if it doesn't // already has one defined. -func ProcessSpecMap(name string, specMap map[string]interface{}, values *helmify.Values) string { +func ProcessSpecMap(name string, specMap map[string]interface{}, values *helmify.Values, defaultEmpty bool) string { - mapConstraint(name, specMap, topology, []interface{}{}, values) - mapConstraint(name, specMap, tolerations, []interface{}{}, values) - mapConstraint(name, specMap, nodeSelector, map[string]string{}, values) + if defaultEmpty { + mapConstraintWithEmpty(name, specMap, topology, []interface{}{}, values) + mapConstraintWithEmpty(name, specMap, tolerations, []interface{}{}, values) + mapConstraintWithEmpty(name, specMap, nodeSelector, map[string]string{}, values) + } + + mapConstraint(name, specMap, topology, values) + mapConstraint(name, specMap, tolerations, values) + mapConstraint(name, specMap, nodeSelector, values) spec, err := yamlformat.Marshal(specMap, 6) if err != nil { @@ -36,11 +42,16 @@ func ProcessSpecMap(name string, specMap map[string]interface{}, values *helmify return spec + topologyExpression + nodeSelectorExpression + tolerationsExpression } -func mapConstraint(name string, specMap map[string]interface{}, constraint string, override interface{}, values *helmify.Values) { +func mapConstraintWithEmpty(name string, specMap map[string]interface{}, constraint string, override interface{}, values *helmify.Values) { + if specMap[constraint] == nil { + (*values)[name].(map[string]interface{})[constraint] = override + } + delete(specMap, constraint) +} + +func mapConstraint(name string, specMap map[string]interface{}, constraint string, values *helmify.Values) { if specMap[constraint] != nil { (*values)[name].(map[string]interface{})[constraint] = specMap[constraint].(interface{}) - } else { - (*values)[name].(map[string]interface{})[constraint] = override } delete(specMap, constraint) } diff --git a/pkg/processor/deployment/deployment.go b/pkg/processor/deployment/deployment.go index 84488dc..63bd53b 100644 --- a/pkg/processor/deployment/deployment.go +++ b/pkg/processor/deployment/deployment.go @@ -165,7 +165,7 @@ func (d deployment) Process(appMeta helmify.AppMetadata, obj *unstructured.Unstr imagePullSecrets.ProcessSpecMap(specMap, &values) } - spec := constraints.ProcessSpecMap(nameCamel, specMap, &values) + spec := constraints.ProcessSpecMap(nameCamel, specMap, &values, appMeta.Config().GenerateDefault) spec = strings.ReplaceAll(spec, "'", "") return true, &result{ From 44599c8fc3d259ae06c0f83ae574d52d633b8d55 Mon Sep 17 00:00:00 2001 From: RealAnna Date: Mon, 13 Mar 2023 09:50:24 +0100 Subject: [PATCH 6/9] fix test Signed-off-by: RealAnna --- pkg/processor/constraints/constraint_test.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/processor/constraints/constraint_test.go b/pkg/processor/constraints/constraint_test.go index 60f6a67..8a27512 100644 --- a/pkg/processor/constraints/constraint_test.go +++ b/pkg/processor/constraints/constraint_test.go @@ -75,7 +75,7 @@ func TestProcessSpecMap(t *testing.T) { } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { - got := ProcessSpecMap("mydep", tt.specMap, tt.values) + got := ProcessSpecMap("mydep", tt.specMap, tt.values, true) require.Contains(t, got, tt.want) require.Equal(t, *tt.wantValues, *tt.values) }) From 0dee28521b36af3cefc89648ae44465fc68fb858 Mon Sep 17 00:00:00 2001 From: RealAnna Date: Mon, 13 Mar 2023 09:54:39 +0100 Subject: [PATCH 7/9] fix test Signed-off-by: RealAnna --- cmd/helmify/flags.go | 2 +- pkg/config/config.go | 4 ++-- pkg/processor/deployment/deployment.go | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/cmd/helmify/flags.go b/cmd/helmify/flags.go index 67efc96..4186ff4 100644 --- a/cmd/helmify/flags.go +++ b/cmd/helmify/flags.go @@ -37,7 +37,7 @@ func ReadFlags() config.Config { flag.BoolVar(&result.VeryVerbose, "vv", false, "Enable very verbose output. Same as verbose but with DEBUG. Example: helmify -vv") flag.BoolVar(&crd, "crd-dir", false, "Enable crd install into 'crds' directory.\nWarning: CRDs placed in 'crds' directory will not be templated by Helm.\nSee https://helm.sh/docs/chart_best_practices/custom_resource_definitions/#some-caveats-and-explanations\nExample: helmify -crd-dir") flag.BoolVar(&result.ImagePullSecrets, "image-pull-secrets", false, "Allows the user to use existing secrets as imagePullSecrets in values.yaml") - flag.BoolVar(&result.GenerateDefault, "default", false, "Allows the user to add empty placeholders for tipical customization options in values.yaml. Currently covers: topology constraints, node selectors, tolerances") + flag.BoolVar(&result.GenerateDefaults, "generate-defaults", false, "Allows the user to add empty placeholders for tipical customization options in values.yaml. Currently covers: topology constraints, node selectors, tolerances") flag.Parse() if h || help { diff --git a/pkg/config/config.go b/pkg/config/config.go index c648333..1c5c6be 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -23,9 +23,9 @@ type Config struct { Crd bool // ImagePullSecrets flag ImagePullSecrets bool - // GenerateDefault enables the generation of empty values placeholders for common customization options of helm chart + // GenerateDefaults enables the generation of empty values placeholders for common customization options of helm chart // current generated values: tolerances, node selectors, topology constraints - GenerateDefault bool + GenerateDefaults bool } func (c *Config) Validate() error { diff --git a/pkg/processor/deployment/deployment.go b/pkg/processor/deployment/deployment.go index 63bd53b..72143de 100644 --- a/pkg/processor/deployment/deployment.go +++ b/pkg/processor/deployment/deployment.go @@ -165,7 +165,7 @@ func (d deployment) Process(appMeta helmify.AppMetadata, obj *unstructured.Unstr imagePullSecrets.ProcessSpecMap(specMap, &values) } - spec := constraints.ProcessSpecMap(nameCamel, specMap, &values, appMeta.Config().GenerateDefault) + spec := constraints.ProcessSpecMap(nameCamel, specMap, &values, appMeta.Config().GenerateDefaults) spec = strings.ReplaceAll(spec, "'", "") return true, &result{ From c2831696e7e4f5a5759c70777eca4f62de59961f Mon Sep 17 00:00:00 2001 From: RealAnna Date: Mon, 13 Mar 2023 10:36:18 +0100 Subject: [PATCH 8/9] fix according to review Signed-off-by: RealAnna --- examples/operator/templates/deployment.yaml | 15 +++++---------- pkg/processor/constraints/constraint.go | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 20 deletions(-) diff --git a/examples/operator/templates/deployment.yaml b/examples/operator/templates/deployment.yaml index 283407a..dcb1b78 100644 --- a/examples/operator/templates/deployment.yaml +++ b/examples/operator/templates/deployment.yaml @@ -104,19 +104,14 @@ spec: runAsNonRoot: true serviceAccountName: {{ include "operator.fullname" . }}-controller-manager terminationGracePeriodSeconds: 10 + topologySpreadConstraints: + - maxSkew: 1 + topologyKey: kubernetes.io/hostname + whenUnsatisfiable: DoNotSchedule volumes: - configMap: name: {{ include "operator.fullname" . }}-manager-config name: manager-config - name: secret-volume secret: - secretName: {{ include "operator.fullname" . }}-secret-ca -{{- if .Values.topologySpreadConstraints }} - topologySpreadConstraints: {{- include "tplvalues.render" (dict "value" .Values.topologySpreadConstraints "context" $) | nindent 8 }} -{{- end }} -{{- if .Values.nodeSelector }} - nodeSelector: {{- include "tplvalues.render" ( dict "value" .Values.nodeSelector "context" $) | nindent 8 }} -{{- end }} -{{- if .Values.tolerations }} - tolerations: {{- include "tplvalues.render" (dict "value" .Values.tolerations "context" .) | nindent 8 }} -{{- end }} + secretName: {{ include "operator.fullname" . }}-secret-ca \ No newline at end of file diff --git a/pkg/processor/constraints/constraint.go b/pkg/processor/constraints/constraint.go index cdca392..2d78201 100644 --- a/pkg/processor/constraints/constraint.go +++ b/pkg/processor/constraints/constraint.go @@ -25,33 +25,33 @@ const tolerationsExpression = "{{- if .Values.tolerations }}\n" + // already has one defined. func ProcessSpecMap(name string, specMap map[string]interface{}, values *helmify.Values, defaultEmpty bool) string { - if defaultEmpty { - mapConstraintWithEmpty(name, specMap, topology, []interface{}{}, values) - mapConstraintWithEmpty(name, specMap, tolerations, []interface{}{}, values) - mapConstraintWithEmpty(name, specMap, nodeSelector, map[string]string{}, values) - } - mapConstraint(name, specMap, topology, values) mapConstraint(name, specMap, tolerations, values) mapConstraint(name, specMap, nodeSelector, values) - spec, err := yamlformat.Marshal(specMap, 6) if err != nil { return "" } - return spec + topologyExpression + nodeSelectorExpression + tolerationsExpression + + if defaultEmpty { + mapConstraintWithEmpty(name, specMap, topology, []interface{}{}, values) + mapConstraintWithEmpty(name, specMap, tolerations, []interface{}{}, values) + mapConstraintWithEmpty(name, specMap, nodeSelector, map[string]string{}, values) + return spec + topologyExpression + nodeSelectorExpression + tolerationsExpression + } + + return spec } func mapConstraintWithEmpty(name string, specMap map[string]interface{}, constraint string, override interface{}, values *helmify.Values) { if specMap[constraint] == nil { (*values)[name].(map[string]interface{})[constraint] = override } - delete(specMap, constraint) + delete(specMap, topology) } func mapConstraint(name string, specMap map[string]interface{}, constraint string, values *helmify.Values) { if specMap[constraint] != nil { (*values)[name].(map[string]interface{})[constraint] = specMap[constraint].(interface{}) } - delete(specMap, constraint) } From 652f30ce59aacb9499c7bfeb50af32eaab524939 Mon Sep 17 00:00:00 2001 From: RealAnna Date: Mon, 13 Mar 2023 10:47:39 +0100 Subject: [PATCH 9/9] fix according to review Signed-off-by: RealAnna --- examples/operator/templates/deployment.yaml | 5 +++- pkg/processor/constraints/constraint.go | 30 ++++++++++++++------- 2 files changed, 24 insertions(+), 11 deletions(-) diff --git a/examples/operator/templates/deployment.yaml b/examples/operator/templates/deployment.yaml index dcb1b78..2374d2d 100644 --- a/examples/operator/templates/deployment.yaml +++ b/examples/operator/templates/deployment.yaml @@ -114,4 +114,7 @@ spec: name: manager-config - name: secret-volume secret: - secretName: {{ include "operator.fullname" . }}-secret-ca \ No newline at end of file + secretName: {{ include "operator.fullname" . }}-secret-ca +{{- if .Values.topologySpreadConstraints }} + topologySpreadConstraints: {{- include "tplvalues.render" (dict "value" .Values.topologySpreadConstraints "context" $) | nindent 8 }} +{{- end }} diff --git a/pkg/processor/constraints/constraint.go b/pkg/processor/constraints/constraint.go index 2d78201..f10ac6a 100644 --- a/pkg/processor/constraints/constraint.go +++ b/pkg/processor/constraints/constraint.go @@ -25,9 +25,6 @@ const tolerationsExpression = "{{- if .Values.tolerations }}\n" + // already has one defined. func ProcessSpecMap(name string, specMap map[string]interface{}, values *helmify.Values, defaultEmpty bool) string { - mapConstraint(name, specMap, topology, values) - mapConstraint(name, specMap, tolerations, values) - mapConstraint(name, specMap, nodeSelector, values) spec, err := yamlformat.Marshal(specMap, 6) if err != nil { return "" @@ -40,18 +37,31 @@ func ProcessSpecMap(name string, specMap map[string]interface{}, values *helmify return spec + topologyExpression + nodeSelectorExpression + tolerationsExpression } - return spec -} + if specMap[topology] != nil { + (*values)[name].(map[string]interface{})[topology] = specMap[topology].(interface{}) + delete(specMap, topology) + spec += topologyExpression + } -func mapConstraintWithEmpty(name string, specMap map[string]interface{}, constraint string, override interface{}, values *helmify.Values) { - if specMap[constraint] == nil { - (*values)[name].(map[string]interface{})[constraint] = override + if specMap[tolerations] != nil { + (*values)[name].(map[string]interface{})[tolerations] = specMap[tolerations].(interface{}) + delete(specMap, tolerations) + spec += tolerationsExpression } - delete(specMap, topology) + if specMap[nodeSelector] != nil { + (*values)[name].(map[string]interface{})[nodeSelector] = specMap[nodeSelector].(interface{}) + delete(specMap, nodeSelector) + spec += nodeSelectorExpression + } + + return spec } -func mapConstraint(name string, specMap map[string]interface{}, constraint string, values *helmify.Values) { +func mapConstraintWithEmpty(name string, specMap map[string]interface{}, constraint string, override interface{}, values *helmify.Values) { if specMap[constraint] != nil { (*values)[name].(map[string]interface{})[constraint] = specMap[constraint].(interface{}) + } else { + (*values)[name].(map[string]interface{})[constraint] = override } + delete(specMap, constraint) }