initial container plumbing

This commit is contained in:
Stavros kois
2023-02-09 19:18:06 +02:00
parent 37d1e36a7b
commit d7e3116bf0
11 changed files with 451 additions and 25 deletions
@@ -0,0 +1,128 @@
suite: container image test
templates:
- common.yaml
tests:
- it: should generate correct image
set:
imageDictToUse: image
image: &image
repository: nginx
tag: 1.19.0
pullPolicy: IfNotPresent
imageGPU:
repository: some-gpu-image
tag: 5.20.0
pullPolicy: Always
workload:
workload-name:
enabled: true
primary: true
type: Deployment
podSpec:
containers:
container-name1:
enabled: true
primary: true
imageSelector: "{{ .Values.imageDictToUse }}"
container-name2:
enabled: true
primary: false
imageSelector: imageGPU
asserts:
- documentIndex: &deploymentDoc 0
isKind:
of: Deployment
- documentIndex: *deploymentDoc
isAPIVersion:
of: apps/v1
- documentIndex: *deploymentDoc
isSubset:
path: spec.template.spec.containers[0]
content:
image: nginx:1.19.0
imagePullPolicy: IfNotPresent
- documentIndex: *deploymentDoc
isSubset:
path: spec.template.spec.containers[1]
content:
image: some-gpu-image:5.20.0
imagePullPolicy: Always
# Failures
- it: should fail with imageSelector trying to access non-existent image
set:
image: *image
workload:
workload-name:
enabled: true
primary: true
type: Deployment
podSpec:
containers:
container-name1:
enabled: true
primary: true
imageSelector: image-dict-that-does-not-exist
asserts:
- failedTemplate:
errorMessage: Container - Expected <.Values.image-dict-that-does-not-exist> to exist
- it: should fail with empty repository in selected image
set:
image: *image
workload:
workload-name:
enabled: true
primary: true
type: Deployment
podSpec:
containers:
container-name1:
enabled: true
primary: true
imageSelector: image
asserts:
- failedTemplate:
errorMessage: Container - Expected non-empty <.Values.image.repository>
- it: should fail with empty tag in selected image
set:
image:
repository: nginx
tag: ""
pullPolicy: IfNotPresent
workload:
workload-name:
enabled: true
primary: true
type: Deployment
podSpec:
containers:
container-name1:
enabled: true
primary: true
imageSelector: image
asserts:
- failedTemplate:
errorMessage: Container - Expected non-empty <.Values.image.tag>
- it: should fail with invalid pullPolicy selected image
set:
image:
repository: nginx
tag: 1.19.0
pullPolicy: invalid
workload:
workload-name:
enabled: true
primary: true
type: Deployment
podSpec:
containers:
container-name1:
enabled: true
primary: true
imageSelector: image
asserts:
- failedTemplate:
errorMessage: Container - Expected <.Values.image.pullPolicy> to be one of [IfNotPresent, Always, Never], but got [invalid]
@@ -0,0 +1,42 @@
suite: container name test
templates:
- common.yaml
tests:
- it: should generate correct container name
set:
image: &image
repository: nginx
tag: 1.19.0
pullPolicy: IfNotPresent
workload:
workload-name:
enabled: true
primary: true
type: Deployment
podSpec:
containers:
container-name1:
enabled: true
primary: true
imageSelector: image
container-name2:
enabled: true
primary: false
imageSelector: image
asserts:
- documentIndex: &deploymentDoc 0
isKind:
of: Deployment
- documentIndex: *deploymentDoc
isAPIVersion:
of: apps/v1
- documentIndex: *deploymentDoc
isSubset:
path: spec.template.spec.containers[0]
content:
name: release-name-common-test
- documentIndex: *deploymentDoc
isSubset:
path: spec.template.spec.containers[1]
content:
name: release-name-common-test-container-name2
@@ -0,0 +1,64 @@
suite: container tty and stdin test
templates:
- common.yaml
tests:
- it: should pass without tty and stdin
set:
image: &image
repository: nginx
tag: 1.19.0
pullPolicy: IfNotPresent
workload:
workload-name:
enabled: true
primary: true
type: Deployment
podSpec:
containers:
container-name1:
enabled: true
primary: true
imageSelector: image
asserts:
- documentIndex: &deploymentDoc 0
isKind:
of: Deployment
- documentIndex: *deploymentDoc
isAPIVersion:
of: apps/v1
- documentIndex: *deploymentDoc
isSubset:
path: spec.template.spec.containers[0]
content:
tty: false
stdin: false
- it: should pass with tty and stdin enabled
set:
image: *image
workload:
workload-name:
enabled: true
primary: true
type: Deployment
podSpec:
containers:
container-name1:
enabled: true
primary: true
imageSelector: image
tty: true
stdin: true
asserts:
- documentIndex: &deploymentDoc 0
isKind:
of: Deployment
- documentIndex: *deploymentDoc
isAPIVersion:
of: apps/v1
- documentIndex: *deploymentDoc
isSubset:
path: spec.template.spec.containers[0]
content:
tty: true
stdin: true
@@ -0,0 +1,41 @@
suite: container validation test
templates:
- common.yaml
tests:
- it: should fail with more than one primary container on a workload
set:
workload:
workload-name:
enabled: true
primary: true
type: Deployment
podSpec:
containers:
container-name1:
enabled: true
primary: true
container-name2:
enabled: true
primary: true
asserts:
- failedTemplate:
errorMessage: Container - Only one container can be primary per workload
- it: should fail with no primary container on a workload
set:
workload:
workload-name:
enabled: true
primary: true
type: Deployment
podSpec:
containers:
container-name1:
enabled: true
primary: false
container-name2:
enabled: true
primary: false
asserts:
- failedTemplate:
errorMessage: Container - At least one enabled container must be primary per workload
@@ -0,0 +1,46 @@
# Container
Assume every key bellow has a prefix of `workload.[workload-name].podSpec`.
| Key | Type | Required | Helm Template | Default | Description |
| :---------------------------------- | :-------: | :------: | :-----------: | :-----: | :-------------------------------- |
| containers.[container-name] | `dict` | ✅ | ❌ | `{}` | Define the container as dict |
| containers.[container-name].enabled | `boolean` | ✅ | ❌ | `false` | Enables or Disables the container |
| containers.[container-name].primary | `boolean` | ✅ | ❌ | `false` | Sets the container as primary |
| containers.[container-name].stdin | `boolean` | ❌ | ❌ | `false` | whether to enable stdin or not |
| containers.[container-name].tty | `boolean` | ❌ | ❌ | `false` | whether to enable tty or not |
---
Appears in:
- `.Values.workload.[workload-name].podSpec.containers`
---
Naming scheme:
- Primary: `$FullName` (release-name-chart-name)
- Non-Primary: `$FullName-$ContainerName` (release-name-chart-name-container-name)
---
Examples:
```yaml
workload:
workload-name:
enabled: true
primary: true
labels:
key: value
annotations:
key: value
podSpec:
containers:
container-name:
enabled: true
primary: true
stdin: true
tty: true
```
@@ -40,6 +40,8 @@
| workload.[workload-name].podSpec.securityContext.sysctls | `list` | ❌ | ❌ | `[]` | Pod's sysctls |
| workload.[workload-name].podSpec.securityContext.sysctls.name | `string` | ✅ | ✅ | `""` | `name` of the sysctl |
| workload.[workload-name].podSpec.securityContext.sysctls.value | `string` | ✅ | ✅ | `""` | `value` of the sysctl |
| workload.[workload-name].podSpec.containers | `dict` | ❌ | ❌ | `{}` | Define container(s) |
| workload.[workload-name].podSpec.initContainers | `dict` | ❌ | ❌ | `{}` | Define initContainer(s) |
---
@@ -75,6 +77,10 @@ Naming scheme:
- [CronJob](cronjob.md)
- [Job](job.md)
> Additional keys, information and examples for `workload.[workload-name].podSpec.containers`.
- [Container](../container/README.md)
---
Examples:
@@ -0,0 +1,42 @@
{{/* Returns the image dictionary */}}
{{/* Call this template:
{{ include "ix.v1.common.lib.container.imageSelector" (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 container.
*/}}
{{- define "ix.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,40 @@
{{/* Containers Basic Validation */}}
{{/* Call this template:
{{ include "ix.v1.common.lib.container.primaryValidation" (dict "rootCtx" $rootCtx "objectData" $objectData) -}}
*/}}
{{- define "ix.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 -}}
@@ -8,4 +8,10 @@ objectData: The object data to be used to render the Pod.
{{- $rootCtx := .rootCtx -}}
{{- $objectData := .objectData -}}
{{- $imageObj := fromJson (include "ix.v1.common.lib.container.imageSelector" (dict "rootCtx" $rootCtx "objectData" $objectData)) }}
- name: {{ $objectData.name }}
image: {{ printf "%s:%s" $imageObj.repository $imageObj.tag }}
imagePullPolicy: {{ $imageObj.pullPolicy }}
tty: {{ $objectData.tty | default false }}
stdin: {{ $objectData.stdin | default false }}
{{- end -}}
@@ -44,12 +44,23 @@ tolerations:
{{- end }}
securityContext:
{{- include "ix.v1.common.lib.pod.securityContext" (dict "rootCtx" $rootCtx "objectData" $objectData) | trim | nindent 2 }}
{{- if $objectData.podSpec.contaienrs }}
{{- if $objectData.podSpec.containers }}
containers:
{{- range $name, $containerValues := $objectData.podSpec.containers -}}
{{- include "ix.v1.common.lib.pod.container" (dict "rootCtx" $rootCtx "objectData" $objectData) | trim | nindent 2 }}
{{- include "ix.v1.common.lib.container.primaryValidation" (dict "rootCtx" $rootCtx "objectData" $objectData) -}}
{{- range $containerName, $containerValues := $objectData.podSpec.containers -}}
{{- if $containerValues.enabled -}}
{{- $container := (mustDeepCopy $containerValues) -}}
{{- $name := include "ix.v1.common.lib.chart.names.fullname" $rootCtx -}}
{{- if not $container.primary -}}
{{- $name = printf "%s-%s" $name $containerName -}}
{{- end -}}
{{- $_ := set $container "name" $name -}}
{{- $_ := set $container "shortName" $containerName -}}
{{- include "ix.v1.common.lib.pod.container" (dict "rootCtx" $rootCtx "objectData" $container) | trim | nindent 2 }}
{{- end -}}
{{- end -}}
{{- end -}}
{{- end }}
#TODO:initContainers:
{{- with (include "ix.v1.common.lib.pod.volumes" (dict "rootCtx" $rootCtx "objectData" $objectData) | trim) }}
volumes:
+21 -21
View File
@@ -77,15 +77,27 @@ securityContext:
supplementalGroups: []
sysctls: []
# -- Resources
# Can be overruled per container
resources:
limits:
cpu: 4000m
memory: 8Gi
requests:
cpu: 10m
memory: 50Mi
containerOptions:
# -- Resources
# Can be overruled per container
resources:
limits:
cpu: 4000m
memory: 8Gi
requests:
cpu: 10m
memory: 50Mi
# -- Timezone for all containers
# Can be overruled per container
TZ: UTC
# -- PUID for all containers
# Can be overruled per container
PUID: 568
# -- UMASK for all containers
# Can be overruled per container
UMASK: "002"
NVIDIA_CAPS:
- all
# -- Options for all pods
# Can be overruled per pod
@@ -109,18 +121,6 @@ podOptions:
# TODO: Add affinity
# TODO: Add topologySpreadConstraints
# -- Timezone for all containers
# Can be overruled per container
TZ: UTC
# -- PUID for all containers
# Can be overruled per container
PUID: 568
# -- UMASK for all containers
# Can be overruled per container
UMASK: "002"
NVIDIA_CAPS:
- all
# -- Persistence
persistence:
shared: