feat(common): BREAKING CHANGE add support for PVC static provisioning and dataSource (#554)

**Description**
This PR aims to add support for static provisioning of PVC-PV volume
pairs.

THis ensures we're in-line with what iX-Common backend for SCALE
supports and expands on that by allowing users on non-SCALE systems to
create custom PVC-PV bindings

It also adds initial support for dataSource, for either backup/snapshot
or PVC cloning purposses.
In addition it ensure that a randomised hash is used when dataSource is
set, so we can force a recrease when it's changed.

This also merged `.Values.volumeClaimTemplates` with
`.Values.persistence` by setting `.type` to `vct` on any persistence
reference.
This means users with statefull sets, need to move **all** their
`.Values.volumeClaimTemplates` references into `.Values.persistence`
like this:

old:
```
volumeClaimTemplates:
  data:
    enabled: true
    mountPath: "/var/lib/ldap/"
```

New:
```
persistence:
  data:
    enabled: true
    type: "vct"
    mountPath: "/var/lib/ldap/"
```

On top of this, this PR breaks ALL VCT's by improving the naming scheme.
It's important to NOT install this update on statefull sets lightly, as
this might destroy your data.

Fixes: #558 
Fixes: #562

**⚙️ Type of change**

- [x] ⚙️ Feature/App addition
- [ ] 🪛 Bugfix
- [x] ⚠️ 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:**
Technically breaking, as this changes the CNPG storage structure in
values.yaml.
The new structure for CNPG storage is the same as .Values.Persistence
(type is always PVC)

Also Breaking because of VolumeClaimTemplates being merged with
Persistence

**✔️ 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 <47820033+stavros-k@users.noreply.github.com>
Co-authored-by: Stavros kois <s.kois@outlook.com>
This commit is contained in:
Kjeld Schouten
2023-11-12 17:18:35 +01:00
committed by GitHub
parent 8e99d4f9d0
commit 02be440b56
34 changed files with 2481 additions and 136 deletions

View File

@@ -3,7 +3,7 @@ appVersion: ""
dependencies:
- name: common
repository: file://../common
version: ~14.5.0
version: ~15.0.0
deprecated: false
description: Helper chart to test different use cases of the common library
home: https://github.com/truecharts/apps/tree/master/charts/library/common-test

View File

@@ -36,9 +36,10 @@ workload:
type: http
port: "{{ .Values.service.main.ports.main.port }}"
volumeClaimTemplates:
persistence:
data:
mountPath: /data
type: vct
accessMode: "ReadWriteOnce"
size: 1Gi

View File

@@ -637,9 +637,10 @@ tests:
primary: true
imageSelector: image
probes: *probes
volumeClaimTemplates:
persistence:
vct-vol:
enabled: true
type: vct
size: 50Gi
targetSelector:
workload-name:

View File

@@ -0,0 +1,335 @@
suite: pv data test
templates:
- common.yaml
release:
name: test-release-name
namespace: test-release-namespace
tests:
- it: should create nfs pv with csi
set:
version: 4.1
persistence:
my-volume1:
enabled: true
type: pvc
static:
mode: nfs
share: /my-path
server: my-server
my-volume2:
enabled: true
type: pvc
static:
mode: nfs
share: /my-path2
server: my-server2
size: 2Gi
mountOptions:
- key: hard
- key: nfsvers
value: "{{ .Values.version }}"
my-volume3:
enabled: true
type: pvc
static:
mode: nfs
share: /my-path3
server: my-server3
size: 3Gi
mountOptions:
- key: hard
- key: nfsvers
value: "{{ .Values.version }}"
asserts:
- documentIndex: &pvDoc 0
isKind:
of: PersistentVolume
- documentIndex: *pvDoc
equal:
path: spec
value:
capacity:
storage: 100Gi
persistentVolumeReclaimPolicy: Delete
storageClassName: test-release-name-common-test-my-volume1-1599277109
accessModes:
- ReadWriteOnce
csi:
driver: nfs.csi.k8s.io
volumeHandle: my-server/my-path#test-release-name-common-test-my-volume1-1599277109
volumeAttributes:
server: my-server
share: /my-path
- documentIndex: &pvcDoc 1
isKind:
of: PersistentVolumeClaim
- documentIndex: *pvcDoc
equal:
path: spec
value:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Gi
storageClassName: test-release-name-common-test-my-volume1-1599277109
volumeName: test-release-name-common-test-my-volume1-1599277109
- documentIndex: &otherPvDoc 2
isKind:
of: PersistentVolume
- documentIndex: *otherPvDoc
equal:
path: spec
value:
capacity:
storage: 2Gi
persistentVolumeReclaimPolicy: Delete
storageClassName: test-release-name-common-test-my-volume2-1702692922
accessModes:
- ReadWriteOnce
mountOptions:
- hard
- nfsvers=4.1
csi:
driver: nfs.csi.k8s.io
volumeHandle: my-server2/my-path2#test-release-name-common-test-my-volume2-1702692922
volumeAttributes:
server: my-server2
share: /my-path2
- documentIndex: &otherPvcDoc 3
isKind:
of: PersistentVolumeClaim
- documentIndex: *otherPvcDoc
equal:
path: spec
value:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
storageClassName: test-release-name-common-test-my-volume2-1702692922
volumeName: test-release-name-common-test-my-volume2-1702692922
- documentIndex: &thirdPvDoc 4
isKind:
of: PersistentVolume
- documentIndex: *thirdPvDoc
equal:
path: spec
value:
capacity:
storage: 3Gi
persistentVolumeReclaimPolicy: Delete
storageClassName: test-release-name-common-test-my-volume3-1705052221
accessModes:
- ReadWriteOnce
mountOptions:
- hard
- nfsvers=4.1
csi:
driver: nfs.csi.k8s.io
volumeHandle: my-server3/my-path3#test-release-name-common-test-my-volume3-1705052221
volumeAttributes:
server: my-server3
share: /my-path3
- documentIndex: &thirdPvcDoc 5
isKind:
of: PersistentVolumeClaim
- documentIndex: *thirdPvcDoc
equal:
path: spec
value:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
storageClassName: test-release-name-common-test-my-volume3-1705052221
volumeName: test-release-name-common-test-my-volume3-1705052221
- it: should create smb pv with csi
set:
version: "3.0"
persistence:
my-volume1:
enabled: true
type: pvc
static:
mode: smb
share: my-share
server: my-server
username: my-user
password: my-password
my-volume2:
enabled: true
type: pvc
static:
mode: smb
share: my-share2
server: my-server2
username: my-user2
password: my-password2
size: 2Gi
mountOptions:
- key: hard
- key: uid
value: 99999999999
- key: vers
value: "{{ .Values.version }}"
my-volume3:
enabled: true
type: pvc
static:
mode: smb
share: my-share3
server: my-server3
username: my-user3
password: my-password3
size: 3Gi
mountOptions:
- key: hard
- key: uid
value: 99999999999
- key: vers
value: "{{ .Values.version }}"
asserts:
- documentIndex: &secretDoc 0
isKind:
of: Secret
- documentIndex: *secretDoc
equal:
path: stringData
value:
username: my-user
password: my-password
- documentIndex: &pvDoc 1
isKind:
of: PersistentVolume
- documentIndex: *pvDoc
equal:
path: spec
value:
capacity:
storage: 100Gi
persistentVolumeReclaimPolicy: Delete
storageClassName: test-release-name-common-test-my-volume1-1627785324
accessModes:
- ReadWriteOnce
csi:
driver: smb.csi.k8s.io
volumeHandle: my-server/my-share#test-release-name-common-test-my-volume1-1627785324
volumeAttributes:
source: //my-server/my-share
nodeStageSecretRef:
name: test-release-name-common-test-my-volume1-1627785324
namespace: test-release-namespace
- documentIndex: &pvcDoc 2
isKind:
of: PersistentVolumeClaim
- documentIndex: *pvcDoc
equal:
path: spec
value:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 100Gi
storageClassName: test-release-name-common-test-my-volume1-1627785324
volumeName: test-release-name-common-test-my-volume1-1627785324
- documentIndex: &otherSecretDoc 3
isKind:
of: Secret
- documentIndex: *otherSecretDoc
equal:
path: stringData
value:
username: my-user2
password: my-password2
- documentIndex: &otherPvDoc 4
isKind:
of: PersistentVolume
- documentIndex: *otherPvDoc
equal:
path: spec
value:
capacity:
storage: 2Gi
persistentVolumeReclaimPolicy: Delete
storageClassName: test-release-name-common-test-my-volume2-1734805617
accessModes:
- ReadWriteOnce
mountOptions:
- hard
- uid=99999999999
- vers=3.0
csi:
driver: smb.csi.k8s.io
volumeHandle: my-server2/my-share2#test-release-name-common-test-my-volume2-1734805617
volumeAttributes:
source: //my-server2/my-share2
nodeStageSecretRef:
name: test-release-name-common-test-my-volume2-1734805617
namespace: test-release-namespace
- documentIndex: &otherPvcDoc 5
isKind:
of: PersistentVolumeClaim
- documentIndex: *otherPvcDoc
equal:
path: spec
value:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
storageClassName: test-release-name-common-test-my-volume2-1734805617
volumeName: test-release-name-common-test-my-volume2-1734805617
- documentIndex: &thirdSecretDoc 6
isKind:
of: Secret
- documentIndex: *thirdSecretDoc
equal:
path: stringData
value:
username: my-user3
password: my-password3
- documentIndex: &thirdPvDoc 7
isKind:
of: PersistentVolume
- documentIndex: *thirdPvDoc
equal:
path: spec
value:
capacity:
storage: 3Gi
persistentVolumeReclaimPolicy: Delete
storageClassName: test-release-name-common-test-my-volume3-1737164916
accessModes:
- ReadWriteOnce
mountOptions:
- hard
- uid=99999999999
- vers=3.0
csi:
driver: smb.csi.k8s.io
volumeHandle: my-server3/my-share3#test-release-name-common-test-my-volume3-1737164916
volumeAttributes:
source: //my-server3/my-share3
nodeStageSecretRef:
name: test-release-name-common-test-my-volume3-1737164916
namespace: test-release-namespace
- documentIndex: &thirdPvcDoc 8
isKind:
of: PersistentVolumeClaim
- documentIndex: *thirdPvcDoc
equal:
path: spec
value:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 3Gi
storageClassName: test-release-name-common-test-my-volume3-1737164916
volumeName: test-release-name-common-test-my-volume3-1737164916

View File

@@ -0,0 +1,239 @@
suite: pv 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 pv created with labels and annotations (nfs-pv-pvc)
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 }}"
persistence:
my-volume1:
enabled: true
type: pvc
static:
mode: nfs
share: /someshare
server: someserver
labels:
label1: "{{ .Values.label1 }}"
label2: label2
annotations:
annotation1: "{{ .Values.annotation1 }}"
annotation2: annotation2
asserts:
- documentIndex: &pvDoc 0
isKind:
of: PersistentVolume
- documentIndex: *pvDoc
isAPIVersion:
of: v1
- documentIndex: *pvDoc
equal:
path: metadata.annotations
value:
annotation1: annotation1
annotation2: annotation2
g_annotation1: global_annotation1
g_annotation2: global_annotation2
pv.kubernetes.io/provisioned-by: nfs.csi.k8s.io
- documentIndex: *pvDoc
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/instance: test-release-name
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/version: *appVer
app.kubernetes.io/name: common-test
g_label1: global_label1
g_label2: global_label2
label1: label1
label2: label2
- it: should pass with pvc created with retain set to true (nfs-pv-pvc)
set:
persistence:
my-volume1:
enabled: true
type: pvc
static:
mode: nfs
share: /someshare
server: someserver
retain: true
asserts:
- documentIndex: *pvDoc
isKind:
of: PersistentVolume
- documentIndex: *pvDoc
equal:
path: metadata.annotations
value:
"helm.sh/resource-policy": keep
pv.kubernetes.io/provisioned-by: nfs.csi.k8s.io
- documentIndex: *pvDoc
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/instance: test-release-name
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/version: *appVer
app.kubernetes.io/name: common-test
- it: should pass with pv created with labels and annotations (smb-pv-pvc)
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 }}"
persistence:
my-volume1:
enabled: true
type: pvc
static:
mode: smb
share: someshare
server: someserver
username: someuser
password: someuserpoassword
labels:
label1: "{{ .Values.label1 }}"
label2: label2
annotations:
annotation1: "{{ .Values.annotation1 }}"
annotation2: annotation2
asserts:
- documentIndex: &secretDoc 0
isKind:
of: Secret
- documentIndex: *secretDoc
isAPIVersion:
of: v1
- documentIndex: *secretDoc
equal:
path: metadata.annotations
value:
annotation1: annotation1
annotation2: annotation2
g_annotation1: global_annotation1
g_annotation2: global_annotation2
- documentIndex: *secretDoc
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/instance: test-release-name
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/version: *appVer
app.kubernetes.io/name: common-test
g_label1: global_label1
g_label2: global_label2
label1: label1
label2: label2
- documentIndex: &pvDoc 1
isKind:
of: PersistentVolume
- documentIndex: *pvDoc
isAPIVersion:
of: v1
- documentIndex: *pvDoc
equal:
path: metadata.annotations
value:
annotation1: annotation1
annotation2: annotation2
g_annotation1: global_annotation1
g_annotation2: global_annotation2
pv.kubernetes.io/provisioned-by: smb.csi.k8s.io
- documentIndex: *pvDoc
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/instance: test-release-name
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/version: *appVer
app.kubernetes.io/name: common-test
g_label1: global_label1
g_label2: global_label2
label1: label1
label2: label2
- it: should pass with pvc created with retain set to true (smb-pv-pvc)
set:
persistence:
my-volume1:
enabled: true
type: pvc
static:
mode: smb
share: someshare
server: someserver
username: someuser
password: someuserpoassword
retain: true
asserts:
- documentIndex: *secretDoc
isKind:
of: Secret
- documentIndex: *secretDoc
isAPIVersion:
of: v1
- documentIndex: *secretDoc
isNull:
path: metadata.annotations
- documentIndex: *pvDoc
isKind:
of: PersistentVolume
- documentIndex: *pvDoc
equal:
path: metadata.annotations
value:
"helm.sh/resource-policy": keep
pv.kubernetes.io/provisioned-by: smb.csi.k8s.io
- documentIndex: *pvDoc
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/instance: test-release-name
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/version: *appVer
app.kubernetes.io/name: common-test

View File

@@ -0,0 +1,77 @@
suite: pv name test
templates:
- common.yaml
release:
name: test-release-name
namespace: test-release-namespace
tests:
- it: should generate correct name
set:
persistence:
my-volume1:
enabled: true
type: pvc
static:
mode: nfs
share: /someshare
server: someserver
my-volume2:
enabled: true
type: pvc
static:
mode: smb
share: someshare
server: someserver
username: someuser
password: someuserpoassword
asserts:
- documentIndex: &pvDoc 0
isKind:
of: PersistentVolume
- documentIndex: *pvDoc
isAPIVersion:
of: v1
- documentIndex: *pvDoc
equal:
path: metadata.name
value: test-release-name-common-test-my-volume1-2156988893
- documentIndex: &pvcDoc 1
isKind:
of: PersistentVolumeClaim
- documentIndex: *pvcDoc
isAPIVersion:
of: v1
- documentIndex: *pvcDoc
equal:
path: metadata.name
value: test-release-name-common-test-my-volume1-2156988893
- documentIndex: &secretDoc 2
isKind:
of: Secret
- documentIndex: *secretDoc
isAPIVersion:
of: v1
- documentIndex: *secretDoc
equal:
path: metadata.name
value: test-release-name-common-test-my-volume2-2027162030
- documentIndex: &pvDoc 3
isKind:
of: PersistentVolume
- documentIndex: *pvDoc
isAPIVersion:
of: v1
- documentIndex: *pvDoc
equal:
path: metadata.name
value: test-release-name-common-test-my-volume2-2027162030
- documentIndex: &otherPvcDoc 4
isKind:
of: PersistentVolumeClaim
- documentIndex: *otherPvcDoc
isAPIVersion:
of: v1
- documentIndex: *otherPvcDoc
equal:
path: metadata.name
value: test-release-name-common-test-my-volume2-2027162030

View File

@@ -43,7 +43,7 @@ tests:
type: not-a-type
asserts:
- failedTemplate:
errorMessage: Persistence - Expected <type> to be one of [pvc, emptyDir, nfs, hostPath, ixVolume, secret, configmap, device], but got [not-a-type]
errorMessage: Persistence - Expected <type> to be one of [pvc, vct, emptyDir, nfs, hostPath, ixVolume, secret, configmap, device], but got [not-a-type]
- it: should fail with invalid accessMode
set:
@@ -157,3 +157,279 @@ tests:
asserts:
- failedTemplate:
errorMessage: Persistent Volume Claim - Namespace [my-namespace] expected to have [ix-] prefix when installed in TrueNAS SCALE
- it: should fail without server on pvc static nfs
set:
persistence:
volume1:
enabled: true
type: pvc
static:
mode: nfs
share: /someshare
asserts:
- failedTemplate:
errorMessage: NFS CSI - Expected <server> to be non-empty
- it: should fail without share on pvc static nfs
set:
persistence:
volume1:
enabled: true
type: pvc
static:
mode: nfs
server: someserver
asserts:
- failedTemplate:
errorMessage: NFS CSI - Expected <share> to be non-empty
- it: should fail without server on pvc static smb
set:
persistence:
volume1:
enabled: true
type: pvc
static:
mode: smb
share: someshare
asserts:
- failedTemplate:
errorMessage: SMB CSI - Expected <server> to be non-empty
- it: should fail without share on pvc static smb
set:
persistence:
volume1:
enabled: true
type: pvc
static:
mode: smb
server: someserver
asserts:
- failedTemplate:
errorMessage: SMB CSI - Expected <share> to be non-empty
- it: should fail without CSI when in ixChartContext on pvc static smb
set:
global:
ixChartContext: {}
persistence:
volume1:
enabled: true
type: pvc
static:
mode: smb
share: someshare
server: someserver
asserts:
- failedTemplate:
errorMessage: SMB CSI - Not supported CSI
- it: should fail without CSI when in ixChartContext on pvc static nfs
set:
global:
ixChartContext: {}
persistence:
volume1:
enabled: true
type: pvc
static:
mode: nfs
share: /someshare
server: someserver
asserts:
- failedTemplate:
errorMessage: NFS CSI - Not supported CSI
- it: should fail without username pvc static smb
set:
persistence:
volume1:
enabled: true
type: pvc
static:
mode: smb
share: someshare
server: someserver
asserts:
- failedTemplate:
errorMessage: SMB CSI - Expected <username> to be non-empty
- it: should fail without password on pvc static smb
set:
persistence:
volume1:
enabled: true
type: pvc
static:
mode: smb
share: someshare
server: someserver
username: someuser
asserts:
- failedTemplate:
errorMessage: SMB CSI - Expected <password> to be non-empty
- it: should fail with server starting with // on pvc static smb
set:
persistence:
volume1:
enabled: true
type: pvc
static:
mode: smb
share: someshare
server: //someserver
username: someuser
password: someuserpoassword
asserts:
- failedTemplate:
errorMessage: SMB CSI - Did not expect <server> to start with [//]
- it: should fail with share starting with / on pvc static smb
set:
persistence:
volume1:
enabled: true
type: pvc
static:
mode: smb
share: /someshare
server: someserver
username: someuser
password: someuserpoassword
asserts:
- failedTemplate:
errorMessage: SMB CSI - Did not expect <share> to start with [/]
- it: should fail without share starting with / on pvc static nfs
set:
persistence:
volume1:
enabled: true
type: pvc
static:
mode: nfs
share: someshare
server: someserver
asserts:
- failedTemplate:
errorMessage: NFS CSI - Expected <share> to start with [/]
- it: should fail with empty key on mountOptions in pvc static nfs
set:
persistence:
volume1:
enabled: true
type: pvc
static:
mode: nfs
share: /someshare
server: someserver
mountOptions:
- key: ""
asserts:
- failedTemplate:
errorMessage: NFS CSI - Expected key in <mountOptions> to be non-empty
- it: should fail with empty key on mountOptions in pvc static smb
set:
persistence:
volume1:
enabled: true
type: pvc
static:
mode: smb
share: someshare
server: someserver
username: someuser
password: someuserpoassword
mountOptions:
- key: ""
asserts:
- failedTemplate:
errorMessage: SMB CSI - Expected key in <mountOptions> to be non-empty
- it: should fail with item in mountOptions not a map in pvc static smb
set:
persistence:
volume1:
enabled: true
type: pvc
static:
mode: smb
share: someshare
server: someserver
username: someuser
password: someuserpoassword
mountOptions:
- not-a-map
asserts:
- failedTemplate:
errorMessage: SMB CSI - Expected <mountOption> item to be a dict, but got [string]
- it: should fail with item in mountOptions not a map in pvc static nfs
set:
persistence:
volume1:
enabled: true
type: pvc
static:
mode: nfs
share: /someshare
server: someserver
mountOptions:
- not-a-map
asserts:
- failedTemplate:
errorMessage: NFS CSI - Expected <mountOption> item to be a dict, but got [string]
- it: should fail with invalid static mode
set:
persistence:
volume1:
enabled: true
type: pvc
static:
mode: not-a-mode
asserts:
- failedTemplate:
errorMessage: Persistence - Expected [static.mode] to be one of [disabled, smb, nfs, custom], but got [not-a-mode]
- it: should fail with missing name in dataSource
set:
persistence:
volume1:
enabled: true
type: pvc
dataSource:
kind: PersistentVolumeClaim
asserts:
- failedTemplate:
errorMessage: Persistence - Expected [dataSource.name] to be non-empty
- it: should fail with missing kind in dataSource
set:
persistence:
volume1:
enabled: true
type: pvc
dataSource:
name: some name
asserts:
- failedTemplate:
errorMessage: Persistence - Expected [dataSource.kind] to be non-empty
- it: should fail with invalid kind in dataSource
set:
persistence:
volume1:
enabled: true
type: pvc
dataSource:
name: some name
kind: invalid
asserts:
- failedTemplate:
errorMessage: Persistence - Expected [dataSource.kind] to be one of [VolumeSnapshot, PersistentVolumeClaim], but got [invalid]

View File

@@ -0,0 +1,831 @@
suite: container volumeMounts test
templates:
- common.yaml
release:
name: test-release-name
namespace: test-release-namespace
tests:
- it: should pass with shared volume on multiple workloads and containers with targetSelectAll
set:
some_path: /some/path
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
probes: &probes
liveness:
enabled: false
readiness:
enabled: false
startup:
enabled: false
container-name2:
enabled: true
primary: false
imageSelector: image
probes: *probes
workload-name2:
enabled: true
primary: false
type: Job
podSpec:
restartPolicy: Never
containers:
container-name1:
enabled: true
primary: true
imageSelector: image
probes: *probes
container-name2:
enabled: true
primary: false
imageSelector: image
probes: *probes
persistence:
shared-vol:
enabled: true
type: emptyDir
mountPath: "{{ .Values.some_path }}"
targetSelectAll: true
nfs-vol-pvc:
enabled: true
type: pvc
static:
mode: nfs
share: /someshare
server: someserver
mountPath: /nfs-mount
targetSelectAll: true
smb-vol-pvc:
enabled: true
type: pvc
static:
mode: smb
share: someshare
server: someserver
username: someuser
password: someuserpoassword
mountPath: /smb-mount
targetSelectAll: true
asserts:
- documentIndex: &deploymentDoc 0
isKind:
of: Deployment
- documentIndex: *deploymentDoc
isAPIVersion:
of: apps/v1
- documentIndex: *deploymentDoc
contains:
path: spec.template.spec.containers[0].volumeMounts
content:
name: shared-vol
mountPath: /some/path
readOnly: false
- documentIndex: *deploymentDoc
contains:
path: spec.template.spec.containers[0].volumeMounts
content:
name: nfs-vol-pvc
mountPath: /nfs-mount
readOnly: false
- documentIndex: *deploymentDoc
contains:
path: spec.template.spec.containers[0].volumeMounts
content:
name: smb-vol-pvc
mountPath: /smb-mount
readOnly: false
- documentIndex: *deploymentDoc
contains:
path: spec.template.spec.containers[1].volumeMounts
content:
name: shared-vol
mountPath: /some/path
readOnly: false
- documentIndex: *deploymentDoc
contains:
path: spec.template.spec.containers[1].volumeMounts
content:
name: nfs-vol-pvc
mountPath: /nfs-mount
readOnly: false
- documentIndex: *deploymentDoc
contains:
path: spec.template.spec.containers[1].volumeMounts
content:
name: smb-vol-pvc
mountPath: /smb-mount
readOnly: false
- documentIndex: &jobDoc 1
isKind:
of: Job
- documentIndex: *jobDoc
isAPIVersion:
of: batch/v1
- documentIndex: *jobDoc
contains:
path: spec.template.spec.containers[0].volumeMounts
content:
name: shared-vol
mountPath: /some/path
readOnly: false
- documentIndex: *jobDoc
contains:
path: spec.template.spec.containers[0].volumeMounts
content:
name: nfs-vol-pvc
mountPath: /nfs-mount
readOnly: false
- documentIndex: *jobDoc
contains:
path: spec.template.spec.containers[0].volumeMounts
content:
name: smb-vol-pvc
mountPath: /smb-mount
readOnly: false
- documentIndex: *jobDoc
contains:
path: spec.template.spec.containers[1].volumeMounts
content:
name: shared-vol
mountPath: /some/path
readOnly: false
- documentIndex: *jobDoc
contains:
path: spec.template.spec.containers[1].volumeMounts
content:
name: nfs-vol-pvc
mountPath: /nfs-mount
readOnly: false
- documentIndex: *jobDoc
contains:
path: spec.template.spec.containers[1].volumeMounts
content:
name: smb-vol-pvc
mountPath: /smb-mount
readOnly: false
- it: should pass with volume on primary workload and container
set:
image: *image
workload:
workload-name:
enabled: true
primary: true
type: Deployment
podSpec:
containers:
container-name1:
enabled: true
primary: true
imageSelector: image
probes: *probes
container-name2:
enabled: true
primary: false
imageSelector: image
probes: *probes
workload-name2:
enabled: true
primary: false
type: Job
podSpec:
restartPolicy: Never
containers:
container-name1:
enabled: true
primary: true
imageSelector: image
probes: *probes
container-name2:
enabled: true
primary: false
imageSelector: image
probes: *probes
persistence:
some-vol:
enabled: true
type: emptyDir
mountPath: /some/path
readOnly: true
asserts:
- documentIndex: &deploymentDoc 0
isKind:
of: Deployment
- documentIndex: *deploymentDoc
isAPIVersion:
of: apps/v1
- documentIndex: *deploymentDoc
contains:
path: spec.template.spec.containers[0].volumeMounts
content:
name: some-vol
mountPath: /some/path
readOnly: true
- documentIndex: *deploymentDoc
notContains:
path: spec.template.spec.containers[1].volumeMounts
content:
name: some-vol
mountPath: /some/path
readOnly: true
- documentIndex: &jobDoc 1
isKind:
of: Job
- documentIndex: *jobDoc
isAPIVersion:
of: batch/v1
- documentIndex: *jobDoc
notContains:
path: spec.template.spec.containers[0].volumeMounts
content:
name: some-vol
mountPath: /some/path
readOnly: true
- documentIndex: *jobDoc
notContains:
path: spec.template.spec.containers[1].volumeMounts
content:
name: some-vol
mountPath: /some/path
readOnly: true
- it: should pass with volume with selected pod and container
set:
image: *image
workload:
workload-name:
enabled: true
primary: true
type: Deployment
podSpec:
containers:
container-name1:
enabled: true
primary: true
imageSelector: image
probes: *probes
container-name2:
enabled: true
primary: false
imageSelector: image
probes: *probes
workload-name2:
enabled: true
primary: false
type: Job
podSpec:
restartPolicy: Never
containers:
container-name1:
enabled: true
primary: true
imageSelector: image
probes: *probes
container-name2:
enabled: true
primary: false
imageSelector: image
probes: *probes
persistence:
some-vol:
enabled: true
type: emptyDir
mountPath: /some/path
readOnly: true
targetSelector:
workload-name:
container-name2: {}
workload-name2:
container-name1: {}
asserts:
- documentIndex: &deploymentDoc 0
isKind:
of: Deployment
- documentIndex: *deploymentDoc
isAPIVersion:
of: apps/v1
- documentIndex: *deploymentDoc
notContains:
path: spec.template.spec.containers[0].volumeMounts
content:
name: some-vol
mountPath: /some/path
readOnly: true
- documentIndex: *deploymentDoc
contains:
path: spec.template.spec.containers[1].volumeMounts
content:
name: some-vol
mountPath: /some/path
readOnly: true
- documentIndex: &jobDoc 1
isKind:
of: Job
- documentIndex: *jobDoc
isAPIVersion:
of: batch/v1
- documentIndex: *jobDoc
contains:
path: spec.template.spec.containers[0].volumeMounts
content:
name: some-vol
mountPath: /some/path
readOnly: true
- documentIndex: *jobDoc
notContains:
path: spec.template.spec.containers[1].volumeMounts
content:
name: some-vol
mountPath: /some/path
readOnly: true
- it: should pass with volume with selected pod and multiple containers
set:
image: *image
workload:
workload-name:
enabled: true
primary: true
type: Deployment
podSpec:
containers:
container-name1:
enabled: true
primary: true
imageSelector: image
probes: *probes
container-name2:
enabled: true
primary: false
imageSelector: image
probes: *probes
workload-name2:
enabled: true
primary: false
type: Job
podSpec:
restartPolicy: Never
containers:
container-name1:
enabled: true
primary: true
imageSelector: image
probes: *probes
container-name2:
enabled: true
primary: false
imageSelector: image
probes: *probes
persistence:
some-vol:
enabled: true
type: emptyDir
mountPath: /some/path
readOnly: true
targetSelector:
workload-name:
container-name1: {}
container-name2: {}
asserts:
- documentIndex: &deploymentDoc 0
isKind:
of: Deployment
- documentIndex: *deploymentDoc
isAPIVersion:
of: apps/v1
- documentIndex: *deploymentDoc
contains:
path: spec.template.spec.containers[0].volumeMounts
content:
name: some-vol
mountPath: /some/path
readOnly: true
- documentIndex: *deploymentDoc
contains:
path: spec.template.spec.containers[1].volumeMounts
content:
name: some-vol
mountPath: /some/path
readOnly: true
- documentIndex: &jobDoc 1
isKind:
of: Job
- documentIndex: *jobDoc
isAPIVersion:
of: batch/v1
- documentIndex: *jobDoc
notContains:
path: spec.template.spec.containers[0].volumeMounts
content:
name: some-vol
mountPath: /some/path
readOnly: true
- documentIndex: *jobDoc
notContains:
path: spec.template.spec.containers[1].volumeMounts
content:
name: some-vol
mountPath: /some/path
readOnly: true
- it: should pass with volume with selected pod and containers and specific values
set:
image: *image
workload:
workload-name:
enabled: true
primary: true
type: Deployment
podSpec:
containers:
container-name1:
enabled: true
primary: true
imageSelector: image
probes: *probes
container-name2:
enabled: true
primary: false
imageSelector: image
probes: *probes
workload-name2:
enabled: true
primary: false
type: Job
podSpec:
restartPolicy: Never
containers:
container-name1:
enabled: true
primary: true
imageSelector: image
probes: *probes
container-name2:
enabled: true
primary: false
imageSelector: image
probes: *probes
persistence:
some-vol:
enabled: true
type: emptyDir
mountPath: /some/path
readOnly: true
targetSelector:
workload-name:
container-name1:
mountPath: /some/other/path
readOnly: false
mountPropagation: None
subPath: /some/sub/path
container-name2: {}
asserts:
- documentIndex: &deploymentDoc 0
isKind:
of: Deployment
- documentIndex: *deploymentDoc
isAPIVersion:
of: apps/v1
- documentIndex: *deploymentDoc
contains:
path: spec.template.spec.containers[0].volumeMounts
content:
name: some-vol
mountPath: /some/other/path
readOnly: false
mountPropagation: None
subPath: /some/sub/path
- documentIndex: *deploymentDoc
contains:
path: spec.template.spec.containers[1].volumeMounts
content:
name: some-vol
mountPath: /some/path
readOnly: true
- documentIndex: &jobDoc 1
isKind:
of: Job
- documentIndex: *jobDoc
isAPIVersion:
of: batch/v1
- documentIndex: *jobDoc
notContains:
path: spec.template.spec.containers[0].volumeMounts
content:
name: some-vol
mountPath: /some/other/path
readOnly: false
mountPropagation: None
subPath: /some/sub/path
- documentIndex: *jobDoc
notContains:
path: spec.template.spec.containers[1].volumeMounts
content:
name: some-vol
mountPath: /some/path
readOnly: true
- it: should pass with volume with selected pod and containers and specific values from tpl
set:
some_path: /some/other/path
some_propagation: None
some_sub_path: /some/sub/path
image: *image
workload:
workload-name:
enabled: true
primary: true
type: Deployment
podSpec:
containers:
container-name1:
enabled: true
primary: true
imageSelector: image
probes: *probes
container-name2:
enabled: true
primary: false
imageSelector: image
probes: *probes
persistence:
some-vol:
enabled: true
type: emptyDir
mountPath: /some/path
readOnly: true
targetSelector:
workload-name:
container-name1:
mountPath: "{{ .Values.some_path }}"
readOnly: false
mountPropagation: "{{ .Values.some_propagation }}"
subPath: "{{ .Values.some_sub_path }}"
container-name2: {}
asserts:
- documentIndex: &deploymentDoc 0
isKind:
of: Deployment
- documentIndex: *deploymentDoc
isAPIVersion:
of: apps/v1
- documentIndex: *deploymentDoc
contains:
path: spec.template.spec.containers[0].volumeMounts
content:
name: some-vol
mountPath: /some/other/path
readOnly: false
mountPropagation: None
subPath: /some/sub/path
- documentIndex: *deploymentDoc
contains:
path: spec.template.spec.containers[1].volumeMounts
content:
name: some-vol
mountPath: /some/path
readOnly: true
- it: should pass with cert mounted as volume with subPath
set:
image: *image
ixCertificates:
"1":
certificate: some_cert
key: some_key
scaleCertificate:
cert-name:
enabled: false
id: 1
workload:
workload-name:
enabled: true
primary: true
type: Deployment
podSpec:
containers:
container-name1:
enabled: true
primary: true
imageSelector: image
probes: *probes
persistence:
cert-vol:
enabled: true
type: secret
objectName: cert-name
readOnly: true
targetSelector:
workload-name:
container-name1:
mountPath: /some/path/cert.crt
readOnly: true
subPath: cert.crt
asserts:
- documentIndex: &deploymentDoc 0
isKind:
of: Deployment
- documentIndex: *deploymentDoc
isAPIVersion:
of: apps/v1
- documentIndex: *deploymentDoc
contains:
path: spec.template.spec.containers[0].volumeMounts
content:
name: cert-vol
mountPath: /some/path/cert.crt
readOnly: true
subPath: cert.crt
- it: should pass with cert mounted as volume with subPath
set:
image: *image
ixCertificates:
"1":
certificate: some_cert
key: some_key
scaleCertificate:
cert-name:
enabled: false
id: 1
workload:
workload-name:
enabled: true
primary: true
type: Deployment
podSpec:
containers:
container-name1:
enabled: true
primary: true
imageSelector: image
probes: *probes
persistence:
cert-vol:
enabled: true
type: secret
objectName: cert-name
readOnly: true
items:
- key: tls.crt
path: cert.crt
targetSelector:
workload-name:
container-name1:
mountPath: /some/path
readOnly: true
asserts:
- documentIndex: &deploymentDoc 0
isKind:
of: Deployment
- documentIndex: *deploymentDoc
isAPIVersion:
of: apps/v1
- documentIndex: *deploymentDoc
contains:
path: spec.template.spec.containers[0].volumeMounts
content:
name: cert-vol
mountPath: /some/path
readOnly: true
# Failures
- it: should fail with invalid mountPropagation
set:
image: *image
workload:
workload-name: &workload
enabled: true
primary: true
type: Deployment
podSpec:
containers:
container-name1:
enabled: true
primary: true
imageSelector: image
persistence:
vol-name:
enabled: true
type: emptyDir
mountPath: /some/path
mountPropagation: HostToContainer
targetSelector:
workload-name:
container-name1:
mountPropagation: invalid
asserts:
- failedTemplate:
errorMessage: Persistence - Expected <mountPropagation> to be one of [None, HostToContainer, Bidirectional], but got [invalid]
- it: should fail with non-boolean readOnly
set:
image: *image
workload:
workload-name: *workload
persistence:
vol-name:
enabled: true
type: emptyDir
mountPath: /some/path
targetSelector:
workload-name:
container-name1:
readOnly: invalid
asserts:
- failedTemplate:
errorMessage: Persistence - Expected <readOnly> to be [boolean], but got [string]
- it: should fail with empty readOnly
set:
image: *image
workload:
workload-name: *workload
persistence:
vol-name:
enabled: true
type: emptyDir
mountPath: /some/path
targetSelector:
workload-name:
container-name1:
readOnly:
asserts:
- failedTemplate:
errorMessage: Persistence - Expected <readOnly> to be [boolean], but got [invalid]
- it: should fail with empty mountPath
set:
image: *image
workload:
workload-name: *workload
persistence:
vol-name:
enabled: true
type: emptyDir
mountPath: ""
targetSelector:
workload-name:
container-name1: {}
asserts:
- failedTemplate:
errorMessage: Persistence - Expected non-empty <mountPath>
- it: should fail with mountPath not starting with /
set:
image: *image
workload:
workload-name: *workload
persistence:
vol-name:
enabled: true
type: emptyDir
targetSelector:
workload-name:
container-name1:
mountPath: some/path
asserts:
- failedTemplate:
errorMessage: Persistence - Expected <mountPath> to start with a forward slash [/]
- it: should fail with non-dict targetSelect.workloadName
set:
image: *image
workload:
workload-name: *workload
persistence:
vol-name:
enabled: true
type: emptyDir
targetSelector:
workload-name: string
asserts:
- failedTemplate:
errorMessage: Persistence - Expected <targetSelector.workload-name> to be a [dict], but got [string]
- it: should fail with empty targetSelect.workloadName
set:
image: *image
workload:
workload-name: *workload
persistence:
vol-name:
enabled: true
type: emptyDir
targetSelector:
workload-name: {}
asserts:
- failedTemplate:
errorMessage: Persistence - Expected non-empty <targetSelector.workload-name>

View File

@@ -0,0 +1,85 @@
suite: pod nfs-pv-pvc volume test
templates:
- common.yaml
release:
name: test-release-name
namespace: test-release-namespace
tests:
- it: should pass with nfs-pv-pvc volume
set:
workload:
workload-name1:
enabled: true
primary: true
type: Deployment
podSpec: {}
persistence:
my-volume1:
enabled: true
type: pvc
static:
mode: nfs
server: my-server
share: /my-path
my-volume2:
enabled: true
type: pvc
static:
mode: nfs
server: my-server2
share: /my-path2
size: 2Gi
my-volume3:
enabled: true
type: pvc
static:
mode: nfs
server: my-server3
share: /my-path3
size: 3Gi
asserts:
- documentIndex: &pvDoc 1
isKind:
of: PersistentVolume
- documentIndex: *pvDoc
equal:
path: metadata.name
value: test-release-name-common-test-my-volume1-1599277109
- documentIndex: &otherPvDoc 3
isKind:
of: PersistentVolume
- documentIndex: *otherPvDoc
equal:
path: metadata.name
value: test-release-name-common-test-my-volume2-1702692922
- documentIndex: &thirdPvDoc 5
isKind:
of: PersistentVolume
- documentIndex: *thirdPvDoc
equal:
path: metadata.name
value: test-release-name-common-test-my-volume3-1705052221
- documentIndex: &deploymentDoc 0
isKind:
of: Deployment
- documentIndex: *deploymentDoc
contains:
path: spec.template.spec.volumes
content:
name: my-volume1
persistentVolumeClaim:
claimName: test-release-name-common-test-my-volume1-1599277109
- documentIndex: *deploymentDoc
contains:
path: spec.template.spec.volumes
content:
name: my-volume2
persistentVolumeClaim:
claimName: test-release-name-common-test-my-volume2-1702692922
- documentIndex: *deploymentDoc
contains:
path: spec.template.spec.volumes
content:
name: my-volume3
persistentVolumeClaim:
claimName: test-release-name-common-test-my-volume3-1705052221

View File

@@ -0,0 +1,91 @@
suite: pod smb-pv-pvc volume test
templates:
- common.yaml
release:
name: test-release-name
namespace: test-release-namespace
tests:
- it: should pass with smb-pv-pvc volume
set:
workload:
workload-name1:
enabled: true
primary: true
type: Deployment
podSpec: {}
persistence:
my-volume1:
enabled: true
type: pvc
static:
mode: smb
server: my-server
share: my-share
username: my-user
password: my-pass
my-volume2:
enabled: true
type: pvc
static:
mode: smb
server: my-server2
share: my-share2
username: my-user2
password: my-pass2
size: 2Gi
my-volume3:
enabled: true
type: pvc
static:
mode: smb
server: my-server3
share: my-share3
username: my-user3
password: my-pass3
size: 3Gi
asserts:
- documentIndex: &pvDoc 2
isKind:
of: PersistentVolume
- documentIndex: *pvDoc
equal:
path: metadata.name
value: test-release-name-common-test-my-volume1-1627785324
- documentIndex: &otherPvDoc 5
isKind:
of: PersistentVolume
- documentIndex: *otherPvDoc
equal:
path: metadata.name
value: test-release-name-common-test-my-volume2-1734805617
- documentIndex: &thirdPvDoc 8
isKind:
of: PersistentVolume
- documentIndex: *thirdPvDoc
equal:
path: metadata.name
value: test-release-name-common-test-my-volume3-1737164916
- documentIndex: &deploymentDoc 0
isKind:
of: Deployment
- documentIndex: *deploymentDoc
contains:
path: spec.template.spec.volumes
content:
name: my-volume1
persistentVolumeClaim:
claimName: test-release-name-common-test-my-volume1-1627785324
- documentIndex: *deploymentDoc
contains:
path: spec.template.spec.volumes
content:
name: my-volume2
persistentVolumeClaim:
claimName: test-release-name-common-test-my-volume2-1734805617
- documentIndex: *deploymentDoc
contains:
path: spec.template.spec.volumes
content:
name: my-volume3
persistentVolumeClaim:
claimName: test-release-name-common-test-my-volume3-1737164916

View File

@@ -1,4 +1,4 @@
suite: volumeClaimTemplates metadata test
suite: volumeClaimTemplate metadata test
templates:
- common.yaml
chart:
@@ -16,9 +16,10 @@ tests:
g_label1: global_label1
annotations:
g_annotation1: global_annotation1
volumeClaimTemplates:
persistence:
my-volume1:
enabled: true
type: vct
labels:
label1: "{{ .Values.label1 }}"
label2: label2

View File

@@ -1,4 +1,4 @@
suite: volumeClaimTemplates name test
suite: volumeClaimTemplate name test
templates:
- common.yaml
release:
@@ -7,11 +7,13 @@ release:
tests:
- it: should generate correct name
set:
volumeClaimTemplates:
persistence:
my-volume1:
enabled: true
type: vct
my-volume2:
enabled: true
type: vct
workload:
main:
enabled: true
@@ -28,8 +30,8 @@ tests:
- documentIndex: *statefulSetDoc
equal:
path: spec.volumeClaimTemplates[0].metadata.name
value: my-volume1
value: test-release-name-common-test-my-volume1
- documentIndex: *statefulSetDoc
equal:
path: spec.volumeClaimTemplates[1].metadata.name
value: my-volume2
value: test-release-name-common-test-my-volume2

View File

@@ -7,9 +7,10 @@ release:
tests:
- it: should fail with annotations not a dict
set:
volumeClaimTemplates:
persistence:
volume1:
enabled: true
type: vct
annotations: not-a-dict
workload:
main:
@@ -23,9 +24,10 @@ tests:
- it: should fail with labels not a dict
set:
volumeClaimTemplates:
persistence:
volume1:
enabled: true
type: vct
labels: not-a-dict
workload:
main:
@@ -39,9 +41,10 @@ tests:
- it: should fail with pod targetSelector not a map
set:
volumeClaimTemplates:
persistence:
volume1:
enabled: true
type: vct
targetSelector: not-a-map
workload:
main:
@@ -51,7 +54,7 @@ tests:
podSpec: {}
asserts:
- failedTemplate:
errorMessage: Volume Claim Templates - Expected <targetSelector> to be [dict], but got [string]
errorMessage: Persistence - Expected [targetSelector] to be [dict], but got [string]
- it: should fail without storageClassName in ixChartContext
set:
@@ -59,9 +62,10 @@ tests:
namespace: ix-namespace
ixChartContext:
storageClassName: ""
volumeClaimTemplates:
persistence:
volume1:
enabled: true
type: vct
workload:
main:
enabled: true
@@ -70,7 +74,7 @@ tests:
podSpec: {}
asserts:
- failedTemplate:
errorMessage: Volume Claim Templates - Expected non-empty <global.ixChartContext.storageClassName>
errorMessage: PVC - Expected non-empty <global.ixChartContext.storageClassName>
- it: should fail without storageClassName in ixChartContext with SCALE-ZFS explicitly set
set:
@@ -78,9 +82,10 @@ tests:
namespace: ix-namespace
ixChartContext:
storageClassName: ""
volumeClaimTemplates:
persistence:
volume1:
enabled: true
type: vct
storageClass: SCALE-ZFS
workload:
main:
@@ -90,13 +95,14 @@ tests:
podSpec: {}
asserts:
- failedTemplate:
errorMessage: Volume Claim Templates - Expected non-empty <global.ixChartContext.storageClassName> on [SCALE-ZFS] storageClass
errorMessage: PVC - Expected non-empty <global.ixChartContext.storageClassName> on [SCALE-ZFS] storageClass
- it: should fail with invalid accessMode
set:
volumeClaimTemplates:
persistence:
volume1:
enabled: true
type: vct
accessModes:
- not-an-access-mode
workload:
@@ -107,4 +113,4 @@ tests:
podSpec: {}
asserts:
- failedTemplate:
errorMessage: Volume Claim Templates - Expected <accessModes> entry to be one of [ReadWriteOnce, ReadOnlyMany, ReadWriteMany, ReadWriteOncePod], but got [not-an-access-mode]
errorMessage: PVC - Expected <accessModes> entry to be one of [ReadWriteOnce, ReadOnlyMany, ReadWriteMany, ReadWriteOncePod], but got [not-an-access-mode]

View File

@@ -1,4 +1,4 @@
suite: volumeClaimTemplates data test
suite: volumeClaimTemplate data test
templates:
- common.yaml
release:
@@ -7,9 +7,10 @@ release:
tests:
- it: should create vct
set:
volumeClaimTemplates:
persistence:
my-volume1:
enabled: true
type: vct
mountPath: /some/path
workload:
main:
@@ -27,7 +28,7 @@ tests:
- documentIndex: *statefulSetDoc
equal:
path: spec.volumeClaimTemplates[0].metadata.name
value: my-volume1
value: test-release-name-common-test-my-volume1
- documentIndex: *statefulSetDoc
equal:
path: spec.volumeClaimTemplates[0].spec.accessModes
@@ -44,9 +45,10 @@ tests:
- it: should create vct with accessModes set as string
set:
some_mode: ReadWriteMany
volumeClaimTemplates:
persistence:
my-volume1:
enabled: true
type: vct
mountPath: /some/path
accessModes: "{{ .Values.some_mode }}"
workload:
@@ -68,9 +70,10 @@ tests:
- it: should create pvc with accessModes set as list
set:
some_mode: ReadWriteMany
volumeClaimTemplates:
persistence:
my-volume1:
enabled: true
type: vct
mountPath: /some/path
accessModes:
- "{{ .Values.some_mode }}"
@@ -94,9 +97,10 @@ tests:
- it: should create pvc with size set
set:
volumeClaimTemplates:
persistence:
my-volume1:
enabled: true
type: vct
mountPath: /some/path
size: 20Gi
workload:
@@ -117,9 +121,10 @@ tests:
- it: should create vct with storageClass set "-"
set:
some_storage_class: "-"
volumeClaimTemplates:
persistence:
my-volume1:
enabled: true
type: vct
mountPath: /some/path
storageClass: "{{ .Values.some_storage_class }}"
workload:
@@ -140,9 +145,10 @@ tests:
- it: should create vct with storageClass set
set:
some_storage_class: some-storage-class
volumeClaimTemplates:
persistence:
my-volume1:
enabled: true
type: vct
mountPath: /some/path
storageClass: "{{ .Values.some_storage_class }}"
workload:
@@ -164,9 +170,10 @@ tests:
set:
fallbackDefaults:
storageClass: some-storage-class
volumeClaimTemplates:
persistence:
my-volume1:
enabled: true
type: vct
mountPath: /some/path
workload:
main:
@@ -190,9 +197,10 @@ tests:
ixChartContext:
storageClassName: ix-storage-class-releasename
some_storage_class: "SCALE-ZFS"
volumeClaimTemplates:
persistence:
my-volume1:
enabled: true
type: vct
mountPath: /some/path
storageClass: "{{ .Values.some_storage_class }}"
workload:
@@ -217,9 +225,10 @@ tests:
ixChartContext:
storageClassName: ix-storage-class-releasename
some_storage_class: "SCALE-ZFS"
volumeClaimTemplates:
persistence:
my-volume1:
enabled: true
type: vct
mountPath: /some/path
workload:
main:

View File

@@ -15,4 +15,4 @@ maintainers:
name: common
sources: null
type: library
version: 14.5.0
version: 15.0.0

View File

@@ -45,25 +45,11 @@ spec:
storage:
pvcTemplate:
{{- with (include "tc.v1.common.lib.storage.storageClassName" ( dict "rootCtx" $ "objectData" $values.storage )) | trim }}
storageClassName: {{ . }}
{{- end }}
accessModes:
- ReadWriteOnce
resources:
requests:
storage: {{ tpl ($values.storage.walsize | default $.Values.fallbackDefaults.vctSize) $ | quote }}
{{- include "tc.v1.common.lib.storage.pvc.spec" (dict "rootCtx" $ "objectData" $values.storage) | trim | nindent 6 }}
walStorage:
pvcTemplate:
{{- with (include "tc.v1.common.lib.storage.storageClassName" ( dict "rootCtx" $ "objectData" $values.storage )) | trim }}
storageClassName: {{ . }}
{{- end }}
accessModes:
- ReadWriteOnce
resources:
requests:
storage: {{ tpl ($values.storage.walsize | default $.Values.fallbackDefaults.vctSize) $ | quote }}
{{- include "tc.v1.common.lib.storage.pvc.spec" (dict "rootCtx" $ "objectData" $values.walStorage) | trim | nindent 6 }}
monitoring:
enablePodMonitor: {{ $values.monitoring.enablePodMonitor | default true }}

View File

@@ -0,0 +1,75 @@
{{/* PersistentVolume Class */}}
{{/* Call this template:
{{ include "tc.v1.common.class.pv" (dict "rootCtx" $ "objectData" $objectData) }}
rootCtx: The root context of the chart.
objectData:
name: The name of the PV.
labels: The labels of the PV.
annotations: The annotations of the PV.
provisioner: The provisioner to use for the PersistentVolume.
driver: The driver to use for the csi
retain: Whether to retain the PV after deletion. (Default: false)
size: The size of the PersistentVolume. (Default: 1Gi)
*/}}
{{- define "tc.v1.common.class.pv" -}}
{{- $rootCtx := .rootCtx -}}
{{- $objectData := .objectData -}}
{{- $retain := $rootCtx.Values.fallbackDefaults.pvcRetain -}}
{{- if not (kindIs "invalid" $objectData.retain) -}}
{{- $retain = $objectData.retain -}}
{{- end -}}
{{- $reclaimPolicy := ternary "Retain" "Delete" $retain -}}
{{- $pvcSize := $rootCtx.Values.fallbackDefaults.pvcSize -}}
{{- with $objectData.size -}}
{{- $pvcSize = tpl . $rootCtx -}}
{{- end }}
---
apiVersion: v1
kind: PersistentVolume
metadata:
name: {{ $objectData.name }}
{{- $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)) -}}
{{- if $retain -}}
{{- $_ := set $annotations "\"helm.sh/resource-policy\"" "keep" -}}
{{- end -}}
{{- $_ := set $annotations "pv.kubernetes.io/provisioned-by" $objectData.provisioner -}}
{{- with (include "tc.v1.common.lib.metadata.render" (dict "rootCtx" $rootCtx "annotations" $annotations) | trim) }}
annotations:
{{- . | nindent 4 }}
{{- end }}
spec:
capacity:
storage: {{ $pvcSize }}
persistentVolumeReclaimPolicy: {{ $reclaimPolicy }}
storageClassName: {{ $objectData.name }}
accessModes:
{{- include "tc.v1.common.lib.pvc.accessModes" (dict "rootCtx" $rootCtx "objectData" $objectData "caller" "Persistent Volume") | trim | nindent 4 -}}
{{- if $objectData.mountOptions }}
mountOptions:
{{- range $opt := $objectData.mountOptions -}}
{{- if $opt.value }}
- {{ printf "%s=%s" (tpl $opt.key $rootCtx) (tpl (include "tc.v1.common.helper.makeIntOrNoop" $opt.value) $rootCtx) }}
{{- else }}
- {{ tpl $opt.key $rootCtx }}
{{- end -}}
{{- end -}}
{{- end -}}
{{- if $objectData.static -}}
{{- if eq "smb" $objectData.static.mode -}}
{{- include "tc.v1.common.lib.storage.smbCSI" (dict "rootCtx" $rootCtx "objectData" $objectData) | trim | nindent 2 -}}
{{- else if eq "nfs" $objectData.static.mode -}}
{{- include "tc.v1.common.lib.storage.nfsCSI" (dict "rootCtx" $rootCtx "objectData" $objectData) | trim | nindent 2 -}}
{{- end -}}
{{- end -}}
{{- end -}}

View File

@@ -1,4 +1,4 @@
{{/* PVC Class */}}
{{/* PersistentVolumeClaim Class */}}
{{/* Call this template:
{{ include "tc.v1.common.class.pvc" (dict "rootCtx" $ "objectData" $objectData) }}
@@ -7,6 +7,10 @@ objectData:
name: The name of the PVC.
labels: The labels of the PVC.
annotations: The annotations of the PVC.
size: The size of the PVC. (Default: 1Gi)
volumeName: The name of the volume to bind to. (Default: "")
retain: Whether to retain the PVC after deletion. (Default: false)
storageClass: The storage class to use. (Absent)
*/}}
{{- define "tc.v1.common.class.pvc" -}}
@@ -43,15 +47,5 @@ metadata:
{{- . | nindent 4 }}
{{- end }}
spec:
accessModes:
{{- include "tc.v1.common.lib.pvc.accessModes" (dict "rootCtx" $rootCtx "objectData" $objectData "caller" "PVC") | trim | nindent 4 }}
resources:
requests:
storage: {{ $pvcSize }}
{{- with $objectData.volumeName }}
volumeName: {{ tpl . $rootCtx }}
{{- end -}}
{{- with (include "tc.v1.common.lib.storage.storageClassName" (dict "rootCtx" $rootCtx "objectData" $objectData "caller" "PVC") | trim) }}
storageClassName: {{ . }}
{{- end -}}
{{- include "tc.v1.common.lib.storage.pvc.spec" (dict "rootCtx" $rootCtx "objectData" $objectData) | trim | nindent 2 }}
{{- end -}}

