This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
{{/* Returns args list */}}
|
||||
{{/* Call this template:
|
||||
{{ include "tc.v1.common.lib.container.args" (dict "rootCtx" $ "objectData" $objectData) }}
|
||||
rootCtx: The root context of the chart.
|
||||
objectData: The object data to be used to render the container.
|
||||
*/}}
|
||||
{{- define "tc.v1.common.lib.container.args" -}}
|
||||
{{- $rootCtx := .rootCtx -}}
|
||||
{{- $objectData := .objectData -}}
|
||||
|
||||
{{- range $key := (list "args" "extraArgs") -}}
|
||||
{{- with (get $objectData $key) -}}
|
||||
{{- if kindIs "string" . }}
|
||||
- {{ tpl . $rootCtx | quote }}
|
||||
{{- else if kindIs "slice" . -}}
|
||||
{{- range $arg := . }}
|
||||
- {{ tpl $arg $rootCtx | quote }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,18 @@
|
||||
{{/* Returns command list */}}
|
||||
{{/* Call this template:
|
||||
{{ include "tc.v1.common.lib.container.command" (dict "rootCtx" $ "objectData" $objectData) }}
|
||||
rootCtx: The root context of the chart.
|
||||
objectData: The object data to be used to render the container.
|
||||
*/}}
|
||||
{{- define "tc.v1.common.lib.container.command" -}}
|
||||
{{- $rootCtx := .rootCtx -}}
|
||||
{{- $objectData := .objectData -}}
|
||||
|
||||
{{- if kindIs "string" $objectData.command }}
|
||||
- {{ tpl $objectData.command $rootCtx | quote }}
|
||||
{{- else if kindIs "slice" $objectData.command -}}
|
||||
{{- range $objectData.command }}
|
||||
- {{ tpl . $rootCtx | quote }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
108
helm-charts/dashy/charts/common/templates/lib/container/_env.tpl
Normal file
108
helm-charts/dashy/charts/common/templates/lib/container/_env.tpl
Normal file
@@ -0,0 +1,108 @@
|
||||
{{/* Returns Env */}}
|
||||
{{/* Call this template:
|
||||
{{ include "tc.v1.common.lib.container.env" (dict "rootCtx" $ "objectData" $objectData) }}
|
||||
rootCtx: The root context of the chart.
|
||||
objectData: The object data to be used to render the container.
|
||||
*/}}
|
||||
{{- define "tc.v1.common.lib.container.env" -}}
|
||||
{{- $rootCtx := .rootCtx -}}
|
||||
{{- $objectData := .objectData -}}
|
||||
|
||||
{{- range $k, $v := $objectData.env -}}
|
||||
{{- include "tc.v1.common.helper.container.envDupeCheck" (dict "rootCtx" $rootCtx "objectData" $objectData "source" "env" "key" $k) }}
|
||||
- name: {{ $k | quote }}
|
||||
{{- if not (kindIs "map" $v) -}}
|
||||
{{- $value := "" -}}
|
||||
{{- if not (kindIs "invalid" $v) -}} {{/* Only tpl non-empty values */}}
|
||||
{{- $value = $v -}}
|
||||
{{- if kindIs "string" $v -}}
|
||||
{{- $value = tpl $v $rootCtx -}}
|
||||
{{- end -}}
|
||||
{{- end }}
|
||||
value: {{ include "tc.v1.common.helper.makeIntOrNoop" $value | quote }}
|
||||
{{- else if kindIs "map" $v }}
|
||||
valueFrom:
|
||||
{{- $refs := (list "configMapKeyRef" "secretKeyRef" "fieldRef") -}}
|
||||
{{- if or (ne (len ($v | keys)) 1) (not (mustHas ($v | keys | first) $refs)) -}}
|
||||
{{- fail (printf "Container - Expected <env> with a ref to have one of [%s], but got [%s]" (join ", " $refs) (join ", " ($v | keys | sortAlpha))) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $name := "" -}}
|
||||
|
||||
|
||||
{{- range $key := (list "configMapKeyRef" "secretKeyRef") -}}
|
||||
{{- if hasKey $v $key }}
|
||||
{{ $key }}:
|
||||
{{- $obj := get $v $key -}}
|
||||
{{- if not $obj.name -}}
|
||||
{{- fail (printf "Container - Expected non-empty <env.%s.name>" $key) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if not $obj.key -}}
|
||||
{{- fail (printf "Container - Expected non-empty <env.%s.key>" $key) -}}
|
||||
{{- end }}
|
||||
key: {{ $obj.key | quote }}
|
||||
|
||||
{{- $name = tpl $obj.name $rootCtx -}}
|
||||
|
||||
{{- $expandName := true -}}
|
||||
{{- if (hasKey $obj "expandObjectName") -}}
|
||||
{{- if not (kindIs "invalid" $obj.expandObjectName) -}}
|
||||
{{- $expandName = $obj.expandObjectName -}}
|
||||
{{- else -}}
|
||||
{{- fail (printf "Container - Expected the defined key [expandObjectName] in <env.%s> to not be empty" $k) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if kindIs "string" $expandName -}}
|
||||
{{- $expandName = tpl $expandName $rootCtx -}}
|
||||
|
||||
{{/* After tpl it becomes a string, not a bool */}}
|
||||
{{- if eq $expandName "true" -}}
|
||||
{{- $expandName = true -}}
|
||||
{{- else if eq $expandName "false" -}}
|
||||
{{- $expandName = false -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if $expandName -}}
|
||||
{{- $item := ($key | trimSuffix "KeyRef" | lower) -}}
|
||||
|
||||
{{- $data := (get $rootCtx.Values $item) -}}
|
||||
{{- $data = (get $data $name) -}}
|
||||
|
||||
{{- if not $data -}}
|
||||
{{- fail (printf "Container - Expected in <env> the referenced %s [%s] to be defined" (camelcase $item) $name) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $found := false -}}
|
||||
{{- range $k, $v := $data.data -}}
|
||||
{{- if eq $k $obj.key -}}
|
||||
{{- $found = true -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if not $found -}}
|
||||
{{- fail (printf "Container - Expected in <env> the referenced key [%s] in %s [%s] to be defined" $obj.key (camelcase $item) $name) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $name = (printf "%s-%s" (include "tc.v1.common.lib.chart.names.fullname" $rootCtx) $name) -}}
|
||||
{{- end }}
|
||||
name: {{ $name | quote }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if hasKey $v "fieldRef" }}
|
||||
fieldRef:
|
||||
{{- if not $v.fieldRef.fieldPath -}}
|
||||
{{- fail "Container - Expected non-empty <env.fieldRef.fieldPath>" -}}
|
||||
{{- end }}
|
||||
fieldPath: {{ $v.fieldRef.fieldPath | quote }}
|
||||
{{- if $v.fieldRef.apiVersion }}
|
||||
apiVersion: {{ $v.fieldRef.apiVersion | quote }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,74 @@
|
||||
{{/* Returns Env From */}}
|
||||
{{/* Call this template:
|
||||
{{ include "tc.v1.common.lib.container.envFrom" (dict "rootCtx" $ "objectData" $objectData) }}
|
||||
rootCtx: The root context of the chart.
|
||||
objectData: The object data to be used to render the container.
|
||||
*/}}
|
||||
{{- define "tc.v1.common.lib.container.envFrom" -}}
|
||||
{{- $rootCtx := .rootCtx -}}
|
||||
{{- $objectData := .objectData -}}
|
||||
|
||||
{{- $refs := (list "configMapRef" "secretRef") -}}
|
||||
{{- range $envFrom := $objectData.envFrom -}}
|
||||
{{- if and (not $envFrom.secretRef) (not $envFrom.configMapRef) -}}
|
||||
{{- fail (printf "Container - Expected <envFrom> entry to have one of [%s]" (join ", " $refs)) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if and $envFrom.secretRef $envFrom.configMapRef -}}
|
||||
{{- fail (printf "Container - Expected <envFrom> entry to have only one of [%s], but got both" (join ", " $refs)) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- range $ref := $refs -}}
|
||||
{{- with (get $envFrom $ref) -}}
|
||||
{{- if not .name -}}
|
||||
{{- fail (printf "Container - Expected non-empty <envFrom.%s.name>" $ref) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $objectName := tpl .name $rootCtx -}}
|
||||
|
||||
{{- $expandName := true -}}
|
||||
{{- if (hasKey . "expandObjectName") -}}
|
||||
{{- if not (kindIs "invalid" .expandObjectName) -}}
|
||||
{{- $expandName = .expandObjectName -}}
|
||||
{{- else -}}
|
||||
{{- fail (printf "Container - Expected the defined key [expandObjectName] in <envFrom.%s> to not be empty" $ref) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if kindIs "string" $expandName -}}
|
||||
{{- $expandName = tpl $expandName $rootCtx -}}
|
||||
|
||||
{{/* After tpl it becomes a string, not a bool */}}
|
||||
{{- if eq $expandName "true" -}}
|
||||
{{- $expandName = true -}}
|
||||
{{- else if eq $expandName "false" -}}
|
||||
{{- $expandName = false -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if $expandName -}}
|
||||
{{- $object := dict -}}
|
||||
{{- $source := "" -}}
|
||||
{{- if eq $ref "configMapRef" -}}
|
||||
{{- $object = (get $rootCtx.Values.configmap $objectName) -}}
|
||||
{{- $source = "ConfigMap" -}}
|
||||
{{- else if eq $ref "secretRef" -}}
|
||||
{{- $object = (get $rootCtx.Values.secret $objectName) -}}
|
||||
{{- $source = "Secret" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if not $object -}}
|
||||
{{- fail (printf "Container - Expected %s [%s] defined in <envFrom> to exist" $source $objectName) -}}
|
||||
{{- end -}}
|
||||
{{- range $k, $v := $object.data -}}
|
||||
{{- include "tc.v1.common.helper.container.envDupeCheck" (dict "rootCtx" $rootCtx "objectData" $objectData "source" (printf "%s - %s" $source $objectName) "key" $k) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $objectName = (printf "%s-%s" (include "tc.v1.common.lib.chart.names.fullname" $rootCtx) $objectName) -}}
|
||||
{{- end }}
|
||||
- {{ $ref }}:
|
||||
name: {{ $objectName | quote }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,23 @@
|
||||
{{/* Returns Env List */}}
|
||||
{{/* Call this template:
|
||||
{{ include "tc.v1.common.lib.container.envList" (dict "rootCtx" $ "objectData" $objectData) }}
|
||||
rootCtx: The root context of the chart.
|
||||
objectData: The object data to be used to render the container.
|
||||
*/}}
|
||||
{{- define "tc.v1.common.lib.container.envList" -}}
|
||||
{{- $rootCtx := .rootCtx -}}
|
||||
{{- $objectData := .objectData -}}
|
||||
|
||||
{{- range $env := $objectData.envList -}}
|
||||
{{- if not $env.name -}}
|
||||
{{- fail "Container - Expected non-empty <envList.name>" -}}
|
||||
{{- end -}} {{/* Empty value is valid */}}
|
||||
{{- include "tc.v1.common.helper.container.envDupeCheck" (dict "rootCtx" $rootCtx "objectData" $objectData "source" "envList" "key" $env.name) -}}
|
||||
{{- $value := $env.value -}}
|
||||
{{- if kindIs "string" $env.value -}}
|
||||
{{- $value = tpl $env.value $rootCtx -}}
|
||||
{{- end }}
|
||||
- name: {{ $env.name | quote }}
|
||||
value: {{ include "tc.v1.common.helper.makeIntOrNoop" $value | quote }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,75 @@
|
||||
{{/* Returns Fixed Env */}}
|
||||
{{/* Call this template:
|
||||
{{ include "tc.v1.common.lib.container.fixedEnv" (dict "rootCtx" $ "objectData" $objectData) }}
|
||||
rootCtx: The root context of the chart.
|
||||
objectData: The object data to be used to render the container.
|
||||
*/}}
|
||||
{{- define "tc.v1.common.lib.container.fixedEnv" -}}
|
||||
{{- $rootCtx := .rootCtx -}}
|
||||
{{- $objectData := .objectData -}}
|
||||
|
||||
{{/* Avoid nil pointers */}}
|
||||
{{- if not (hasKey $objectData "fixedEnv") -}}
|
||||
{{- $_ := set $objectData "fixedEnv" dict -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $nvidiaCaps := $rootCtx.Values.containerOptions.NVIDIA_CAPS -}}
|
||||
|
||||
{{- if $objectData.fixedEnv.NVIDIA_CAPS -}}
|
||||
{{- $nvidiaCaps = $objectData.fixedEnv.NVIDIA_CAPS -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if not (deepEqual $nvidiaCaps (mustUniq $nvidiaCaps)) -}}
|
||||
{{- fail (printf "Container - Expected <fixedEnv.NVIDIA_CAPS> to have only unique values, but got [%s]" (join ", " $nvidiaCaps)) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $caps := (list "all" "compute" "utility" "graphics" "video") -}}
|
||||
{{- range $cap := $nvidiaCaps -}}
|
||||
{{- if not (mustHas $cap $caps) -}}
|
||||
{{- fail (printf "Container - Expected <fixedEnv.NVIDIA_CAPS> entry to be one of [%s], but got [%s]" (join ", " $caps) $cap) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $secContext := fromJson (include "tc.v1.common.lib.container.securityContext.calculate" (dict "rootCtx" $rootCtx "objectData" $objectData)) -}}
|
||||
|
||||
{{- $fixed := list -}}
|
||||
{{- $TZ := $objectData.fixedEnv.TZ | default $rootCtx.Values.TZ -}}
|
||||
{{- $UMASK := $objectData.fixedEnv.UMASK | default $rootCtx.Values.securityContext.container.UMASK -}}
|
||||
{{- $PUID := $objectData.fixedEnv.PUID | default $rootCtx.Values.securityContext.container.PUID -}}
|
||||
{{- if and (not (kindIs "invalid" $objectData.fixedEnv.PUID)) (eq (int $objectData.fixedEnv.PUID) 0) -}}
|
||||
{{- $PUID = $objectData.fixedEnv.PUID -}}
|
||||
{{- end -}}
|
||||
{{/* calculatedFSGroup is passed from the pod */}}
|
||||
{{- $PGID := $objectData.calculatedFSGroup -}}
|
||||
|
||||
{{- $fixed = mustAppend $fixed (dict "k" "TZ" "v" $TZ) -}}
|
||||
{{- $fixed = mustAppend $fixed (dict "k" "UMASK" "v" $UMASK) -}}
|
||||
{{- $fixed = mustAppend $fixed (dict "k" "UMASK_SET" "v" $UMASK) -}}
|
||||
{{/* TODO: Offer gpu section in resources for native helm and adjust this include, then we can remove the "if inside ixChartContext" */}}
|
||||
{{- if eq (include "tc.v1.common.lib.container.resources.gpu" (dict "rootCtx" $rootCtx "objectData" $objectData "returnBool" true)) "true" -}}
|
||||
{{- $fixed = mustAppend $fixed (dict "k" "NVIDIA_DRIVER_CAPABILITIES" "v" (join "," $nvidiaCaps)) -}}
|
||||
{{- else -}} {{/* Only when in SCALE */}}
|
||||
{{- if hasKey $rootCtx.Values.global "ixChartContext" -}}
|
||||
{{- $fixed = mustAppend $fixed (dict "k" "NVIDIA_VISIBLE_DEVICES" "v" "void") -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{/* If running as root and PUID is set (0 or greater), set related envs */}}
|
||||
{{- if and (or (eq (int $secContext.runAsUser) 0) (eq (int $secContext.runAsGroup) 0)) (ge (int $PUID) 0) -}}
|
||||
{{- $fixed = mustAppend $fixed (dict "k" "PUID" "v" $PUID) -}}
|
||||
{{- $fixed = mustAppend $fixed (dict "k" "USER_ID" "v" $PUID) -}}
|
||||
{{- $fixed = mustAppend $fixed (dict "k" "UID" "v" $PUID) -}}
|
||||
{{- $fixed = mustAppend $fixed (dict "k" "PGID" "v" $PGID) -}}
|
||||
{{- $fixed = mustAppend $fixed (dict "k" "GROUP_ID" "v" $PGID) -}}
|
||||
{{- $fixed = mustAppend $fixed (dict "k" "GID" "v" $PGID) -}}
|
||||
{{- end -}}
|
||||
{{/* If rootFS is readOnly OR does not as root, let s6 containers to know that fs is readonly */}}
|
||||
{{- if or $secContext.readOnlyRootFilesystem $secContext.runAsNonRoot -}}
|
||||
{{- $fixed = mustAppend $fixed (dict "k" "S6_READ_ONLY_ROOT" "v" "1") -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- range $env := $fixed -}}
|
||||
{{- include "tc.v1.common.helper.container.envDupeCheck" (dict "rootCtx" $rootCtx "objectData" $objectData "source" "fixedEnv" "key" $env.k) }}
|
||||
- name: {{ $env.k | quote }}
|
||||
value: {{ (include "tc.v1.common.helper.makeIntOrNoop" $env.v) | quote }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,42 @@
|
||||
{{/* Returns the image dictionary */}}
|
||||
{{/* Call this template:
|
||||
{{ include "tc.v1.common.lib.container.imageSelector" (dict "rootCtx" $ "objectData" $objectData) }}
|
||||
rootCtx: The root context of the chart.
|
||||
objectData: The object data to be used to render the container.
|
||||
*/}}
|
||||
{{- define "tc.v1.common.lib.container.imageSelector" -}}
|
||||
{{- $rootCtx := .rootCtx -}}
|
||||
{{- $objectData := .objectData -}}
|
||||
|
||||
{{- $imageObj := dict -}}
|
||||
|
||||
{{- $selector := "image" -}}
|
||||
{{- with $objectData.imageSelector -}}
|
||||
{{- $selector = tpl . $rootCtx -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if hasKey $rootCtx.Values $selector -}}
|
||||
{{- $imageObj = get $rootCtx.Values $selector -}}
|
||||
{{- else -}}
|
||||
{{- fail (printf "Container - Expected <.Values.%s> to exist" $selector) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if not $imageObj.repository -}}
|
||||
{{- fail (printf "Container - Expected non-empty <.Values.%s.repository>" $selector) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if not $imageObj.tag -}}
|
||||
{{- fail (printf "Container - Expected non-empty <.Values.%s.tag>" $selector) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if not $imageObj.pullPolicy -}}
|
||||
{{- $_ := set $imageObj "pullPolicy" "IfNotPresent" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $policies := (list "IfNotPresent" "Always" "Never") -}}
|
||||
{{- if not (mustHas $imageObj.pullPolicy $policies) -}}
|
||||
{{- fail (printf "Container - Expected <.Values.%s.pullPolicy> to be one of [%s], but got [%s]" $selector (join ", " $policies) $imageObj.pullPolicy) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $imageObj | toJson -}}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,37 @@
|
||||
{{/* Returns lifecycle */}}
|
||||
{{/* Call this template:
|
||||
{{ include "tc.v1.common.lib.container.lifecycle" (dict "rootCtx" $ "objectData" $objectData) }}
|
||||
rootCtx: The root context of the chart.
|
||||
objectData: The object data to be used to render the container.
|
||||
*/}}
|
||||
{{- define "tc.v1.common.lib.container.lifecycle" -}}
|
||||
{{- $rootCtx := .rootCtx -}}
|
||||
{{- $objectData := .objectData -}}
|
||||
|
||||
{{- $hooks := (list "preStop" "postStart") -}}
|
||||
{{- $types := (list "exec" "http" "https") -}}
|
||||
{{- with $objectData.lifecycle -}}
|
||||
{{- range $hook, $hookValues := . -}}
|
||||
{{- if not (mustHas $hook $hooks) -}}
|
||||
{{- fail (printf "Container - Expected <lifecycle> <hook> to be one of [%s], but got [%s]" (join ", " $hooks) $hook) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if not $hookValues.type -}}
|
||||
{{- fail "Container - Expected non-empty <lifecycle> <type>" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if not (mustHas $hookValues.type $types) -}}
|
||||
{{- fail (printf "Container - Expected <lifecycle> <type> to be one of [%s], but got [%s]" (join ", " $types) $hookValues.type) -}}
|
||||
{{- end }}
|
||||
{{ $hook }}:
|
||||
{{- if eq $hookValues.type "exec" -}}
|
||||
{{- include "tc.v1.common.lib.container.actions.exec" (dict "rootCtx" $rootCtx "objectData" $hookValues "caller" "lifecycle") | trim | nindent 2 -}}
|
||||
{{- else if mustHas $hookValues.type (list "http" "https") -}}
|
||||
{{- include "tc.v1.common.lib.container.actions.httpGet" (dict "rootCtx" $rootCtx "objectData" $hookValues "caller" "lifecycle") | trim | nindent 2 -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,87 @@
|
||||
{{/* Returns ports list */}}
|
||||
{{/* Call this template:
|
||||
{{ include "tc.v1.common.lib.container.ports" (dict "rootCtx" $ "objectData" $objectData) }}
|
||||
rootCtx: The root context of the chart.
|
||||
objectData: The object data to be used to render the container.
|
||||
*/}}
|
||||
{{- define "tc.v1.common.lib.container.ports" -}}
|
||||
{{- $rootCtx := .rootCtx -}}
|
||||
{{- $objectData := .objectData -}}
|
||||
|
||||
{{- range $serviceName, $serviceValues := $rootCtx.Values.service -}}
|
||||
{{- $podSelected := false -}}
|
||||
{{/* If service is enabled... */}}
|
||||
{{- if $serviceValues.enabled -}}
|
||||
|
||||
{{/* If there is a selector */}}
|
||||
{{- if $serviceValues.targetSelector -}}
|
||||
|
||||
{{/* And pod is selected */}}
|
||||
{{- if eq $serviceValues.targetSelector $objectData.podShortName -}}
|
||||
{{- $podSelected = true -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- else -}}
|
||||
{{/* If no selector is defined but pod is primary */}}
|
||||
{{- if $objectData.podPrimary -}}
|
||||
{{- $podSelected = true -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if $podSelected -}}
|
||||
{{- range $portName, $portValues := $serviceValues.ports -}}
|
||||
{{- $containerSelected := false -}}
|
||||
|
||||
{{/* If service is enabled... */}}
|
||||
{{- if $portValues.enabled -}}
|
||||
{{/* If there is a selector */}}
|
||||
{{- if $portValues.targetSelector -}}
|
||||
|
||||
{{/* And container is selected */}}
|
||||
{{- if eq $portValues.targetSelector $objectData.shortName -}}
|
||||
{{- $containerSelected = true -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- else -}}
|
||||
{{/* If no selector is defined but container is primary */}}
|
||||
{{- if $objectData.primary -}}
|
||||
{{- $containerSelected = true -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/* If the container is selected render port */}}
|
||||
{{- if $containerSelected -}}
|
||||
{{- $containerPort := $portValues.targetPort | default $portValues.port -}}
|
||||
{{- if kindIs "string" $containerPort -}}
|
||||
{{- $containerPort = (tpl $containerPort $rootCtx) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $tcpProtocols := (list "tcp" "http" "https") -}}
|
||||
{{- $protocol := tpl ($portValues.protocol | default $rootCtx.Values.fallbackDefaults.serviceProtocol) $rootCtx -}}
|
||||
{{- if mustHas $protocol $tcpProtocols -}}
|
||||
{{- $protocol = "tcp" -}}
|
||||
{{- end }}
|
||||
- name: {{ $portName }}
|
||||
containerPort: {{ $containerPort }}
|
||||
protocol: {{ $protocol | upper }}
|
||||
{{- with $portValues.hostPort }}
|
||||
hostPort: {{ . }}
|
||||
{{- else }}
|
||||
hostPort: null
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- end -}}
|
||||
{{/* Turning hostNetwork on, it creates hostPort automatically and turning it back off does not remove them. Setting hostPort explicitly to null will remove them.
|
||||
There are still cases that hostPort is not removed, for example, if you have a TCP and UDP port with the same number. Only the TCPs hostPort will be removed.
|
||||
Also note that setting hostPort to null always, it will NOT affect hostNetwork, as it will still create the hostPorts.
|
||||
It only helps to remove them when hostNetwork is turned off.
|
||||
*/}}
|
||||
@@ -0,0 +1,40 @@
|
||||
{{/* Containers Basic Validation */}}
|
||||
{{/* Call this template:
|
||||
{{ include "tc.v1.common.lib.container.primaryValidation" (dict "rootCtx" $rootCtx "objectData" $objectData) -}}
|
||||
*/}}
|
||||
{{- define "tc.v1.common.lib.container.primaryValidation" -}}
|
||||
{{- $objectData := .objectData -}}
|
||||
{{- $rootCtx := .rootCtx -}}
|
||||
|
||||
{{/* Initialize values */}}
|
||||
{{- $hasPrimary := false -}}
|
||||
{{- $hasEnabled := false -}}
|
||||
|
||||
{{/* Go over the contaienrs */}}
|
||||
{{- range $name, $container := $objectData.podSpec.containers -}}
|
||||
|
||||
{{/* If container is enabled */}}
|
||||
{{- if $container.enabled -}}
|
||||
{{- $hasEnabled = true -}}
|
||||
|
||||
{{/* And container is primary */}}
|
||||
{{- if and (hasKey $container "primary") ($container.primary) -}}
|
||||
|
||||
{{/* Fail if there is already a primary container */}}
|
||||
{{- if $hasPrimary -}}
|
||||
{{- fail "Container - Only one container can be primary per workload" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $hasPrimary = true -}}
|
||||
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- end -}}
|
||||
|
||||
{{/* Require at least one primary container, if any enabled */}}
|
||||
{{- if and $hasEnabled (not $hasPrimary) -}}
|
||||
{{- fail "Container - At least one enabled container must be primary per workload" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,98 @@
|
||||
{{/* Returns Probes */}}
|
||||
{{/* Call this template:
|
||||
{{ include "tc.v1.common.lib.container.probes" (dict "rootCtx" $ "objectData" $objectData) }}
|
||||
rootCtx: The root context of the chart.
|
||||
objectData: The object data to be used to render the container.
|
||||
*/}}
|
||||
{{- define "tc.v1.common.lib.container.probes" -}}
|
||||
{{- $rootCtx := .rootCtx -}}
|
||||
{{- $objectData := .objectData -}}
|
||||
|
||||
{{- $probeNames := (list "liveness" "readiness" "startup") -}}
|
||||
{{- $probeTypes := (list "http" "https" "tcp" "grpc" "exec") -}}
|
||||
|
||||
{{- if not $objectData.probes -}}
|
||||
{{- fail "Container - Expected non-empty <probes>" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- range $key := $probeNames -}}
|
||||
{{- if not (get $objectData.probes $key) -}}
|
||||
{{- fail (printf "Container - Expected <probes.%s> to be defined" $key) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- range $probeName, $probe := $objectData.probes -}}
|
||||
|
||||
{{- if not (mustHas $probeName $probeNames) -}}
|
||||
{{- fail (printf "Container - Expected probe to be one of [%s], but got [%s]" (join ", " $probeNames) $probeName) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $isEnabled := true -}}
|
||||
{{- if kindIs "bool" $probe.enabled -}}
|
||||
{{- $isEnabled = $probe.enabled -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if $isEnabled -}}
|
||||
|
||||
{{- $probeType := $rootCtx.Values.fallbackDefaults.probeType -}}
|
||||
|
||||
{{- with $probe.type -}}
|
||||
{{- $probeType = tpl . $rootCtx -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if not (mustHas $probeType $probeTypes) -}}
|
||||
{{- fail (printf "Container - Expected probe type to be one of [%s], but got [%s]" (join ", " $probeTypes) $probeType) -}}
|
||||
{{- end }}
|
||||
{{ $probeName }}Probe:
|
||||
{{- if (mustHas $probeType (list "http" "https")) -}}
|
||||
{{- include "tc.v1.common.lib.container.actions.httpGet" (dict "rootCtx" $rootCtx "objectData" $probe "caller" "probes") | trim | nindent 2 -}}
|
||||
{{- else if eq $probeType "tcp" -}}
|
||||
{{- include "tc.v1.common.lib.container.actions.tcpSocket" (dict "rootCtx" $rootCtx "objectData" $probe "caller" "probes") | trim | nindent 2 -}}
|
||||
{{- else if eq $probeType "grpc" -}}
|
||||
{{- include "tc.v1.common.lib.container.actions.grpc" (dict "rootCtx" $rootCtx "objectData" $probe "caller" "probes") | trim | nindent 2 -}}
|
||||
{{- else if eq $probeType "exec" -}}
|
||||
{{- include "tc.v1.common.lib.container.actions.exec" (dict "rootCtx" $rootCtx "objectData" $probe "caller" "probes") | trim | nindent 2 -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- include "tc.v1.common.lib.container.probeTimeouts" (dict "rootCtx" $rootCtx "objectData" $probe "probeName" $probeName) | trim | nindent 2 -}}
|
||||
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/* Returns Probe Timeouts */}}
|
||||
{{/* Call this template:
|
||||
{{ include "tc.v1.common.lib.container.probeTimeouts" (dict "rootCtx" $ "objectData" $objectData) }}
|
||||
rootCtx: The root context of the chart.
|
||||
objectData: The object data to be used to render the container.
|
||||
*/}}
|
||||
{{- define "tc.v1.common.lib.container.probeTimeouts" -}}
|
||||
{{- $rootCtx := .rootCtx -}}
|
||||
{{- $objectData := .objectData -}}
|
||||
{{- $probeName := .probeName -}}
|
||||
|
||||
{{- $timeouts := mustDeepCopy (get $rootCtx.Values.fallbackDefaults.probeTimeouts $probeName) -}}
|
||||
|
||||
{{- if $objectData.spec -}} {{/* Overwrite with defined timeouts */}}
|
||||
{{- $timeouts = mustMergeOverwrite $timeouts $objectData.spec -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $keys := (list "initialDelaySeconds" "failureThreshold" "successThreshold" "timeoutSeconds" "periodSeconds") -}}
|
||||
{{- range $key := $keys -}}
|
||||
{{- $number := get $timeouts $key -}}
|
||||
{{- if not (mustHas (kindOf $number) (list "float64" "int" "int64")) -}}
|
||||
{{- fail (printf "Container - Expected <probes> <%s> to be a number, but got [%v]" $key $number) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if mustHas $probeName (list "liveness" "startup") -}}
|
||||
{{- if ne (int $timeouts.successThreshold) 1 -}}
|
||||
{{- fail (printf "Container - Expected <probes> <successThreshold> to be 1 on [%s] probe" $probeName) -}}
|
||||
{{- end -}}
|
||||
{{- end }}
|
||||
initialDelaySeconds: {{ $timeouts.initialDelaySeconds }}
|
||||
failureThreshold: {{ $timeouts.failureThreshold }}
|
||||
successThreshold: {{ $timeouts.successThreshold }}
|
||||
timeoutSeconds: {{ $timeouts.timeoutSeconds }}
|
||||
periodSeconds: {{ $timeouts.periodSeconds }}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,140 @@
|
||||
{{/* Returns Resources */}}
|
||||
{{/* Call this template:
|
||||
{{ include "tc.v1.common.lib.container.resources" (dict "rootCtx" $ "objectData" $objectData) }}
|
||||
rootCtx: The root context of the chart.
|
||||
objectData: The object data to be used to render the container.
|
||||
*/}}
|
||||
{{- define "tc.v1.common.lib.container.resources" -}}
|
||||
{{- $rootCtx := .rootCtx -}}
|
||||
{{- $objectData := .objectData -}}
|
||||
|
||||
{{- $resources := mustDeepCopy $rootCtx.Values.resources -}}
|
||||
|
||||
{{- if $objectData.resources -}}
|
||||
{{- $resources = mustMergeOverwrite $resources $objectData.resources -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- include "tc.v1.common.lib.container.resources.validation" (dict "resources" $resources) -}}
|
||||
|
||||
requests:
|
||||
cpu: {{ $resources.requests.cpu }}
|
||||
memory: {{ $resources.requests.memory }}
|
||||
{{- if $resources.limits }}
|
||||
limits:
|
||||
{{- with $resources.limits.cpu }} {{/* Passing 0, will not render it, meaning unlimited */}}
|
||||
cpu: {{ . }}
|
||||
{{- end -}}
|
||||
{{- with $resources.limits.memory }} {{/* Passing 0, will not render it, meaning unlimited */}}
|
||||
memory: {{ . }}
|
||||
{{- end -}}
|
||||
{{- include "tc.v1.common.lib.container.resources.gpu" (dict "rootCtx" $rootCtx "objectData" $objectData) | trim | nindent 2 -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/* Returns GPU resource */}}
|
||||
{{/* Call this template:
|
||||
{{ include "tc.v1.common.lib.container.resources.gpu" (dict "rootCtx" $rootCtx "objectData" $objectData) }}
|
||||
rootCtx: The root context of the chart.
|
||||
objectData: The object data to be used to render the container.
|
||||
*/}}
|
||||
{{- define "tc.v1.common.lib.container.resources.gpu" -}}
|
||||
{{- $objectData := .objectData -}}
|
||||
{{- $rootCtx := .rootCtx -}}
|
||||
{{- $returnBool := .returnBool -}}
|
||||
|
||||
{{- $gpuResource := list -}}
|
||||
|
||||
{{- range $GPUValues := $rootCtx.Values.scaleGPU -}}
|
||||
{{- if not $GPUValues.gpu -}}
|
||||
{{- fail "Container - Expected non-empty <scaleGPU.gpu>" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $selected := false -}}
|
||||
|
||||
{{/* Parse selector if defined */}}
|
||||
{{- if $GPUValues.targetSelector -}}
|
||||
{{- range $podName, $containers := $GPUValues.targetSelector -}}
|
||||
{{- if not $containers -}}
|
||||
{{- fail "Container - Expected non-empty list under pod in <scaleGPU.targetSelector>" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if and (eq $podName $objectData.podShortName) (mustHas $objectData.shortName $containers) -}}
|
||||
{{- $selected = true -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{/* If no selector, select primary pod/container */}}
|
||||
{{- else if and $objectData.podPrimary $objectData.primary -}}
|
||||
{{- $selected = true -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if $selected -}}
|
||||
{{- $gpuResource = mustAppend $gpuResource $GPUValues.gpu -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if not $returnBool -}}
|
||||
{{- range $gpu := $gpuResource -}}
|
||||
{{- range $k, $v := $gpu -}}
|
||||
{{- if or (kindIs "invalid" $v) (eq (toString $v) "") -}}
|
||||
{{- fail "Container - Expected non-empty <scaleGPU> <value>" -}}
|
||||
{{- end -}} {{/* Don't try to schedule 0 GPUs */}}
|
||||
{{- if gt (int $v) 0 }}
|
||||
{{ $k }}: {{ $v | quote }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- else -}}
|
||||
{{- if $gpuResource -}}
|
||||
{{- "true" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- end -}}
|
||||
|
||||
{{/* Validates resources to match a pattern */}}
|
||||
{{/* Call this template:
|
||||
{{ include "tc.v1.common.lib.container.resources.validation" (dict "resources" $resources) }}
|
||||
rootCtx: The root context of the chart.
|
||||
resources: The resources object
|
||||
*/}}
|
||||
{{- define "tc.v1.common.lib.container.resources.validation" -}}
|
||||
{{- $resources := .resources -}}
|
||||
{{/* CPU: https://regex101.com/r/D4HouI/1 */}}
|
||||
{{/* MEM: https://regex101.com/r/NNPV2D/1 */}}
|
||||
{{- $regex := (dict
|
||||
"cpu" "^(0\\.[1-9]|[1-9][0-9]*)(\\.[0-9]|m?)$"
|
||||
"memory" "^[1-9][0-9]*([EPTGMK]i?|e[0-9]+)?$") -}}
|
||||
{{- $errorMsg := (dict
|
||||
"cpu" "(Plain Integer - eg. 1), (Float - eg. 0.5), (Milicpu - eg. 500m)"
|
||||
"memory" "(Suffixed with E/P/T/G/M/K - eg. 1G), (Suffixed with Ei/Pi/Ti/Gi/Mi/Ki - eg. 1Gi), (Plain Integer in bytes - eg. 1024), (Exponent - eg. 134e6)") -}}
|
||||
|
||||
{{- $resourceTypes := (list "cpu" "memory") -}}
|
||||
|
||||
{{- range $category := (list "requests") -}} {{/* We can also add "limits" here if we want to require them */}}
|
||||
{{- if not (get $resources $category) -}}
|
||||
{{- fail (printf "Container - Expected non-empty <resources.%s>" $category) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- range $type := $resourceTypes -}}
|
||||
{{- if not (get (get $resources $category) $type) -}}
|
||||
{{- fail (printf "Container - Expected non-empty <resources.%s.%s>" $category $type) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- range $key := (list "requests" "limits") -}}
|
||||
{{- $resourceCategory := (get $resources $key) -}}
|
||||
{{- if $resourceCategory -}}
|
||||
|
||||
{{- range $type := $resourceTypes -}}
|
||||
{{- $resourceValue := (get $resourceCategory $type) -}}
|
||||
{{- if $resourceValue -}} {{/* Only try to match defined values */}}
|
||||
{{- if not (mustRegexMatch (get $regex $type) (toString $resourceValue)) -}}
|
||||
{{- fail (printf "Container - Expected <resources.%s.%s> to have one of the following formats [%s], but got [%s]" $key $type (get $errorMsg $type) $resourceValue) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,181 @@
|
||||
{{/* Returns Container Security Context */}}
|
||||
{{/* Call this template:
|
||||
{{ include "tc.v1.common.lib.container.securityContext" (dict "rootCtx" $ "objectData" $objectData) }}
|
||||
rootCtx: The root context of the chart.
|
||||
objectData: The object data to be used to render the container.
|
||||
*/}}
|
||||
{{- define "tc.v1.common.lib.container.securityContext" -}}
|
||||
{{- $rootCtx := .rootCtx -}}
|
||||
{{- $objectData := .objectData -}}
|
||||
|
||||
{{/* Initialize from the "global" options */}}
|
||||
{{- $secContext := fromJson (include "tc.v1.common.lib.container.securityContext.calculate" (dict "rootCtx" $rootCtx "objectData" $objectData)) }}
|
||||
runAsNonRoot: {{ $secContext.runAsNonRoot }}
|
||||
runAsUser: {{ $secContext.runAsUser }}
|
||||
runAsGroup: {{ $secContext.runAsGroup }}
|
||||
readOnlyRootFilesystem: {{ $secContext.readOnlyRootFilesystem }}
|
||||
allowPrivilegeEscalation: {{ $secContext.allowPrivilegeEscalation }}
|
||||
privileged: {{ $secContext.privileged }}
|
||||
seccompProfile:
|
||||
type: {{ $secContext.seccompProfile.type }}
|
||||
{{- if eq $secContext.seccompProfile.type "Localhost" }}
|
||||
localhostProfile: {{ $secContext.seccompProfile.profile }}
|
||||
{{- end }}
|
||||
capabilities:
|
||||
{{- if $secContext.capabilities.add }}
|
||||
add:
|
||||
{{- range $secContext.capabilities.add }}
|
||||
- {{ . }}
|
||||
{{- end -}}
|
||||
{{- else }}
|
||||
add: []
|
||||
{{- end -}}
|
||||
{{- if $secContext.capabilities.drop }}
|
||||
drop:
|
||||
{{- range $secContext.capabilities.drop }}
|
||||
- {{ . }}
|
||||
{{- end -}}
|
||||
{{- else }}
|
||||
drop: []
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/* Calculates Container Security Context */}}
|
||||
{{/* Call this template:
|
||||
{{ include "tc.v1.common.lib.container.securityContext.calculate" (dict "rootCtx" $ "objectData" $objectData) }}
|
||||
rootCtx: The root context of the chart.
|
||||
objectData: The object data to be used to render the container.
|
||||
*/}}
|
||||
{{- define "tc.v1.common.lib.container.securityContext.calculate" -}}
|
||||
{{- $rootCtx := .rootCtx -}}
|
||||
{{- $objectData := .objectData -}}
|
||||
|
||||
{{- $mustPrivileged := false -}}
|
||||
{{- range $persistenceName, $persistenceValues := $rootCtx.Values.persistence -}}
|
||||
{{- if $persistenceValues.enabled -}}
|
||||
{{- if eq $persistenceValues.type "device" -}}
|
||||
{{- $volume := (fromJson (include "tc.v1.common.lib.container.volumeMount.isSelected" (dict "persistenceName" $persistenceName "persistenceValues" $persistenceValues "objectData" $objectData "key" "persistence"))) -}}
|
||||
{{- if $volume -}} {{/* If a volume is returned, it means that the container has an assigned device */}}
|
||||
{{- $mustPrivileged = true -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if not $rootCtx.Values.securityContext.container -}}
|
||||
{{- fail "Container - Expected non-empty <.Values.securityContext.container>" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/* Initialize from the "global" options */}}
|
||||
{{- $secContext := mustDeepCopy $rootCtx.Values.securityContext.container -}}
|
||||
|
||||
{{/* Override with containers options */}}
|
||||
{{- with $objectData.securityContext -}}
|
||||
{{- $secContext = mustMergeOverwrite $secContext . -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/* Validations, as we might endup with null values after merge */}}
|
||||
{{- range $key := (list "runAsUser" "runAsGroup") -}}
|
||||
{{- $value := (get $secContext $key) -}}
|
||||
{{- if not (mustHas (kindOf $value) (list "float64" "int" "int64")) -}}
|
||||
{{- fail (printf "Container - Expected <securityContext.%s> to be [int], but got [%v] of type [%s]" $key $value (kindOf $value)) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if or (eq (int $secContext.runAsUser) 0) (eq (int $secContext.runAsGroup) 0) -}}
|
||||
{{- $_ := set $secContext "runAsNonRoot" false -}}
|
||||
{{- else -}}
|
||||
{{- $_ := set $secContext "runAsNonRoot" true -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if $secContext.privileged -}} {{/* When privileged is true, allowPrivilegeEscalation is required */}}
|
||||
{{- $_ := set $secContext "allowPrivilegeEscalation" true -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if $mustPrivileged -}}
|
||||
{{- $_ := set $secContext "privileged" true -}}
|
||||
{{- $_ := set $secContext "allowPrivilegeEscalation" true -}}
|
||||
{{- $_ := set $secContext "runAsNonRoot" false -}}
|
||||
{{- $_ := set $secContext "runAsUser" 0 -}}
|
||||
{{- $_ := set $secContext "runAsGroup" 0 -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- range $key := (list "privileged" "allowPrivilegeEscalation" "runAsNonRoot" "readOnlyRootFilesystem") -}}
|
||||
{{- $value := (get $secContext $key) -}}
|
||||
{{- if not (kindIs "bool" $value) -}}
|
||||
{{- fail (printf "Container - Expected <securityContext.%s> to be [bool], but got [%s] of type [%s]" $key $value (kindOf $value)) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if not $secContext.seccompProfile -}}
|
||||
{{- fail "Container - Expected <securityContext.seccompProfile> to be defined" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $profiles := (list "RuntimeDefault" "Localhost" "Unconfined") -}}
|
||||
{{- if not (mustHas $secContext.seccompProfile.type $profiles) -}}
|
||||
{{- fail (printf "Container - Expected <securityContext.seccompProfile> to be one of [%s], but got [%s]" (join ", " $profiles) $secContext.seccompProfile.type) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if eq $secContext.seccompProfile.type "Localhost" -}}
|
||||
{{- if not $secContext.seccompProfile.profile -}}
|
||||
{{- fail "Container - Expected <securityContext.seccompProfile.profile> to be defined on type [Localhost]" -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if not $secContext.capabilities -}}
|
||||
{{- fail "Container - Expected <securityContext.capabilities> to be defined" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $tempObjectData := (dict "shortName" $objectData.podShortName "primary" $objectData.podPrimary) -}}
|
||||
{{- $portRange := fromJson (include "tc.v1.common.lib.helpers.securityContext.getPortRange" (dict "rootCtx" $rootCtx "objectData" $tempObjectData)) -}}
|
||||
{{- if and $portRange.low (le (int $portRange.low) 1024) -}} {{/* If a container wants to bind a port <= 1024 add NET_BIND_SERVICE */}}
|
||||
{{- $addCap := $secContext.capabilities.add -}}
|
||||
{{- if not (mustHas "NET_BIND_SERIVCE" $addCap) -}}
|
||||
{{- $addCap = mustAppend $addCap "NET_BIND_SERVICE" -}}
|
||||
{{- end -}}
|
||||
{{- $_ := set $secContext.capabilities "add" $addCap -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Most containers that run as root, is because it has to chown
|
||||
files before switching to another user.
|
||||
Lets add automatically the CHOWN cap.
|
||||
*/}}
|
||||
{{- if eq (int $secContext.runAsUser) 0 -}}
|
||||
|
||||
{{- if not (kindIs "bool" $secContext.capabilities.disableS6Caps) -}}
|
||||
{{- fail (printf "Container - Expected <securityContext.capabilities.disableS6Caps> to be [bool], but got [%s] of type [%s]" $secContext.capabilities.disableS6Caps (kindOf $secContext.capabilities.disableS6Caps)) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $addCap := $secContext.capabilities.add -}}
|
||||
|
||||
{{- if not $secContext.capabilities.disableS6Caps -}}
|
||||
{{- $addCap = mustAppend $addCap "CHOWN" -}}
|
||||
{{- $addCap = mustAppend $addCap "SETUID" -}}
|
||||
{{- $addCap = mustAppend $addCap "SETGID" -}}
|
||||
{{- $addCap = mustAppend $addCap "FOWNER" -}}
|
||||
{{- $addCap = mustAppend $addCap "DAC_OVERRIDE" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $_ := set $secContext.capabilities "add" $addCap -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- range $key := (list "add" "drop") -}}
|
||||
{{- $item := (get $secContext.capabilities $key) -}}
|
||||
{{- if not (kindIs "slice" $item) -}}
|
||||
{{- fail (printf "Container - Expected <securityContext.capabilities.%s> to be [list], but got [%s]" $key (kindOf $item)) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- range $item -}}
|
||||
{{- if not (kindIs "string" .) -}}
|
||||
{{- fail (printf "Container - Expected items of <securityContext.capabilities.%s> to be [string], but got [%s]" $key (kindOf .)) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if not (deepEqual (uniq $item) $item) -}}
|
||||
{{- fail (printf "Container - Expected items of <securityContext.capabilities.%s> to be unique, but got [%s]" $key (join ", " $item)) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $secContext | toJson -}}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,33 @@
|
||||
{{/* Returns termination */}}
|
||||
{{/* Call this template:
|
||||
{{ include "tc.v1.common.lib.container.termination" (dict "rootCtx" $ "objectData" $objectData) }}
|
||||
rootCtx: The root context of the chart.
|
||||
objectData: The object data to be used to render the container.
|
||||
*/}}
|
||||
{{- define "tc.v1.common.lib.container.termination" -}}
|
||||
{{- $rootCtx := .rootCtx -}}
|
||||
{{- $objectData := .objectData -}}
|
||||
|
||||
{{- $termination := (dict "messagePath" "" "messagePolicy" "") -}}
|
||||
|
||||
{{- with $objectData.termination -}}
|
||||
{{- with .messagePath -}}
|
||||
{{- $_ := set $termination "messagePath" (tpl . $rootCtx) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- with .messagePolicy -}}
|
||||
|
||||
{{- $policy := (tpl . $rootCtx) -}}
|
||||
|
||||
{{- $policies := (list "File" "FallbackToLogsOnError") -}}
|
||||
{{- if not (mustHas $policy $policies) -}}
|
||||
{{- fail (printf "Container - Expected <termination.messagePolicy> to be one of [%s], but got [%s]" (join ", " $policies) $policy) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $_ := set $termination "messagePolicy" $policy -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- end -}}
|
||||
|
||||
{{- $termination | toJson -}}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,147 @@
|
||||
{{/* Returns volumeMount list */}}
|
||||
{{/* Call this template:
|
||||
{{ include "tc.v1.common.lib.container.volumeMount" (dict "rootCtx" $ "objectData" $objectData) }}
|
||||
rootCtx: The root context of the chart.
|
||||
objectData: The object data to be used to render the container.
|
||||
*/}}
|
||||
{{- define "tc.v1.common.lib.container.volumeMount" -}}
|
||||
{{- $rootCtx := .rootCtx -}}
|
||||
{{- $objectData := .objectData -}}
|
||||
|
||||
{{- $volMounts := list -}}
|
||||
|
||||
{{- $codeServerIgnoredTypes := (list "configmap" "secret") -}}
|
||||
{{- $keys := (list "persistence") -}}
|
||||
{{- if eq $objectData.podType "StatefulSet" -}}
|
||||
{{- $keys = mustAppend $keys "volumeClaimTemplates" -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- range $key := $keys -}}
|
||||
{{- range $persistenceName, $persistenceValues := (get $rootCtx.Values $key) -}}
|
||||
{{- if $persistenceValues.enabled -}}
|
||||
{{/* Dont try to mount configmap/sercet to codeserver */}}
|
||||
{{- if not (and (eq $objectData.shortName "codeserver") (mustHas $persistenceValues.type $codeServerIgnoredTypes)) -}}
|
||||
{{- $volMount := (fromJson (include "tc.v1.common.lib.container.volumeMount.isSelected" (dict "persistenceName" $persistenceName "persistenceValues" $persistenceValues "objectData" $objectData "key" $key))) -}}
|
||||
{{- if $volMount -}}
|
||||
{{- $volMounts = mustAppend $volMounts $volMount -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- range $volMount := $volMounts -}}
|
||||
{{/* Expand values */}}
|
||||
{{- $_ := set $volMount "mountPath" (tpl $volMount.mountPath $rootCtx) -}}
|
||||
{{- $_ := set $volMount "subPath" (tpl $volMount.subPath $rootCtx) -}}
|
||||
{{- $_ := set $volMount "mountPropagation" (tpl $volMount.mountPropagation $rootCtx) -}}
|
||||
|
||||
{{- if not $volMount.mountPath -}}
|
||||
{{- fail (printf "%s - Expected non-empty <mountPath>" (camelcase $volMount.key)) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if not (hasPrefix "/" $volMount.mountPath) -}}
|
||||
{{- fail (printf "%s - Expected <mountPath> to start with a forward slash [/]" (camelcase $volMount.key)) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $propagationTypes := (list "None" "HostToContainer" "Bidirectional") -}}
|
||||
{{- if and $volMount.mountPropagation (not (mustHas $volMount.mountPropagation $propagationTypes)) -}}
|
||||
{{- fail (printf "%s - Expected <mountPropagation> to be one of [%s], but got [%s]" (camelcase $volMount.key) (join ", " $propagationTypes) $volMount.mountPropagation) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if not (kindIs "bool" $volMount.readOnly) -}}
|
||||
{{- fail (printf "%s - Expected <readOnly> to be [boolean], but got [%s]" (camelcase $volMount.key) (kindOf $volMount.readOnly)) -}}
|
||||
{{- end }}
|
||||
- name: {{ $volMount.name }}
|
||||
mountPath: {{ $volMount.mountPath }}
|
||||
readOnly: {{ $volMount.readOnly }}
|
||||
{{- with $volMount.subPath }}
|
||||
subPath: {{ . }}
|
||||
{{- end -}}
|
||||
{{- with $volMount.mountPropagation }}
|
||||
mountPropagation: {{ . }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- end -}}
|
||||
|
||||
{{- define "tc.v1.common.lib.container.volumeMount.isSelected" -}}
|
||||
{{- $persistenceName := .persistenceName -}}
|
||||
{{- $persistenceValues := .persistenceValues -}}
|
||||
{{- $objectData := .objectData -}}
|
||||
{{- $key := .key -}}
|
||||
|
||||
{{/* Initialize from the default values */}}
|
||||
{{- $volMount := dict -}}
|
||||
{{- $_ := set $volMount "name" $persistenceName -}}
|
||||
{{- $_ := set $volMount "key" $key -}}
|
||||
{{- if eq $persistenceValues.type "device" -}} {{/* On devices use the hostPath as default if mountpath is not defined */}}
|
||||
{{- $_ := set $volMount "mountPath" ($persistenceValues.mountPath | default $persistenceValues.hostPath | default "") -}}
|
||||
{{- else -}}
|
||||
{{- $_ := set $volMount "mountPath" ($persistenceValues.mountPath | default "") -}}
|
||||
{{- end -}}
|
||||
{{- $_ := set $volMount "subPath" ($persistenceValues.subPath | default "") -}}
|
||||
{{- $_ := set $volMount "readOnly" ($persistenceValues.readOnly | default false) -}}
|
||||
{{- $_ := set $volMount "mountPropagation" ($persistenceValues.mountPropagation | default "") -}}
|
||||
|
||||
{{- $return := false -}}
|
||||
{{/* If targetSelectAll is set, means all pods/containers */}} {{/* targetSelectAll does not make sense for vct */}}
|
||||
{{- if and $persistenceValues.targetSelectAll (ne $key "volumeClaimTemplates") -}}
|
||||
{{- $return = true -}}
|
||||
{{/* Set custom path on autopermissions container */}}
|
||||
{{- if and (eq $objectData.shortName "autopermissions") $persistenceValues.autoPermissions -}}
|
||||
{{- if $persistenceValues.autoPermissions.enabled -}}
|
||||
{{- $return = true -}}
|
||||
{{- $_ := set $volMount "mountPath" (printf "/mounts/%v" $persistenceName) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/* If the container is the autopermission */}}
|
||||
{{- else if (eq $objectData.shortName "autopermissions") -}}
|
||||
{{- if $persistenceValues.autoPermissions -}}
|
||||
{{- if $persistenceValues.autoPermissions.enabled -}}
|
||||
{{- $return = true -}}
|
||||
{{- $_ := set $volMount "mountPath" (printf "/mounts/%v" $persistenceName) -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/* Else if selector is defined */}}
|
||||
{{- else if $persistenceValues.targetSelector -}}
|
||||
{{/* If pod is selected */}}
|
||||
{{- if mustHas $objectData.podShortName ($persistenceValues.targetSelector | keys) -}}
|
||||
{{- $selectorValues := (get $persistenceValues.targetSelector $objectData.podShortName) -}}
|
||||
{{- if not (kindIs "map" $selectorValues) -}}
|
||||
{{- fail (printf "%s - Expected <targetSelector.%s> to be a [dict], but got [%s]" (camelcase $key) $objectData.podShortName (kindOf $selectorValues)) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if not $selectorValues -}}
|
||||
{{- fail (printf "%s - Expected non-empty <targetSelector.%s>" (camelcase $key) $objectData.podShortName) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/* If container is selected */}}
|
||||
{{- if or (mustHas $objectData.shortName ($selectorValues | keys)) (eq $objectData.shortName "codeserver") -}}
|
||||
{{/* Merge with values that might be set for the specific container */}}
|
||||
{{- $fetchedSelectorValues := (get $selectorValues $objectData.shortName) -}}
|
||||
{{- if and (eq $objectData.shortName "codeserver") (not $fetchedSelectorValues) -}}
|
||||
{{- $fetchedSelectorValues = (get $selectorValues ($selectorValues | keys | first)) -}}
|
||||
{{- end -}}
|
||||
{{- $volMount = mustMergeOverwrite $volMount $fetchedSelectorValues -}}
|
||||
{{- $return = true -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/* if its the codeserver */}}
|
||||
{{- else if (eq $objectData.shortName "codeserver") -}}
|
||||
{{- $return = true -}}
|
||||
|
||||
{{/* Else if not selector, but pod and container is primary */}}
|
||||
{{- else if and $objectData.podPrimary $objectData.primary -}}
|
||||
{{- $return = true -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if $return -}} {{/* If it's selected, return the volumeMount */}}
|
||||
{{- $volMount | toJson -}}
|
||||
{{- else -}} {{/* Else return an empty dict */}}
|
||||
{{- dict | toJson -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,18 @@
|
||||
{{/* Returns exec action */}}
|
||||
{{/* Call this template:
|
||||
{{ include "tc.v1.common.lib.container.actions.exec" (dict "rootCtx" $ "objectData" $objectData "caller" $caller) }}
|
||||
rootCtx: The root context of the chart.
|
||||
objectData: The object data to be used to render the container.
|
||||
*/}}
|
||||
{{- define "tc.v1.common.lib.container.actions.exec" -}}
|
||||
{{- $rootCtx := .rootCtx -}}
|
||||
{{- $objectData := .objectData -}}
|
||||
{{- $caller := .caller -}}
|
||||
|
||||
{{- if not $objectData.command -}}
|
||||
{{- fail (printf "Container - Expected non-empty <%s> <command> on [exec] type" $caller) -}}
|
||||
{{- end }}
|
||||
exec:
|
||||
command:
|
||||
{{- include "tc.v1.common.lib.container.command" (dict "rootCtx" $rootCtx "objectData" $objectData) | trim | nindent 4}}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,23 @@
|
||||
{{/* Returns grpc action */}}
|
||||
{{/* Call this template:
|
||||
{{ include "tc.v1.common.lib.container.actions.tcpSocket" (dict "rootCtx" $ "objectData" $objectData "caller" $caller) }}
|
||||
rootCtx: The root context of the chart.
|
||||
objectData: The object data to be used to render the container.
|
||||
*/}}
|
||||
{{- define "tc.v1.common.lib.container.actions.grpc" -}}
|
||||
{{- $rootCtx := .rootCtx -}}
|
||||
{{- $objectData := .objectData -}}
|
||||
{{- $caller := .caller -}}
|
||||
|
||||
{{- if not $objectData.port -}}
|
||||
{{- fail (printf "Container - Expected non-empty <%s> <port> on [grpc] type" $caller) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $port := $objectData.port -}}
|
||||
|
||||
{{- if kindIs "string" $port -}}
|
||||
{{- $port = tpl $port $rootCtx -}}
|
||||
{{- end }}
|
||||
grpc:
|
||||
port: {{ $port }}
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,53 @@
|
||||
{{/* Returns httpGet action */}}
|
||||
{{/* Call this template:
|
||||
{{ include "tc.v1.common.lib.container.actions.httpGet" (dict "rootCtx" $ "objectData" $objectData "caller" $caller) }}
|
||||
rootCtx: The root context of the chart.
|
||||
objectData: The object data to be used to render the container.
|
||||
*/}}
|
||||
{{- define "tc.v1.common.lib.container.actions.httpGet" -}}
|
||||
{{- $rootCtx := .rootCtx -}}
|
||||
{{- $objectData := .objectData -}}
|
||||
{{- $caller := .caller -}}
|
||||
|
||||
{{- if not $objectData.port -}}
|
||||
{{- fail (printf "Container - Expected non-empty <%s> <port> on [http] type" $caller) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $port := $objectData.port -}}
|
||||
{{- $path := "/" -}}
|
||||
{{- $scheme := "http" -}}
|
||||
|
||||
{{- if kindIs "string" $port -}}
|
||||
{{- $port = tpl $port $rootCtx -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- with $objectData.path -}}
|
||||
{{- $path = tpl . $rootCtx -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- if not (hasPrefix "/" $path) -}}
|
||||
{{- fail (printf "Container - Expected <%s> <path> to start with a forward slash [/] on <http> type" $caller) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- with $objectData.type -}}
|
||||
{{- $scheme = tpl . $rootCtx -}}
|
||||
{{- end }}
|
||||
httpGet:
|
||||
{{- with $objectData.host }}
|
||||
host: {{ tpl . $rootCtx }}
|
||||
{{- end }}
|
||||
port: {{ $port }}
|
||||
path: {{ $path }}
|
||||
scheme: {{ $scheme | upper }}
|
||||
{{- with $objectData.httpHeaders }}
|
||||
httpHeaders:
|
||||
{{- range $name, $value := . }}
|
||||
{{- if not $value -}}
|
||||
{{- fail "Container - Expected non-empty <value> on <httpHeaders>" -}}
|
||||
{{- end }}
|
||||
- name: {{ $name }}
|
||||
value: {{ tpl (toString $value) $rootCtx | quote }}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- end -}}
|
||||
@@ -0,0 +1,23 @@
|
||||
{{/* Returns tcpSocket action */}}
|
||||
{{/* Call this template:
|
||||
{{ include "tc.v1.common.lib.container.actions.tcpSocket" (dict "rootCtx" $ "objectData" $objectData "caller" $caller) }}
|
||||
rootCtx: The root context of the chart.
|
||||
objectData: The object data to be used to render the container.
|
||||
*/}}
|
||||
{{- define "tc.v1.common.lib.container.actions.tcpSocket" -}}
|
||||
{{- $rootCtx := .rootCtx -}}
|
||||
{{- $objectData := .objectData -}}
|
||||
{{- $caller := .caller -}}
|
||||
|
||||
{{- if not $objectData.port -}}
|
||||
{{- fail (printf "Container - Expected non-empty <%s> <port> on [tcp] type" $caller) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- $port := $objectData.port -}}
|
||||
|
||||
{{- if kindIs "string" $port -}}
|
||||
{{- $port = tpl $port $rootCtx -}}
|
||||
{{- end }}
|
||||
tcpSocket:
|
||||
port: {{ $port }}
|
||||
{{- end -}}
|
||||
Reference in New Issue
Block a user