Port recent KAH changes (#548)

* port 3.0.1 fixes from KAH

* more naming fixes ported from kah

* port all latest KAH fixes

* port new tests from KAH

* Polishing and fixes

* update common-test version
This commit is contained in:
Kjeld Schouten-Lebbing
2021-06-10 23:52:55 +02:00
committed by GitHub
parent c5d49155d5
commit 3ecc210d6b
23 changed files with 712 additions and 757 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
apiVersion: v2
kubeVersion: ">=1.16.0-0"
name: common-test
version: 3.0.3
version: 3.0.4
# upstream_version:
appVersion: none
description: Helper chart to test different use cases of the common library
@@ -1,12 +0,0 @@
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: ingressroutes.traefik.containo.us
spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: IngressRoute
plural: ingressroutes
singular: ingressroute
scope: Namespaced
@@ -1,12 +0,0 @@
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: ingressroutetcps.traefik.containo.us
spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: IngressRouteTCP
plural: ingressroutetcps
singular: ingressroutetcp
scope: Namespaced
@@ -1,13 +0,0 @@
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: ingressrouteudps.traefik.containo.us
spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: IngressRouteUDP
plural: ingressrouteudps
singular: ingressrouteudp
scope: Namespaced
@@ -1,12 +0,0 @@
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: middlewares.traefik.containo.us
spec:
group: traefik.containo.us
version: v1alpha1
names:
kind: Middleware
plural: middlewares
singular: middleware
scope: Namespaced
+1 -1
View File
@@ -18,4 +18,4 @@ maintainers:
name: common
sources:
type: library
version: 5.1.3
version: 6.0.0
@@ -32,6 +32,9 @@ spec:
{{- end }}
labels:
{{- include "common.labels.selectorLabels" . | nindent 8 }}
{{- with .Values.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- include "common.controller.pod" . | nindent 6 }}
{{- end }}
@@ -50,6 +50,9 @@ spec:
{{- end }}
labels:
{{- include "common.labels.selectorLabels" . | nindent 8 }}
{{- with .Values.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- include "common.controller.pod" . | nindent 6 }}
{{- end }}
+13 -28
View File
@@ -1,36 +1,21 @@
{{/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
`SPDX-License-Identifier: Apache-2.0`
This file is considered to be modified by the TrueCharts Project.
*/}}
{{/*
Renders the PersistentVolumeClaim objects required by the chart by returning a concatinated list
of all the entries of the persistence key.
Renders the Persistent Volume Claim objects required by the chart.
*/}}
{{- define "common.pvc" -}}
{{- $perDict := dict }}
{{- range $index, $item := .Values.persistenceList -}}
{{- $name := ( printf "list-%s" ( $index | toString ) ) }}
{{- if $item.name }}
{{- $name = $item.name }}
{{- end }}
{{- $_ := set $perDict $name $item }}
{{- end }}
{{- $per := merge .Values.persistence $perDict }}
{{- $_ := set .Values "persistence" (deepCopy $per) -}}
{{- /* Generate pvc as required */ -}}
{{- range $index, $PVC := .Values.persistence }}
{{- $emptyDir := false -}}
{{- if $PVC.emptyDir -}}
{{- if $PVC.emptyDir.enabled -}}
{{- $emptyDir = true -}}
{{- end -}}
{{- end -}}
{{- if and $PVC.enabled (not (or $emptyDir $PVC.existingClaim)) -}}
{{- if and $PVC.enabled (eq (default "pvc" $PVC.type) "pvc") (not $PVC.existingClaim) -}}
{{- $persistenceValues := $PVC -}}
{{- if not $persistenceValues.nameOverride -}}
{{- $_ := set $persistenceValues "nameOverride" $index -}}
@@ -1,21 +1,3 @@
{{/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
`SPDX-License-Identifier: Apache-2.0`
This file is considered to be modified by the TrueCharts Project.
*/}}
{{/*
This template serves as the blueprint for the StatefulSet objects that are created
within the common library.
@@ -31,9 +13,8 @@ metadata:
{{- with .Values.controller.labels }}
{{- toYaml . | nindent 4 }}
{{- end }}
annotations:
{{- include "common.annotations.workload" . | nindent 4 }}
{{- with .Values.controller.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
@@ -55,13 +36,15 @@ spec:
serviceName: {{ include "common.names.fullname" . }}
template:
metadata:
annotations:
{{- include "common.annotations.workload.spec" . | nindent 8 }}
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "common.labels.selectorLabels" . | nindent 8 }}
{{- with .Values.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- include "common.controller.pod" . | nindent 6 }}
volumeClaimTemplates:
@@ -3,25 +3,24 @@ This template serves as the blueprint for the mountPermissions job that is run
before chart installation.
*/}}
{{- define "common.class.mountPermissions" -}}
{{- if .Values.hostPathMounts -}}
{{- if .Values.persistence -}}
{{- $jobName := include "common.names.fullname" . -}}
{{- $user := 568 -}}
{{- $group := 568 -}}
{{- if .Values.env -}}
{{- $user = dig "PUID" $user .Values.env -}}
{{- $user = dig "PUID" $user .Values.env -}}
{{- $group = dig "PGID" $group .Values.env -}}
{{- end -}}
{{- $user = dig "runAsUser" $user .Values.podSecurityContext -}}
{{- $group := 568 -}}
{{- if and .Values.env -}}
{{- $group = dig "PGID" $group .Values.env -}}
{{- end -}}
{{- $group = dig "fsGroup" $group .Values.podSecurityContext -}}
{{- $hostPathMounts := dict -}}
{{- range $name, $mount := .Values.hostPathMounts -}}
{{- 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
@@ -83,6 +82,6 @@ spec:
path: {{ required "hostPath not set" $hpm.hostPath }}
{{ end }}
{{- end }}
{{- end -}}
{{- end -}}
{{- end -}}
@@ -1,21 +1,3 @@
{{/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
`SPDX-License-Identifier: Apache-2.0`
This file is considered to be modified by the TrueCharts Project.
*/}}
{{/*
This template serves as a blueprint for all PersistentVolumeClaim objects that are created
within the common library.
@@ -58,4 +40,7 @@ spec:
{{- if $values.storageClass }}
storageClassName: {{ if (eq "-" $values.storageClass) }}""{{- else if (eq "SCALE-ZFS" $values.storageClass ) }}{{ ( printf "%v-%v" "ix-storage-class" .Release.Name ) }}{{- else }}{{ $values.storageClass | quote }}{{- end }}
{{- end }}
{{- if $values.volumeName }}
volumeName: {{ $values.volumeName | quote }}
{{- end }}
{{- end -}}
@@ -1,21 +1,3 @@
{{/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
`SPDX-License-Identifier: Apache-2.0`
This file is considered to be modified by the TrueCharts Project.
*/}}
{{/*
This template serves as a blueprint for all Service objects that are created
within the common library.
@@ -1,21 +1,3 @@
{{/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
`SPDX-License-Identifier: Apache-2.0`
This file is considered to be modified by the TrueCharts Project.
*/}}
{{/*
Return the name of the primary port for a given Service object.
*/}}
@@ -1,24 +1,10 @@
{{/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
`SPDX-License-Identifier: Apache-2.0`
This file is considered to be modified by the TrueCharts Project.
*/}}
{{/* Expand the name of the chart */}}
{{- define "common.names.name" -}}
{{- default .Chart.Name (default .Values.nameOverride .Values.global.nameOverride) | trunc 63 | trimSuffix "-" -}}
{{- $globalNameOverride := "" -}}
{{- if hasKey .Values "global" -}}
{{- $globalNameOverride = (default $globalNameOverride .Values.global.nameOverride) -}}
{{- end -}}
{{- default .Chart.Name (default .Values.nameOverride $globalNameOverride) | trunc 63 | trimSuffix "-" -}}
{{- end -}}
{{/*
@@ -28,13 +14,17 @@ If release name contains chart name it will be used as a full name.
*/}}
{{- define "common.names.fullname" -}}
{{- $name := include "common.names.name" . -}}
{{- if or .Values.fullnameOverride .Values.global.fullnameOverride -}}
{{- $name = default .Values.fullnameOverride .Values.global.fullnameOverride -}}
{{- $globalFullNameOverride := "" -}}
{{- if hasKey .Values "global" -}}
{{- $globalFullNameOverride = (default $globalFullNameOverride .Values.global.fullnameOverride) -}}
{{- end -}}
{{- if or .Values.fullnameOverride $globalFullNameOverride -}}
{{- $name = default .Values.fullnameOverride $globalFullNameOverride -}}
{{- else -}}
{{- if contains $name .Release.Name -}}
{{- $name := .Release.Name -}}
{{- $name = .Release.Name -}}
{{- else -}}
{{- $name := printf "%s-%s" .Release.Name $name -}}
{{- $name = printf "%s-%s" .Release.Name $name -}}
{{- end -}}
{{- end -}}
{{- trunc 63 $name | trimSuffix "-" -}}
@@ -1,22 +1,3 @@
{{/*
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
`SPDX-License-Identifier: Apache-2.0`
This file is considered to be modified by the TrueCharts Project.
*/}}
{{/*
Probes selection logic.
*/}}
@@ -1,34 +1,25 @@
{{/* Volumes included by the controller */}}
{{- define "common.controller.volumeMounts" -}}
{{- range $index, $PVC := .Values.persistence }}
{{- if $PVC.enabled }}
- mountPath: {{ $PVC.mountPath | default (printf "/%v" $index) }}
{{- range $index, $item := .Values.persistence }}
{{- $mountPath := (printf "/%v" $index) -}}
{{- if eq "hostPath" (default "pvc" $item.type) -}}
{{- $mountPath = $item.hostPath -}}
{{- end -}}
{{- with $item.mountPath -}}
{{- $mountPath = . -}}
{{- end }}
{{- if and $item.enabled (ne $mountPath "-") }}
- mountPath: {{ $mountPath }}
name: {{ $index }}
{{- if $PVC.subPath }}
subPath: {{ $PVC.subPath }}
{{- with $item.subPath }}
subPath: {{ . }}
{{- end }}
{{- with $item.readOnly }}
readOnly: {{ . }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Creates mountpoints to mount devices directly to the same path inside the container
*/}}
{{ range $name, $dmm := .Values.deviceMounts }}
{{- if $dmm.enabled -}}
{{ if $dmm.name }}
{{ $name = $dmm.name }}
{{ end }}
- name: devicemount-{{ $name }}
mountPath: {{ $dmm.devicePath }}
{{ if $dmm.subPath }}
subPath: {{ $dmm.subPath }}
{{ end }}
{{- end -}}
{{ end }}
{{- if .Values.additionalVolumeMounts }}
{{- toYaml .Values.additionalVolumeMounts | nindent 0 }}
{{- end }}
{{- if eq .Values.controller.type "statefulset" }}
{{- range $index, $vct := .Values.volumeClaimTemplates }}
- mountPath: {{ $vct.mountPath }}
@@ -39,18 +30,4 @@ Creates mountpoints to mount devices directly to the same path inside the contai
{{- end }}
{{- end }}
{{/* Creates mountpoints to mount hostPaths directly to the container */}}
{{- range $name, $hpm := .Values.hostPathMounts }}
{{- if $hpm.enabled }}
{{- $name = default $name $hpm.name }}
- name: hostpathmounts-{{ $name }}
mountPath: {{ $hpm.mountPath }}
{{- if $hpm.subPath }}
subPath: {{ $hpm.subPath }}
{{- end }}
{{- if $hpm.readOnly }}
readOnly: {{ $hpm.readOnly }}
{{- end }}
{{- end }}
{{ end }}
{{- end -}}
@@ -5,98 +5,43 @@ Volumes included by the controller.
{{- range $index, $persistence := .Values.persistence }}
{{- if $persistence.enabled }}
- name: {{ $index }}
{{- if $persistence.existingClaim }}
{{- /* Always prefer an existingClaim if that is set */}}
persistentVolumeClaim:
claimName: {{ $persistence.existingClaim }}
{{- else -}}
{{- /* Always prefer an emptyDir next if that is set */}}
{{- $emptyDir := false -}}
{{- if $persistence.emptyDir -}}
{{- if $persistence.emptyDir.enabled -}}
{{- $emptyDir = true -}}
{{- end -}}
{{- end -}}
{{- if $emptyDir }}
{{- if or $persistence.emptyDir.medium $persistence.emptyDir.sizeLimit }}
emptyDir:
{{- with $persistence.emptyDir.medium }}
medium: "{{ . }}"
{{- if eq (default "pvc" $persistence.type) "pvc" }}
{{- $pvcName := (include "common.names.fullname" $) -}}
{{- if $persistence.existingClaim }}
{{- /* Always prefer an existingClaim if that is set */}}
{{- $pvcName = $persistence.existingClaim -}}
{{- else -}}
{{- /* Otherwise refer to the PVC name */}}
{{- if $persistence.nameOverride -}}
{{- if not (eq $persistence.nameOverride "-") -}}
{{- $pvcName = (printf "%s-%s" (include "common.names.fullname" $) $persistence.nameOverride) -}}
{{- end -}}
{{- else -}}
{{- $pvcName = (printf "%s-%s" (include "common.names.fullname" $) $index) -}}
{{- end -}}
{{- end }}
{{- with $persistence.emptyDir.sizeLimit }}
sizeLimit: "{{ . }}"
{{- end }}
{{- else }}
emptyDir: {}
{{- end }}
{{- else -}}
{{- /* Otherwise refer to the PVC name */}}
{{- $pvcName := (include "common.names.fullname" $) -}}
{{- if $persistence.nameOverride -}}
{{- if not (eq $persistence.nameOverride "-") -}}
{{- $pvcName = (printf "%s-%s" (include "common.names.fullname" $) $persistence.nameOverride) -}}
{{- end -}}
{{- else -}}
{{- $pvcName = (printf "%s-%s" (include "common.names.fullname" $) $index) -}}
{{- end }}
persistentVolumeClaim:
claimName: {{ $pvcName }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
{{- if .Values.additionalVolumes }}
{{- toYaml .Values.additionalVolumes | nindent 0 }}
{{- end }}
{{- range $name, $dm := .Values.deviceMounts -}}
{{ if $dm.enabled }}
{{ if $dm.name }}
{{ $name = $dm.name }}
{{ end }}
- name: devicemount-{{ $name }}
{{ if $dm.emptyDir }}
emptyDir: {}
{{- else -}}
hostPath:
path: {{ required "hostPath not set" $dm.devicePath }}
{{ end }}
{{ end }}
{{- end -}}
{{/*
Creates Volumes for hostPaths which can be directly mounted to a container
*/}}
{{- range $name, $hpm := .Values.hostPathMounts -}}
{{ if $hpm.enabled }}
{{ if $hpm.name }}
{{ $name = $hpm.name }}
{{ end }}
- name: hostpathmounts-{{ $name }}
{{- /* Always prefer an emptyDir next if that is set */}}
{{- $emptyDir := false -}}
{{- if $hpm.emptyDir -}}
{{- if $hpm.emptyDir.enabled -}}
{{- $emptyDir = true -}}
{{- else if eq $persistence.type "emptyDir" }}
{{- $emptyDir := dict -}}
{{- with $persistence.medium -}}
{{- $_ := set $emptyDir "medium" . -}}
{{- end -}}
{{- end -}}
{{- if $emptyDir }}
{{- if or $hpm.emptyDir.medium $hpm.emptyDir.sizeLimit }}
emptyDir:
{{- with $hpm.emptyDir.medium }}
medium: "{{ . }}"
{{- with $persistence.sizeLimit -}}
{{- $_ := set $emptyDir "sizeLimit" . -}}
{{- end }}
{{- with $hpm.emptyDir.sizeLimit }}
sizeLimit: "{{ . }}"
{{- end }}
{{- else }}
emptyDir: {}
{{- end }}
{{- else }}
emptyDir: {{- $emptyDir | toYaml | nindent 4 }}
{{- else if eq $persistence.type "hostPath" }}
hostPath:
path: {{ required "hostPath not set" $hpm.hostPath }}
{{ end }}
{{ end }}
{{- end -}}
{{- end -}}
path: {{ required "hostPath not set" $persistence.hostPath }}
{{- with $persistence.hostPathType }}
type: {{ . }}
{{- end }}
{{- else if eq $persistence.type "custom" }}
{{- toYaml $persistence.volumeSpec | nindent 2 }}
{{- else }}
{{- fail (printf "Not a valid persistence.type (%s)" .Values.persistence.type) }}
{{- end }}
{{- end }}
{{- end }}
{{- end }}
+235 -285
View File
@@ -1,247 +1,243 @@
package common
import (
"testing"
"github.com/stretchr/testify/suite"
"testing"
"github.com/truecharts/apps/tests/helmunit"
"github.com/stretchr/testify/suite"
)
type ContainerTestSuite struct {
suite.Suite
Chart helmunit.HelmChart
suite.Suite
Chart helmunit.HelmChart
}
func (suite *ContainerTestSuite) SetupSuite() {
suite.Chart = helmunit.New("common-test", "../../common-test")
suite.Chart.UpdateDependencies()
suite.Chart.UpdateDependencies()
}
// We need this function to kick off the test suite, otherwise
// "go test" won't know about our tests
func TestContainer(t *testing.T) {
suite.Run(t, new(ContainerTestSuite))
suite.Run(t, new(ContainerTestSuite))
}
func (suite *ContainerTestSuite) TestCommand() {
tests := map[string]struct {
values []string
expectedCommand []string
}{
"Default": {values: nil, expectedCommand: nil},
"SingleString": {values: []string{"command=/bin/sh"}, expectedCommand: []string{"/bin/sh"}},
"StringList": {values: []string{"command={/bin/sh,-c}"}, expectedCommand: []string{"/bin/sh", "-c"}},
}
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())
}
tests := map[string]struct {
values []string
expectedCommand []string
}{
"Default": {values: nil, expectedCommand: nil},
"SingleString": {values: []string{"command=/bin/sh"}, expectedCommand: []string{"/bin/sh"}},
"StringList": {values: []string{"command={/bin/sh,-c}"}, expectedCommand: []string{"/bin/sh", "-c"}},
}
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())
}
deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test")
suite.Assertions.NotEmpty(deploymentManifest)
containers, _ := deploymentManifest.Path("spec.template.spec.containers").Children()
containerCommand := containers[0].Path("command")
deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test")
suite.Assertions.NotEmpty(deploymentManifest)
containers, _ := deploymentManifest.Path("spec.template.spec.containers").Children()
containerCommand := containers[0].Path("command")
if tc.expectedCommand == nil {
suite.Assertions.Empty(containerCommand)
} else {
var actualDataList []string
actualData, _ := containerCommand.Children()
for _, key := range actualData {
actualDataList = append(actualDataList, key.Data().(string))
}
suite.Assertions.EqualValues(tc.expectedCommand, actualDataList)
}
})
}
if tc.expectedCommand == nil {
suite.Assertions.Empty(containerCommand)
} else {
var actualDataList []string
actualData, _ := containerCommand.Children()
for _, key := range actualData {
actualDataList = append(actualDataList, key.Data().(string))
}
suite.Assertions.EqualValues(tc.expectedCommand, actualDataList)
}
})
}
}
func (suite *ContainerTestSuite) TestArgs() {
tests := map[string]struct {
values []string
expectedArgs []string
}{
"Default": {values: nil, expectedArgs: nil},
"SingleString": {values: []string{"args=sleep infinity"}, expectedArgs: []string{"sleep infinity"}},
"StringList": {values: []string{"args={sleep,infinity}"}, expectedArgs: []string{"sleep", "infinity"}},
}
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())
}
tests := map[string]struct {
values []string
expectedArgs []string
}{
"Default": {values: nil, expectedArgs: nil},
"SingleString": {values: []string{"args=sleep infinity"}, expectedArgs: []string{"sleep infinity"}},
"StringList": {values: []string{"args={sleep,infinity}"}, expectedArgs: []string{"sleep", "infinity"}},
}
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())
}
deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test")
suite.Assertions.NotEmpty(deploymentManifest)
containers, _ := deploymentManifest.Path("spec.template.spec.containers").Children()
containerArgs := containers[0].Path("args")
deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test")
suite.Assertions.NotEmpty(deploymentManifest)
containers, _ := deploymentManifest.Path("spec.template.spec.containers").Children()
containerArgs := containers[0].Path("args")
if tc.expectedArgs == nil {
suite.Assertions.Empty(containerArgs)
} else {
var actualDataList []string
actualData, _ := containerArgs.Children()
for _, key := range actualData {
actualDataList = append(actualDataList, key.Data().(string))
}
suite.Assertions.EqualValues(tc.expectedArgs, actualDataList)
}
})
}
if tc.expectedArgs == nil {
suite.Assertions.Empty(containerArgs)
} else {
var actualDataList []string
actualData, _ := containerArgs.Children()
for _, key := range actualData {
actualDataList = append(actualDataList, key.Data().(string))
}
suite.Assertions.EqualValues(tc.expectedArgs, actualDataList)
}
})
}
}
func (suite *ContainerTestSuite) TestEnv() {
tests := map[string]struct {
values []string
expectedEnv map[string]string
}{
"Default": {values: nil, expectedEnv: nil},
"KeyValueString": {values: []string{"env.string=value_of_env"}, expectedEnv: map[string]string{"string": "value_of_env"}},
"KeyValueFloat": {values: []string{"env.float=4.2"}, expectedEnv: map[string]string{"float": "4.2"}},
"KeyValueBool": {values: []string{"env.bool=false"}, expectedEnv: map[string]string{"bool": "false"}},
"KeyValueInt": {values: []string{"env.int=42"}, expectedEnv: map[string]string{"int": "42"}},
"List": {values: []string{"env[0].name=STATIC_ENV_FROM_LIST", "env[0].value=STATIC_ENV_VALUE_FROM_LIST"}, expectedEnv: map[string]string{"STATIC_ENV_FROM_LIST": "STATIC_ENV_VALUE_FROM_LIST"}},
"ValueFrom": {values: []string{"env[0].name=STATIC_ENV_FROM_LIST", "env[0].valueFrom.fieldRef.fieldPath=spec.nodeName"}, expectedEnv: map[string]string{"STATIC_ENV_FROM_LIST": "spec.nodeName"}},
"KeyValue+ExplicitValueFrom": {values: []string{"env.STATIC_ENV=value_of_env", "env.STATIC_ENV_FROM.valueFrom.fieldRef.fieldPath=spec.nodeName"}, expectedEnv: map[string]string{"STATIC_ENV": "value_of_env", "STATIC_ENV_FROM": "spec.nodeName"}},
"ImplicitValueFrom": {values: []string{"env.NODE_NAME.fieldRef.fieldPath=spec.nodeName"}, expectedEnv: map[string]string{"NODE_NAME": "spec.nodeName"}},
"Templated": {values: []string{`env.DYN_ENV=\{\{ .Release.Name \}\}-admin`}, expectedEnv: map[string]string{"DYN_ENV": "common-test-admin"}},
"Mixed": {
values: []string{
`env.DYN_ENV=\{\{ .Release.Name \}\}-admin`,
"env.STATIC_ENV=value_of_env",
"env.STATIC_EXPLICIT_ENV_FROM.valueFrom.fieldRef.fieldPath=spec.nodeName",
"env.STATIC_IMPLICIT_ENV_FROM.fieldRef.fieldPath=spec.nodeName",
},
expectedEnv: map[string]string{
"DYN_ENV": "common-test-admin",
"STATIC_ENV": "value_of_env",
"STATIC_EXPLICIT_ENV_FROM": "spec.nodeName",
"STATIC_IMPLICIT_ENV_FROM": "spec.nodeName",
},
},
}
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())
}
tests := map[string]struct {
values []string
expectedEnv map[string]string
}{
"Default": {values: nil, expectedEnv: nil},
"KeyValueString": {values: []string{"env.string=value_of_env"}, expectedEnv: map[string]string{"string": "value_of_env"}},
"KeyValueFloat": {values: []string{"env.float=4.2"}, expectedEnv: map[string]string{"float": "4.2"}},
"KeyValueBool": {values: []string{"env.bool=false"}, expectedEnv: map[string]string{"bool": "false"}},
"KeyValueInt": {values: []string{"env.int=42"}, expectedEnv: map[string]string{"int": "42"}},
"KeyValue+ExplicitValueFrom": {values: []string{"env.STATIC_ENV=value_of_env", "env.STATIC_ENV_FROM.valueFrom.fieldRef.fieldPath=spec.nodeName"}, expectedEnv: map[string]string{"STATIC_ENV": "value_of_env", "STATIC_ENV_FROM": "spec.nodeName"}},
"ImplicitValueFrom": {values: []string{"env.NODE_NAME.fieldRef.fieldPath=spec.nodeName"}, expectedEnv: map[string]string{"NODE_NAME": "spec.nodeName"}},
"Templated": {values: []string{`env.DYN_ENV=\{\{ .Release.Name \}\}-admin`}, expectedEnv: map[string]string{"DYN_ENV": "common-test-admin"}},
"Mixed": {
values: []string{
`env.DYN_ENV=\{\{ .Release.Name \}\}-admin`,
"env.STATIC_ENV=value_of_env",
"env.STATIC_EXPLICIT_ENV_FROM.valueFrom.fieldRef.fieldPath=spec.nodeName",
"env.STATIC_IMPLICIT_ENV_FROM.fieldRef.fieldPath=spec.nodeName",
},
expectedEnv: map[string]string{
"DYN_ENV": "common-test-admin",
"STATIC_ENV": "value_of_env",
"STATIC_EXPLICIT_ENV_FROM": "spec.nodeName",
"STATIC_IMPLICIT_ENV_FROM": "spec.nodeName",
},
},
}
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())
}
deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test")
suite.Assertions.NotEmpty(deploymentManifest)
containers, _ := deploymentManifest.Path("spec.template.spec.containers").Children()
containerEnv := containers[0].Path("env")
deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test")
suite.Assertions.NotEmpty(deploymentManifest)
containers, _ := deploymentManifest.Path("spec.template.spec.containers").Children()
containerEnv := containers[0].Path("env")
if tc.expectedEnv == nil {
suite.Assertions.Empty(containerEnv)
} else {
actualDataMap := make(map[string]string)
actualData, _ := containerEnv.Children()
for _, value := range actualData {
envVar, _ := value.ChildrenMap()
envName := envVar["name"].Data().(string)
var envValue string
if _, ok := envVar["valueFrom"]; ok {
envValue = value.Path("valueFrom.fieldRef.fieldPath").Data().(string)
} else {
envValue = value.Path("value").Data().(string)
}
actualDataMap[envName] = envValue
}
suite.Assertions.EqualValues(tc.expectedEnv, actualDataMap)
}
})
}
if tc.expectedEnv == nil {
suite.Assertions.Empty(containerEnv)
} else {
actualDataMap := make(map[string]string)
actualData, _ := containerEnv.Children()
for _, value := range actualData {
envVar, _ := value.ChildrenMap()
envName := envVar["name"].Data().(string)
var envValue string
if _, ok := envVar["valueFrom"]; ok {
envValue = value.Path("valueFrom.fieldRef.fieldPath").Data().(string)
} else {
envValue = value.Path("value").Data().(string)
}
actualDataMap[envName] = envValue
}
suite.Assertions.EqualValues(tc.expectedEnv, actualDataMap)
}
})
}
}
func (suite *ContainerTestSuite) TestEnvFrom() {
tests := map[string]struct {
values []string
expectSecret bool
expectedSecretName string
}{
"Default": {values: nil, expectSecret: false, expectedSecretName: ""},
"FromSecret": {values: []string{"secret.STATIC_SECRET=value_of_secret"}, expectSecret: true, expectedSecretName: "common-test"},
}
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())
}
tests := map[string]struct {
values []string
expectSecret bool
expectedSecretName string
}{
"Default": {values: nil, expectSecret: false, expectedSecretName: ""},
"FromSecret": {values: []string{"secret.STATIC_SECRET=value_of_secret"}, expectSecret: true, expectedSecretName: "common-test"},
}
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())
}
secretManifest := suite.Chart.Manifests.Get("Secret", tc.expectedSecretName)
if tc.expectSecret {
suite.Assertions.NotEmpty(secretManifest)
} else {
suite.Assertions.Empty(secretManifest)
}
secretManifest := suite.Chart.Manifests.Get("Secret", tc.expectedSecretName)
if tc.expectSecret {
suite.Assertions.NotEmpty(secretManifest)
} else {
suite.Assertions.Empty(secretManifest)
}
deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test")
suite.Assertions.NotEmpty(deploymentManifest)
deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test")
suite.Assertions.NotEmpty(deploymentManifest)
containers, _ := deploymentManifest.Path("spec.template.spec.containers").Children()
containerEnvFrom, _ := containers[0].Path("envFrom").Children()
containers, _ := deploymentManifest.Path("spec.template.spec.containers").Children()
containerEnvFrom, _ := containers[0].Path("envFrom").Children()
if !tc.expectSecret {
suite.Assertions.Empty(containerEnvFrom)
} else {
suite.Assertions.EqualValues(tc.expectedSecretName, containerEnvFrom[0].Path("secretRef.name").Data().(string))
}
})
}
if !tc.expectSecret {
suite.Assertions.Empty(containerEnvFrom)
} else {
suite.Assertions.EqualValues(tc.expectedSecretName, containerEnvFrom[0].Path("secretRef.name").Data().(string))
}
})
}
}
func (suite *ContainerTestSuite) TestPorts() {
tests := map[string]struct {
values []string
expectedPortName string
expectedPort int
expectedProtocol string
}{
"Default": {values: nil, expectedPortName: "main", expectedPort: 0, expectedProtocol: "TCP"},
"CustomName": {values: []string{"service.main.ports.main.enabled=false", "service.main.ports.server.enabled=true", "service.main.ports.server.port=8080"}, expectedPortName: "server", expectedPort: 8080, expectedProtocol: "TCP"},
"ProtocolHTTP": {values: []string{"service.main.ports.main.protocol=HTTP"}, expectedPortName: "main", expectedPort: 0, expectedProtocol: "TCP"},
"ProtocolHTTPS": {values: []string{"service.main.ports.main.protocol=HTTP"}, expectedPortName: "main", expectedPort: 0, expectedProtocol: "TCP"},
"ProtocolUDP": {values: []string{"service.main.ports.main.protocol=UDP"}, expectedPortName: "main", expectedPort: 0, expectedProtocol: "UDP"},
}
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())
}
tests := map[string]struct {
values []string
expectedPortName string
expectedPort int
expectedProtocol string
}{
"Default": {values: nil, expectedPortName: "main", expectedPort: 0, expectedProtocol: "TCP"},
"CustomName": {values: []string{"service.main.ports.main.enabled=false", "service.main.ports.server.enabled=true", "service.main.ports.server.port=8080"}, expectedPortName: "server", expectedPort: 8080, expectedProtocol: "TCP"},
"ProtocolHTTP": {values: []string{"service.main.ports.main.protocol=HTTP"}, expectedPortName: "main", expectedPort: 0, expectedProtocol: "TCP"},
"ProtocolHTTPS": {values: []string{"service.main.ports.main.protocol=HTTP"}, expectedPortName: "main", expectedPort: 0, expectedProtocol: "TCP"},
"ProtocolUDP": {values: []string{"service.main.ports.main.protocol=UDP"}, expectedPortName: "main", expectedPort: 0, expectedProtocol: "UDP"},
}
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())
}
deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test")
suite.Assertions.NotEmpty(deploymentManifest)
containers, _ := deploymentManifest.Path("spec.template.spec.containers").Children()
containerPorts, _ := containers[0].Path("ports").Children()
suite.Assertions.NotEmpty(containerPorts[0])
suite.Assertions.EqualValues(tc.expectedPortName, containerPorts[0].Path("name").Data())
suite.Assertions.EqualValues(tc.expectedProtocol, containerPorts[0].Path("protocol").Data())
deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test")
suite.Assertions.NotEmpty(deploymentManifest)
containers, _ := deploymentManifest.Path("spec.template.spec.containers").Children()
containerPorts, _ := containers[0].Path("ports").Children()
suite.Assertions.NotEmpty(containerPorts[0])
suite.Assertions.EqualValues(tc.expectedPortName, containerPorts[0].Path("name").Data())
suite.Assertions.EqualValues(tc.expectedProtocol, containerPorts[0].Path("protocol").Data())
if tc.expectedPort == 0 {
suite.Assertions.Empty(containerPorts[0].Path("containerPort").Data())
} else {
suite.Assertions.EqualValues(tc.expectedPort, containerPorts[0].Path("containerPort").Data())
}
})
}
if tc.expectedPort == 0 {
suite.Assertions.Empty(containerPorts[0].Path("containerPort").Data())
} else {
suite.Assertions.EqualValues(tc.expectedPort, containerPorts[0].Path("containerPort").Data())
}
})
}
}
func (suite *ContainerTestSuite) TestPersistenceVolumeMounts() {
values := `
values := `
persistence:
config:
enabled: true
cache:
enabled: true
emptyDir:
enabled: true
type: emptyDir
claimWithCustomMountPath:
enabled: true
mountPath: /custom
@@ -251,102 +247,56 @@ func (suite *ContainerTestSuite) TestPersistenceVolumeMounts() {
enabled: true
existingClaim: myClaim
subPath: "mySubPath"
`
tests := map[string]struct {
values *string
volumeToTest string
expectedMountPath string
expectedSubPath string
}{
"MountWithoutMountPath": {values: &values, volumeToTest: "config", expectedMountPath: "/config"},
"EmptyDir": {values: &values, volumeToTest: "cache", expectedMountPath: "/cache"},
"MountWithCustomMountPath": {values: &values, volumeToTest: "claimWithCustomMountPath", expectedMountPath: "/custom"},
"MountWithSubPath": {values: &values, volumeToTest: "claimWithSubPath", expectedMountPath: "/claimWithSubPath", expectedSubPath: "mySubPath"},
}
for name, tc := range tests {
suite.Suite.Run(name, func() {
err := suite.Chart.Render(nil, nil, tc.values)
if err != nil {
suite.FailNow(err.Error())
}
deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test")
suite.Assertions.NotEmpty(deploymentManifest)
containers, _ := deploymentManifest.Path("spec.template.spec.containers").Children()
containerVolumeMounts, _ := containers[0].Path("volumeMounts").Children()
suite.Assertions.NotEmpty(containerVolumeMounts)
for _, volumeMount := range containerVolumeMounts {
volumeMountName := volumeMount.Path("name").Data().(string)
if volumeMountName == tc.volumeToTest {
suite.Assertions.EqualValues(tc.expectedMountPath, volumeMount.Path("mountPath").Data())
if tc.expectedSubPath == "" {
suite.Assertions.Empty(volumeMount.Path("subPath").Data())
} else {
suite.Assertions.EqualValues(tc.expectedSubPath, volumeMount.Path("subPath").Data())
}
break
}
}
})
}
}
func (suite *ContainerTestSuite) TestPersistenceHostpathMounts() {
values := `
hostPathMounts:
- name: data
enabled: true
mountPath: /data
hostPath: /tmp
- name: config
enabled: true
hostPath: /tmp
mountPath: /config
subPath: mySubPath
- name: cache
enabled: true
mountPath: /cache
emptyDir:
hostpath-data:
enabled: true
type: hostPath
mountPath: /data
hostPath: /tmp
hostpath-dev:
enabled: true
type: hostPath
hostPath: /dev
subPath: mySubPath
`
tests := map[string]struct {
values *string
volumeToTest string
expectedMountPath string
expectedSubPath string
}{
"EmptyDir": {values: &values, volumeToTest: "cache", expectedMountPath: "/cache"},
"WithMountPath": {values: &values, volumeToTest: "hostpathmounts-data", expectedMountPath: "/data"},
"WithSubPath": {values: &values, volumeToTest: "hostpathmounts-config", expectedMountPath: "/config", expectedSubPath: "mySubPath"},
}
for name, tc := range tests {
suite.Suite.Run(name, func() {
err := suite.Chart.Render(nil, nil, tc.values)
if err != nil {
suite.FailNow(err.Error())
}
tests := map[string]struct {
values *string
volumeToTest string
expectedMountPath string
expectedSubPath string
}{
"MountWithoutMountPath": {values: &values, volumeToTest: "config", expectedMountPath: "/config"},
"EmptyDir": {values: &values, volumeToTest: "cache", expectedMountPath: "/cache"},
"MountWithCustomMountPath": {values: &values, volumeToTest: "claimWithCustomMountPath", expectedMountPath: "/custom"},
"MountWithSubPath": {values: &values, volumeToTest: "claimWithSubPath", expectedMountPath: "/claimWithSubPath", expectedSubPath: "mySubPath"},
"HostPathMount": {values: &values, volumeToTest: "hostpath-data", expectedMountPath: "/data"},
"HostPathMountWithSubPath": {values: &values, volumeToTest: "hostpath-dev", expectedMountPath: "/dev", expectedSubPath: "mySubPath"},
}
for name, tc := range tests {
suite.Suite.Run(name, func() {
err := suite.Chart.Render(nil, nil, tc.values)
if err != nil {
suite.FailNow(err.Error())
}
deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test")
suite.Assertions.NotEmpty(deploymentManifest)
containers, _ := deploymentManifest.Path("spec.template.spec.containers").Children()
containerVolumeMounts, _ := containers[0].Path("volumeMounts").Children()
suite.Assertions.NotEmpty(containerVolumeMounts)
deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test")
suite.Assertions.NotEmpty(deploymentManifest)
containers, _ := deploymentManifest.Path("spec.template.spec.containers").Children()
containerVolumeMounts, _ := containers[0].Path("volumeMounts").Children()
suite.Assertions.NotEmpty(containerVolumeMounts)
for _, volumeMount := range containerVolumeMounts {
volumeMountName := volumeMount.Path("name").Data().(string)
if volumeMountName == tc.volumeToTest {
suite.Assertions.EqualValues(tc.expectedMountPath, volumeMount.Path("mountPath").Data())
for _, volumeMount := range containerVolumeMounts {
volumeMountName := volumeMount.Path("name").Data().(string)
if volumeMountName == tc.volumeToTest {
suite.Assertions.EqualValues(tc.expectedMountPath, volumeMount.Path("mountPath").Data())
if tc.expectedSubPath == "" {
suite.Assertions.Empty(volumeMount.Path("subPath").Data())
} else {
suite.Assertions.EqualValues(tc.expectedSubPath, volumeMount.Path("subPath").Data())
}
break
}
}
})
}
if tc.expectedSubPath == "" {
suite.Assertions.Empty(volumeMount.Path("subPath").Data())
} else {
suite.Assertions.EqualValues(tc.expectedSubPath, volumeMount.Path("subPath").Data())
}
break
}
}
})
}
}
@@ -34,10 +34,12 @@ func (suite *PermissionsJobTestSuite) TestPresence() {
},
"WithHostPathMount": {
values: []string{
"hostPathMounts[0].name=data",
"hostPathMounts[0].enabled=true",
"hostPathMounts[0].mountPath=/data",
"hostPathMounts[0].hostPath=/tmp",
"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,
},
@@ -64,27 +66,20 @@ func (suite *PermissionsJobTestSuite) TestVolumesAndMounts() {
values []string
expectedVolumes []string
}{
"Default": {
"MultiplepersistenceList": {
values: []string{
"hostPathMounts[0].name=data",
"hostPathMounts[0].enabled=true",
"hostPathMounts[0].mountPath=/data",
"hostPathMounts[0].hostPath=/tmp",
},
expectedVolumes: nil,
},
"MultipleHostPathMounts": {
values: []string{
"hostPathMounts[0].name=data",
"hostPathMounts[0].enabled=true",
"hostPathMounts[0].setPermissions=true",
"hostPathMounts[0].mountPath=/data",
"hostPathMounts[0].hostPath=/tmp",
"hostPathMounts[1].name=config",
"hostPathMounts[1].enabled=true",
"hostPathMounts[1].setPermissions=true",
"hostPathMounts[1].mountPath=/config",
"hostPathMounts[1].hostPath=/tmp",
"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"},
},
@@ -124,16 +119,18 @@ func (suite *PermissionsJobTestSuite) TestVolumesAndMounts() {
func (suite *PermissionsJobTestSuite) TestCommand() {
baseValues := []string{
"hostPathMounts[0].name=data",
"hostPathMounts[0].enabled=true",
"hostPathMounts[0].setPermissions=true",
"hostPathMounts[0].mountPath=/data",
"hostPathMounts[0].hostPath=/tmp",
"hostPathMounts[1].name=config",
"hostPathMounts[1].enabled=true",
"hostPathMounts[1].setPermissions=true",
"hostPathMounts[1].mountPath=/config",
"hostPathMounts[1].hostPath=/tmp",
"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
+26 -73
View File
@@ -118,23 +118,28 @@ func (suite *PodTestSuite) TestPersistenceItems() {
persistence:
cache:
enabled: true
emptyDir:
enabled: true
type: emptyDir
config:
enabled: true
emptyDir:
enabled: false
data:
enabled: true
existingClaim: dataClaim
custom-mount:
enabled: true
type: custom
volumeSpec:
downwardAPI:
items:
- path: "labels"
fieldRef:
fieldPath: metadata.labels
`
tests := map[string]struct {
values *string
expectedVolumes []string
}{
"Default": {values: nil, expectedVolumes: nil},
"MultipleItems": {values: &values, expectedVolumes: []string{"config", "cache", "data"}},
"MultipleItems": {values: &values, expectedVolumes: []string{"config", "cache", "data", "custom-mount"}},
}
for name, tc := range tests {
suite.Suite.Run(name, func() {
@@ -214,8 +219,7 @@ func (suite *PodTestSuite) TestPersistenceEmptyDir() {
persistence:
config:
enabled: true
emptyDir:
enabled: true
type: emptyDir
`
tests := map[string]struct {
values []string
@@ -223,8 +227,8 @@ func (suite *PodTestSuite) TestPersistenceEmptyDir() {
expectedSizeLimit string
}{
"Enabled": {values: nil, expectedMedium: "", expectedSizeLimit: ""},
"WithMedium": {values: []string{"persistence.config.emptyDir.medium=memory"}, expectedMedium: "memory", expectedSizeLimit: ""},
"WithSizeLimit": {values: []string{"persistence.config.emptyDir.medium=memory", "persistence.config.emptyDir.sizeLimit=1Gi"}, expectedMedium: "memory", expectedSizeLimit: "1Gi"},
"WithMedium": {values: []string{"persistence.config.medium=memory"}, expectedMedium: "memory", expectedSizeLimit: ""},
"WithSizeLimit": {values: []string{"persistence.config.medium=memory", "persistence.config.sizeLimit=1Gi"}, expectedMedium: "memory", expectedSizeLimit: "1Gi"},
}
for name, tc := range tests {
suite.Suite.Run(name, func() {
@@ -256,23 +260,25 @@ func (suite *PodTestSuite) TestPersistenceEmptyDir() {
func (suite *PodTestSuite) TestHostPathVolumes() {
values := `
hostPathMounts:
- name: data
enabled: true
mountPath: "/data"
hostPath: "/tmp1"
- name: config
enabled: true
emptyDir:
persistence:
hostpathmounts-data:
enabled: true
mountPath: "/data"
type: hostPath
hostPath: "/tmp1"
mountPath: "/data"
hostpathmounts-with-type:
enabled: true
type: hostPath
hostPath: "/tmp2"
hostPathType: "Directory"
mountPath: "/data2"
`
tests := map[string]struct {
values *string
expectedVolumes []string
}{
"Default": {values: nil, expectedVolumes: nil},
"MultipleItems": {values: &values, expectedVolumes: []string{"hostpathmounts-data", "hostpathmounts-config"}},
"MultipleItems": {values: &values, expectedVolumes: []string{"hostpathmounts-data", "hostpathmounts-with-type"}},
}
for name, tc := range tests {
suite.Suite.Run(name, func() {
@@ -297,59 +303,6 @@ func (suite *PodTestSuite) TestHostPathVolumes() {
}
}
func (suite *PodTestSuite) TestHostPathVolumePaths() {
values := `
hostPathMounts:
- name: data
enabled: true
mountPath: "/data"
hostPath: "/tmp1"
- name: config
enabled: true
emptyDir:
enabled: true
mountPath: "/data"
`
tests := map[string]struct {
values *string
volumeToTest string
expectedPath string
emptyDir bool
}{
"HostPath": {values: &values, volumeToTest: "hostpathmounts-data", expectedPath: "/tmp1", emptyDir: false},
"EmptyDir": {values: &values, volumeToTest: "hostpathmounts-config", expectedPath: "", emptyDir: true},
}
for name, tc := range tests {
suite.Suite.Run(name, func() {
err := suite.Chart.Render(nil, nil, tc.values)
if err != nil {
suite.FailNow(err.Error())
}
deploymentManifest := suite.Chart.Manifests.Get("Deployment", "common-test")
volumes, _ := deploymentManifest.Path("spec.template.spec.volumes").Children()
for _, volume := range volumes {
volumeName := volume.Path("name").Data().(string)
if volumeName == tc.volumeToTest {
if tc.expectedPath == "" {
suite.Assertions.Nil(volume.Path("hostPath.path"))
} else {
suite.Assertions.EqualValues(tc.expectedPath, volume.Path("hostPath.path").Data())
}
if tc.emptyDir == false {
suite.Assertions.Nil(volume.Path("emptyDir"))
} else {
suite.Assertions.NotNil(volume.Path("emptyDir"))
}
break
}
}
})
}
}
func (suite *PodTestSuite) TestVolumeClaimTemplates() {
values := `
volumeClaimTemplates:
+1 -1
View File
@@ -30,7 +30,7 @@ func (suite *ServiceTestSuite) TestServiceName() {
expectedName string
}{
"Default": {values: nil, expectedName: "common-test"},
"CustomName": {values: []string{"service.main.nameOverride=http"}, expectedName: "common-test-http"},
"CustomName": {values: []string{"service.main.nameOverride=main"}, expectedName: "common-test-main"},
}
for name, tc := range tests {
suite.Suite.Run(name, func() {
+321 -32
View File
@@ -45,6 +45,9 @@ args: []
# -- Set annotations on the pod
podAnnotations: {}
# -- Set labels on the pod
podLabels: {}
# -- Add a Horizontal Pod Autoscaler
# @default -- <disabled>
autoscaling:
@@ -79,10 +82,6 @@ secret: {}
# C) PASSWD:
# envFrom:
# ...
# D) - name: TZ
# value: UTC
# E) - name: TZ
# value: '{{ .Release.Name }}'
env: {}
## Variables with values set from templates, example
## With a release name of: demo, the example env value will be: demo-admin
@@ -298,27 +297,34 @@ ingress:
# hosts:
# - chart-example.local
# -- Configure the persistent volumes for the chart here.
# -- Configure persistenceList for the chart here.
# Additional items can be added by adding a items similar to persistence
# @default -- []
persistenceList: []
# -- Configure persistence for the chart here.
# Additional items can be added by adding a dictionary key similar to the 'config' key.
# @default -- See below
persistence:
# -- Default persistence for configuration files.
# @default -- See below
config:
# -- Enables or disables the persistent volume
# -- Enables or disables the persistence item
enabled: false
# -- Where to mount the volume in the main container.
mountPath: /config
# -- Sets the persistence type
# Valid options are pvc, emptyDir, hostPath or custom
type: pvc
# -- Where to mount the volume in the main container.
# Defaults to `/<name_of_the_volume>`,
# setting to '-' creates the volume but disables the volumeMount.
mountPath: # /config
# -- Specify if the volume should be mounted read-only.
readOnly: false
# -- Override the name suffix that is used for this volume.
nameOverride:
emptyDir:
# -- Create an emptyDir volume instead of a persistent volume.
# [[ref]] (https://kubernetes.io/docs/concepts/storage/volumes/#emptydir)
enabled: false
# -- Storage Class for the config volume.
# If set to `-`, dynamic provisioning is disabled.
# If set to `SCALE-ZFS`, the default provisioner for TrueNAS SCALE is used.
@@ -343,31 +349,56 @@ persistence:
# - Set to true to retain the PVC upon `helm uninstall`
skipuninstall: false
# -- Create an emptyDir volume to share between all containers
# [[ref]]https://kubernetes.io/docs/concepts/storage/volumes/#emptydir)
# @default -- See below
shared:
# -- Create an emptyDir volume to share between all containers
enabled: false
emptyDir:
enabled: true
# -- Where to mount the shared volume in the main container.
type: emptyDir
mountPath: /shared
# -- Mount a path on the host to the main container.
hostPathMounts: []
# - name: "data"
# enabled: false
# emptyDir:
# enabled: false
# medium: ""
# mountPath: "/data"
# subPath: some-subpath
# hostPath: ""
# readOnly: false
# -- Set the medium to "Memory" to mount a tmpfs (RAM-backed filesystem) instead
# of the storage medium that backs the node.
medium: # Memory
# -- Specify any additional volumes here. (e.g. to mount nfs volumes directly)
additionalVolumes: []
# -- If the `SizeMemoryBackedVolumes` feature gate is enabled, you can
# specify a size for memory backed volumes.
sizeLimit: # 1Gi
# -- Specify any additional volume mounts for the main container here.
additionalVolumeMounts: []
# -- Example of a hostPath mount
# [[ref]]https://kubernetes.io/docs/concepts/storage/volumes/#hostpath)
# @default -- See below
host-dev:
enabled: false
type: hostPath
# -- Which path on the host should be mounted.
hostPath: /dev
# -- Where to mount the path in the main container.
# Defaults to the value of `hostPath`
mountPath: # /myDev
# -- Specifying a hostPathType adds a check before trying to mount the path.
# See Kubernetes documentation for options.
hostPathType: ""
# -- Specify if the path should be mounted read-only.
readOnly: true
# -- Example of a custom mount
# @default -- See below
custom-mount:
enabled: false
type: custom
# -- Where to mount the volume in the main container.
# Defaults to `/<name_of_the_volume>`,
# setting to '-' creates the volume but disables the volumeMount.
mountPath: # /custom-mount
# -- Specify if the volume should be mounted read-only.
readOnly: false
# -- Define the custom Volume spec here
# [[ref]](https://kubernetes.io/docs/concepts/storage/volumes/)
volumeSpec: {}
# configMap:
# defaultMode: 420
# name: my-settings
# -- Used in conjunction with `controller.type: statefulset` to create individual disks for each instance.
volumeClaimTemplates: []
@@ -414,3 +445,261 @@ resources: {}
# requests:
# cpu: 100m
# memory: 128Mi
# -- The common chart supports several add-ons. These can be configured under this key.
# @default -- See below
addons:
# -- The common chart supports adding a VPN add-on. It can be configured under this key.
# For more info, check out [our docs](http://docs.k8s-at-home.com/our-helm-charts/common-library-add-ons/#wireguard-vpn)
# @default -- See values.yaml
vpn:
# -- Enable running a VPN in the pod to route traffic through a VPN
enabled: false
# -- Specify the VPN type. Valid options are openvpn or wireguard
type: openvpn
# -- OpenVPN specific configuration
# @default -- See below
openvpn:
image:
# -- Specify the openvpn client image
repository: dperson/openvpn-client
# -- Specify the openvpn client image tag
tag: latest
# -- Specify the openvpn client image pull policy
pullPolicy: IfNotPresent
# -- Credentials to connect to the VPN Service (used with -a)
auth: # "user;password"
# -- Optionally specify an existing secret that contains the credentials.
# Credentials should be stored under the `VPN_AUTH` key
authSecret: # my-vpn-secret
# -- WireGuard specific configuration
# @default -- See below
wireguard:
image:
# -- Specify the WireGuard image
repository: docker pull ghcr.io/k8s-at-home/wireguard
# -- Specify the WireGuard image tag
tag: v1.0.20210424
# -- Specify the WireGuard image pull policy
pullPolicy: IfNotPresent
# -- Set the VPN container securityContext
# @default -- See values.yaml
securityContext:
capabilities:
add:
- NET_ADMIN
- SYS_MODULE
# -- All variables specified here will be added to the vpn sidecar container
# See the documentation of the VPN image for all config values
env: {}
# TZ: UTC
# -- Provide a customized vpn configuration file to be used by the VPN.
configFile: # |-
# Some Example Config
# remote greatvpnhost.com 8888
# auth-user-pass
# Cipher AES
# -- Reference an existing secret that contains the VPN configuration file
# The chart expects it to be present under the `vpnConfigfile` key.
configFileSecret:
# -- Provide custom up/down scripts that can be used by the vpn configuration.
# @default -- See values.yaml
scripts:
up: # |-
# #!/bin/bash
# echo "connected" > /shared/vpnstatus
down: # |-
# #!/bin/bash
# echo "disconnected" > /shared/vpnstatus
additionalVolumeMounts: []
# -- Optionally specify a livenessProbe, e.g. to check if the connection is still
# being protected by the VPN
livenessProbe: {}
# exec:
# command:
# - sh
# - -c
# - if [ $(curl -s https://ipinfo.io/country) == 'US' ]; then exit 0; else exit $?; fi
# initialDelaySeconds: 30
# periodSeconds: 60
# failureThreshold: 1
# If set to true, will deploy a network policy that blocks all outbound
# traffic except traffic specified as allowed
networkPolicy:
enabled: false
# The egress configuration for your network policy, All outbound traffic
# From the pod will be blocked unless specified here. Your cluster must
# have a CNI that supports network policies (Canal, Calico, etc...)
# https://kubernetes.io/docs/concepts/services-networking/network-policies/
# https://github.com/ahmetb/kubernetes-network-policy-recipes
egress:
# - to:
# - ipBlock:
# cidr: 0.0.0.0/0
# ports:
# - port: 53
# protocol: UDP
# - port: 53
# protocol: TCP
# -- The common library supports adding a code-server add-on to access files. It can be configured under this key.
# For more info, check out [our docs](http://docs.k8s-at-home.com/our-helm-charts/common-library-add-ons/#code-server)
# @default -- See values.yaml
codeserver:
# -- Enable running a code-server container in the pod
enabled: false
image:
# -- Specify the code-server image
repository: codercom/code-server
# -- Specify the code-server image tag
tag: 3.9.2
# -- Specify the code-server image pull policy
pullPolicy: IfNotPresent
# -- Set any environment variables for code-server here
env: {}
# TZ: UTC
# -- Set codeserver command line arguments.
# Consider setting --user-data-dir to a persistent location to preserve code-server setting changes
args:
- --auth
- none
# - --user-data-dir
# - "/config/.vscode"
# -- Specify a list of volumes that get mounted in the code-server container.
# At least 1 volumeMount is required!
volumeMounts: []
# - name: config
# mountPath: /data/config
# -- Specify the working dir that will be opened when code-server starts
# If not given, the app will default to the mountpah of the first specified volumeMount
workingDir: ""
# -- Optionally allow access a Git repository by passing in a private SSH key
# @default -- See below
git:
# -- Raw SSH private key
deployKey: ""
# -- Base64-encoded SSH private key. When both variables are set, the raw SSH key takes precedence.
deployKeyBase64: ""
# -- Existing secret containing SSH private key
# The chart expects it to be present under the `id_rsa` key.
deployKeySecret: ""
service:
# -- Enable a service for the code-server add-on.
enabled: true
type: ClusterIP
# Specify the default port information
ports:
codeserver:
port: 12321
enabled: true
protocol: TCP
targetPort: codeserver
## Specify the nodePort value for the LoadBalancer and NodePort service types.
## ref: https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport
##
# nodePort:
annotations: {}
labels: {}
ingress:
# -- Enable an ingress for the code-server add-on.
enabled: false
nameOverride: codeserver
annotations: {}
# kubernetes.io/ingress.class: nginx
# kubernetes.io/tls-acme: "true"
labels: {}
hosts:
- host: code.chart-example.local
paths:
- path: /
# Ignored if not kubeVersion >= 1.14-0
pathType: Prefix
tls: []
# - secretName: chart-example-tls
# hosts:
# - code.chart-example.local
securityContext:
runAsUser: 0
# -- The common library supports adding a promtail add-on to to access logs and ship them to loki. It can be configured under this key.
# @default -- See values.yaml
promtail:
# -- Enable running a promtail container in the pod
enabled: false
image:
# -- Specify the promtail image
repository: grafana/promtail
# -- Specify the promtail image tag
tag: 2.2.0
# -- Specify the promtail image pull policy
pullPolicy: IfNotPresent
# -- Set any environment variables for promtail here
env: {}
# -- Set promtail command line arguments
args: []
# -- The URL to Loki
loki: ""
# -- The paths to logs on the volume
logs: []
# - name: log
# path: /config/logs/*.log
# -- Specify a list of volumes that get mounted in the promtail container.
# At least 1 volumeMount is required!
volumeMounts: []
# - name: config
# mountPath: /config
# readOnly: true
securityContext:
runAsUser: 0
# -- The common library supports adding a netshoot add-on to troubleshoot network issues within a Pod. It can be configured under this key.
# @default -- See values.yaml
netshoot:
# -- Enable running a netshoot container in the pod
enabled: false
image:
# -- Specify the netshoot image
repository: nicolaka/netshoot
# -- Specify the netshoot image tag
tag: latest
# -- Specify the netshoot image pull policy
pullPolicy: Always
# -- Set any environment variables for netshoot here
env: {}
securityContext:
capabilities:
add:
- NET_ADMIN