Skip to content
Closed
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
65 changes: 65 additions & 0 deletions pkg/app/app_e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package app
import (
"bufio"
"os"
"strings"
"testing"

"github.com/arttor/helmify/pkg/config"
Expand Down Expand Up @@ -58,3 +59,67 @@ func TestApp(t *testing.T) {
assert.NoError(t, err)
}
}

func TestDuplicateSelectorLabelKustomize(t *testing.T) {
const chartName = "test-dup-selector"
input := `apiVersion: apps/v1
kind: Deployment
metadata:
name: platform-operator
namespace: default
labels:
app.kubernetes.io/name: platform-operator
control-plane: controller-manager
spec:
selector:
matchLabels:
app.kubernetes.io/name: platform-operator
control-plane: controller-manager
template:
metadata:
labels:
app.kubernetes.io/name: platform-operator
control-plane: controller-manager
spec:
containers:
- name: manager
image: controller:latest
---
apiVersion: v1
kind: Service
metadata:
name: platform-operator-service
labels:
app.kubernetes.io/name: platform-operator
spec:
selector:
app.kubernetes.io/name: platform-operator
control-plane: controller-manager
ports:
- port: 8080
`
reader := bufio.NewReader(strings.NewReader(input))
err := Start(reader, config.Config{ChartName: chartName})
assert.NoError(t, err)

t.Cleanup(func() {
_ = os.RemoveAll(chartName)
})

helmLint := action.NewLint()
helmLint.Strict = true
helmLint.Namespace = "test-ns"
result := helmLint.Run([]string{chartName}, nil)
for _, err = range result.Errors {
assert.NoError(t, err)
}
assert.Empty(t, result.Errors)

deplContent, err := os.ReadFile(chartName + "/templates/deployment.yaml")
assert.NoError(t, err)
assert.NotContains(t, string(deplContent), "app.kubernetes.io/name: platform-operator")

svcContent, err := os.ReadFile(chartName + "/templates/service.yaml")
assert.NoError(t, err)
assert.NotContains(t, string(svcContent), "app.kubernetes.io/name: platform-operator")
}
30 changes: 22 additions & 8 deletions pkg/processor/daemonset/daemonset.go
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,20 @@ func (d daemonset) Process(appMeta helmify.AppMetadata, obj *unstructured.Unstru

name := appMeta.TrimName(obj.GetName())

matchLabels, err := yamlformat.Marshal(map[string]interface{}{"matchLabels": dae.Spec.Selector.MatchLabels}, 0)
if err != nil {
return true, nil, err
if dae.Spec.Selector != nil && dae.Spec.Selector.MatchLabels != nil {
delete(dae.Spec.Selector.MatchLabels, "app.kubernetes.io/name")
}
var matchLabels string
if dae.Spec.Selector != nil && len(dae.Spec.Selector.MatchLabels) > 0 {
matchLabels, err = yamlformat.Marshal(map[string]interface{}{"matchLabels": dae.Spec.Selector.MatchLabels}, 0)
if err != nil {
return true, nil, err
}
} else {
matchLabels = "matchLabels:"
}
matchExpr := ""
if dae.Spec.Selector.MatchExpressions != nil {
if dae.Spec.Selector != nil && dae.Spec.Selector.MatchExpressions != nil {
matchExpr, err = yamlformat.Marshal(map[string]interface{}{"matchExpressions": dae.Spec.Selector.MatchExpressions}, 0)
if err != nil {
return true, nil, err
Expand All @@ -82,11 +90,17 @@ func (d daemonset) Process(appMeta helmify.AppMetadata, obj *unstructured.Unstru
selector = strings.Trim(selector, " \n")
selector = string(yamlformat.Indent([]byte(selector), 4))

podLabels, err := yamlformat.Marshal(dae.Spec.Template.ObjectMeta.Labels, 8)
if err != nil {
return true, nil, err
delete(dae.Spec.Template.ObjectMeta.Labels, "app.kubernetes.io/name")
var podLabels string
if len(dae.Spec.Template.ObjectMeta.Labels) > 0 {
podLabels, err = yamlformat.Marshal(dae.Spec.Template.ObjectMeta.Labels, 8)
if err != nil {
return true, nil, err
}
podLabels += fmt.Sprintf("\n {{- include \"%s.selectorLabels\" . | nindent 8 }}", appMeta.ChartName())
} else {
podLabels = fmt.Sprintf(" {{- include \"%s.selectorLabels\" . | nindent 8 }}", appMeta.ChartName())
}
podLabels += fmt.Sprintf("\n {{- include \"%s.selectorLabels\" . | nindent 8 }}", appMeta.ChartName())

podAnnotations := ""
if len(dae.Spec.Template.ObjectMeta.Annotations) != 0 {
Expand Down
70 changes: 70 additions & 0 deletions pkg/processor/daemonset/daemonset_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package daemonset

import (
"bytes"
"testing"

"github.com/arttor/helmify/pkg/metadata"
Expand Down Expand Up @@ -73,4 +74,73 @@ func Test_daemonset_Process(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, false, processed)
})

t.Run("processed with duplicate app.kubernetes.io/name in selector and pod labels", func(t *testing.T) {
const daeWithDuplicateYaml = `apiVersion: apps/v1
kind: DaemonSet
metadata:
name: platform-operator-daemon
labels:
app.kubernetes.io/name: platform-operator
control-plane: controller-manager
spec:
selector:
matchLabels:
app.kubernetes.io/name: platform-operator
control-plane: controller-manager
template:
metadata:
labels:
app.kubernetes.io/name: platform-operator
control-plane: controller-manager
spec:
containers:
- name: manager
image: controller:latest`
obj := internal.GenerateObj(daeWithDuplicateYaml)
processed, template, err := testInstance.Process(&metadata.Service{}, obj)
assert.NoError(t, err)
assert.True(t, processed)
var buf bytes.Buffer
err = template.Write(&buf)
assert.NoError(t, err)
out := buf.String()
assert.NotContains(t, out, "app.kubernetes.io/name: platform-operator")
assert.Contains(t, out, "control-plane: controller-manager")
assert.Contains(t, out, `{{- include ".selectorLabels" . | nindent 6 }}`)
assert.Contains(t, out, `{{- include ".selectorLabels" . | nindent 8 }}`)
})

t.Run("processed with only app.kubernetes.io/name in selector and pod labels", func(t *testing.T) {
const daeOnlyNameYaml = `apiVersion: apps/v1
kind: DaemonSet
metadata:
name: platform-operator-daemon
labels:
app.kubernetes.io/name: platform-operator
spec:
selector:
matchLabels:
app.kubernetes.io/name: platform-operator
template:
metadata:
labels:
app.kubernetes.io/name: platform-operator
spec:
containers:
- name: manager
image: controller:latest`
obj := internal.GenerateObj(daeOnlyNameYaml)
processed, template, err := testInstance.Process(&metadata.Service{}, obj)
assert.NoError(t, err)
assert.True(t, processed)
var buf bytes.Buffer
err = template.Write(&buf)
assert.NoError(t, err)
out := buf.String()
assert.NotContains(t, out, "app.kubernetes.io/name: platform-operator")
assert.NotContains(t, out, "matchLabels: {}")
assert.Contains(t, out, "matchLabels:\n {{- include \".selectorLabels\" . | nindent 6 }}")
assert.Contains(t, out, "labels:\n {{- include \".selectorLabels\" . | nindent 8 }}")
})
}
30 changes: 22 additions & 8 deletions pkg/processor/deployment/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,12 +93,20 @@ func (d deployment) Process(appMeta helmify.AppMetadata, obj *unstructured.Unstr
return true, nil, err
}

matchLabels, err := yamlformat.Marshal(map[string]interface{}{"matchLabels": depl.Spec.Selector.MatchLabels}, 0)
if err != nil {
return true, nil, err
if depl.Spec.Selector != nil && depl.Spec.Selector.MatchLabels != nil {
delete(depl.Spec.Selector.MatchLabels, "app.kubernetes.io/name")
}
var matchLabels string
if depl.Spec.Selector != nil && len(depl.Spec.Selector.MatchLabels) > 0 {
matchLabels, err = yamlformat.Marshal(map[string]interface{}{"matchLabels": depl.Spec.Selector.MatchLabels}, 0)
if err != nil {
return true, nil, err
}
} else {
matchLabels = "matchLabels:"
}
matchExpr := ""
if depl.Spec.Selector.MatchExpressions != nil {
if depl.Spec.Selector != nil && depl.Spec.Selector.MatchExpressions != nil {
matchExpr, err = yamlformat.Marshal(map[string]interface{}{"matchExpressions": depl.Spec.Selector.MatchExpressions}, 0)
if err != nil {
return true, nil, err
Expand All @@ -108,11 +116,17 @@ func (d deployment) Process(appMeta helmify.AppMetadata, obj *unstructured.Unstr
selector = strings.Trim(selector, " \n")
selector = string(yamlformat.Indent([]byte(selector), 4))

podLabels, err := yamlformat.Marshal(depl.Spec.Template.ObjectMeta.Labels, 8)
if err != nil {
return true, nil, err
delete(depl.Spec.Template.ObjectMeta.Labels, "app.kubernetes.io/name")
var podLabels string
if len(depl.Spec.Template.ObjectMeta.Labels) > 0 {
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())
} else {
podLabels = fmt.Sprintf(" {{- include \"%s.selectorLabels\" . | nindent 8 }}", appMeta.ChartName())
}
podLabels += fmt.Sprintf("\n {{- include \"%s.selectorLabels\" . | nindent 8 }}", appMeta.ChartName())

podAnnotations := ""
if len(depl.Spec.Template.ObjectMeta.Annotations) != 0 {
Expand Down
70 changes: 70 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 @@ -135,6 +136,75 @@ func Test_deployment_Process(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, false, processed)
})

t.Run("processed with duplicate app.kubernetes.io/name in selector and pod labels", func(t *testing.T) {
const deplWithDuplicateYaml = `apiVersion: apps/v1
kind: Deployment
metadata:
name: platform-operator
labels:
app.kubernetes.io/name: platform-operator
control-plane: controller-manager
spec:
selector:
matchLabels:
app.kubernetes.io/name: platform-operator
control-plane: controller-manager
template:
metadata:
labels:
app.kubernetes.io/name: platform-operator
control-plane: controller-manager
spec:
containers:
- name: manager
image: controller:latest`
obj := internal.GenerateObj(deplWithDuplicateYaml)
processed, template, err := testInstance.Process(&metadata.Service{}, obj)
assert.NoError(t, err)
assert.True(t, processed)
var buf bytes.Buffer
err = template.Write(&buf)
assert.NoError(t, err)
out := buf.String()
assert.NotContains(t, out, "app.kubernetes.io/name: platform-operator")
assert.Contains(t, out, "control-plane: controller-manager")
assert.Contains(t, out, `{{- include ".selectorLabels" . | nindent 6 }}`)
assert.Contains(t, out, `{{- include ".selectorLabels" . | nindent 8 }}`)
})

t.Run("processed with only app.kubernetes.io/name in selector and pod labels", func(t *testing.T) {
const deplOnlyNameYaml = `apiVersion: apps/v1
kind: Deployment
metadata:
name: platform-operator
labels:
app.kubernetes.io/name: platform-operator
spec:
selector:
matchLabels:
app.kubernetes.io/name: platform-operator
template:
metadata:
labels:
app.kubernetes.io/name: platform-operator
spec:
containers:
- name: manager
image: controller:latest`
obj := internal.GenerateObj(deplOnlyNameYaml)
processed, template, err := testInstance.Process(&metadata.Service{}, obj)
assert.NoError(t, err)
assert.True(t, processed)
var buf bytes.Buffer
err = template.Write(&buf)
assert.NoError(t, err)
out := buf.String()
assert.NotContains(t, out, "app.kubernetes.io/name: platform-operator")
assert.NotContains(t, out, "matchLabels: {}")
assert.Contains(t, out, "matchLabels:\n {{- include \".selectorLabels\" . | nindent 6 }}")
assert.Contains(t, out, "labels:\n {{- include \".selectorLabels\" . | nindent 8 }}")
})
}

var singleQuotesTest = []struct {
Expand Down
14 changes: 11 additions & 3 deletions pkg/processor/poddisruptionbudget/pdb.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,17 @@ func (r pdb) Process(appMeta helmify.AppMetadata, obj *unstructured.Unstructured
name := appMeta.TrimName(obj.GetName())
nameCamel := strcase.ToLowerCamel(name)

selector, _ := yaml.Marshal(pdb.Spec.Selector)
selector = yamlformat.Indent(selector, 4)
selector = bytes.TrimRight(selector, "\n ")
if pdb.Spec.Selector != nil && pdb.Spec.Selector.MatchLabels != nil {
delete(pdb.Spec.Selector.MatchLabels, "app.kubernetes.io/name")
}
var selector string
if pdb.Spec.Selector == nil || (len(pdb.Spec.Selector.MatchLabels) == 0 && len(pdb.Spec.Selector.MatchExpressions) == 0) {
selector = " matchLabels:"
} else {
s, _ := yaml.Marshal(pdb.Spec.Selector)
s = yamlformat.Indent(s, 4)
selector = string(bytes.TrimRight(s, "\n "))
}

if spec.MaxUnavailable != nil {
_, err := values.Add(spec.MaxUnavailable.IntValue(), nameCamel, "maxUnavailable")
Expand Down
Loading