View File

@@ -10,21 +10,16 @@ objectData: The object data to be used to render the container.
{{- $volMounts := list -}}
{{- $codeServerIgnoredTypes := (list "configmap" "secret") -}}
{{- $keys := (list "persistence") -}}
{{- if eq $objectData.podType "StatefulSet" -}}
{{- $keys = mustAppend $keys "volumeClaimTemplates" -}}
{{- end -}}
{{- $codeServerIgnoredTypes := (list "configmap" "secret" "vct") -}}
{{- 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 -}}
{{- range $persistenceName, $persistenceValues := $rootCtx.Values.persistence -}}
{{/* TLDR: Enabled + Not VCT without STS */}}
{{- if and $persistenceValues.enabled (not (and (eq $persistenceValues.type "vct") (ne $objectData.podType "StatefulSet"))) -}}
{{/* Dont try to mount configmap/sercet/vct 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))) -}}
{{- if $volMount -}}
{{- $volMounts = mustAppend $volMounts $volMount -}}
{{- end -}}
{{- end -}}
{{- end -}}
@@ -37,20 +32,20 @@ objectData: The object data to be used to render the container.
{{- $_ := set $volMount "mountPropagation" (tpl $volMount.mountPropagation $rootCtx) -}}
{{- if not $volMount.mountPath -}}
{{- fail (printf "%s - Expected non-empty <mountPath>" (camelcase $volMount.key)) -}}
{{- fail (printf "Persistence - Expected non-empty <mountPath>") -}}
{{- end -}}
{{- if not (hasPrefix "/" $volMount.mountPath) -}}
{{- fail (printf "%s - Expected <mountPath> to start with a forward slash [/]" (camelcase $volMount.key)) -}}
{{- fail (printf "Persistence - Expected <mountPath> to start with a forward slash [/]") -}}
{{- 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) -}}
{{- fail (printf "Persistence - Expected <mountPropagation> to be one of [%s], but got [%s]" (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)) -}}
{{- fail (printf "Persistence - Expected <readOnly> to be [boolean], but got [%s]" (kindOf $volMount.readOnly)) -}}
{{- end }}
- name: {{ $volMount.name }}
mountPath: {{ $volMount.mountPath }}
@@ -69,12 +64,10 @@ objectData: The object data to be used to render the container.
{{- $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 -}}
@@ -86,7 +79,7 @@ objectData: The object data to be used to render the container.
{{- $return := false -}}
{{/* If targetSelectAll is set, means all pods/containers */}} {{/* targetSelectAll does not make sense for vct */}}
{{- if and $persistenceValues.targetSelectAll (ne $key "volumeClaimTemplates") -}}
{{- if and $persistenceValues.targetSelectAll (ne $persistenceValues.type "vct") -}}
{{- $return = true -}}
{{/* Set custom path on autopermissions container */}}
{{- if and (eq $objectData.shortName "autopermissions") $persistenceValues.autoPermissions -}}
@@ -107,15 +100,19 @@ objectData: The object data to be used to render the container.
{{/* Else if selector is defined */}}
{{- else if $persistenceValues.targetSelector -}}
{{- if not (kindIs "map" $persistenceValues.targetSelector) -}}
{{- fail (printf "Persistence - Expected [targetSelector] to be a [dict] but got [%s]" (kindOf $persistenceValues.targetSelector)) -}}
{{- end -}}
{{/* 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)) -}}
{{- fail (printf "Persistence - Expected <targetSelector.%s> to be a [dict], but got [%s]" $objectData.podShortName (kindOf $selectorValues)) -}}
{{- end -}}
{{- if not $selectorValues -}}
{{- fail (printf "%s - Expected non-empty <targetSelector.%s>" (camelcase $key) $objectData.podShortName) -}}
{{- fail (printf "Persistence - Expected non-empty <targetSelector.%s>" $objectData.podShortName) -}}
{{- end -}}
{{/* If container is selected */}}

View File

@@ -29,6 +29,10 @@ objectData: The object data to be used to render the Pod.
{{/* If targetSelector is set, check if pod is selected */}}
{{- else if $persistence.targetSelector -}}
{{- if not (kindIs "map" $persistence.targetSelector) -}}
{{- fail (printf "Persistence - Expected [targetSelector] to be [dict], but got [%s]" (kindOf $persistence.targetSelector)) -}}
{{- end -}}
{{- if (mustHas $objectData.shortName (keys $persistence.targetSelector)) -}}
{{- $selected = true -}}
{{- end -}}

View File

@@ -8,7 +8,7 @@ objectData: The object data to be used to render the volume.
{{- $rootCtx := .rootCtx -}}
{{- $objectData := .objectData -}}
{{- $pvcName := (printf "%s-%s" (include "tc.v1.common.lib.chart.names.fullname" $rootCtx) $objectData.shortName) -}}
{{- $pvcName := include "tc.v1.common.lib.storage.pvc.name" (dict "rootCtx" $rootCtx "objectName" $objectData.shortName "objectData" $objectData) -}}
{{- with $objectData.existingClaim -}}
{{- $pvcName = tpl . $rootCtx -}}
{{- end }}

View File

@@ -0,0 +1,21 @@
{{/* NFS CSI */}}
{{/* Call this template:
{{ include "tc.v1.common.lib.storage.nfsCSI" (dict "rootCtx" $ "objectData" $objectData) }}
rootCtx: The root context of the chart.
objectData:
driver: The name of the driver.
server: The server address.
share: The share to the NFS share.
*/}}
{{- define "tc.v1.common.lib.storage.nfsCSI" -}}
{{- $rootCtx := .rootCtx -}}
{{- $objectData := .objectData }}
csi:
driver: {{ $objectData.static.driver }}
{{- /* Create a unique handle, server/share#release-app-volumeName */}}
volumeHandle: {{ printf "%s%s#%s" $objectData.static.server $objectData.static.share $objectData.name }}
volumeAttributes:
server: {{ tpl $objectData.static.server $rootCtx }}
share: {{ tpl $objectData.static.share $rootCtx }}
{{- end -}}

View File

@@ -0,0 +1,23 @@
{{/* SMB CSI */}}
{{/* Call this template:
{{ include "tc.v1.common.lib.storage.smbCSI" (dict "rootCtx" $ "objectData" $objectData) }}
rootCtx: The root context of the chart.
objectData:
driver: The name of the driver.
server: The server address.
share: The share to the SMB share.
*/}}
{{- define "tc.v1.common.lib.storage.smbCSI" -}}
{{- $rootCtx := .rootCtx -}}
{{- $objectData := .objectData }}
csi:
driver: {{ $objectData.static.driver }}
{{- /* Create a unique handle, server/share#release-app-volumeName */}}
volumeHandle: {{ printf "%s/%s#%s" $objectData.static.server $objectData.static.share $objectData.name }}
volumeAttributes:
source: {{ printf "//%v/%v" (tpl $objectData.static.server $rootCtx) (tpl $objectData.static.share $rootCtx) }}
nodeStageSecretRef:
name: {{ $objectData.name }}
namespace: {{ $rootCtx.Release.Namespace }}
{{- end -}}

