diff --git a/library/common-testing/ci/configmap-values.yaml b/library/common-testing/ci/configmap-values.yaml new file mode 100644 index 0000000000..9d4938f00c --- /dev/null +++ b/library/common-testing/ci/configmap-values.yaml @@ -0,0 +1,57 @@ +image: + repository: traefik/whoami + pullPolicy: IfNotPresent + tag: latest + +service: + main: + ports: + main: + protocol: HTTP + port: 8080 + +controllers: + main: + pod: + containers: + main: + args: + - --port + - "8080" + probes: + liveness: + enabled: true + readiness: + enabled: true + startup: + enabled: true + +key1: value1 +key2: 80 +key3: pair +key4: value2 +key5: 81 +key6: false + +configmap: + kv-test: + enabled: true + data: + key: "{{ .Values.key1 }}" + key1: "{{ .Values.key4 }}" + key2: "{{ .Values.key5 }}" + key3: "{{ .Values.key6 }}" + + file-test: + enabled: true + data: + nginx.conf2: | + alias {{ .Values.key3 }} + listen {{ .Values.key2 }} + function { + # some json + "key": { + "key2": "value", + "key3": "value2" + } + } diff --git a/library/common-testing/tests/configmap/data_test.yaml b/library/common-testing/tests/configmap/data_test.yaml index fa7641b24e..bc4422915b 100644 --- a/library/common-testing/tests/configmap/data_test.yaml +++ b/library/common-testing/tests/configmap/data_test.yaml @@ -44,32 +44,49 @@ tests: some multi line string text asserts: - - documentIndex: &configmapDoc 0 - isKind: - of: ConfigMap - documentIndex: *configmapDoc equal: path: data value: - foo: |- + foo: | some multi line string text - it: should pass with scalar data with tpl set: - data: some_text + data: Some other text configmaps: - my-configmap1: + my-configmap: enabled: true data: foo: | - Some other text + file start {{ .Values.data }} asserts: - documentIndex: *configmapDoc equal: path: data value: - foo: |- + foo: | + file start + Some other text + + - it: should pass with scalar data from tpl + set: + data: | + Some other text + some_text + configmaps: + my-configmap1: + enabled: true + data: + foo: | + {{- .Values.data | nindent 2 }} + asserts: + - documentIndex: *configmapDoc + equal: + path: data + value: + foo: | Some other text some_text diff --git a/library/common-testing/tests/configmap/validation_test.yaml b/library/common-testing/tests/configmap/validation_test.yaml index 35283486b5..0df4242b3e 100644 --- a/library/common-testing/tests/configmap/validation_test.yaml +++ b/library/common-testing/tests/configmap/validation_test.yaml @@ -34,7 +34,7 @@ tests: foo: bar asserts: - failedTemplate: - errorMessage: Configmap - Expected to be a dictionary, but got [string] + errorMessage: ConfigMap - Expected to be a dictionary, but got [string] - it: should fail with annotations not a dict set: @@ -46,7 +46,7 @@ tests: foo: bar asserts: - failedTemplate: - errorMessage: Configmap - Expected to be a dictionary, but got [string] + errorMessage: ConfigMap - Expected to be a dictionary, but got [string] - it: should fail with data not a dict set: @@ -56,7 +56,7 @@ tests: data: "not a dict" asserts: - failedTemplate: - errorMessage: Configmap - Expected to be a dictionary, but got [string] + errorMessage: ConfigMap - Expected to be a dictionary, but got [string] - it: should fail with empty data set: @@ -66,4 +66,4 @@ tests: data: {} asserts: - failedTemplate: - errorMessage: Configmap - Expected non-empty + errorMessage: ConfigMap - Expected non-empty diff --git a/library/common-testing/tests/secret/data_test.yaml b/library/common-testing/tests/secret/data_test.yaml new file mode 100644 index 0000000000..9587cfd9ea --- /dev/null +++ b/library/common-testing/tests/secret/data_test.yaml @@ -0,0 +1,111 @@ +suite: secret data test +templates: + - common.yaml +tests: + - it: should pass with key-value data + set: + secrets: + my-secret1: + enabled: true + data: + foo: bar + asserts: + - documentIndex: &secretDoc 0 + isKind: + of: Secret + - documentIndex: *secretDoc + equal: + path: stringData + value: + foo: bar + - documentIndex: *secretDoc + equal: + path: type + value: Opaque + + - it: should pass with custom secret type + set: + secrets: + my-secret1: + enabled: true + type: SomeCustomType + data: + foo: bar + asserts: + - documentIndex: *secretDoc + equal: + path: type + value: SomeCustomType + + + - it: should pass with key-value data from tpl + set: + data: bar + secrets: + my-secret1: + enabled: true + data: + foo: "{{ .Values.data }}" + asserts: + - documentIndex: *secretDoc + equal: + path: stringData + value: + foo: bar + + - it: should pass with scalar data + set: + secrets: + my-secret1: + enabled: true + data: + foo: | + some multi line + string text + asserts: + - documentIndex: *secretDoc + equal: + path: stringData + value: + foo: | + some multi line + string text + + - it: should pass with scalar data with tpl + set: + data: Some other text + secrets: + my-secret: + enabled: true + data: + foo: | + file start + {{ .Values.data }} + asserts: + - documentIndex: *secretDoc + equal: + path: stringData + value: + foo: | + file start + Some other text + + - it: should pass with scalar data from tpl + set: + data: | + Some other text + some_text + secrets: + my-secret: + enabled: true + data: + foo: | + {{- .Values.data | nindent 2 }} + asserts: + - documentIndex: *secretDoc + equal: + path: stringData + value: + foo: | + Some other text + some_text diff --git a/library/common-testing/tests/secret/labels_test.yaml b/library/common-testing/tests/secret/labels_test.yaml new file mode 100644 index 0000000000..f595cca413 --- /dev/null +++ b/library/common-testing/tests/secret/labels_test.yaml @@ -0,0 +1,54 @@ +suite: secret test +templates: + - common.yaml +chart: + appVersion: &appVer v9.9.9 +tests: + - it: should pass with secret created with labels and annotations + documentIndex: &secretDoc 0 + set: + label1: label1 + label2: global_label2 + annotation1: annotation1 + annotation2: global_annotation2 + global: + labels: + g_label1: global_label1 + g_label2: "{{ .Values.label2 }}" + annotations: + g_annotation1: global_annotation1 + g_annotation2: "{{ .Values.annotation2 }}" + secrets: + my-secret1: + enabled: true + labels: + label1: "{{ .Values.label1 }}" + label2: label2 + annotations: + annotation1: "{{ .Values.annotation1 }}" + annotation2: annotation2 + data: + foo: bar + asserts: + - isKind: + of: Secret + - equal: + path: metadata.annotations + value: + annotation1: annotation1 + annotation2: annotation2 + g_annotation1: global_annotation1 + g_annotation2: global_annotation2 + - equal: + path: metadata.labels + value: + app: common-test-1.0.0 + release: release-name + helm-revision: 0 + helm.sh/chart: common-test-1.0.0 + app.kubernetes.io/managed-by: Helm + app.kubernetes.io/version: v9.9.9 + g_label1: global_label1 + g_label2: global_label2 + label1: label1 + label2: label2 diff --git a/library/common-testing/tests/secret/name_test.yaml b/library/common-testing/tests/secret/name_test.yaml new file mode 100644 index 0000000000..a8bde274c2 --- /dev/null +++ b/library/common-testing/tests/secret/name_test.yaml @@ -0,0 +1,36 @@ +suite: secret name test +templates: + - common.yaml +tests: + - it: should generate correct name + set: + secrets: + my-secret1: + enabled: true + data: + foo: bar + my-secret2: + enabled: true + data: + foo: bar + asserts: + - documentIndex: &secretDoc 0 + isKind: + of: Secret + - documentIndex: *secretDoc + isAPIVersion: + of: v1 + - documentIndex: *secretDoc + equal: + path: metadata.name + value: release-name-common-test-my-secret1 + - documentIndex: &secretDoc2 1 + isKind: + of: Secret + - documentIndex: *secretDoc2 + isAPIVersion: + of: v1 + - documentIndex: *secretDoc2 + equal: + path: metadata.name + value: release-name-common-test-my-secret2 diff --git a/library/common-testing/tests/secret/validation_test.yaml b/library/common-testing/tests/secret/validation_test.yaml new file mode 100644 index 0000000000..4f85f563d2 --- /dev/null +++ b/library/common-testing/tests/secret/validation_test.yaml @@ -0,0 +1,81 @@ +suite: secret validation test +templates: + - common.yaml +tests: + - it: should fail with name longer than 63 characters + set: + secrets: + my-secret-super-long-name-that-is-longer-than-63-characters: + enabled: true + data: + foo: bar + asserts: + - failedTemplate: + errorMessage: Name [release-name-common-test-my-secret-super-long-name-that-is-longer-than-63-characters] is not valid. Must start and end with an alphanumeric character. It can contain '-'. And must be at most 63 characters. + + - it: should fail with name starting with underscore + set: + secrets: + _my-secret: + enabled: true + data: + foo: bar + asserts: + - failedTemplate: + errorMessage: Name [release-name-common-test-_my-secret] is not valid. Must start and end with an alphanumeric character. It can contain '-'. And must be at most 63 characters. + + - it: should fail with labels not a dict + set: + secrets: + my-secret: + enabled: true + labels: "not a dict" + data: + foo: bar + asserts: + - failedTemplate: + errorMessage: Secret - Expected to be a dictionary, but got [string] + + - it: should fail with annotations not a dict + set: + secrets: + my-secret: + enabled: true + annotations: "not a dict" + data: + foo: bar + asserts: + - failedTemplate: + errorMessage: Secret - Expected to be a dictionary, but got [string] + + - it: should fail with data not a dict + set: + secrets: + my-secret: + enabled: true + data: "not a dict" + asserts: + - failedTemplate: + errorMessage: Secret - Expected to be a dictionary, but got [string] + + - it: should fail with empty data + set: + secrets: + my-secret: + enabled: true + data: {} + asserts: + - failedTemplate: + errorMessage: Secret - Expected non-empty + + - it: should fail with empty type key + set: + secrets: + my-secret: + enabled: true + type: "" + data: + foo: bar + asserts: + - failedTemplate: + errorMessage: Secret - Found key, but it's empty diff --git a/library/common/1.0.1/docs/secrets.md b/library/common/1.0.1/docs/secrets.md new file mode 100644 index 0000000000..911da0118c --- /dev/null +++ b/library/common/1.0.1/docs/secrets.md @@ -0,0 +1,50 @@ +# Secret + +| Key | Type | Required | Helm Template | Default | Description | +| :-------------------------------- | :-------: | :------: | :-----------: | :------: | :-------------------------------- | +| secrets | `dict` | ❌ | ❌ | `{}` | Define the secrets as dicts | +| secrets.[secret-name] | `dict` | ✅ | ❌ | `{}` | Holds secret definition | +| secrets.[secret-name].enabled | `boolean` | ✅ | ❌ | `false` | Enables or Disables the secret | +| secrets.[secret-name].labels | `dict` | ❌ | ✅ | `{}` | Additional labels for secret | +| secrets.[secret-name].annotations | `dict` | ❌ | ✅ | `{}` | Additional annotations for secret | +| secrets.[secret-name].type | `string` | ❌ | ✅ | `Opaque` | Custom secret type | +| secrets.[secret-name].data | `dict` | ✅ | ✅ | `{}` | Define the data of the secret | + +--- + +Appears in: + +- `.Values.secrets` + +--- + +Naming scheme: + +- `$FullName-$SecretName` (release-name-chart-name-SecretName) + +--- + +Examples: + +```yaml +secrets: + + secret-name: + enabled: true + labels: + key: value + type: CustomSecretType + keytpl: "{{ .Values.some.value }}" + annotations: + key: value + keytpl: "{{ .Values.some.value }}" + data: + key: value + + other-secret-name: + enabled: true + data: + key: | + multi line + text value +``` diff --git a/library/common/1.0.1/templates/classes/_configmap.tpl b/library/common/1.0.1/templates/classes/_configmap.tpl index e09251db06..eac7680146 100644 --- a/library/common/1.0.1/templates/classes/_configmap.tpl +++ b/library/common/1.0.1/templates/classes/_configmap.tpl @@ -23,7 +23,7 @@ metadata: {{- with (include "ix.v1.common.lib.metadata.render" (dict "rootCtx" $rootCtx "labels" $labels) | trim) }} labels: {{- . | nindent 4 }} - {{- end }} + {{- end -}} {{- $annotations := (mustMerge ($objectData.annotations | default dict) (include "ix.v1.common.lib.metadata.allAnnotations" $rootCtx | fromYaml)) -}} {{- with (include "ix.v1.common.lib.metadata.render" (dict "rootCtx" $rootCtx "annotations" $annotations) | trim) }} annotations: @@ -31,4 +31,5 @@ metadata: {{- end }} data: {{- tpl (toYaml $objectData.data) $rootCtx | nindent 2 }} + {{/* This comment is here to add a new line */}} {{- end -}} diff --git a/library/common/1.0.1/templates/classes/_secret.tpl b/library/common/1.0.1/templates/classes/_secret.tpl index e69de29bb2..8ec8019b0b 100644 --- a/library/common/1.0.1/templates/classes/_secret.tpl +++ b/library/common/1.0.1/templates/classes/_secret.tpl @@ -0,0 +1,56 @@ +{{/* Secret Class */}} +{{/* Call this template: +{{ include "ix.v1.common.class.secret" (dict "objectData" $objectData "rootCtx" $) }} + +rootCtx: The root context of the template. It is used to access the global context. +objectData: + name: The name of the secret. + labels: The labels of the secret. + annotations: The annotations of the secret. + type: The type of the secret. + data: The data of the secret. +*/}} + +{{- define "ix.v1.common.class.secret" -}} + + {{- $rootCtx := .rootCtx -}} + {{- $objectData := .objectData -}} + {{- $secretType := "Opaque" -}} + + {{- if eq $objectData.type "certificate" -}} + {{- $secretType = "kubernetes.io/tls" -}} + {{- else if eq $objectData.type "imagePullSecret" -}} + {{- $secretType = "kubernetes.io/dockerconfigjson" -}} + {{- else if $objectData.type -}} + {{- $secretType = $objectData.type -}} + {{- end }} +--- +apiVersion: v1 +kind: Secret +type: {{ $secretType }} +metadata: + name: {{ $objectData.name }} + {{- $labels := (mustMerge ($objectData.labels | default dict) (include "ix.v1.common.lib.metadata.allLabels" $rootCtx | fromYaml)) -}} + {{- with (include "ix.v1.common.lib.metadata.render" (dict "rootCtx" $rootCtx "labels" $labels) | trim) }} + labels: + {{- . | nindent 4 }} + {{- end -}} + {{- $annotations := (mustMerge ($objectData.annotations | default dict) (include "ix.v1.common.lib.metadata.allAnnotations" $rootCtx | fromYaml)) -}} + {{- with (include "ix.v1.common.lib.metadata.render" (dict "rootCtx" $rootCtx "annotations" $annotations) | trim) }} + annotations: + {{- . | nindent 4 }} + {{- end -}} + {{- if (mustHas $objectData.type (list "certificate" "imagePullSecret")) }} +data: + {{- if eq $objectData.type "certificate" }} + {{/* TODO: print certificate values and test */}} + {{- else if eq $objectData.type "imagePullSecret" }} + {{/* TODO: test this */}} + .dockerconfigjson: {{ $objectData.data | toJson | b64enc }} + {{- end -}} + {{- else }} +stringData: + {{- tpl (toYaml $objectData.data) $rootCtx | nindent 2 }} + {{/* This comment is here to add a new line */}} + {{- end -}} +{{- end -}} diff --git a/library/common/1.0.1/templates/lib/configmap/_validation.tpl b/library/common/1.0.1/templates/lib/configmap/_validation.tpl index 0163b526c5..27fafe1dd0 100644 --- a/library/common/1.0.1/templates/lib/configmap/_validation.tpl +++ b/library/common/1.0.1/templates/lib/configmap/_validation.tpl @@ -12,19 +12,19 @@ objectData: {{- $objectData := .objectData -}} {{- if not $objectData.data -}} - {{- fail "Configmap - Expected non-empty " -}} + {{- fail "ConfigMap - Expected non-empty " -}} {{- end -}} {{- if not (kindIs "map" $objectData.data) -}} - {{- fail (printf "Configmap - Expected to be a dictionary, but got [%v]" (kindOf $objectData.data)) -}} + {{- fail (printf "ConfigMap - Expected to be a dictionary, but got [%v]" (kindOf $objectData.data)) -}} {{- end -}} {{- if and $objectData.labels (not (kindIs "map" $objectData.labels)) -}} - {{- fail (printf "Configmap - Expected to be a dictionary, but got [%v]" (kindOf $objectData.labels)) -}} + {{- fail (printf "ConfigMap - Expected to be a dictionary, but got [%v]" (kindOf $objectData.labels)) -}} {{- end -}} {{- if and $objectData.annotations (not (kindIs "map" $objectData.annotations)) -}} - {{- fail (printf "Configmap - Expected to be a dictionary, but got [%v]" (kindOf $objectData.annotations)) -}} + {{- fail (printf "ConfigMap - Expected to be a dictionary, but got [%v]" (kindOf $objectData.annotations)) -}} {{- end -}} {{- end -}} diff --git a/library/common/1.0.1/templates/lib/secret/_validation.tpl b/library/common/1.0.1/templates/lib/secret/_validation.tpl new file mode 100644 index 0000000000..c03d62125b --- /dev/null +++ b/library/common/1.0.1/templates/lib/secret/_validation.tpl @@ -0,0 +1,34 @@ +{{/* Secret Validation */}} +{{/* Call this template: +{{ include "ix.v1.common.lib.secret.validation" (dict "objectData" $objectData) -}} +objectData: + name: The name of the secret. + labels: The labels of the secret. + annotations: The annotations of the secret. + data: The data of the secret. +*/}} + +{{- define "ix.v1.common.lib.secret.validation" -}} + {{- $objectData := .objectData -}} + + {{- if not $objectData.data -}} + {{- fail "Secret - Expected non-empty " -}} + {{- end -}} + + {{- if not (kindIs "map" $objectData.data) -}} + {{- fail (printf "Secret - Expected to be a dictionary, but got [%v]" (kindOf $objectData.data)) -}} + {{- end -}} + + {{- if and (hasKey $objectData "type") (not $objectData.type) -}} + {{- fail (printf "Secret - Found key, but it's empty") -}} + {{- end -}} + + {{- if and $objectData.labels (not (kindIs "map" $objectData.labels)) -}} + {{- fail (printf "Secret - Expected to be a dictionary, but got [%v]" (kindOf $objectData.labels)) -}} + {{- end -}} + + {{- if and $objectData.annotations (not (kindIs "map" $objectData.annotations)) -}} + {{- fail (printf "Secret - Expected to be a dictionary, but got [%v]" (kindOf $objectData.annotations)) -}} + {{- end -}} + +{{- end -}} diff --git a/library/common/1.0.1/templates/loader/_apply.tpl b/library/common/1.0.1/templates/loader/_apply.tpl index 07d9b0f626..27301be0c0 100644 --- a/library/common/1.0.1/templates/loader/_apply.tpl +++ b/library/common/1.0.1/templates/loader/_apply.tpl @@ -1,7 +1,11 @@ {{/* Loads all spawners */}} {{- define "ix.v1.common.loader.apply" -}} + {{/* Render configmap(s) */}} {{- include "ix.v1.common.spawner.configmaps" . | nindent 0 -}} + {{/* Render secret(s) */}} + {{- include "ix.v1.common.spawner.secrets" . | nindent 0 -}} + {{- end -}} diff --git a/library/common/1.0.1/templates/spawner/_secret.tpl b/library/common/1.0.1/templates/spawner/_secret.tpl index e69de29bb2..b9f1ccdd59 100644 --- a/library/common/1.0.1/templates/spawner/_secret.tpl +++ b/library/common/1.0.1/templates/spawner/_secret.tpl @@ -0,0 +1,29 @@ +{{/* Secret Spawwner */}} +{{/* Call this template: +{{ include "ix.v1.common.spawner.secrets" . -}} +*/}} + +{{- define "ix.v1.common.spawner.secrets" -}} + + {{- range $name, $secret := .Values.secrets -}} + + {{- if $secret.enabled -}} + + {{/* Create a copy of the secret */}} + {{- $objectData := (mustDeepCopy $secret) -}} + + {{- $objectName := (printf "%s-%s" (include "ix.common.lib.chart.names.fullname" $) $name) -}} + {{/* Perform validations */}} + {{- include "ix.v1.common.lib.chart.names.validation" (dict "name" $objectName) -}} + {{- include "ix.v1.common.lib.secret.validation" (dict "objectData" $objectData) -}} + + {{/* Set the name of the secret */}} + {{- $_ := set $objectData "name" $objectName -}} + {{/* Call class to create the object */}} + {{- include "ix.v1.common.class.secret" (dict "objectData" $objectData "rootCtx" $) -}} + + {{- end -}} + + {{- end -}} + +{{- end -}} diff --git a/library/common/1.0.1/values.yaml b/library/common/1.0.1/values.yaml index e74ecdbc30..37a388e3b7 100644 --- a/library/common/1.0.1/values.yaml +++ b/library/common/1.0.1/values.yaml @@ -49,19 +49,19 @@ configmaps: {} # data: {} # -- Secrets -secrets: - # -- Secret name - secret-name: - # -- Enables the secret - enabled: false - # -- Secret labels - labels: {} - # -- Secret annotations - annotations: {} - # -- Secret data - data: - # -- Secret data (stringData) - key: value +secrets: {} + # # -- Secret name + # secret-name: + # # -- Enables the secret + # enabled: false + # # -- Secret labels + # labels: {} + # # -- Secret annotations + # annotations: {} + # # -- Secret data + # data: + # # -- Secret data (stringData) + # key: value # -- Service Account: serviceAccount: