mirror of
https://github.com/truenas/charts.git
synced 2024-04-21 15:21:45 +00:00
initial container plumbing
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user