feat(common): add support for defining a list of volumeSnapshots (#589)

**Description**
Adds support for adding a list of volumesnapshots to each PVC
persistence object.
Also adds a root level volumeSnapshots list for custom volumeSnapshots

⚒️ Fixes  #571

**⚙️ Type of change**

- [x] ⚙️ Feature/App addition
- [ ] 🪛 Bugfix
- [ ] ⚠️ Breaking change (fix or feature that would cause existing
functionality to not work as expected)
- [ ] 🔃 Refactor of current code

**🧪 How Has This Been Tested?**
<!--
Please describe the tests that you ran to verify your changes. Provide
instructions so we can reproduce. Please also list any relevant details
for your test configuration
-->

**📃 Notes:**
<!-- Please enter any other relevant information here -->

**✔️ Checklist:**

- [x] ⚖️ My code follows the style guidelines of this project
- [x] 👀 I have performed a self-review of my own code
- [x] #️⃣ I have commented my code, particularly in hard-to-understand
areas
- [x] 📄 I have made corresponding changes to the documentation
- [x] ⚠️ My changes generate no new warnings
- [x] 🧪 I have added tests to this description that prove my fix is
effective or that my feature works
- [x] ⬆️ I increased versions for any altered app according to semantic
versioning

** App addition**

If this PR is an app addition please make sure you have done the
following.

- [x] 🪞 I have opened a PR on
[truecharts/containers](https://github.com/truecharts/containers) adding
the container to TrueCharts mirror repo.
- [x] 🖼️ I have added an icon in the Chart's root directory called
`icon.png`

---

_Please don't blindly check all the boxes. Read them and only check
those that apply.
Those checkboxes are there for the reviewer to see what is this all
about and
the status of this PR with a quick glance._

---------

Co-authored-by: Stavros kois <s.kois@outlook.com>
This commit is contained in:
Kjeld Schouten
2023-11-18 14:13:44 +01:00
committed by GitHub
parent 5b74f29bb9
commit 9605b7a321
14 changed files with 455 additions and 5 deletions

View File

@@ -0,0 +1,79 @@
suite: persistence pvc with snapshots test
templates:
- common.yaml
release:
name: test-release-name
namespace: test-release-namespace
tests:
- it: should generate correct pvc and snapshot
set:
persistence:
my-volume1:
enabled: true
type: pvc
volumeSnapshots:
- name: example1
enabled: true
volumeSnapshotClassName: some-name
my-volume2:
enabled: true
type: pvc
volumeSnapshots:
- name: example1
enabled: true
volumeSnapshotClassName: some-name
asserts:
- documentIndex: &pvcDoc 0
isKind:
of: PersistentVolumeClaim
- documentIndex: *pvcDoc
isAPIVersion:
of: v1
- documentIndex: *pvcDoc
equal:
path: metadata.name
value: test-release-name-common-test-my-volume1
- documentIndex: &volumeSnapshotDoc 1
isKind:
of: VolumeSnapshot
- documentIndex: *volumeSnapshotDoc
isAPIVersion:
of: snapshot.storage.k8s.io/v1
- documentIndex: *volumeSnapshotDoc
equal:
path: metadata.name
value: test-release-name-common-test-my-volume1-example1
- documentIndex: *volumeSnapshotDoc
equal:
path: spec
value:
volumeSnapshotClassName: some-name
source:
persistentVolumeClaimName: test-release-name-common-test-my-volume1
- documentIndex: &otherPvcDoc 2
isKind:
of: PersistentVolumeClaim
- documentIndex: *otherPvcDoc
isAPIVersion:
of: v1
- documentIndex: *otherPvcDoc
equal:
path: metadata.name
value: test-release-name-common-test-my-volume2
- documentIndex: &otherVolumeSnapshotDoc 3
isKind:
of: VolumeSnapshot
- documentIndex: *otherVolumeSnapshotDoc
isAPIVersion:
of: snapshot.storage.k8s.io/v1
- documentIndex: *otherVolumeSnapshotDoc
equal:
path: metadata.name
value: test-release-name-common-test-my-volume2-example1
- documentIndex: *otherVolumeSnapshotDoc
equal:
path: spec
value:
volumeSnapshotClassName: some-name
source:
persistentVolumeClaimName: test-release-name-common-test-my-volume2

View File

@@ -30,10 +30,13 @@ tests:
annotation1: "{{ .Values.annotation1 }}"
annotation2: annotation2
asserts:
- documentIndex: &storageClassDoc 0
- documentIndex: &priorityClassDoc 0
isKind:
of: PriorityClass
- documentIndex: *storageClassDoc
- documentIndex: &priorityClassDoc 0
isAPIVersion:
of: scheduling.k8s.io/v1
- documentIndex: *priorityClassDoc
equal:
path: metadata.annotations
value:
@@ -41,7 +44,7 @@ tests:
annotation2: annotation2
g_annotation1: global_annotation1
g_annotation2: global_annotation2
- documentIndex: *storageClassDoc
- documentIndex: *priorityClassDoc
equal:
path: metadata.labels
value:

View File

@@ -1,4 +1,4 @@
suite: priorityClass name test
suite: priorityClass spec test
templates:
- common.yaml
release:

View File

@@ -34,6 +34,9 @@ tests:
- documentIndex: &storageClassDoc 0
isKind:
of: StorageClass
- documentIndex: *storageClassDoc
isAPIVersion:
of: storage.k8s.io/v1
- documentIndex: *storageClassDoc
equal:
path: metadata.annotations

View File

@@ -1,4 +1,4 @@
suite: storageClass name test
suite: storageClass spec test
templates:
- common.yaml
release:

View File

@@ -0,0 +1,64 @@
suite: volumeSnapshot metadata test
templates:
- common.yaml
chart:
appVersion: &appVer v9.9.9
release:
name: test-release-name
namespace: test-release-namespace
tests:
- it: should pass with volumeSnapshot created with labels and annotations
set:
label1: label1
label2: global_label2
annotation1: annotation1
annotation2: global_annotation2
global:
labels:
g_label1: global_label1
g_label2: "{{ .Values.label2 }}"
annotations:
g_annotation1: global_annotation1
g_annotation2: "{{ .Values.annotation2 }}"
volumeSnapshots:
- name: example1
enabled: true
source:
volumeSnapshotContentName: some-name
labels:
label1: "{{ .Values.label1 }}"
label2: label2
annotations:
annotation1: "{{ .Values.annotation1 }}"
annotation2: annotation2
asserts:
- documentIndex: &volumeSnapshotDoc 0
isKind:
of: VolumeSnapshot
- documentIndex: &volumeSnapshotDoc 0
isAPIVersion:
of: snapshot.storage.k8s.io/v1
- documentIndex: *volumeSnapshotDoc
equal:
path: metadata.annotations
value:
annotation1: annotation1
annotation2: annotation2
g_annotation1: global_annotation1
g_annotation2: global_annotation2
- documentIndex: *volumeSnapshotDoc
equal:
path: metadata.labels
value:
app: common-test-1.0.0
release: test-release-name
helm-revision: "0"
helm.sh/chart: common-test-1.0.0
app.kubernetes.io/name: common-test
app.kubernetes.io/instance: test-release-name
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/version: *appVer
g_label1: global_label1
g_label2: global_label2
label1: label1
label2: label2

View File

@@ -0,0 +1,39 @@
suite: volumeSnapshot name test
templates:
- common.yaml
release:
name: test-release-name
namespace: test-release-namespace
tests:
- it: should generate correct name
set:
volumeSnapshots:
- name: example1
enabled: true
source:
volumeSnapshotContentName: some-name
- name: example2
enabled: true
source:
volumeSnapshotContentName: some-name
asserts:
- documentIndex: &volumeSnapshotDoc 0
isKind:
of: VolumeSnapshot
- documentIndex: *volumeSnapshotDoc
isAPIVersion:
of: snapshot.storage.k8s.io/v1
- documentIndex: *volumeSnapshotDoc
equal:
path: metadata.name
value: test-release-name-common-test-example1
- documentIndex: &otherVolumeSnapshotDoc 1
isKind:
of: VolumeSnapshot
- documentIndex: *otherVolumeSnapshotDoc
isAPIVersion:
of: snapshot.storage.k8s.io/v1
- documentIndex: *otherVolumeSnapshotDoc
equal:
path: metadata.name
value: test-release-name-common-test-example2

View File

@@ -0,0 +1,106 @@
suite: volumeSnapshot spec test
templates:
- common.yaml
release:
name: test-release-name
namespace: test-release-namespace
tests:
- it: should generate correct spec
set:
volumeSnapshots:
- name: example1
enabled: true
source:
volumeSnapshotContentName: some-name
- name: example2
enabled: true
source:
persistentVolumeClaimName: some-pvc-name
asserts:
- documentIndex: &volumeSnapshotDoc 0
isKind:
of: VolumeSnapshot
- documentIndex: *volumeSnapshotDoc
isAPIVersion:
of: snapshot.storage.k8s.io/v1
- documentIndex: *volumeSnapshotDoc
equal:
path: spec
value:
source:
volumeSnapshotContentName: some-name
- documentIndex: &otherVolumeSnapshotDoc 1
isKind:
of: VolumeSnapshot
- documentIndex: *otherVolumeSnapshotDoc
isAPIVersion:
of: snapshot.storage.k8s.io/v1
- documentIndex: *otherVolumeSnapshotDoc
equal:
path: spec
value:
source:
persistentVolumeClaimName: some-pvc-name
- it: should generate correct spec with volumeSnapshotClass
set:
volumeSnapshots:
- name: example1
enabled: true
volumeSnapshotClassName: some-class
source:
volumeSnapshotContentName: some-name
asserts:
- documentIndex: &volumeSnapshotDoc 0
isKind:
of: VolumeSnapshot
- documentIndex: *volumeSnapshotDoc
equal:
path: spec
value:
volumeSnapshotClassName: some-class
source:
volumeSnapshotContentName: some-name
# Failures
- it: should fail without name
set:
volumeSnapshots:
- enabled: true
source:
volumeSnapshotContentName: some-name
asserts:
- failedTemplate:
errorMessage: VolumeSnapshot - Expected non empty [name]
- it: should fail without source object
set:
volumeSnapshots:
- name: example1
enabled: true
asserts:
- failedTemplate:
errorMessage: VolumeSnapshot - Expected non empty [source]
- it: should fail without a valid source
set:
volumeSnapshots:
- name: example1
enabled: true
source:
invalid: invalid
asserts:
- failedTemplate:
errorMessage: VolumeSnapshot - Expected exactly one of the valid source types [volumeSnapshotContentName, persistentVolumeClaimName]. Found [0]
- it: should fail with more than one valid source
set:
volumeSnapshots:
- name: example1
enabled: true
source:
volumeSnapshotContentName: some-name
persistentVolumeClaimName: some-pvc-name
asserts:
- failedTemplate:
errorMessage: VolumeSnapshot - Expected exactly one of the valid source types [volumeSnapshotContentName, persistentVolumeClaimName]. Found [2]

View File

@@ -0,0 +1,46 @@
{{/* volumesnapshot Class */}}
{{/* Call this template:
{{ include "tc.v1.common.class.volumesnapshot" (dict "rootCtx" $ "objectData" $objectData) }}
rootCtx: The root context of the chart.
objectData:
name: The name of the volumesnapshot.
labels: The labels of the volumesnapshot.
annotations: The annotations of the volumesnapshot.
namespace: The namespace of the volumesnapshot. (Optional)
*/}}
{{- define "tc.v1.common.class.volumesnapshot" -}}
{{- $rootCtx := .rootCtx -}}
{{- $objectData := .objectData }}
---
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
name: {{ $objectData.name }}
namespace: {{ include "tc.v1.common.lib.metadata.namespace" (dict "rootCtx" $rootCtx "objectData" $objectData "caller" "volumesnapshot") }}
{{- $labels := (mustMerge ($objectData.labels | default dict) (include "tc.v1.common.lib.metadata.allLabels" $rootCtx | fromYaml)) -}}
{{- with (include "tc.v1.common.lib.metadata.render" (dict "rootCtx" $rootCtx "labels" $labels) | trim) }}
labels:
{{- . | nindent 4 }}
{{- end -}}
{{- $annotations := (mustMerge ($objectData.annotations | default dict) (include "tc.v1.common.lib.metadata.allAnnotations" $rootCtx | fromYaml)) -}}
{{- with (include "tc.v1.common.lib.metadata.render" (dict "rootCtx" $rootCtx "annotations" $annotations) | trim) }}
annotations:
{{- . | nindent 4 }}
{{- end }}
spec:
{{- with $objectData.volumeSnapshotClassName }}
volumeSnapshotClassName: {{ . }}
{{- end -}}
{{- if $objectData.source }}
source:
{{- with $objectData.source.persistentVolumeClaimName }}
persistentVolumeClaimName: {{ . }}
{{- end -}}
{{- with $objectData.source.volumeSnapshotContentName }}
volumeSnapshotContentName: {{ . }}
{{- end -}}
{{- end -}}
{{- end -}}

View File

@@ -0,0 +1,29 @@
{{/* volumeSnapshot Validation */}}
{{/* Call this template:
{{ include "tc.v1.common.lib.volumesnapshot.validation" (dict "objectData" $objectData) -}}
objectData:
rootCtx: The root context of the chart.
objectData: The volumesnapshot object.
*/}}
{{- define "tc.v1.common.lib.volumesnapshot.validation" -}}
{{- $rootCtx := .rootCtx -}}
{{- $objectData := .objectData -}}
{{- if not $objectData.source -}}
{{- fail "VolumeSnapshot - Expected non empty [source]" -}}
{{- end -}}
{{- $sourceTypes := (list "volumeSnapshotContentName" "persistentVolumeClaimName") -}}
{{- $sourceCount := 0 -}}
{{- range $t := $sourceTypes -}}
{{- if (get $objectData.source $t) -}}
{{- $sourceCount = add1 $sourceCount -}}
{{- end -}}
{{- end -}}
{{- if ne $sourceCount 1 -}}
{{- fail (printf "VolumeSnapshot - Expected exactly one of the valid source types [%s]. Found [%d]" (join ", " $sourceTypes) $sourceCount) -}}
{{- end -}}
{{- end -}}

View File

@@ -46,6 +46,9 @@
{{/* Render PVC(s) */}}
{{- include "tc.v1.common.spawner.pvc" . | nindent 0 -}}
{{/* Render volumeSnapshot(s) */}}
{{- include "tc.v1.common.spawner.volumesnapshot" . | nindent 0 -}}
{{/* Render ingress(s) */}}
{{- include "tc.v1.common.spawner.ingress" . | nindent 0 -}}

View File

@@ -74,6 +74,29 @@
{{/* Call class to create the object */}}
{{- include "tc.v1.common.class.pvc" (dict "rootCtx" $ "objectData" $objectData) -}}
{{/* Create VolumeSnapshots */}}
{{- range $volSnap := $objectData.volumeSnapshots -}}
{{/* Create a copy of the volumesnapshot */}}
{{- $volSnapData := (mustDeepCopy $volSnap) -}}
{{/* PVC FullName - Snapshot Name*/}}
{{- $snapshotName := printf "%s-%s" $objectData.name $volSnap.name -}}
{{/* Perform validations */}} {{/* volumesnapshots have a max name length of 253 */}}
{{- include "tc.v1.common.lib.chart.names.validation" (dict "name" $snapshotName "length" 253) -}}
{{- include "tc.v1.common.lib.metadata.validation" (dict "objectData" $volSnapData "caller" "PVC - VolumeSnapshot") -}}
{{/* Set the name of the volumesnapshot */}}
{{- $_ := set $volSnapData "name" $snapshotName -}}
{{- $_ := set $volSnapData "shortName" $volSnap.name -}}
{{- $_ := set $volSnapData "source" (dict "persistentVolumeClaimName" $objectData.name) -}}
{{- include "tc.v1.common.lib.volumesnapshot.validation" (dict "objectData" $volSnapData) -}}
{{/* Call class to create the object */}}
{{- include "tc.v1.common.class.volumesnapshot" (dict "rootCtx" $ "objectData" $volSnapData) -}}
{{- end -}}
{{- end -}}
{{- if eq $objectData.type "iscsi" -}}

View File

@@ -0,0 +1,38 @@
{{/* volumesnapshot Spawwner */}}
{{/* Call this template:
{{ include "tc.v1.common.spawner.volumesnapshot" $ -}}
*/}}
{{- define "tc.v1.common.spawner.volumesnapshot" -}}
{{- $fullname := include "tc.v1.common.lib.chart.names.fullname" $ -}}
{{- range $volumesnapshot := .Values.volumeSnapshots -}}
{{/* Create a copy of the volumesnapshot */}}
{{- $objectData := (mustDeepCopy $volumesnapshot) -}}
{{- if not $objectData.name -}}
{{- fail "VolumeSnapshot - Expected non empty [name]" -}}
{{- end -}}
{{- $objectName := (printf "%s-%s" $fullname $volumesnapshot.name) -}}
{{- if hasKey $objectData "expandObjectName" -}}
{{- if not $objectData.expandObjectName -}}
{{- $objectName = $volumesnapshot.name -}}
{{- end -}}
{{- end -}}
{{/* Perform validations */}} {{/* volumesnapshots have a max name length of 253 */}}
{{- include "tc.v1.common.lib.chart.names.validation" (dict "name" $objectName "length" 253) -}}
{{- include "tc.v1.common.lib.volumesnapshot.validation" (dict "objectData" $objectData) -}}
{{- include "tc.v1.common.lib.metadata.validation" (dict "objectData" $objectData "caller" "VolumeSnapshot") -}}
{{/* Set the name of the volumesnapshot */}}
{{- $_ := set $objectData "name" $objectName -}}
{{- $_ := set $objectData "shortName" $volumesnapshot.name -}}
{{/* Call class to create the object */}}
{{- include "tc.v1.common.class.volumesnapshot" (dict "rootCtx" $ "objectData" $objectData) -}}
{{- end -}}
{{- end -}}

View File

@@ -307,11 +307,28 @@ persistence:
# driver: "somedriver"
# # Custom CSI definition here
# csi: {}
# example-volumesnapshot:
# enabled: true
# type: pvc
# mountPath: /shared
# targetSelectAll: true
# volumeSnapshots:
# - name: "mysnapshot"
# volumeSnapshotClassName: "mysnapshotclass" (optional)
persistenceList: []
deviceList: []
volumeSnapshots: []
# volumeSnapshots:
# - name: "mycustomsnapshot"
# volumeSnapshotClassName: "mycustomsnapshot" (optional)
# source:
# # pick one
# persistentVolumeClaimName: "mypvcname" (does not get altered)
# volumeSnapshotContentName: "mysnapshotname"
# -- Injected from SCALE middleware
# Only for reference here
ixExternalInterfacesConfiguration: []