From ccbe4446e0bfa5cadabbe03ece957d5204b036e1 Mon Sep 17 00:00:00 2001 From: Stavros kois Date: Sat, 11 Feb 2023 17:05:07 +0200 Subject: [PATCH] device vol type --- .../tests/persistence/validation_test.yaml | 2 +- .../tests/pod/volume_device_test.yaml | 110 ++++++++++++++++++ .../common/1.0.0/docs/persistence/README.md | 25 ++-- .../common/1.0.0/docs/persistence/device.md | 28 +++++ .../1.0.0/templates/lib/pod/_volumes.tpl | 2 + .../templates/lib/pod/volumes/_device.tpl | 35 ++++++ .../templates/lib/storage/_validation.tpl | 2 +- .../1.0.0/templates/spawner/_service.tpl | 2 +- library/common/1.0.0/values.yaml | 25 ---- 9 files changed, 191 insertions(+), 40 deletions(-) create mode 100644 library/common-test/tests/pod/volume_device_test.yaml create mode 100644 library/common/1.0.0/docs/persistence/device.md create mode 100644 library/common/1.0.0/templates/lib/pod/volumes/_device.tpl diff --git a/library/common-test/tests/persistence/validation_test.yaml b/library/common-test/tests/persistence/validation_test.yaml index 4422f92d24..ea921d7b16 100644 --- a/library/common-test/tests/persistence/validation_test.yaml +++ b/library/common-test/tests/persistence/validation_test.yaml @@ -40,7 +40,7 @@ tests: type: not-a-type asserts: - failedTemplate: - errorMessage: Persistence - Expected to be one of [pvc, emptyDir, nfs, hostPath, ixVolume, secret, configmap], but got [not-a-type] + errorMessage: Persistence - Expected to be one of [pvc, emptyDir, nfs, hostPath, ixVolume, secret, configmap, device], but got [not-a-type] - it: should fail without storageClassName in ixChartContext set: diff --git a/library/common-test/tests/pod/volume_device_test.yaml b/library/common-test/tests/pod/volume_device_test.yaml new file mode 100644 index 0000000000..3e314d258c --- /dev/null +++ b/library/common-test/tests/pod/volume_device_test.yaml @@ -0,0 +1,110 @@ +suite: pod device volume test +templates: + - common.yaml +tests: + - it: should pass with device volume + set: + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: {} + persistence: + dev-vol: + enabled: true + type: device + hostPath: /dev/something + asserts: + - documentIndex: &deploymentDoc 0 + isKind: + of: Deployment + - documentIndex: *deploymentDoc + contains: + path: spec.template.spec.volumes + content: + name: dev-vol + hostPath: + path: /dev/something + + - it: should pass with device volume and type + set: + some_path: /dev/something + some_type: BlockDevice + workload: + workload-name1: + enabled: true + primary: true + type: Deployment + podSpec: {} + persistence: + dev-vol: + enabled: true + type: device + hostPath: "{{ .Values.some_path }}" + hostPathType: "{{ .Values.some_type }}" + asserts: + - documentIndex: *deploymentDoc + isKind: + of: Deployment + - documentIndex: *deploymentDoc + contains: + path: spec.template.spec.volumes + content: + name: dev-vol + hostPath: + path: /dev/something + type: BlockDevice + +# Failures + - it: should fail without hostPath + set: + workload: + some-workload: + enabled: true + primary: true + type: Deployment + podSpec: {} + persistence: + volume1: + enabled: true + type: device + hostPath: "" + asserts: + - failedTemplate: + errorMessage: Persistence - Expected non-empty on type + + - it: should fail with relative hostPath + set: + workload: + some-workload: + enabled: true + primary: true + type: Deployment + podSpec: {} + persistence: + volume1: + enabled: true + type: device + hostPath: some-path + asserts: + - failedTemplate: + errorMessage: Persistence - Expected to start with a forward slash [/] on type + + - it: should fail with invalid hostPathType + set: + workload: + some-workload: + enabled: true + primary: true + type: Deployment + podSpec: {} + persistence: + volume1: + enabled: true + type: device + hostPath: /some-path + hostPathType: invalid + asserts: + - failedTemplate: + errorMessage: Persistence - Expected to be one of [DirectoryOrCreate, Directory, FileOrCreate, File, Socket, CharDevice, BlockDevice], but got [invalid] diff --git a/library/common/1.0.0/docs/persistence/README.md b/library/common/1.0.0/docs/persistence/README.md index 91c382073a..ecd022d927 100644 --- a/library/common/1.0.0/docs/persistence/README.md +++ b/library/common/1.0.0/docs/persistence/README.md @@ -1,17 +1,17 @@ # 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].type | `string` | ❌ | ❌ | `pvc` | Define the persistence type (pvc, ixVolume, nfs, hostPath, configmap, secret) | -| 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].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].type | `string` | ❌ | ❌ | `pvc` | Define the persistence type (pvc, ixVolume, nfs, hostPath, configmap, secret, device) | +| 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].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) @@ -38,6 +38,7 @@ Naming scheme: - [emptyDir](emptyDir.md) - [ixVolume](ixVolume.md) - [hostPath](hostPath.md) +- [device](device.md) - [secret](secret.md) - [pvc](pvc.md) - [nfs](nfs.md) diff --git a/library/common/1.0.0/docs/persistence/device.md b/library/common/1.0.0/docs/persistence/device.md new file mode 100644 index 0000000000..bf9d07ae3e --- /dev/null +++ b/library/common/1.0.0/docs/persistence/device.md @@ -0,0 +1,28 @@ +# Device + +| Key | Type | Required | Helm Template | Default | Description | +| :------------------------------------- | :------: | :------: | :-----------: | :-----: | :---------------------- | +| persistence.[volume-name].hostPath | `string` | ✅ | ✅ | `""` | Define the hostPath | +| persistence.[volume-name].hostPathType | `string` | ❌ | ✅ | `""` | Define the hostPathType | + +> `device` type is pretty much the same as `hostPath`. The only difference is that if a `device` type is defined. +> We can take additional actions, like setting supplementalGroups to the container assigned, so it can utilize the device. + +--- + +Notes: + +View common `keys` of `persistence` in [persistence Documentation](README.md). + +--- + +Examples: + +```yaml +persistence: + dev-vol: + enabled: true + type: device + hostPath: /path/to/host + hostPathType: BlockDevice +``` 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 69a3580467..4de9e0bea1 100644 --- a/library/common/1.0.0/templates/lib/pod/_volumes.tpl +++ b/library/common/1.0.0/templates/lib/pod/_volumes.tpl @@ -51,6 +51,8 @@ objectData: The object data to be used to render the Pod. {{- include "ix.v1.common.lib.pod.volume.emptyDir" (dict "rootCtx" $rootCtx "objectData" $persistence) | trim | nindent 0 -}} {{- else if eq "nfs" $type -}} {{- include "ix.v1.common.lib.pod.volume.nfs" (dict "rootCtx" $rootCtx "objectData" $persistence) | trim | nindent 0 -}} + {{- else if eq "device" $type -}} + {{- include "ix.v1.common.lib.pod.volume.device" (dict "rootCtx" $rootCtx "objectData" $persistence) | trim | nindent 0 -}} {{- end -}} {{- end -}} diff --git a/library/common/1.0.0/templates/lib/pod/volumes/_device.tpl b/library/common/1.0.0/templates/lib/pod/volumes/_device.tpl new file mode 100644 index 0000000000..166952d6f5 --- /dev/null +++ b/library/common/1.0.0/templates/lib/pod/volumes/_device.tpl @@ -0,0 +1,35 @@ +{{/* Returns device (hostPath) Volume */}} +{{/* Call this template: +{{ include "ix.v1.common.lib.pod.volume.device" (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.device" -}} + {{- $rootCtx := .rootCtx -}} + {{- $objectData := .objectData -}} + + {{- $hostPathType := "" -}} + {{- if $objectData.hostPathType -}} + {{- $hostPathType = tpl $objectData.hostPathType $rootCtx -}} + {{- end -}} + + {{- if not $objectData.hostPath -}} + {{- fail "Persistence - Expected non-empty on type" -}} + {{- end -}} + {{- $hostPath := tpl $objectData.hostPath $rootCtx -}} + + {{- if not (hasPrefix "/" $hostPath) -}} + {{- fail "Persistence - Expected to start with a forward slash [/] on type" -}} + {{- end -}} + + {{- $types := (list "DirectoryOrCreate" "Directory" "FileOrCreate" "File" "Socket" "CharDevice" "BlockDevice") -}} + {{- if and $hostPathType (not (mustHas $hostPathType $types)) -}} + {{- fail (printf "Persistence - Expected to be one of [%s], but got [%s]" (join ", " $types) $hostPathType) -}} + {{- end }} +- name: {{ $objectData.shortName }} + hostPath: + path: {{ $hostPath }} + {{- with $hostPathType }} + type: {{ $hostPathType }} + {{- end -}} +{{- end -}} diff --git a/library/common/1.0.0/templates/lib/storage/_validation.tpl b/library/common/1.0.0/templates/lib/storage/_validation.tpl index c7b77db47a..ace282295b 100644 --- a/library/common/1.0.0/templates/lib/storage/_validation.tpl +++ b/library/common/1.0.0/templates/lib/storage/_validation.tpl @@ -10,7 +10,7 @@ objectData: {{- $rootCtx := .rootCtx -}} {{- $objectData := .objectData -}} - {{- $types := (list "pvc" "emptyDir" "nfs" "hostPath" "ixVolume" "secret" "configmap") -}} + {{- $types := (list "pvc" "emptyDir" "nfs" "hostPath" "ixVolume" "secret" "configmap" "device") -}} {{- if not (mustHas $objectData.type $types) -}} {{- fail (printf "Persistence - Expected to be one of [%s], but got [%s]" (join ", " $types) $objectData.type) -}} {{- end -}} diff --git a/library/common/1.0.0/templates/spawner/_service.tpl b/library/common/1.0.0/templates/spawner/_service.tpl index 9cb233c7da..c97fc25901 100644 --- a/library/common/1.0.0/templates/spawner/_service.tpl +++ b/library/common/1.0.0/templates/spawner/_service.tpl @@ -22,8 +22,8 @@ {{/* Perform validations */}} {{- include "ix.v1.common.lib.chart.names.validation" (dict "name" $objectName) -}} - {{- include "ix.v1.common.lib.service.validation" (dict "rootCtx" $ "objectData" $objectData) -}} {{- include "ix.v1.common.lib.metadata.validation" (dict "objectData" $objectData "caller" "Service") -}} + {{- include "ix.v1.common.lib.service.validation" (dict "rootCtx" $ "objectData" $objectData) -}} {{/* Set the name of the service account */}} {{- $_ := set $objectData "name" $objectName -}} diff --git a/library/common/1.0.0/values.yaml b/library/common/1.0.0/values.yaml index 5a1f15a4a3..930752debd 100644 --- a/library/common/1.0.0/values.yaml +++ b/library/common/1.0.0/values.yaml @@ -299,7 +299,6 @@ scaleGPU: pod-name: - container-name - # -- SCALE Certificate scaleCertificate: # -- Certificate name @@ -322,27 +321,3 @@ scaleCertificate: container-name: certPath: "" keyPath: "" - -# -- Device -device: - # -- Device name - device-name: - # -- Enables the device - enabled: false - # -- Device host path - hostPath: /host/device/path - # -- Options that apply to all volumeMounts - # Can be overruled per volumeMount under targetSelector - mountPath: /shared - readOnly: False - subPath: "" - mountPropagation: "" - # Where to define the volume and mount the volume - # targetSelector: all - targetSelector: - pod-name: - container-name: - mountPath: /shared - readOnly: False - subPath: "" - mountPropagation: ""