feat: support existing persistent volume (#105)
Statefulset `volumeClaimTemplates` create new volumes and `PersistentVolumeClaims` which cannot be mutated. This adds the ability to declare a `persistentVolume` as existing and provide the required PV and PVC data for binding a volume to the statefulset. This is especially useful for restoring backup snapshots during disaster recovery efforts, but could also be used for initial data migrations or other scenarios where users would like to deploy this chart with existing CouchDB data.
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..1377554
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+*.swp
diff --git a/couchdb/Chart.yaml b/couchdb/Chart.yaml
index e2bda0d..0cdd6ed 100644
--- a/couchdb/Chart.yaml
+++ b/couchdb/Chart.yaml
@@ -1,6 +1,6 @@
apiVersion: v1
name: couchdb
-version: 4.1.1
+version: 4.2.0
appVersion: 3.2.1
description: A database featuring seamless multi-master sync, that scales from
big data to mobile, with an intuitive HTTP/JSON API and designed for
diff --git a/couchdb/README.md b/couchdb/README.md
index 2cb7c73..3e6f468 100644
--- a/couchdb/README.md
+++ b/couchdb/README.md
@@ -1,6 +1,6 @@
# CouchDB
-![Version: 4.1.1](https://img.shields.io/badge/Version-4.1.1-informational?style=flat-square) ![AppVersion: 3.2.1](https://img.shields.io/badge/AppVersion-3.2.1-informational?style=flat-square)
+![Version: 4.2.0](https://img.shields.io/badge/Version-4.2.0-informational?style=flat-square) ![AppVersion: 3.2.1](https://img.shields.io/badge/AppVersion-3.2.1-informational?style=flat-square)
Apache CouchDB is a database featuring seamless multi-master sync, that scales
from big data to mobile, with an intuitive HTTP/JSON API and designed for
@@ -18,7 +18,7 @@
```bash
$ helm repo add couchdb https://apache.github.io/couchdb-helm
$ helm install couchdb/couchdb \
- --version=4.1.1 \
+ --version=4.2.0 \
--set allowAdminParty=true \
--set couchdbConfig.couchdb.uuid=$(curl https://www.uuidgenerator.net/api/version4 2>/dev/null | tr -d -)
```
@@ -44,7 +44,7 @@
```bash
$ helm install \
--name my-release \
- --version=4.1.1 \
+ --version=4.2.0 \
--set couchdbConfig.couchdb.uuid=decafbaddecafbaddecafbaddecafbad \
couchdb/couchdb
```
@@ -78,7 +78,7 @@
```bash
$ helm install \
--name my-release \
- --version=4.1.1 \
+ --version=4.2.0 \
--set createAdminSecret=false \
--set couchdbConfig.couchdb.uuid=decafbaddecafbaddecafbaddecafbad \
couchdb/couchdb
@@ -133,7 +133,7 @@
```bash
$ helm repo add couchdb https://apache.github.io/couchdb-helm
-$ helm upgrade my-release --version=4.1.1 couchdb/couchdb
+$ helm upgrade my-release --version=4.2.0 couchdb/couchdb
```
## Configuration
@@ -164,68 +164,72 @@
A variety of other parameters are also configurable. See the comments in the
`values.yaml` file for further details:
-| Parameter | Default |
-|--------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------|
-| `adminUsername` | admin |
-| `adminPassword` | auto-generated |
-| `adminHash` | |
-| `cookieAuthSecret` | auto-generated |
-| `image.repository` | couchdb |
-| `image.tag` | 3.2.1 |
-| `image.pullPolicy` | IfNotPresent |
-| `searchImage.repository` | kocolosk/couchdb-search |
-| `searchImage.tag` | 0.1.0 |
-| `searchImage.pullPolicy` | IfNotPresent |
-| `initImage.repository` | busybox |
-| `initImage.tag` | latest |
-| `initImage.pullPolicy` | Always |
-| `ingress.enabled` | false |
-| `ingress.hosts` | chart-example.local |
-| `ingress.annotations` | |
-| `ingress.path` | / |
-| `ingress.tls` | |
-| `persistentVolume.accessModes` | ReadWriteOnce |
-| `persistentVolume.storageClass` | Default for the Kube cluster |
-| `persistentVolume.annotations` | {} |
-| `podManagementPolicy` | Parallel |
-| `affinity` | |
-| `topologySpreadConstraints` | |
-| `annotations` | |
-| `tolerations` | |
-| `resources` | |
-| `autoSetup.enabled` | false (if set to true, must have `service.enabled` set to true and a correct `adminPassword` - deploy it with the `--wait` flag to avoid first jobs failure) |
-| `autoSetup.image.repository` | curlimages/curl |
-| `autoSetup.image.tag` | latest |
-| `autoSetup.image.pullPolicy` | Always |
-| `autoSetup.defaultDatabases` | [`_global_changes`] |
-| `service.annotations` | |
-| `service.enabled` | true |
-| `service.type` | ClusterIP |
-| `service.externalPort` | 5984 |
-| `dns.clusterDomainSuffix` | cluster.local |
-| `networkPolicy.enabled` | true |
-| `serviceAccount.enabled` | true |
-| `serviceAccount.create` | true |
-| `serviceAccount.imagePullSecrets` | |
-| `sidecars` | {} |
-| `livenessProbe.enabled` | true |
-| `livenessProbe.failureThreshold` | 3 |
-| `livenessProbe.initialDelaySeconds` | 0 |
-| `livenessProbe.periodSeconds` | 10 |
-| `livenessProbe.successThreshold` | 1 |
-| `livenessProbe.timeoutSeconds` | 1 |
-| `readinessProbe.enabled` | true |
-| `readinessProbe.failureThreshold` | 3 |
-| `readinessProbe.initialDelaySeconds` | 0 |
-| `readinessProbe.periodSeconds` | 10 |
-| `readinessProbe.successThreshold` | 1 |
-| `readinessProbe.timeoutSeconds` | 1 |
-| `prometheusPort.enabled` | false |
-| `prometheusPort.port` | 17896 |
-| `prometheusPort.bind_address` | 0.0.0.0 |
-| `placementConfig.enabled` | false |
-| `placementConfig.image.repository` | caligrafix/couchdb-autoscaler-placement-manager |
-| `placementConfig.image.tag` | 0.1.0 |
+| Parameter | Default |
+| -------------------------------------- | ------------------------------------------------ |
+| `adminUsername` | admin |
+| `adminPassword` | auto-generated |
+| `adminHash` | |
+| `cookieAuthSecret` | auto-generated |
+| `image.repository` | couchdb |
+| `image.tag` | 3.2.1 |
+| `image.pullPolicy` | IfNotPresent |
+| `searchImage.repository` | kocolosk/couchdb-search |
+| `searchImage.tag` | 0.1.0 |
+| `searchImage.pullPolicy` | IfNotPresent |
+| `initImage.repository` | busybox |
+| `initImage.tag` | latest |
+| `initImage.pullPolicy` | Always |
+| `ingress.enabled` | false |
+| `ingress.hosts` | chart-example.local |
+| `ingress.annotations` | |
+| `ingress.path` | / |
+| `ingress.tls` | |
+| `persistentVolume.accessModes` | ReadWriteOnce |
+| `persistentVolume.storageClass` | Default for the Kube cluster |
+| `persistentVolume.annotations` | {} |
+| `persistentVolume.existingClaims` | [] (a list of existing PV/PVC volume value objects with `volumeName`, `claimName`, `persistentVolumeName` and `volumeSource` defined) |
+| `persistentVolume.volumeName` | |
+| `persistentVolume.claimName` | |
+| `persistentVolume.volumeSource` | |
+| `podManagementPolicy` | Parallel |
+| `affinity` | |
+| `topologySpreadConstraints` | |
+| `annotations` | |
+| `tolerations` | |
+| `resources` | |
+| `autoSetup.enabled` | false (if set to true, must have `service.enabled` set to true and a correct `adminPassword` - deploy it with the `--wait` flag to avoid first jobs failure) |
+| `autoSetup.image.repository` | curlimages/curl |
+| `autoSetup.image.tag` | latest |
+| `autoSetup.image.pullPolicy` | Always |
+| `autoSetup.defaultDatabases` | [`_global_changes`] |
+| `service.annotations` | |
+| `service.enabled` | true |
+| `service.type` | ClusterIP |
+| `service.externalPort` | 5984 |
+| `dns.clusterDomainSuffix` | cluster.local |
+| `networkPolicy.enabled` | true |
+| `serviceAccount.enabled` | true |
+| `serviceAccount.create` | true |
+| `serviceAccount.imagePullSecrets` | |
+| `sidecars` | {} |
+| `livenessProbe.enabled` | true |
+| `livenessProbe.failureThreshold` | 3 |
+| `livenessProbe.initialDelaySeconds` | 0 |
+| `livenessProbe.periodSeconds` | 10 |
+| `livenessProbe.successThreshold` | 1 |
+| `livenessProbe.timeoutSeconds` | 1 |
+| `readinessProbe.enabled` | true |
+| `readinessProbe.failureThreshold` | 3 |
+| `readinessProbe.initialDelaySeconds` | 0 |
+| `readinessProbe.periodSeconds` | 10 |
+| `readinessProbe.successThreshold` | 1 |
+| `readinessProbe.timeoutSeconds` | 1 |
+| `prometheusPort.enabled` | false |
+| `prometheusPort.port` | 17896 |
+| `prometheusPort.bind_address` | 0.0.0.0 |
+| `placementConfig.enabled` | false |
+| `placementConfig.image.repository` | caligrafix/couchdb-autoscaler-placement-manager |
+| `placementConfig.image.tag` | 0.1.0 |
## Feedback, Issues, Contributing
diff --git a/couchdb/templates/_helpers.tpl b/couchdb/templates/_helpers.tpl
index 2f5c1a4..e33f85c 100644
--- a/couchdb/templates/_helpers.tpl
+++ b/couchdb/templates/_helpers.tpl
@@ -64,8 +64,6 @@
{{- end -}}
{{- end -}}
-
-
{{/*
Labels used to define Pods in the CouchDB statefulset
*/}}
@@ -102,3 +100,46 @@
{{- define "couchdb.uuid" -}}
{{- required "A value for couchdbConfig.couchdb.uuid must be set" (.Values.couchdbConfig.couchdb | default dict).uuid -}}
{{- end -}}
+
+{{/*
+Repurpose volume claim metadata whether using the new volume claim template
+or existing volume claims.
+*/}}
+{{- define "persistentVolume.metadata" -}}
+{{- $context := index . "context" -}}
+{{- $claim := index . "claim" -}}
+name: {{ $claim.claimName | default "database-storage" }}
+labels:
+ app: {{ template "couchdb.name" $context }}
+ release: {{ $context.Release.Name }}
+{{- with $context.Values.persistentVolume.annotations }}
+annotations:
+ {{- toYaml . | nindent 6 }}
+{{- end }}
+{{- end -}}
+
+{{/*
+Repurpose volume claim spec whether using the new volume claim template
+or an existing volume claim.
+*/}}
+{{- define "persistentVolume.spec" -}}
+{{- $context := index . "context" -}}
+{{- $claim := index . "claim" -}}
+accessModes:
+{{- range $context.Values.persistentVolume.accessModes }}
+- {{ . | quote }}
+{{- end }}
+resources:
+ requests:
+ storage: {{ $context.Values.persistentVolume.size | quote }}
+{{- if $context.Values.persistentVolume.storageClass }}
+{{- if (eq "-" $context.Values.persistentVolume.storageClass) }}
+storageClassName: ""
+{{- else }}
+storageClassName: "{{ $context.Values.persistentVolume.storageClass }}"
+{{- end }}
+{{- end }}
+{{- if $claim.persistentVolumeName }}
+volumeName: {{ $claim.persistentVolumeName }}
+{{- end }}
+{{- end -}}
diff --git a/couchdb/templates/persistentvolume.yaml b/couchdb/templates/persistentvolume.yaml
new file mode 100644
index 0000000..3349b83
--- /dev/null
+++ b/couchdb/templates/persistentvolume.yaml
@@ -0,0 +1,24 @@
+{{- if and .Values.persistentVolume.enabled .Values.persistentVolume.existingClaims -}}
+{{- range $claim := .Values.persistentVolume.existingClaims }}
+apiVersion: v1
+kind: PersistentVolume
+metadata:
+ name: {{ $claim.persistentVolumeName }}
+spec:
+{{- if $.Values.persistentVolume.storageClass }}
+{{- if (eq "-" $.Values.persistentVolume.storageClass) }}
+ storageClassName: ""
+{{- else }}
+ storageClassName: "{{ $.Values.persistentVolume.storageClass }}"
+{{- end }}
+{{- end }}
+ accessModes:
+ {{- range $.Values.persistentVolume.accessModes }}
+ - {{ . | quote }}
+ {{- end }}
+ capacity:
+ storage: {{ $.Values.persistentVolume.size }}
+{{ toYaml $claim.volumeSource | indent 2 }}
+---
+{{- end }}
+{{- end }}
diff --git a/couchdb/templates/persistentvolumeclaim.yaml b/couchdb/templates/persistentvolumeclaim.yaml
new file mode 100644
index 0000000..5371682
--- /dev/null
+++ b/couchdb/templates/persistentvolumeclaim.yaml
@@ -0,0 +1,12 @@
+{{- if and .Values.persistentVolume.enabled .Values.persistentVolume.existingClaims -}}
+{{- $context := . }}
+{{- range $claim := .Values.persistentVolume.existingClaims }}
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+ {{- include "persistentVolume.metadata" (dict "context" $context "claim" $claim) | nindent 2 }}
+spec:
+ {{- include "persistentVolume.spec" (dict "context" $context "claim" $claim) | nindent 2 }}
+---
+{{- end }}
+{{- end }}
diff --git a/couchdb/templates/statefulset.yaml b/couchdb/templates/statefulset.yaml
index a71f6bc..a844ada 100644
--- a/couchdb/templates/statefulset.yaml
+++ b/couchdb/templates/statefulset.yaml
@@ -207,30 +207,16 @@
{{- if not .Values.persistentVolume.enabled }}
- name: database-storage
emptyDir: {}
+{{- else if and .Values.persistentVolume.enabled .Values.persistentVolume.existingClaims }}
+ {{- range $claim := .Values.persistentVolume.existingClaims }}
+ - name: {{ $claim.volumeName }}
+ persistentVolumeClaim:
+ claimName: {{ $claim.claimName }}
+ {{- end }}
{{- else }}
volumeClaimTemplates:
- metadata:
- name: database-storage
- labels:
- app: {{ template "couchdb.name" . }}
- release: {{ .Release.Name }}
- {{- with .Values.persistentVolume.annotations }}
- annotations:
- {{- toYaml . | nindent 10 }}
- {{- end }}
+ {{- include "persistentVolume.metadata" (dict "context" .) | nindent 8 }}
spec:
- accessModes:
- {{- range .Values.persistentVolume.accessModes }}
- - {{ . | quote }}
- {{- end }}
- resources:
- requests:
- storage: {{ .Values.persistentVolume.size | quote }}
- {{- if .Values.persistentVolume.storageClass }}
- {{- if (eq "-" .Values.persistentVolume.storageClass) }}
- storageClassName: ""
- {{- else }}
- storageClassName: "{{ .Values.persistentVolume.storageClass }}"
- {{- end }}
- {{- end }}
+ {{- include "persistentVolume.spec" (dict "context" .) | nindent 8 }}
{{- end }}
diff --git a/couchdb/values.yaml b/couchdb/values.yaml
index a1db0a5..6c0667e 100644
--- a/couchdb/values.yaml
+++ b/couchdb/values.yaml
@@ -67,6 +67,8 @@
# provisioner.
persistentVolume:
enabled: false
+ # NOTE: the number of existing claims must match the cluster size
+ existingClaims: []
annotations: {}
accessModes:
- ReadWriteOnce