View File

@@ -13,7 +13,6 @@ objectData: The object data of the pvc
If storageClass is defined on the objectData:
* "-" returns "", which means requesting a PV without class
* "SCALE-ZFS" returns the value set on Values.global.ixChartContext.storageClassName
(*) "SCALE-SMB" returns the value set on Values.global.ixChartContext.smbStorageClassName (Example for the future)
* Else return the original defined storageClass
Else if we are in an ixChartContext, always return the storageClassName defined on the ixChartContext

View File

@@ -1,39 +1,44 @@
{{/* PVC Validation */}}
{{/* Persistence Validation */}}
{{/* Call this template:
{{ include "tc.v1.common.lib.persistence.validation" (dict "objectData" $objectData) -}}
objectData:
rootCtx: The root context of the chart.
objectData: The pvc object.
objectData: The persistence object.
*/}}
{{- define "tc.v1.common.lib.persistence.validation" -}}
{{- $rootCtx := .rootCtx -}}
{{- $objectData := .objectData -}}
{{- $types := (list "pvc" "emptyDir" "nfs" "hostPath" "ixVolume" "secret" "configmap" "device") -}}
{{- $types := (list "pvc" "vct" "emptyDir" "nfs" "hostPath" "ixVolume" "secret" "configmap" "device") -}}
{{- if not (mustHas $objectData.type $types) -}}
{{- fail (printf "Persistence - Expected <type> to be one of [%s], but got [%s]" (join ", " $types) $objectData.type) -}}
{{- end -}}
{{- if and $objectData.static $objectData.static.mode -}}
{{- $validModes := (list "disabled" "smb" "nfs" "custom") -}}
{{- if not (mustHas $objectData.static.mode $validModes) -}}
{{- fail (printf "Persistence - Expected [static.mode] to be one of [%s], but got [%s]" (join ", " $validModes) $objectData.static.mode) -}}
{{- end -}}
{{- end -}}
{{- if $objectData.dataSource -}}
{{- if not $objectData.dataSource.name -}}
{{- fail "Persistence - Expected [dataSource.name] to be non-empty" -}}
{{- end -}}
{{- if not $objectData.dataSource.kind -}}
{{- fail "Persistence - Expected [dataSource.kind] to be non-empty" -}}
{{- end -}}
{{- $validKinds := (list "VolumeSnapshot" "PersistentVolumeClaim") -}}
{{- if not (mustHas $objectData.dataSource.kind $validKinds) -}}
{{- fail (printf "Persistence - Expected [dataSource.kind] to be one of [%s], but got [%s]" (join ", " $validKinds) $objectData.dataSource.kind) -}}
{{- end -}}
{{- end -}}
{{- if and $objectData.targetSelector (not (kindIs "map" $objectData.targetSelector)) -}}
{{- fail (printf "Persistence - Expected <targetSelector> to be [dict], but got [%s]" (kindOf $objectData.targetSelector)) -}}
{{- end -}}
{{- end -}}
{{/* VCT Validation */}}
{{/* Call this template:
{{ include "tc.v1.common.lib.vct.validation" (dict "objectData" $objectData) -}}
objectData:
rootCtx: The root context of the chart.
objectData: The vct object.
*/}}
{{- define "tc.v1.common.lib.vct.validation" -}}
{{- $objectData := .objectData -}}
{{- if and $objectData.targetSelector (not (kindIs "map" $objectData.targetSelector)) -}}
{{- fail (printf "Volume Claim Templates - Expected <targetSelector> to be [dict], but got [%s]" (kindOf $objectData.targetSelector)) -}}
{{- end -}}
{{- end -}}

View File

@@ -0,0 +1,50 @@
{{/* Validate NFS CSI */}}
{{/* Call this template:
{{ include "tc.v1.common.lib.storage.nfsCSI.validation" (dict "rootCtx" $ "objectData" $objectData) }}
rootCtx: The root context of the chart.
objectData:
driver: The name of the driver.
mountOptions: The mount options.
server: The server address.
share: The share to the NFS share.
*/}}
{{- define "tc.v1.common.lib.storage.nfsCSI.validation" -}}
{{- $rootCtx := .rootCtx -}}
{{- $objectData := .objectData -}}
{{- if hasKey $rootCtx.Values.global "ixChartContext" -}}
{{- if not $rootCtx.Values.global.ixChartContext.hasNFSCSI -}}
{{- fail "NFS CSI - Not supported CSI" -}}
{{- end -}}
{{- end -}}
{{- $required := (list "server" "share") -}}
{{- range $item := $required -}}
{{- if not (get $objectData.static $item) -}}
{{- fail (printf "NFS CSI - Expected <%v> to be non-empty" $item) -}}
{{- end -}}
{{- end -}}
{{- if not (hasPrefix "/" $objectData.static.share) -}}
{{- fail "NFS CSI - Expected <share> to start with [/]" -}}
{{- end -}}
{{/* TODO: Allow only specific opts / set specific opts by default?
{{- $validOpts := list -}} */}}
{{- range $opt := $objectData.mountOptions -}}
{{- if not (kindIs "map" $opt) -}}
{{- fail (printf "NFS CSI - Expected <mountOption> item to be a dict, but got [%s]" (kindOf $opt)) -}}
{{- end -}}
{{- if not $opt.key -}}
{{- fail "NFS CSI - Expected key in <mountOptions> to be non-empty" -}}
{{- end -}}
{{/*
{{- $key := tpl $opt.key $rootCtx -}}
{{- if not (mustHas $key $validOpts) -}}
{{- fail (printf "NFS CSI - Expected <mountOptions> to be one of [%v], but got [%v]" (join ", " $validOpts) $opt) -}}
{{- end -}}
*/}}
{{- end -}}
{{- end -}}

View File

@@ -0,0 +1,54 @@
{{/* Validate SMB CSI */}}
{{/* Call this template:
{{ include "tc.v1.common.lib.storage.smbCSI.validation" (dict "rootCtx" $ "objectData" $objectData) }}
rootCtx: The root context of the chart.
objectData:
driver: The name of the driver.
mountOptions: The mount options.
server: The server address.
share: The share to the SMB share.
*/}}
{{- define "tc.v1.common.lib.storage.smbCSI.validation" -}}
{{- $rootCtx := .rootCtx -}}
{{- $objectData := .objectData -}}
{{- if hasKey $rootCtx.Values.global "ixChartContext" -}}
{{- if not $rootCtx.Values.global.ixChartContext.hasSMBCSI -}}
{{- fail "SMB CSI - Not supported CSI" -}}
{{- end -}}
{{- end -}}
{{- $required := (list "server" "share" "username" "password") -}}
{{- range $item := $required -}}
{{- if not (get $objectData.static $item) -}}
{{- fail (printf "SMB CSI - Expected <%v> to be non-empty" $item) -}}
{{- end -}}
{{- end -}}
{{- if hasPrefix "//" $objectData.static.server -}}
{{- fail "SMB CSI - Did not expect <server> to start with [//]" -}}
{{- end -}}
{{- if hasPrefix "/" $objectData.static.share -}}
{{- fail "SMB CSI - Did not expect <share> to start with [/]" -}}
{{- end -}}
{{/* TODO: Allow only specific opts? / set specific opts by default?
{{- $validOpts := list -}} */}}
{{- range $opt := $objectData.mountOptions -}}
{{- if not (kindIs "map" $opt) -}}
{{- fail (printf "SMB CSI - Expected <mountOption> item to be a dict, but got [%s]" (kindOf $opt)) -}}
{{- end -}}
{{- if not $opt.key -}}
{{- fail "SMB CSI - Expected key in <mountOptions> to be non-empty" -}}
{{- end -}}
{{/*
{{- $key := tpl $opt.key $rootCtx -}}
{{- if not (mustHas $key $validOpts) -}}
{{- fail (printf "SMB CSI - Expected <mountOptions> to be one of [%v], but got [%v]" (join ", " $validOpts) $opt) -}}
{{- end -}}
*/}}
{{- end -}}
{{- end -}}

View File

@@ -8,15 +8,15 @@ objectData: The object data to be used to render the Pod.
{{- $rootCtx := .rootCtx -}}
{{- $objectData := .objectData -}}
{{- range $name, $vctValues := $rootCtx.Values.volumeClaimTemplates -}}
{{- range $name, $vctValues := $rootCtx.Values.persistence -}}
{{- if $vctValues.enabled -}}
{{- if and $vctValues.enabled (eq $vctValues.type "vct") -}}
{{- $vct := (mustDeepCopy $vctValues) -}}
{{- $selected := false -}}
{{- $_ := set $vct "shortName" $name -}}
{{- include "tc.v1.common.lib.vct.validation" (dict "objectData" $vct) -}}
{{- include "tc.v1.common.lib.persistence.validation" (dict "objectData" $vct) -}}
{{- include "tc.v1.common.lib.chart.names.validation" (dict "name" $vct.shortName) -}}
{{- include "tc.v1.common.lib.metadata.validation" (dict "objectData" $vct "caller" "Volume Claim Templates") -}}
@@ -40,7 +40,7 @@ objectData: The object data to be used to render the Pod.
{{- $vctSize = tpl . $rootCtx -}}
{{- end }}
- metadata:
name: {{ $vct.shortName }}
name: {{ include "tc.v1.common.lib.storage.pvc.name" (dict "rootCtx" $rootCtx "objectName" $vct.shortName "objectData" $vctValues) }}
{{- $labels := $vct.labels | default dict -}}
{{- with (include "tc.v1.common.lib.metadata.render" (dict "rootCtx" $rootCtx "labels" $labels) | trim) }}
labels:
@@ -52,14 +52,7 @@ objectData: The object data to be used to render the Pod.
{{- . | nindent 6 }}
{{- end }}
spec:
{{- with (include "tc.v1.common.lib.storage.storageClassName" (dict "rootCtx" $rootCtx "objectData" $vct "caller" "Volume Claim Templates") | trim) }}
storageClassName: {{ . }}
{{- end }}
accessModes:
{{- include "tc.v1.common.lib.pvc.accessModes" (dict "rootCtx" $rootCtx "objectData" $vct "caller" "Volume Claim Templates") | trim | nindent 6 }}
resources:
requests:
storage: {{ $vctSize }}
{{- include "tc.v1.common.lib.storage.pvc.spec" (dict "rootCtx" $rootCtx "objectData" $vctValues) | trim | nindent 4 }}
{{- end -}}
{{- end -}}
{{- end -}}

View File

@@ -0,0 +1,51 @@
{{/* Returns Persitent Volume Claim name*/}}
{{/* Call this template:
{{ include "tc.v1.common.lib.storage.pvc.name" (dict "rootCtx" $ "objectName" $objectName "objectData" $objectData) }}
objectName: the base name of the object without any alteration or sanitation
rootCtx: The root context of the chart.
objectData: The object data to be used to render the Pod.
*/}}
{{- define "tc.v1.common.lib.storage.pvc.name" -}}
{{- $rootCtx := .rootCtx -}}
{{- $objectName := .objectName -}}
{{- $objectData := .objectData -}}
{{- $hashValues := "" -}}
{{- $renderedName := (printf "%s-%s" (include "tc.v1.common.lib.chart.names.fullname" $rootCtx) $objectName) -}}
{{/* Perform validations */}}
{{- include "tc.v1.common.lib.chart.names.validation" (dict "name" $renderedName) -}}
{{- $modes := (list "smb" "nfs") -}}
{{- if $objectData.static -}}
{{- if and $objectData.static.mode (mustHas $objectData.static.mode $modes) -}}
{{- $size := $objectData.size | default $rootCtx.Values.fallbackDefaults.pvcSize -}}
{{/* Create a unique name taking into account server and share,
without this, changing one of those values is not possible */}}
{{- $hashValues = (printf "%s-%s-%s" $size $objectData.static.server $objectData.static.share) -}}
{{- if $objectData.domain -}}
{{- $hashValues = (printf "%s-%s" $hashValues $objectData.domain) -}}
{{- end -}}
{{- else if eq $objectData.static.mode "custom" -}}
{{- $hashValues = (printf "%s-%v" $size $objectData.csi) -}}
{{- end -}}
{{- end -}}
{{/* Create a hash from the dataSource settings to ensure a new PVC is created when a dataSource is set*/}}
{{- if $objectData.dataSource -}}
{{- $hashValues = (printf "%s-%s-%s" $hashValues $objectData.dataSource.kind $objectData.dataSource.name) -}}
{{- end -}}
{{- $objectName = $renderedName -}}
{{- if $hashValues -}}
{{- $hash := adler32sum $hashValues -}}
{{- $objectName = (printf "%s-%v" $renderedName $hash) -}}
{{- end -}}
{{/* Return the new objectName */}}
{{- $objectName -}}
{{- end -}}

View File

@@ -0,0 +1,38 @@
{{/* Returns Persitant Volume Claim Spec*/}}
{{/* Call this template:
{{ include "tc.v1.common.lib.storage.pvc.spec" (dict "rootCtx" $ "objectData" $objectData) }}
rootCtx: The root context of the chart.
objectData: The object data to be used to render the Pod.
*/}}
{{- define "tc.v1.common.lib.storage.pvc.spec" -}}
{{- $rootCtx := .rootCtx -}}
{{- $objectData := .objectData -}}
{{- $size := $rootCtx.Values.fallbackDefaults.pvcSize -}}
{{- with $objectData.size -}}
{{- $size = tpl . $rootCtx -}}
{{- end }}
accessModes:
{{- include "tc.v1.common.lib.pvc.accessModes" (dict "rootCtx" $rootCtx "objectData" $objectData "caller" "PVC") | trim | nindent 2 }}
resources:
requests:
storage: {{ $size }}
{{- with $objectData.volumeName }}
volumeName: {{ tpl . $rootCtx }}
{{- end -}}
{{- with (include "tc.v1.common.lib.storage.storageClassName" (dict "rootCtx" $rootCtx "objectData" $objectData "caller" "PVC") | trim) }}
storageClassName: {{ . }}
{{- end -}}
{{- with $objectData.dataSource -}}
{{- $sourceName := .name -}}
{{- if eq .kind "PersistentVolumeClaim" -}}
{{- with get $rootCtx.persistence $sourceName -}}
{{- $sourceName := (include "tc.v1.common.lib.storage.pvc.name" (dict "rootCtx" $rootCtx "objectName" $sourceName "objectData" .)) -}}
{{- end -}}
{{- end }}
dataSource:
kind: {{ .kind }}
name: {{ $sourceName }}
{{- end -}}
{{- end -}}

View File

@@ -4,7 +4,6 @@
*/}}
{{- define "tc.v1.common.spawner.pvc" -}}
{{- $fullname := include "tc.v1.common.lib.chart.names.fullname" $ -}}
{{- range $name, $persistence := .Values.persistence -}}
@@ -19,23 +18,63 @@
{{- include "tc.v1.common.lib.persistence.validation" (dict "rootCtx" $ "objectData" $objectData) -}}
{{- include "tc.v1.common.lib.metadata.validation" (dict "objectData" $objectData "caller" "Persistence") -}}
{{/* Only spawn PVC if its enabled and type of "pvc" */}}
{{- if and (eq "pvc" $objectData.type) (not $objectData.existingClaim) -}}
{{/* Only spawn PVC if its enabled and any type of "pvc" */}}
{{- $types := (list "pvc") -}}
{{- if and (mustHas $objectData.type $types) (not $objectData.existingClaim) -}}
{{- $objectName := (printf "%s-%s" $fullname $name) -}}
{{/* Perform validations */}}
{{- include "tc.v1.common.lib.chart.names.validation" (dict "name" $objectName) -}}
{{/* Set the name of the secret */}}
{{- $_ := set $objectData "name" $objectName -}}
{{/* Set the name of the PVC */}}
{{- $_ := set $objectData "name" (include "tc.v1.common.lib.storage.pvc.name" (dict "rootCtx" $ "objectName" $name "objectData" $objectData)) -}}
{{- $_ := set $objectData "shortName" $name -}}
{{- if and $objectData.static $objectData.static.mode (ne $objectData.static.mode "disabled") -}}
{{- $_ := set $objectData "storageClass" ($objectData.storageClass | default $objectData.name) -}}
{{- $_ := set $objectData "volumeName" $objectData.name -}}
{{- if eq $objectData.static.mode "smb" -}}
{{/* Validate SMB CSI */}}
{{- include "tc.v1.common.lib.storage.smbCSI.validation" (dict "rootCtx" $ "objectData" $objectData) -}}
{{- $_ := set $objectData "provisioner" "smb.csi.k8s.io" -}}
{{- $_ := set $objectData.static "driver" "smb.csi.k8s.io" -}}
{{/* Create secret with creds */}}
{{- $secretData := (dict
"name" $objectData.name
"labels" ($objectData.labels | default dict)
"annotations" ($objectData.annotations | default dict)
"data" (dict "username" $objectData.static.username "password" $objectData.static.password)
) -}}
{{- with $objectData.domain -}}
{{- $_ := set $secretData.data "domain" . -}}
{{- end -}}
{{- include "tc.v1.common.class.secret" (dict "rootCtx" $ "objectData" $secretData) -}}
{{- else if eq $objectData.static.mode "nfs" -}}
{{/* Validate NFS CSI */}}
{{- include "tc.v1.common.lib.storage.nfsCSI.validation" (dict "rootCtx" $ "objectData" $objectData) -}}
{{- $_ := set $objectData "provisioner" "nfs.csi.k8s.io" -}}
{{- $_ := set $objectData.static "driver" "nfs.csi.k8s.io" -}}
{{- else if eq $objectData.static.mode "custom" -}}
{{- $_ := set $objectData "provisioner" $objectData.static.provisioner -}}
{{- $_ := set $objectData.static "driver" $objectData.static.driver -}}
{{- end -}}
{{/* Create the PV */}}
{{- include "tc.v1.common.class.pv" (dict "rootCtx" $ "objectData" $objectData) -}}
{{- else if $objectData.volumeName -}}
{{- $_ := set $objectData "storageClass" ($objectData.storageClass | default $objectData.name) -}}
{{- end -}}
{{/* Call class to create the object */}}
{{- include "tc.v1.common.class.pvc" (dict "rootCtx" $ "objectData" $objectData) -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- end -}}

View File

@@ -222,6 +222,67 @@ persistence:
mountPath: /dev/shm
medium: Memory
targetSelectAll: true
# vct:
# enabled: true
# type: vct
# mountPath: /shared
# dynamic-pvc:
# enabled: true
# type: pvc
# mountPath: /shared
# targetSelectAll: true
# dynamic-pvc-dataSource:
# enabled: true
# type: pvc
# mountPath: /shared
# targetSelectAll: true
# dataSource:
# kind: "PersistentVolumeClaim"
# name: "existingPVC"
# existing-claim:
# enabled: true
# type: pvc
# existingClaim: "someclaim"
# mountPath: /shared
# targetSelectAll: true
# existingpv-pvc:
# enabled: true
# type: pvc
# mountPath: /shared
# targetSelectAll: true
# volumeName: "somePV"
# static-nfs-pvc:
# enabled: true
# type: pvc
# mountPath: /shared
# targetSelectAll: true
# static:
# mode: nfs
# server: "/someserver"
# share: "someshare"
# static-smb-pvc:
# enabled: true
# type: pvc
# mountPath: /shared
# targetSelectAll: true
# static:
# mode: smb
# server: "/someserver"
# share: "someshare"
# domain: "somedomain"
# user: "someuser"
# password: "somepass"
# static-custom-pvc:
# enabled: true
# type: pvc
# mountPath: /shared
# targetSelectAll: true
# static:
# mode: custom
# provisioner: "some.provisioner"
# driver: "somedriver"
# # Custom CSI definition here
# csi: {}
persistenceList: []
@@ -255,9 +316,6 @@ serviceAccount: {}
# -- (docs/rbac.md)
rbac: {}
# -- (docs/volumeClaimTemplates) (StatefulSet only)
volumeClaimTemplates: {}
# -- (docs/scaleExternalInterface.md)
scaleExternalInterface: []
@@ -807,10 +865,14 @@ cnpg:
primaryUpdateStrategy: unsupervised
# -- enable to create extra pgbouncer for readonly access
acceptRO: false
# -- storage size for the two pvc's per instance
storage:
size: "256Gi"
walsize: "256Gi"
# # -- storage size for the data pvc's
# # Follows the same spec as .Values.Persistence type=PVC
# storage:
# size: "256Gi"
# # -- storage size for the wal pvc's
# # Follows the same spec as .Values.Persistence type=PVC
# walStorage:
# size: "256Gi"
# -- Gets scaled to 0 if hibernation is true
pooler:
instances: 2