helm test revert (+1 squashed commits) (#931)

Squashed commits:

[36ca93235] actually finish echo command (+8 squashed commit)

Squashed commit:

[27c3e9d63] fix typo

[8daa4395e] use name not a derivitive

[d8a24b1d8] force a testrun

[edacc59e4] give more perms

[9706a9860] bump

[09f9d9f4e] Code thining on common

[8adfddf2b] try moving autopermissions to initcontainer

[42c7f76a4] fix: have autopermissions use command instead of arg
This commit is contained in:
Kjeld Schouten-Lebbing
2021-09-08 22:14:04 +02:00
committed by GitHub
parent b94d3c0d0f
commit 0aa2131b28
6 changed files with 42 additions and 307 deletions

View File

@@ -18,4 +18,4 @@ maintainers:
name: common
sources: null
type: library
version: 6.13.8
version: 6.13.9

View File

@@ -38,8 +38,6 @@ Main entrypoint for the common library chart. It will render all underlying temp
{{ include "common.configmap.portal" . | nindent 0 }}
{{ include "common.job.mountPermissions" . | nindent 0 }}
{{ include "common.networkpolicy" . | nindent 0 }}
{{- end -}}

View File

@@ -1,83 +0,0 @@
{{/*
This template serves as the blueprint for the mountPermissions job that is run
before chart installation.
*/}}
{{- define "common.job.mountPermissions" -}}
{{- if .Values.persistence -}}
{{- $jobName := include "common.names.fullname" . -}}
{{- $group := 568 -}}
{{- if .Values.env -}}
{{- $group = dig "PGID" $group .Values.env -}}
{{- end -}}
{{- $group = dig "fsGroup" $group .Values.podSecurityContext -}}
{{- $hostPathMounts := dict -}}
{{- range $name, $mount := .Values.persistence -}}
{{- if and $mount.enabled $mount.setPermissions -}}
{{- $name = default ( $name| toString ) $mount.name -}}
{{- $_ := set $hostPathMounts $name $mount -}}
{{- end -}}
{{- end }}
{{- if $hostPathMounts -}}
---
apiVersion: batch/v1
kind: Job
metadata:
name: {{ printf "%s-auto-permissions" $jobName }}
labels:
{{- include "common.labels" . | nindent 4 }}
annotations:
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-weight": "-10"
"helm.sh/hook-delete-policy": hook-succeeded,hook-failed,before-hook-creation
spec:
template:
metadata:
spec:
restartPolicy: Never
containers:
- name: set-mount-permissions
image: alpine:3.3
command: ["/bin/sh", "-c"]
args:
{{- range $_, $hpm := $hostPathMounts }}
- chown -R {{ printf ":%d %s" (int $group) ( $hpm.mountPath | squote ) }}
- chmod -R g+w {{ $hpm.mountPath | squote }}
{{- end }}
volumeMounts:
{{- range $name, $hpm := $hostPathMounts }}
- name: {{ printf "hostpathmounts-%s" $name }}
mountPath: {{ $hpm.mountPath }}
{{- if $hpm.subPath }}
subPath: {{ $hpm.subPath }}
{{- end }}
{{- end }}
volumes:
{{- range $name, $hpm := $hostPathMounts }}
- name: {{ printf "hostpathmounts-%s" $name }}
{{- /* Always prefer an emptyDir next if that is set */}}
{{- $emptyDir := false -}}
{{- if $hpm.emptyDir -}}
{{- if $hpm.emptyDir.enabled -}}
{{- $emptyDir = true -}}
{{- end -}}
{{- end -}}
{{- if $emptyDir }}
{{- if or $hpm.emptyDir.medium $hpm.emptyDir.sizeLimit }}
emptyDir:
{{- with $hpm.emptyDir.medium }}
medium: "{{ . }}"
{{- end }}
{{- with $hpm.emptyDir.sizeLimit }}
sizeLimit: "{{ . }}"
{{- end }}
{{- else }}
emptyDir: {}
{{- end }}
{{- else }}
hostPath:
path: {{ required "hostPath not set" $hpm.hostPath }}
{{ end }}
{{- end }}
{{- end -}}
{{- end -}}
{{- end -}}

View File

@@ -0,0 +1,39 @@
{{/*
This template serves as the blueprint for the mountPermissions job that is run
before chart installation.
*/}}
{{- define "common.controller.autopermissions" -}}
{{- $group := 568 -}}
{{- if .Values.env -}}
{{- $group = dig "PGID" $group .Values.env -}}
{{- end -}}
{{- $group = dig "fsGroup" $group .Values.podSecurityContext -}}
{{- $hostPathMounts := dict -}}
{{- range $name, $mount := .Values.persistence -}}
{{- if and $mount.enabled $mount.setPermissions -}}
{{- $name = default ( $name| toString ) $mount.name -}}
{{- $_ := set $hostPathMounts $name $mount -}}
{{- end -}}
{{- end }}
- name: autopermissions
image: alpine:3.3
securityContext:
allowPrivilegeEscalation: false
runAsUser: 0
runAsGroup: 0
privileged: true
allowPrivilegeEscalation: true
command:
- "/bin/sh"
- "-c"
- "echo 'Automatically correcting permissions...';{{ range $_, $hpm := $hostPathMounts }}chown -R {{ $group }} {{ $hpm.mountPath | squote }}; chmod -R g+w {{ $hpm.mountPath | squote }};{{ end }}"
volumeMounts:
{{- range $name, $hpm := $hostPathMounts }}
- name: {{ $name }}
mountPath: {{ $hpm.mountPath }}
{{- if $hpm.subPath }}
subPath: {{ $hpm.subPath }}
{{- end }}
{{- end }}
{{- end -}}

View File

@@ -38,8 +38,9 @@ enableServiceLinks: {{ .Values.enableServiceLinks }}
{{- with .Values.termination.gracePeriodSeconds }}
terminationGracePeriodSeconds: {{ . }}
{{- end }}
{{- with .Values.initContainers }}
initContainers:
{{- include "common.controller.autopermissions" . | nindent 2 }}
{{- with .Values.initContainers }}
{{- toYaml . | nindent 2 }}
{{- end }}
containers:

View File

@@ -1,220 +0,0 @@
package common
import (
"testing"
"github.com/truecharts/apps/tests/helmunit"
"github.com/stretchr/testify/suite"
)
type PermissionsJobTestSuite struct {
suite.Suite
Chart helmunit.HelmChart
}
func (suite *PermissionsJobTestSuite) SetupSuite() {
suite.Chart = helmunit.New("common-test", "../../common-test")
suite.Chart.UpdateDependencies()
}
// We need this function to kick off the test suite, otherwise
// "go test" won't know about our tests
func TestPermissionsJob(t *testing.T) {
suite.Run(t, new(PermissionsJobTestSuite))
}
func (suite *PermissionsJobTestSuite) TestPresence() {
tests := map[string]struct {
values []string
expectedJob bool
}{
"Default": {
values: nil,
expectedJob: false,
},
"WithHostPathMount": {
values: []string{
"persistenceList[0].name=data",
"persistenceList[0].type=hostPath",
"persistenceList[0].enabled=true",
"persistenceList[0].mountPath=/data",
"persistenceList[0].setPermissions=true",
"persistenceList[0].hostPath=/tmp",
},
expectedJob: true,
},
}
for name, tc := range tests {
suite.Suite.Run(name, func() {
err := suite.Chart.Render(nil, tc.values, nil)
if err != nil {
suite.FailNow(err.Error())
}
jobManifest := suite.Chart.Hooks.Get("Job", "common-test-auto-permissions")
if tc.expectedJob {
suite.Assertions.NotEmpty(jobManifest)
} else {
suite.Assertions.Empty(jobManifest)
}
})
}
}
func (suite *PermissionsJobTestSuite) TestVolumesAndMounts() {
tests := map[string]struct {
values []string
expectedVolumes []string
}{
"MultiplepersistenceList": {
values: []string{
"persistenceList[0].name=data",
"persistenceList[0].type=hostPath",
"persistenceList[0].enabled=true",
"persistenceList[0].setPermissions=true",
"persistenceList[0].mountPath=/data",
"persistenceList[0].hostPath=/tmp",
"persistenceList[1].name=config",
"persistenceList[1].type=hostPath",
"persistenceList[1].enabled=true",
"persistenceList[1].setPermissions=true",
"persistenceList[1].mountPath=/config",
"persistenceList[1].hostPath=/tmp",
},
expectedVolumes: []string{"hostpathmounts-config", "hostpathmounts-data"},
},
}
for name, tc := range tests {
suite.Suite.Run(name, func() {
err := suite.Chart.Render(nil, tc.values, nil)
if err != nil {
suite.FailNow(err.Error())
}
jobManifest := suite.Chart.Hooks.Get("Job", "common-test-auto-permissions")
suite.Assertions.NotEmpty(jobManifest)
jobVolumes, _ := jobManifest.Path("spec.template.spec.volumes").Search("name").Children()
containers, _ := jobManifest.Path("spec.template.spec.containers").Children()
jobVolumeMounts, _ := containers[0].Path("volumeMounts").Search("name").Children()
if tc.expectedVolumes != nil {
actualVolumes := []string{}
actualVolumeMounts := []string{}
for _, v := range jobVolumes {
actualVolumes = append(actualVolumes, v.Data().(string))
}
for _, v := range jobVolumeMounts {
actualVolumeMounts = append(actualVolumeMounts, v.Data().(string))
}
suite.Assertions.EqualValues(tc.expectedVolumes, actualVolumeMounts)
suite.Assertions.EqualValues(tc.expectedVolumes, actualVolumes)
} else {
suite.Assertions.Empty(jobVolumes)
}
})
}
}
func (suite *PermissionsJobTestSuite) TestCommand() {
baseValues := []string{
"persistenceList[0].name=data",
"persistenceList[0].type=hostPath",
"persistenceList[0].enabled=true",
"persistenceList[0].setPermissions=true",
"persistenceList[0].mountPath=/data",
"persistenceList[0].hostPath=/tmp",
"persistenceList[1].name=config",
"persistenceList[1].type=hostPath",
"persistenceList[1].enabled=true",
"persistenceList[1].setPermissions=true",
"persistenceList[1].mountPath=/config",
"persistenceList[1].hostPath=/tmp",
}
tests := map[string]struct {
values []string
expectedCommand []string
expectedArgs []string
}{
"DefaultPermissionsForMultipleMounts": {
values: baseValues,
expectedCommand: []string{
"/bin/sh", "-c",
},
expectedArgs: []string{
"chown -R :568 '/config'", "chown -R :568 '/data'",
},
},
"DefaultPermissionsForDisabledpodSecurityContext": {
values: append(baseValues,
"podSecurityContext.allowPrivilegeEscalation=false",
),
expectedCommand: []string{
"/bin/sh", "-c",
},
expectedArgs: []string{
"chown -R :568 '/config'", "chown -R :568 '/data'",
},
},
"PermissionsForFsGroup": {
values: append(baseValues,
"podSecurityContext.fsGroup=666",
),
expectedCommand: []string{
"/bin/sh", "-c",
},
expectedArgs: []string{
"chown -R :666 '/config'", "chown -R :666 '/data'",
},
},
"PermissionsForPgid": {
values: append(baseValues,
"env.PGID=666",
),
expectedCommand: []string{
"/bin/sh", "-c",
},
expectedArgs: []string{
"chown -R :666 '/config'", "chown -R :666 '/data'",
},
},
}
for name, tc := range tests {
suite.Suite.Run(name, func() {
err := suite.Chart.Render(nil, tc.values, nil)
if err != nil {
suite.FailNow(err.Error())
}
jobManifest := suite.Chart.Hooks.Get("Job", "common-test-auto-permissions")
suite.Assertions.NotEmpty(jobManifest)
containers, _ := jobManifest.Path("spec.template.spec.containers").Children()
command, _ := containers[0].Path("command").Children()
args, _ := containers[0].Path("args").Children()
if tc.expectedCommand != nil {
actualCommand := []string{}
for _, v := range command {
actualCommand = append(actualCommand, v.Data().(string))
}
suite.Assertions.EqualValues(tc.expectedCommand, actualCommand)
} else {
suite.Assertions.Empty(command)
}
if tc.expectedArgs != nil {
actualArgs := []string{}
for _, v := range args {
actualArgs = append(actualArgs, v.Data().(string))
}
suite.Assertions.EqualValues(tc.expectedArgs, actualArgs)
} else {
suite.Assertions.Empty(args)
}
})
}
}