diff --git a/library/common-test/tests/pod/volume_configmap_test.yaml b/library/common-test/tests/pod/volume_configmap_test.yaml new file mode 100644 index 0000000000..3db3a4eb58 --- /dev/null +++ b/library/common-test/tests/pod/volume_configmap_test.yaml @@ -0,0 +1,194 @@ +suite: pod configmap volume test +templates: + - common.yaml +tests: + - it: should pass with configmap volume + set: + some_object: some-object-name + some_mode: "0777" + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: {} + persistence: + conf-vol: + enabled: true + type: configmap + objectName: "{{ .Values.some_object }}" + defaultMode: "{{ .Values.some_mode }}" + asserts: + - documentIndex: &deploymentDoc 0 + isKind: + of: Deployment + - documentIndex: *deploymentDoc + contains: + path: spec.template.spec.volumes + content: + name: conf-vol + configMap: + name: release-name-common-test-some-object-name + defaultMode: 0777 + + - it: should pass with configmap volume with items + set: + some_object: some-object-name + some_mode: "0777" + some_key: some-key + some_path: some-path + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: {} + persistence: + conf-vol: + enabled: true + type: configmap + objectName: "{{ .Values.some_object }}" + defaultMode: "{{ .Values.some_mode }}" + items: + - key: "{{ .Values.some_key }}" + path: "{{ .Values.some_path }}" + - key: some-other-key + path: some-other-path + asserts: + - documentIndex: *deploymentDoc + isKind: + of: Deployment + - documentIndex: *deploymentDoc + contains: + path: spec.template.spec.volumes + content: + name: conf-vol + configMap: + name: release-name-common-test-some-object-name + defaultMode: 0777 + items: + - key: some-key + path: some-path + - key: some-other-key + path: some-other-path + + - it: should pass with configmap volume without expanding object name + set: + some_object: some-object-name + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: {} + persistence: + conf-vol: + enabled: true + type: configmap + objectName: "{{ .Values.some_object }}" + expandObjectName: false + asserts: + - documentIndex: *deploymentDoc + isKind: + of: Deployment + - documentIndex: *deploymentDoc + contains: + path: spec.template.spec.volumes + content: + name: conf-vol + configMap: + name: some-object-name + +# Failures + - it: should fail without objectName in configmap + set: + workload: + some-workload: + enabled: true + primary: true + type: Deployment + podSpec: {} + persistence: + volume1: + enabled: true + type: configmap + objectName: "" + asserts: + - failedTemplate: + errorMessage: Persistence - Expected non-empty on type + + - it: should fail with defaultMode not a string in configmap + set: + workload: + some-workload: + enabled: true + primary: true + type: Deployment + podSpec: {} + persistence: + volume1: + enabled: true + type: configmap + objectName: some-object-name + defaultMode: 1234 + asserts: + - failedTemplate: + errorMessage: Persistence - Expected to be [string], but got [float64] + + - it: should fail with defaultMode not in format of "0000"-"0777" in configmap + set: + workload: + some-workload: + enabled: true + primary: true + type: Deployment + podSpec: {} + persistence: + volume1: + enabled: true + type: configmap + objectName: some-object-name + defaultMode: "123" + asserts: + - failedTemplate: + errorMessage: Persistence - Expected to have be in format of ["0777"], but got ["123"] + + - it: should fail without key in items in configmap + set: + workload: + some-workload: + enabled: true + primary: true + type: Deployment + podSpec: {} + persistence: + volume1: + enabled: true + type: configmap + objectName: some-object-name + items: + - key: "" + path: some-path + asserts: + - failedTemplate: + errorMessage: Persistence - Expected non-empty + + - it: should fail without path in items in configmap + set: + workload: + some-workload: + enabled: true + primary: true + type: Deployment + podSpec: {} + persistence: + volume1: + enabled: true + type: configmap + objectName: some-object-name + items: + - key: some-key + path: "" + asserts: + - failedTemplate: + errorMessage: Persistence - Expected non-empty diff --git a/library/common-test/tests/pod/volume_emptyDIr_test.yaml b/library/common-test/tests/pod/volume_emptyDIr_test.yaml index fd9b3853c0..b851576d00 100644 --- a/library/common-test/tests/pod/volume_emptyDIr_test.yaml +++ b/library/common-test/tests/pod/volume_emptyDIr_test.yaml @@ -120,4 +120,4 @@ tests: medium: not-a-valid-medium asserts: - failedTemplate: - errorMessage: Persistence - Expected [medium] to be one of ["", Memory], but got [not-a-valid-medium] on emptyDir type + errorMessage: Persistence - Expected [medium] to be one of ["", Memory], but got [not-a-valid-medium] on type diff --git a/library/common-test/tests/pod/volume_nfs_test.yaml b/library/common-test/tests/pod/volume_nfs_test.yaml index b70b1298ad..175ebe6ce6 100644 --- a/library/common-test/tests/pod/volume_nfs_test.yaml +++ b/library/common-test/tests/pod/volume_nfs_test.yaml @@ -47,7 +47,7 @@ tests: path: "" asserts: - failedTemplate: - errorMessage: Persistence - Expected non-empty [path] on NFS type + errorMessage: Persistence - Expected non-empty [path] on type - it: should fail with path not starting with / in nfs set: @@ -64,7 +64,7 @@ tests: path: some-relative-path asserts: - failedTemplate: - errorMessage: Persistence - Expected [path] to start with a forward slash [/] on NFS type + errorMessage: Persistence - Expected [path] to start with a forward slash [/] on type - it: should fail without server in nfs set: @@ -82,4 +82,4 @@ tests: server: "" asserts: - failedTemplate: - errorMessage: Persistence - Expected non-empty [server] on NFS type + errorMessage: Persistence - Expected non-empty [server] on type diff --git a/library/common/1.0.0/docs/persistence.md b/library/common/1.0.0/docs/persistence.md index f6a9e7d606..4af8b58455 100644 --- a/library/common/1.0.0/docs/persistence.md +++ b/library/common/1.0.0/docs/persistence.md @@ -1,28 +1,34 @@ # Persistence -| Key | Type | Required | Helm Template | Default | Description | -| :----------------------------------------------------------------------------- | :-----------: | :-------------: | :----------------: | :-----------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------- | -| persistence | `dict` | ❌ | ❌ | `{}` | Define the persistence as dicts | -| persistence.[volume-name] | `dict` | ✅ | ❌ | `{}` | Holds persistence definition | -| persistence.[volume-name].enabled | `boolean` | ✅ | ❌ | `false` | Enables or Disables the persistence | -| persistence.[volume-name].labels | `dict` | ❌ | ✅ (On value only) | `{}` | Additional labels for persistence | -| persistence.[volume-name].annotations | `dict` | ❌ | ✅ (On value only) | `{}` | Additional annotations for persistence | -| persistence.[volume-name].type | `string` | ❌ | ❌ | `pvc` | Define the persistence type (pvc, ixVolume, nfs, hostPath, configmap, secret) | -| persistence.[volume-name].retain | `boolean` | ❌ | ❌ | `{{ .Values.global.fallbackDefaults.pvcRetain }}` | Define wether the to add helm annotation to retain resource on uninstall (Middleware should also retain it when deleting the NS) | -| persistence.[volume-name].accessModes | `string/list` | ❌ | ✅ | `{{ .Values.global.fallbackDefaults.pvcAccessModes }}` | Define the accessModes of the PVC, if it's single can be defined as a string, multiple as a list | -| persistence.[volume-name].size | `string` | ❌ | ✅ | pvc: `{{ .Values.global.fallbackDefaults.pvcSize }}` emptyDir: `""` | Define the size of the PVC, or the sizeLimit of the emptyDir | -| persistence.[volume-name].volumeName | `string` | ❌ | ✅ | | Define the volumeName of a PV, backing the claim | -| persistence.[volume-name].existingClaim | `string` | ❌ | ✅ | | Define an existing claim to use | -| persistence.[volume-name].storageClassName | `string` | ❌ | ✅ | See `templates/lib/storage/_storageClassName.tpl` | Define an existing claim to use | -| persistence.[volume-name].targetSelectAll | `boolean` | ❌ | ❌ | `false` | Define wether to define this volume to all workloads and mount it on all containers | -| persistence.[volume-name].targetSelector | `dict` | ❌ | ❌ | `{}` | Define a dict with pod and containers to mount | -| persistence.[volume-name].mountPath | `string` | ❌ | ✅ | `""` | Default mountPath for all container | -| persistence.[volume-name].path | `string` | ✅(On nfs type) | ✅ | `""` | Define the nfs export share path | -| persistence.[volume-name].server | `string` | ✅(On nfs type) | ✅ | `""` | Define the nfs server | -| persistence.[volume-name].medium | `string` | ❌ | ✅ | `""` | Define the medium of emptyDir (Memory, "") | -| persistence.[volume-name].targetSelector.[pod-name] | `dict` | ❌ | ❌ | `{}` | Define a dict named after the pod to define the volume | -| persistence.[volume-name].targetSelector.[pod-name].[container-name] | `dict` | ❌ | ❌ | `{}` | Define a dict named after the container to mount the volume | -| persistence.[volume-name].targetSelector.[pod-name].[container-name].mountPath | `string` | ❌ | ✅ | `[volume-name].mountPath` | Define the mountPath for the container | +| Key | Type | Required | Helm Template | Default | Description | +| :----------------------------------------------------------------------------- | :-----------: | :--------------------------: | :----------------: | :-----------------------------------------------------------------: | :------------------------------------------------------------------------------------------------------------------------------- | +| persistence | `dict` | ❌ | ❌ | `{}` | Define the persistence as dicts | +| persistence.[volume-name] | `dict` | ✅ | ❌ | `{}` | Holds persistence definition | +| persistence.[volume-name].enabled | `boolean` | ✅ | ❌ | `false` | Enables or Disables the persistence | +| persistence.[volume-name].labels | `dict` | ❌ | ✅ (On value only) | `{}` | Additional labels for persistence | +| persistence.[volume-name].annotations | `dict` | ❌ | ✅ (On value only) | `{}` | Additional annotations for persistence | +| persistence.[volume-name].type | `string` | ❌ | ❌ | `pvc` | Define the persistence type (pvc, ixVolume, nfs, hostPath, configmap, secret) | +| persistence.[volume-name].retain | `boolean` | ❌ | ❌ | `{{ .Values.global.fallbackDefaults.pvcRetain }}` | Define wether the to add helm annotation to retain resource on uninstall (Middleware should also retain it when deleting the NS) | +| persistence.[volume-name].accessModes | `string/list` | ❌ | ✅ | `{{ .Values.global.fallbackDefaults.pvcAccessModes }}` | Define the accessModes of the PVC, if it's single can be defined as a string, multiple as a list | +| persistence.[volume-name].size | `string` | ❌ | ✅ | pvc: `{{ .Values.global.fallbackDefaults.pvcSize }}` emptyDir: `""` | Define the size of the PVC, or the sizeLimit of the emptyDir | +| persistence.[volume-name].volumeName | `string` | ❌ | ✅ | | Define the volumeName of a PV, backing the claim | +| persistence.[volume-name].existingClaim | `string` | ❌ | ✅ | | Define an existing claim to use | +| persistence.[volume-name].storageClassName | `string` | ❌ | ✅ | See `templates/lib/storage/_storageClassName.tpl` | Define an existing claim to use | +| persistence.[volume-name].targetSelectAll | `boolean` | ❌ | ❌ | `false` | Define wether to define this volume to all workloads and mount it on all containers | +| persistence.[volume-name].targetSelector | `dict` | ❌ | ❌ | `{}` | Define a dict with pod and containers to mount | +| persistence.[volume-name].mountPath | `string` | ❌ | ✅ | `""` | Default mountPath for all container | +| persistence.[volume-name].path | `string` | ✅(On nfs type) | ✅ | `""` | Define the nfs export share path | +| persistence.[volume-name].server | `string` | ✅(On nfs type) | ✅ | `""` | Define the nfs server | +| persistence.[volume-name].medium | `string` | ❌ | ✅ | `""` | Define the medium of emptyDir (Memory, "") | +| persistence.[volume-name].objectName | `string` | ✅(On configmap/secret type) | ✅ | `""` | Define the configmap or secret name | +| persistence.[volume-name].expandObjectName | `boolean` | ❌ | ❌ | `true` | Wether to expand (adding the fullname as prefix) the configmap or secret name | +| persistence.[volume-name].defaultMode | `string` | ❌ | ✅ | `""` | Define the defaultMode (must be a string in format of "0777") | +| persistence.[volume-name].items | `list` | ❌ | ❌ | `[]` | Define a list of items for configmap/secret | +| persistence.[volume-name].items.key | `string` | ✅ | ✅ | `""` | Define the key of the configmap/secret | +| persistence.[volume-name].items.path | `string` | ✅ | ✅ | `""` | Define the path | +| persistence.[volume-name].targetSelector.[pod-name] | `dict` | ❌ | ❌ | `{}` | Define a dict named after the pod to define the volume | +| persistence.[volume-name].targetSelector.[pod-name].[container-name] | `dict` | ❌ | ❌ | `{}` | Define a dict named after the container to mount the volume | +| persistence.[volume-name].targetSelector.[pod-name].[container-name].mountPath | `string` | ❌ | ✅ | `[volume-name].mountPath` | Define the mountPath for the container | > When `targetSelectAll` is `true`, it will define the volume to all pods (`targetSelector` is ignored in this case) > When `targetSelector` is defined, referencing pod(s) it will define the volume to those pod(s) @@ -75,4 +81,16 @@ persistence: type: emptyDir medium: Memory size: 2Gi + + configmap-vol: + enabled: true + type: configmap + objectName: configmap-name + expandObjecName: false + defaultMode: "0777" + items: + - key: key1 + path: path1 + - key: key2 + path: path2 ``` diff --git a/library/common/1.0.0/templates/lib/pod/_volumes.tpl b/library/common/1.0.0/templates/lib/pod/_volumes.tpl index 807722ae12..f13d667c61 100644 --- a/library/common/1.0.0/templates/lib/pod/_volumes.tpl +++ b/library/common/1.0.0/templates/lib/pod/_volumes.tpl @@ -42,6 +42,7 @@ objectData: The object data to be used to render the Pod. {{- else if eq "hostPath" $type -}} {{- else if eq "secret" $type -}} {{- else if eq "configmap" $type -}} + {{- include "ix.v1.common.lib.pod.volume.configmap" (dict "rootCtx" $rootCtx "objectData" $persistence) | trim | nindent 0 -}} {{- else if eq "emptyDir" $type -}} {{- include "ix.v1.common.lib.pod.volume.emptyDir" (dict "rootCtx" $rootCtx "objectData" $persistence) | trim | nindent 0 -}} {{- else if eq "nfs" $type -}} diff --git a/library/common/1.0.0/templates/lib/pod/volumes/_configmap.tpl b/library/common/1.0.0/templates/lib/pod/volumes/_configmap.tpl new file mode 100644 index 0000000000..8cf299e8fd --- /dev/null +++ b/library/common/1.0.0/templates/lib/pod/volumes/_configmap.tpl @@ -0,0 +1,57 @@ +{{/* Returns ConfigMap Volume */}} +{{/* Call this template: +{{ include "ix.v1.common.lib.pod.volume.configmap" (dict "rootCtx" $ "objectData" $objectData) }} +rootCtx: The root context of the template. It is used to access the global context. +objectData: The object data to be used to render the volume. +*/}} +{{- define "ix.v1.common.lib.pod.volume.configmap" -}} + {{- $rootCtx := .rootCtx -}} + {{- $objectData := .objectData -}} + + {{- $objectName := tpl $objectData.objectName $rootCtx -}} + {{- $expandName := true -}} + {{- if kindIs "bool" $objectData.expandObjectName -}} + {{- $expandName = $objectData.expandObjectName -}} + {{- end -}} + + {{- if $expandName -}} + {{- $objectName = (printf "%s-%s" (include "ix.v1.common.lib.chart.names.fullname" $rootCtx) $objectName) -}} + {{- end -}} + + {{- $defMode := "" -}} + + {{- if not $objectData.objectName -}} + {{- fail "Persistence - Expected non-empty on type" -}} + {{- end -}} + + {{- if (and $objectData.defaultMode (not (kindIs "string" $objectData.defaultMode))) -}} + {{- fail (printf "Persistence - Expected to be [string], but got [%s]" (kindOf $objectData.defaultMode)) -}} + {{- end -}} + + {{- with $objectData.defaultMode -}} + {{- $defMode = tpl $objectData.defaultMode $rootCtx -}} + {{- end -}} + + {{- if and $defMode (not (mustRegexMatch "^[0-9]{4}$" $defMode)) -}} + {{- fail (printf "Persistence - Expected to have be in format of [\"0777\"], but got [%q]" $defMode) -}} + {{- end }} +- name: {{ $objectData.shortName }} + configMap: + name: {{ $objectName }} + {{- with $defMode }} + defaultMode: {{ . }} + {{- end -}} + {{- with $objectData.items }} + items: + {{- range . -}} + {{- if not .key -}} + {{- fail "Persistence - Expected non-empty " -}} + {{- end -}} + {{- if not .path -}} + {{- fail "Persistence - Expected non-empty " -}} + {{- end }} + - key: {{ tpl .key $rootCtx }} + path: {{ tpl .path $rootCtx }} + {{- end -}} + {{- end -}} +{{- end -}} diff --git a/library/common/1.0.0/templates/lib/pod/volumes/_emptyDir.tpl b/library/common/1.0.0/templates/lib/pod/volumes/_emptyDir.tpl index 72525246eb..f3ca1ffb0a 100644 --- a/library/common/1.0.0/templates/lib/pod/volumes/_emptyDir.tpl +++ b/library/common/1.0.0/templates/lib/pod/volumes/_emptyDir.tpl @@ -18,7 +18,7 @@ objectData: The object data to be used to render the volume. {{- end -}} {{- if and $medium (ne $medium "Memory") -}} - {{- fail (printf "Persistence - Expected [medium] to be one of [\"\", Memory], but got [%s] on emptyDir type" $medium) -}} + {{- fail (printf "Persistence - Expected [medium] to be one of [\"\", Memory], but got [%s] on type" $medium) -}} {{- end }} - name: {{ $objectData.shortName }} {{- if or $medium $size }} diff --git a/library/common/1.0.0/templates/lib/pod/volumes/_nfs.tpl b/library/common/1.0.0/templates/lib/pod/volumes/_nfs.tpl index 0f806ff04b..d1e845db34 100644 --- a/library/common/1.0.0/templates/lib/pod/volumes/_nfs.tpl +++ b/library/common/1.0.0/templates/lib/pod/volumes/_nfs.tpl @@ -9,16 +9,16 @@ objectData: The object data to be used to render the volume. {{- $objectData := .objectData -}} {{- if not $objectData.path -}} - {{- fail "Persistence - Expected non-empty [path] on NFS type" -}} + {{- fail "Persistence - Expected non-empty [path] on type" -}} {{- end -}} {{- $path := tpl $objectData.path $rootCtx -}} {{- if not (hasPrefix "/" $path) -}} - {{- fail "Persistence - Expected [path] to start with a forward slash [/] on NFS type" -}} + {{- fail "Persistence - Expected [path] to start with a forward slash [/] on type" -}} {{- end -}} {{- if not $objectData.server -}} - {{- fail "Persistence - Expected non-empty [server] on NFS type" -}} + {{- fail "Persistence - Expected non-empty [server] on type" -}} {{- end }} - name: {{ $objectData.shortName }} nfs: