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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions examples/app/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,13 @@ spec:
labels:
app: myapp
{{- include "app.selectorLabels" . | nindent 8 }}
{{- if .Values.myapp.podLabels }}
{{- toYaml .Values.myapp.podLabels | nindent 8 }}
{{- end }}
annotations:
{{- with .Values.myapp.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
affinity: {{- toYaml .Values.myapp.affinity | nindent 8 }}
containers:
Expand Down
2 changes: 2 additions & 0 deletions examples/app/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ myapp:
nodeSelector:
region: east
type: user-node
podAnnotations: {}
podLabels: {}
podSecurityContext:
fsGroup: 20000
runAsNonRoot: true
Expand Down
7 changes: 7 additions & 0 deletions examples/operator/templates/deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,13 @@ spec:
labels:
control-plane: controller-manager
{{- include "operator.selectorLabels" . | nindent 8 }}
{{- if .Values.controllerManager.podLabels }}
{{- toYaml .Values.controllerManager.podLabels | nindent 8 }}
{{- end }}
annotations:
{{- with .Values.controllerManager.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
containers:
- args: {{- toYaml .Values.controllerManager.kubeRbacProxy.args | nindent 8 }}
Expand Down
2 changes: 2 additions & 0 deletions examples/operator/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ controllerManager:
nodeSelector:
region: east
type: user-node
podAnnotations: {}
podLabels: {}
podSecurityContext:
runAsNonRoot: true
replicas: 1
Expand Down
20 changes: 14 additions & 6 deletions pkg/processor/deployment/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -108,23 +108,31 @@ func (d deployment) Process(appMeta helmify.AppMetadata, obj *unstructured.Unstr
selector = strings.Trim(selector, " \n")
selector = string(yamlformat.Indent([]byte(selector), 4))

nameCamel := strcase.ToLowerCamel(name)
podLabels, err := yamlformat.Marshal(depl.Spec.Template.ObjectMeta.Labels, 8)
if err != nil {
return true, nil, err
}
podLabels += fmt.Sprintf("\n {{- include \"%s.selectorLabels\" . | nindent 8 }}", appMeta.ChartName())
podLabels += fmt.Sprintf("\n {{- include \"%s.selectorLabels\" . | nindent 8 }}\n {{- if .Values.%s.podLabels }}\n {{- toYaml .Values.%s.podLabels | nindent 8 }}\n {{- end }}", appMeta.ChartName(), nameCamel, nameCamel)
err = unstructured.SetNestedField(values, make(map[string]interface{}), nameCamel, "podLabels")
if err != nil {
return true, nil, err
}

podAnnotations := ""
podAnnotations := "\n annotations:"
if len(depl.Spec.Template.ObjectMeta.Annotations) != 0 {
podAnnotations, err = yamlformat.Marshal(map[string]interface{}{"annotations": depl.Spec.Template.ObjectMeta.Annotations}, 6)
staticAnnotations, err := yamlformat.Marshal(depl.Spec.Template.ObjectMeta.Annotations, 8)
if err != nil {
return true, nil, err
}

podAnnotations = "\n" + podAnnotations
podAnnotations += "\n" + staticAnnotations
}
podAnnotations += fmt.Sprintf("\n {{- with .Values.%s.podAnnotations }}\n {{- toYaml . | nindent 8 }}\n {{- end }}", nameCamel)
err = unstructured.SetNestedField(values, make(map[string]interface{}), nameCamel, "podAnnotations")
if err != nil {
return true, nil, err
}

nameCamel := strcase.ToLowerCamel(name)
specMap, podValues, err := pod.ProcessSpec(nameCamel, appMeta, depl.Spec.Template.Spec, 0)
if err != nil {
return true, nil, err
Expand Down
121 changes: 121 additions & 0 deletions pkg/processor/deployment/deployment_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package deployment

import (
"bytes"
"testing"

"github.com/arttor/helmify/pkg/metadata"
Expand Down Expand Up @@ -137,6 +138,126 @@ func Test_deployment_Process(t *testing.T) {
})
}

const (
// strDeplNoAnnotations has no pod template annotations — tests that podAnnotations is
// still seeded in values and the values-driven block is present in the template.
strDeplNoAnnotations = `apiVersion: apps/v1
kind: Deployment
metadata:
labels:
control-plane: controller-manager
name: my-operator-controller-manager
namespace: my-operator-system
spec:
replicas: 1
selector:
matchLabels:
control-plane: controller-manager
template:
metadata:
labels:
control-plane: controller-manager
spec:
containers:
- name: manager
image: controller:latest
`
// strDeplWithAnnotations has static pod template annotations — tests that static
// annotations are preserved and the values-driven block is appended after them.
strDeplWithAnnotations = `apiVersion: apps/v1
kind: Deployment
metadata:
labels:
control-plane: controller-manager
name: my-operator-controller-manager
namespace: my-operator-system
spec:
replicas: 1
selector:
matchLabels:
control-plane: controller-manager
template:
metadata:
labels:
control-plane: controller-manager
annotations:
kubectl.kubernetes.io/default-container: manager
spec:
containers:
- name: manager
image: controller:latest
`
)

func Test_deployment_podAnnotations(t *testing.T) {
var testInstance deployment

t.Run("no static annotations - values seeded and template block present", func(t *testing.T) {
obj := internal.GenerateObj(strDeplNoAnnotations)
processed, tmpl, err := testInstance.Process(&metadata.Service{}, obj)
assert.NoError(t, err)
assert.True(t, processed)

// podAnnotations should be seeded as empty map in values
// the deployment name "my-operator-controller-manager" trims to "controller-manager"
// which becomes "controllerManager" in lowerCamel
vals := tmpl.Values()
controllerManager, ok := vals["myOperatorControllerManager"].(map[string]interface{})
assert.True(t, ok, "expected myOperatorControllerManager key in values")
podAnnotations, ok := controllerManager["podAnnotations"]
assert.True(t, ok, "expected podAnnotations key in values")
assert.Equal(t, map[string]interface{}{}, podAnnotations)

// Template output must contain the values-driven annotations block
var buf bytes.Buffer
assert.NoError(t, tmpl.Write(&buf))
output := buf.String()
assert.Contains(t, output, "{{- with .Values.myOperatorControllerManager.podAnnotations }}")
assert.Contains(t, output, "{{- toYaml . | nindent 8 }}")
assert.Contains(t, output, "annotations:")
})

t.Run("static annotations preserved and values block appended", func(t *testing.T) {
obj := internal.GenerateObj(strDeplWithAnnotations)
processed, tmpl, err := testInstance.Process(&metadata.Service{}, obj)
assert.NoError(t, err)
assert.True(t, processed)

var buf bytes.Buffer
assert.NoError(t, tmpl.Write(&buf))
output := buf.String()

// Static annotation must be in the output
assert.Contains(t, output, "kubectl.kubernetes.io/default-container: manager")
// Values-driven block must also be present
assert.Contains(t, output, "{{- with .Values.myOperatorControllerManager.podAnnotations }}")
})
}

func Test_deployment_podLabels(t *testing.T) {
var testInstance deployment

t.Run("podLabels seeded in values and template block present", func(t *testing.T) {
obj := internal.GenerateObj(strDeplNoAnnotations)
processed, tmpl, err := testInstance.Process(&metadata.Service{}, obj)
assert.NoError(t, err)
assert.True(t, processed)

vals := tmpl.Values()
controllerManager, ok := vals["myOperatorControllerManager"].(map[string]interface{})
assert.True(t, ok, "expected myOperatorControllerManager key in values")
podLabels, ok := controllerManager["podLabels"]
assert.True(t, ok, "expected podLabels key in values")
assert.Equal(t, map[string]interface{}{}, podLabels)

var buf bytes.Buffer
assert.NoError(t, tmpl.Write(&buf))
output := buf.String()
assert.Contains(t, output, "{{- if .Values.myOperatorControllerManager.podLabels }}")
assert.Contains(t, output, "{{- toYaml .Values.myOperatorControllerManager.podLabels | nindent 8 }}")
})
}

var singleQuotesTest = []struct {
input string
expected string
Expand Down
Loading