diff --git a/charts/openhab/DESIGN.md b/charts/openhab/DESIGN.md index 15e357286..aa122cf73 100644 --- a/charts/openhab/DESIGN.md +++ b/charts/openhab/DESIGN.md @@ -32,8 +32,29 @@ openHAB has three durable directory classes: things, sitemaps, rules, and service configuration. - `/openhab/addons` stores drop-in addon JAR files. -The chart creates one PVC per directory by default. Each PVC can be sized -independently or replaced with an existing claim for migration scenarios. +By default, the chart retains the established layout of one PVC per directory. +Set `persistence.claim.enabled=true` to create one release-specific +`-data` PVC instead. In that mode, the chart mounts the `userdata`, +`conf`, and `addons` subdirectories into their respective openHAB paths. A +`create-persistence-subpaths` init container creates those subdirectories before +the main container starts, so the mounts do not replace the non-empty directory +structure supplied by the image. + +The per-directory `size`, `storageClass`, and `accessMode` settings configure +the default dedicated PVCs. `existingClaim` takes precedence for an individual +directory in either storage mode. + +`subPath` is an explicit escape hatch only for an existing or legacy dedicated +PVC; it is deliberately rejected for the chart-managed shared PVC, whose +directory names are fixed by the chart. Every `subPath` must be relative and cannot +contain traversal segments. An existing claim used for more than one openHAB +directory must provide a `subPath` for every use. Mounting one claim's root at +multiple application paths aliases unrelated data directories and is therefore +a template-time configuration error. + +The backup CronJob uses the same claim and subpath resolution as the StatefulSet +and creates selected backup subpaths before its read-only backup mounts are +attached. This keeps backups aligned with the running workload's storage view. ## Configuration Design diff --git a/charts/openhab/README.md b/charts/openhab/README.md index 347bd9098..f0cb517e0 100644 --- a/charts/openhab/README.md +++ b/charts/openhab/README.md @@ -134,16 +134,35 @@ Use feature flags instead to enable optional components. ### Persistence Parameters +The default remains the established three-PVC layout. To opt into a single +shared PVC, follow the [storage migration procedure](UPGRADING.md#storage-layout-migration) +and set `persistence.claim.enabled=true`. +In shared-PVC mode, the per-directory size, storage class, and access-mode +settings are not used. + | Parameter | Description | Default | |-----------|-------------|---------| +| `persistence.claim.enabled` | Opt into one shared PVC for userdata, conf, and addons | `false` | +| `persistence.claim.size` | Generated release-specific data PVC size | `5Gi` | +| `persistence.claim.storageClass` | Generated PVC storage class | `""` (cluster default) | | `persistence.userdata.enabled` | Enable userdata PVC | `true` | -| `persistence.userdata.size` | userdata PVC size | `5Gi` | +| `persistence.userdata.size` | userdata dedicated PVC size | `5Gi` | | `persistence.userdata.storageClass` | Storage class | `""` (cluster default) | | `persistence.userdata.existingClaim` | Use existing PVC | `""` | +| `persistence.userdata.subPath` | Relative directory in an existing or dedicated userdata PVC | unset | | `persistence.conf.enabled` | Enable conf PVC | `true` | -| `persistence.conf.size` | conf PVC size | `1Gi` | +| `persistence.conf.size` | conf dedicated PVC size | `1Gi` | +| `persistence.conf.existingClaim` | Existing PVC for conf | `""` | +| `persistence.conf.subPath` | Relative directory in an existing or dedicated conf PVC | unset | | `persistence.addons.enabled` | Enable addons PVC | `true` | -| `persistence.addons.size` | addons PVC size | `2Gi` | +| `persistence.addons.size` | addons dedicated PVC size | `2Gi` | +| `persistence.addons.existingClaim` | Existing PVC for addons | `""` | +| `persistence.addons.subPath` | Relative directory in an existing or dedicated addons PVC | unset | + +> **Warning:** A new PVC may contain a `lost+found` directory at its root. +> openHAB then does not recognize the mounted directory as empty on its first +> start, skips initialization, and fails to start. Use a dedicated, empty +> `subPath` instead of mounting the PVC root in this case. ### ConfigMap Parameters diff --git a/charts/openhab/UPGRADING.md b/charts/openhab/UPGRADING.md new file mode 100644 index 000000000..c91b93c65 --- /dev/null +++ b/charts/openhab/UPGRADING.md @@ -0,0 +1,71 @@ +# Upgrading openHAB + +## Storage layout migration + +This release adds an optional chart-managed shared PVC with `userdata`, `conf`, +and `addons` subpaths. The default remains the existing three chart-managed +PVCs, so a normal upgrade preserves the current storage layout. + +### Previous main-branch behavior + +`persistence.userdata`, `persistence.conf`, and `persistence.addons` each +created their own PVC by default. Their independent `size`, `storageClass`, +and `accessMode` settings applied to those PVCs. An `existingClaim` replaced +the PVC for that individual directory. The chart allowed these three settings +to remain configured alongside `existingClaim`; in that case they had no +effect because the existing PVC took precedence. + +### Opt in to a shared PVC + +There are two supported arrangements: + +1. Set `persistence.claim.enabled=true`. With no per-directory `existingClaim`, + the chart creates one `-data` PVC using `persistence.claim`. It mounts the `userdata`, + `conf`, and `addons` subpaths at the corresponding openHAB directories. +2. Set `existingClaim` for any one, two, or all three directories. The + remaining enabled directories use the chart-managed shared PVC. `subPath` + can be set only for an existing claim; chart-managed shared subpaths are + fixed. Per-directory `size`, `storageClass`, and `accessMode` values are + not used in shared-PVC mode. + +### Preserve the current three-PVC layout + +This is the default behavior. Existing releases can be upgraded normally, +including with `--reuse-values`; their PVC names and roots remain unchanged. + +```yaml +persistence: + userdata: + size: 5Gi + storageClass: + conf: + size: 1Gi + storageClass: + addons: + size: 2Gi + storageClass: +``` + +Use the actual existing settings, which can be inspected with: + +```bash +kubectl get pvc -n +``` + +Then upgrade with those values (or use `--reuse-values`): + +```bash +helm upgrade -n -f openhab-storage-upgrade.yaml +``` + +### Migrate into the new shared PVC + +Back up the three existing PVCs first. Create or allow the chart to create a +shared PVC sized for all data, then copy the old PVC roots into `userdata`, +`conf`, and `addons` respectively using a temporary pod or your storage +provider's migration tool. Only after verifying the copies should the new +release mount that shared PVC with the default subpaths. Finally upgrade with +`persistence.claim.enabled=true`. + +Do not delete the old PVCs until openHAB has started successfully and the data +has been verified. diff --git a/charts/openhab/docs/storage.md b/charts/openhab/docs/storage.md index a4e39ae67..9d27246e7 100644 --- a/charts/openhab/docs/storage.md +++ b/charts/openhab/docs/storage.md @@ -6,11 +6,11 @@ historical persistence data. ## Directories Overview -| Directory | PVC Key | Default Size | Content | -|-----------|---------|-------------|---------| -| `/openhab/userdata` | `persistence.userdata` | 5Gi | Runtime state, JSONDB, logs, persistence data | -| `/openhab/conf` | `persistence.conf` | 1Gi | Items, things, rules, sitemaps, services config | -| `/openhab/addons` | `persistence.addons` | 2Gi | Drop-in JAR bindings/addons | +| Directory | Default PVC | Shared-PVC subPath | Content | +|-----------|-------------|--------------------|---------| +| `/openhab/userdata` | Dedicated userdata PVC | `userdata` | Runtime state, JSONDB, logs, persistence data | +| `/openhab/conf` | Dedicated conf PVC | `conf` | Items, things, rules, sitemaps, services config | +| `/openhab/addons` | Dedicated addons PVC | `addons` | Drop-in JAR bindings/addons | ## userdata @@ -48,20 +48,96 @@ Most users will keep this empty (addons installed via the UI go to `userdata`). **Minimum recommended size**: 2Gi. -## Using Existing PVCs +## PVC Configuration -If you have pre-existing data on PVCs, use `existingClaim`: +By default, the chart creates one dedicated PVC per openHAB directory, matching +the historical chart behavior. Set `persistence.claim.enabled=true` to opt into +one shared PVC. In shared-PVC mode, the chart mounts every directory through a +relative `subPath` and an init container creates these directories before +openHAB starts. + +### Default: create three dedicated PVCs + +With the default values, the chart creates `-userdata`, +`-conf`, and `-addons`. No persistence configuration is +required. Configure each directory independently when needed. + +### Opt in to a single shared PVC + +Set `persistence.claim.enabled=true` to create one release-specific PVC named +`-data`, mounted with the `userdata`, `conf`, and `addons` subpaths: + +```yaml +persistence: + claim: + enabled: true + storageClass: local-path + accessMode: ReadWriteOnce + size: 10Gi +``` + +The per-directory `size`, `storageClass`, and `accessMode` settings are not +used in shared-PVC mode. + +### Use existing PVCs per directory + +Set `existingClaim` for any combination of one, two, or all three directories. +When shared-PVC mode is enabled, an enabled directory without an existing claim +uses the chart-managed shared PVC. A single existing PVC can be mounted at its root; an existing PVC shared +by multiple openHAB directories requires a distinct `subPath` for every +directory: + +```yaml +persistence: + userdata: + existingClaim: openhab-userdata + conf: + existingClaim: openhab-conf + subPath: data/openhab-conf +``` + +For one existing shared PVC, repeat its name for each directory that should use +it. When multiple directories resolve to the same claim, the chart renders one +Kubernetes volume and mounts each configured `subPath` from it. ```yaml persistence: userdata: - existingClaim: my-openhab-userdata + existingClaim: my-openhab-data + subPath: userdata conf: - existingClaim: my-openhab-conf + existingClaim: my-openhab-data + subPath: conf addons: - existingClaim: my-openhab-addons + existingClaim: my-openhab-data + subPath: addons +``` + +`subPath` is available only with an `existingClaim` or in the default dedicated +PVC mode. It must be relative and +must not contain `..` segments. When one existing claim is used for multiple +directories, each directory must use a distinct `subPath`. + +### Configure dedicated PVCs + +Set `size`, `storageClass`, or `accessMode` under a directory to configure its +dedicated PVC. An `existingClaim` takes precedence for that directory. + +```yaml +persistence: + userdata: + size: 10Gi + storageClass: local-path ``` +This is the default and preserves compatibility with previous releases. + +> **Warning:** Some filesystems create a `lost+found` directory at the root of +> a new PVC. openHAB then does not consider the mounted directory empty during +> its first start, skips initialization, and fails to start. Mount a dedicated, +> empty `subPath` (for example `openhab/userdata`) instead of the PVC root in +> this case. + ## Storage Class Recommendations For home automation, low-latency local storage is preferred: @@ -71,12 +147,6 @@ persistence: userdata: storageClass: "local-path" # k3s default size: 10Gi - conf: - storageClass: "local-path" - size: 2Gi - addons: - storageClass: "local-path" - size: 5Gi ``` ## Backup diff --git a/charts/openhab/templates/NOTES.txt b/charts/openhab/templates/NOTES.txt index 8e4fbbdf3..2e0c1191c 100644 --- a/charts/openhab/templates/NOTES.txt +++ b/charts/openhab/templates/NOTES.txt @@ -74,7 +74,7 @@ App : {{ .Chart.AppVersion }} ================================================================================ {{- if .Values.persistence.userdata.enabled }} - userdata ({{ .Values.persistence.userdata.size }}): Runtime state, logs, JSONDB + userdata ({{ if .Values.persistence.claim.enabled }}shared PVC {{ .Values.persistence.claim.size }}{{ else }}{{ .Values.persistence.userdata.size }} dedicated PVC{{ end }}): Runtime state, logs, JSONDB PVC: {{ include "openhab.userdataPvcName" . }} Mount: /openhab/userdata {{- else }} @@ -83,7 +83,7 @@ App : {{ .Chart.AppVersion }} {{- end }} {{- if .Values.persistence.conf.enabled }} - conf ({{ .Values.persistence.conf.size }}): Configuration files synced before startup + conf ({{ if .Values.persistence.claim.enabled }}shared PVC{{ else }}{{ .Values.persistence.conf.size }} dedicated PVC{{ end }}): Configuration files synced before startup PVC: {{ include "openhab.confPvcName" . }} Mount: /openhab/conf {{- else }} @@ -92,7 +92,7 @@ App : {{ .Chart.AppVersion }} {{- end }} {{- if .Values.persistence.addons.enabled }} - addons ({{ .Values.persistence.addons.size }}): Drop-in JAR addons + addons ({{ if .Values.persistence.claim.enabled }}shared PVC{{ else }}{{ .Values.persistence.addons.size }} dedicated PVC{{ end }}): Drop-in JAR addons PVC: {{ include "openhab.addonsPvcName" . }} Mount: /openhab/addons {{- end }} diff --git a/charts/openhab/templates/_helpers.tpl b/charts/openhab/templates/_helpers.tpl index 5040267d9..54d160d66 100644 --- a/charts/openhab/templates/_helpers.tpl +++ b/charts/openhab/templates/_helpers.tpl @@ -112,6 +112,91 @@ Validate pod labels do not override immutable selector labels. {{- end -}} {{- end }} +{{/* +Validate persistent volume configuration. +*/}} +{{- define "openhab.validatePersistence" -}} +{{- $volumes := dict "userdata" .Values.persistence.userdata "conf" .Values.persistence.conf "addons" .Values.persistence.addons }} +{{- range $name, $volume := $volumes }} +{{- if and (not $volume.enabled) $volume.existingClaim }} +{{- fail (printf "persistence.%s must be enabled when existingClaim is configured." $name) }} +{{- end }} +{{- if and (hasKey $volume "subPath") (not $volume.existingClaim) $.Values.persistence.claim.enabled }} +{{- fail (printf "persistence.%s.subPath requires existingClaim when persistence.claim.enabled is true." $name) }} +{{- end }} +{{- if and $volume.subPath (or (hasPrefix "/" $volume.subPath) (eq $volume.subPath ".") (eq $volume.subPath "..") (regexMatch "(^|/)\\.\\.(/|$)" $volume.subPath)) }} +{{- fail (printf "persistence.%s.subPath must be a relative path without traversal segments." $name) }} +{{- end }} +{{- end }} +{{- range $name, $volume := $volumes }} +{{- if and $volume.enabled $volume.existingClaim (not $volume.subPath) }} +{{- range $otherName, $otherVolume := $volumes }} +{{- if and (ne $name $otherName) $otherVolume.enabled (eq $volume.existingClaim $otherVolume.existingClaim) }} +{{- fail (printf "existingClaim %q is used by multiple directories; set subPath for every directory that uses the same existing PVC." $volume.existingClaim) }} +{{- end }} +{{- end }} +{{- end }} +{{- range $name, $volume := $volumes }} +{{- if and $volume.enabled $volume.existingClaim $volume.subPath }} +{{- range $otherName, $otherVolume := $volumes }} +{{- if and (ne $name $otherName) $otherVolume.enabled (eq $volume.existingClaim $otherVolume.existingClaim) (eq $volume.subPath $otherVolume.subPath) }} +{{- fail (printf "existingClaim %q uses subPath %q for multiple directories; each directory must use a distinct subPath." $volume.existingClaim $volume.subPath) }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} +{{- end }} + +{{/* Return true when the legacy dedicated-PVC layout is active. */}} +{{- define "openhab.userdataUsesDedicatedClaim" -}} +{{- $volume := .Values.persistence.userdata -}} +{{- if not .Values.persistence.claim.enabled }}true{{- else }}false{{- end -}} +{{- end }} +{{- define "openhab.confUsesDedicatedClaim" -}} +{{- $volume := .Values.persistence.conf -}} +{{- if not .Values.persistence.claim.enabled }}true{{- else }}false{{- end -}} +{{- end }} +{{- define "openhab.addonsUsesDedicatedClaim" -}} +{{- $volume := .Values.persistence.addons -}} +{{- if not .Values.persistence.claim.enabled }}true{{- else }}false{{- end -}} +{{- end }} + +{{/* Resolve subpaths: the opt-in shared PVC uses fixed directory names; legacy PVCs default to root. */}} +{{- define "openhab.userdataSubPath" -}} +{{- $volume := .Values.persistence.userdata -}} +{{- if hasKey $volume "subPath" }}{{ get $volume "subPath" }}{{- else if or $volume.existingClaim (eq (include "openhab.userdataUsesDedicatedClaim" .) "true") }}{{- else }}userdata{{- end -}} +{{- end }} +{{- define "openhab.confSubPath" -}} +{{- $volume := .Values.persistence.conf -}} +{{- if hasKey $volume "subPath" }}{{ get $volume "subPath" }}{{- else if or $volume.existingClaim (eq (include "openhab.confUsesDedicatedClaim" .) "true") }}{{- else }}conf{{- end -}} +{{- end }} +{{- define "openhab.addonsSubPath" -}} +{{- $volume := .Values.persistence.addons -}} +{{- if hasKey $volume "subPath" }}{{ get $volume "subPath" }}{{- else if or $volume.existingClaim (eq (include "openhab.addonsUsesDedicatedClaim" .) "true") }}{{- else }}addons{{- end -}} +{{- end }} + +{{/* Render one chart-managed per-directory PVC. */}} +{{- define "openhab.directoryPvc" -}} +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: {{ include (printf "openhab.%sPvcName" .name) .root }} + namespace: {{ include "openhab.namespace" .root }} + labels: + {{- include "openhab.labels" .root | nindent 4 }} +spec: + accessModes: + - {{ default "ReadWriteOnce" .volume.accessMode }} + resources: + requests: + storage: {{ default .defaultSize .volume.size }} + {{- if .volume.storageClass }} + storageClassName: {{ .volume.storageClass }} + {{- end }} +{{ end }} + {{/* Resolve the admin secret name. */}} @@ -123,26 +208,53 @@ Resolve the admin secret name. {{- end }} {{- end }} +{{/* +Resolve the chart-managed shared PVC name. +*/}} +{{- define "openhab.managedPvcName" -}} +{{- printf "%s-data" (include "openhab.fullname" .) | trunc 63 | trimSuffix "-" -}} +{{- end }} + {{/* Resolve the userdata PVC name. */}} {{- define "openhab.userdataPvcName" -}} {{- if .Values.persistence.userdata.existingClaim }} {{- .Values.persistence.userdata.existingClaim }} +{{- else if eq (include "openhab.userdataUsesDedicatedClaim" .) "true" }} +{{- printf "%s-userdata" (include "openhab.fullname" .) | trunc 63 | trimSuffix "-" -}} {{- else }} -{{- printf "%s-userdata" (include "openhab.fullname" .) }} +{{- include "openhab.managedPvcName" . }} {{- end }} {{- end }} +{{/* +Resolve the userdata Kubernetes volume name. +*/}} +{{- define "openhab.userdataVolumeName" -}} +{{- $claimName := include "openhab.userdataPvcName" . }} +{{- if .Values.persistence.userdata.existingClaim }}{{ printf "pvc-%s" (sha256sum $claimName | trunc 8) }}{{ else if eq (include "openhab.userdataUsesDedicatedClaim" .) "true" }}{{ print "userdata" }}{{ else }}{{ print "openhab-data" }}{{ end -}} +{{- end }} + {{/* Resolve the conf PVC name. */}} {{- define "openhab.confPvcName" -}} {{- if .Values.persistence.conf.existingClaim }} {{- .Values.persistence.conf.existingClaim }} +{{- else if eq (include "openhab.confUsesDedicatedClaim" .) "true" }} +{{- printf "%s-conf" (include "openhab.fullname" .) | trunc 63 | trimSuffix "-" -}} {{- else }} -{{- printf "%s-conf" (include "openhab.fullname" .) }} +{{- include "openhab.managedPvcName" . }} +{{- end }} {{- end }} + +{{/* +Resolve the conf Kubernetes volume name. +*/}} +{{- define "openhab.confVolumeName" -}} +{{- $claimName := include "openhab.confPvcName" . }} +{{- if .Values.persistence.conf.existingClaim }}{{ printf "pvc-%s" (sha256sum $claimName | trunc 8) }}{{ else if eq (include "openhab.confUsesDedicatedClaim" .) "true" }}{{ print "conf" }}{{ else }}{{ print "openhab-data" }}{{ end -}} {{- end }} {{/* @@ -151,7 +263,17 @@ Resolve the addons PVC name. {{- define "openhab.addonsPvcName" -}} {{- if .Values.persistence.addons.existingClaim }} {{- .Values.persistence.addons.existingClaim }} +{{- else if eq (include "openhab.addonsUsesDedicatedClaim" .) "true" }} +{{- printf "%s-addons" (include "openhab.fullname" .) | trunc 63 | trimSuffix "-" -}} {{- else }} -{{- printf "%s-addons" (include "openhab.fullname" .) }} +{{- include "openhab.managedPvcName" . }} +{{- end }} {{- end }} + +{{/* +Resolve the addons Kubernetes volume name. +*/}} +{{- define "openhab.addonsVolumeName" -}} +{{- $claimName := include "openhab.addonsPvcName" . }} +{{- if .Values.persistence.addons.existingClaim }}{{ printf "pvc-%s" (sha256sum $claimName | trunc 8) }}{{ else if eq (include "openhab.addonsUsesDedicatedClaim" .) "true" }}{{ print "addons" }}{{ else }}{{ print "openhab-data" }}{{ end -}} {{- end }} diff --git a/charts/openhab/templates/backup-cronjob.yaml b/charts/openhab/templates/backup-cronjob.yaml index c57183b94..9d86c2893 100644 --- a/charts/openhab/templates/backup-cronjob.yaml +++ b/charts/openhab/templates/backup-cronjob.yaml @@ -1,5 +1,8 @@ {{/* SPDX-License-Identifier: Apache-2.0 */}} {{- if .Values.backup.enabled }} +{{- $userdataSubPath := include "openhab.userdataSubPath" . }} +{{- $confSubPath := include "openhab.confSubPath" . }} +{{- $hasBackupSubPath := or (and .Values.backup.include.userdata $userdataSubPath) (and .Values.backup.include.conf $confSubPath) }} apiVersion: batch/v1 kind: CronJob metadata: @@ -33,6 +36,34 @@ spec: runAsGroup: 9001 fsGroup: 9001 initContainers: + {{- if $hasBackupSubPath }} + - name: create-backup-subpaths + image: "{{ .Values.backup.images.utility.repository }}:{{ .Values.backup.images.utility.tag }}" + imagePullPolicy: {{ .Values.backup.images.utility.pullPolicy }} + command: ["/bin/mkdir", "-p"] + args: + {{- if and .Values.backup.include.userdata $userdataSubPath }} + - {{ printf "/persistence/userdata/%s" $userdataSubPath | quote }} + {{- end }} + {{- if and .Values.backup.include.conf $confSubPath }} + - {{ printf "/persistence/conf/%s" $confSubPath | quote }} + {{- end }} + {{- with .Values.backup.resources }} + resources: + {{- toYaml . | nindent 16 }} + {{- end }} + securityContext: + allowPrivilegeEscalation: false + volumeMounts: + {{- if and .Values.backup.include.userdata $userdataSubPath }} + - name: userdata + mountPath: /persistence/userdata + {{- end }} + {{- if and .Values.backup.include.conf $confSubPath }} + - name: conf + mountPath: /persistence/conf + {{- end }} + {{- end }} - name: backup image: "{{ .Values.backup.images.utility.repository }}:{{ .Values.backup.images.utility.tag }}" imagePullPolicy: {{ .Values.backup.images.utility.pullPolicy }} @@ -46,11 +77,17 @@ spec: - name: userdata mountPath: /openhab/userdata readOnly: true + {{- if $userdataSubPath }} + subPath: {{ $userdataSubPath | quote }} + {{- end }} {{- end }} {{- if .Values.backup.include.conf }} - name: conf mountPath: /openhab/conf readOnly: true + {{- if $confSubPath }} + subPath: {{ $confSubPath | quote }} + {{- end }} {{- end }} - name: backup-scripts mountPath: /scripts diff --git a/charts/openhab/templates/pvc.yaml b/charts/openhab/templates/pvc.yaml index 6ac47bdf3..0153c4c12 100644 --- a/charts/openhab/templates/pvc.yaml +++ b/charts/openhab/templates/pvc.yaml @@ -1,57 +1,35 @@ {{/* SPDX-License-Identifier: Apache-2.0 */}} -{{- if and .Values.persistence.userdata.enabled (not .Values.persistence.userdata.existingClaim) }} -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: {{ include "openhab.fullname" . }}-userdata - namespace: {{ include "openhab.namespace" . }} - labels: - {{- include "openhab.labels" . | nindent 4 }} -spec: - accessModes: - - {{ .Values.persistence.userdata.accessMode }} - resources: - requests: - storage: {{ .Values.persistence.userdata.size }} - {{- if .Values.persistence.userdata.storageClass }} - storageClassName: {{ .Values.persistence.userdata.storageClass }} - {{- end }} +{{- $userdataDedicated := eq (include "openhab.userdataUsesDedicatedClaim" .) "true" }} +{{- $confDedicated := eq (include "openhab.confUsesDedicatedClaim" .) "true" }} +{{- $addonsDedicated := eq (include "openhab.addonsUsesDedicatedClaim" .) "true" }} +{{- $needsManagedClaim := and .Values.persistence.claim.enabled (or (and .Values.persistence.userdata.enabled (not .Values.persistence.userdata.existingClaim)) (and .Values.persistence.conf.enabled (not .Values.persistence.conf.existingClaim)) (and .Values.persistence.addons.enabled (not .Values.persistence.addons.existingClaim))) }} +{{- if and .Values.persistence.userdata.enabled (not .Values.persistence.userdata.existingClaim) $userdataDedicated }} +{{- include "openhab.directoryPvc" (dict "root" . "name" "userdata" "volume" .Values.persistence.userdata "defaultSize" "5Gi") }} {{- end }} -{{- if and .Values.persistence.conf.enabled (not .Values.persistence.conf.existingClaim) }} ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: {{ include "openhab.fullname" . }}-conf - namespace: {{ include "openhab.namespace" . }} - labels: - {{- include "openhab.labels" . | nindent 4 }} -spec: - accessModes: - - {{ .Values.persistence.conf.accessMode }} - resources: - requests: - storage: {{ .Values.persistence.conf.size }} - {{- if .Values.persistence.conf.storageClass }} - storageClassName: {{ .Values.persistence.conf.storageClass }} - {{- end }} +{{- if and .Values.persistence.conf.enabled (not .Values.persistence.conf.existingClaim) $confDedicated }} +{{- include "openhab.directoryPvc" (dict "root" . "name" "conf" "volume" .Values.persistence.conf "defaultSize" "1Gi") }} +{{- end }} +{{- if and .Values.persistence.addons.enabled (not .Values.persistence.addons.existingClaim) $addonsDedicated }} +{{- include "openhab.directoryPvc" (dict "root" . "name" "addons" "volume" .Values.persistence.addons "defaultSize" "2Gi") }} {{- end }} -{{- if and .Values.persistence.addons.enabled (not .Values.persistence.addons.existingClaim) }} +{{- if $needsManagedClaim }} +{{- if or (and .Values.persistence.userdata.enabled (not .Values.persistence.userdata.existingClaim) $userdataDedicated) (and .Values.persistence.conf.enabled (not .Values.persistence.conf.existingClaim) $confDedicated) (and .Values.persistence.addons.enabled (not .Values.persistence.addons.existingClaim) $addonsDedicated) }} --- +{{- end }} apiVersion: v1 kind: PersistentVolumeClaim metadata: - name: {{ include "openhab.fullname" . }}-addons + name: {{ include "openhab.managedPvcName" . }} namespace: {{ include "openhab.namespace" . }} labels: {{- include "openhab.labels" . | nindent 4 }} spec: accessModes: - - {{ .Values.persistence.addons.accessMode }} + - {{ .Values.persistence.claim.accessMode }} resources: requests: - storage: {{ .Values.persistence.addons.size }} - {{- if .Values.persistence.addons.storageClass }} - storageClassName: {{ .Values.persistence.addons.storageClass }} + storage: {{ .Values.persistence.claim.size }} + {{- if .Values.persistence.claim.storageClass }} + storageClassName: {{ .Values.persistence.claim.storageClass }} {{- end }} {{- end }} diff --git a/charts/openhab/templates/statefulset.yaml b/charts/openhab/templates/statefulset.yaml index 9249ee7df..60bb2f870 100644 --- a/charts/openhab/templates/statefulset.yaml +++ b/charts/openhab/templates/statefulset.yaml @@ -3,10 +3,15 @@ {{- include "openhab.validateAdmin" . }} {{- include "openhab.validateConfigMaps" . }} {{- include "openhab.validatePodLabels" . }} +{{- include "openhab.validatePersistence" . }} {{- $hasSitemaps := and .Values.configMaps.sitemaps.enabled (gt (len (.Values.configMaps.sitemaps.files | default dict)) 0) }} {{- $hasThings := and .Values.configMaps.things.enabled (gt (len (.Values.configMaps.things.files | default dict)) 0) }} {{- $hasItems := and .Values.configMaps.items.enabled (gt (len (.Values.configMaps.items.files | default dict)) 0) }} {{- $hasConfigMaps := or $hasSitemaps $hasThings $hasItems }} +{{- $userdataSubPath := include "openhab.userdataSubPath" . }} +{{- $confSubPath := include "openhab.confSubPath" . }} +{{- $addonsSubPath := include "openhab.addonsSubPath" . }} +{{- $hasPersistenceSubPath := or (and .Values.persistence.userdata.enabled $userdataSubPath) (and .Values.persistence.conf.enabled $confSubPath) (and .Values.persistence.addons.enabled $addonsSubPath) }} apiVersion: apps/v1 kind: StatefulSet metadata: @@ -51,6 +56,41 @@ spec: {{- toYaml .Values.podSecurityContext | nindent 8 }} {{- if $hasConfigMaps }} initContainers: + {{- else if $hasPersistenceSubPath }} + initContainers: + {{- end }} + {{- if $hasPersistenceSubPath }} + - name: create-persistence-subpaths + image: "{{ .Values.configMaps.syncImage.repository }}:{{ .Values.configMaps.syncImage.tag }}" + imagePullPolicy: {{ .Values.configMaps.syncImage.pullPolicy }} + command: ["/bin/mkdir", "-p"] + args: + {{- if and .Values.persistence.userdata.enabled $userdataSubPath }} + - {{ printf "/persistence/userdata/%s" $userdataSubPath | quote }} + {{- end }} + {{- if and .Values.persistence.conf.enabled $confSubPath }} + - {{ printf "/persistence/conf/%s" $confSubPath | quote }} + {{- end }} + {{- if and .Values.persistence.addons.enabled $addonsSubPath }} + - {{ printf "/persistence/addons/%s" $addonsSubPath | quote }} + {{- end }} + securityContext: + allowPrivilegeEscalation: false + volumeMounts: + {{- if and .Values.persistence.userdata.enabled $userdataSubPath }} + - name: {{ include "openhab.userdataVolumeName" . }} + mountPath: /persistence/userdata + {{- end }} + {{- if and .Values.persistence.conf.enabled $confSubPath }} + - name: {{ include "openhab.confVolumeName" . }} + mountPath: /persistence/conf + {{- end }} + {{- if and .Values.persistence.addons.enabled $addonsSubPath }} + - name: {{ include "openhab.addonsVolumeName" . }} + mountPath: /persistence/addons + {{- end }} + {{- end }} + {{- if $hasConfigMaps }} - name: sync-configmaps image: "{{ .Values.configMaps.syncImage.repository }}:{{ .Values.configMaps.syncImage.tag }}" imagePullPolicy: {{ .Values.configMaps.syncImage.pullPolicy }} @@ -67,8 +107,11 @@ spec: securityContext: allowPrivilegeEscalation: false volumeMounts: - - name: conf + - name: {{ include "openhab.confVolumeName" . }} mountPath: /openhab/conf + {{- if $confSubPath }} + subPath: {{ $confSubPath | quote }} + {{- end }} {{- if $hasSitemaps }} - name: sitemaps mountPath: /config-src/sitemaps @@ -122,36 +165,58 @@ spec: {{- toYaml .Values.resources | nindent 12 }} volumeMounts: {{- if .Values.persistence.userdata.enabled }} - - name: userdata + - name: {{ include "openhab.userdataVolumeName" . }} mountPath: /openhab/userdata + {{- if $userdataSubPath }} + subPath: {{ $userdataSubPath | quote }} + {{- end }} {{- end }} {{- if .Values.persistence.conf.enabled }} - - name: conf + - name: {{ include "openhab.confVolumeName" . }} mountPath: /openhab/conf + {{- if $confSubPath }} + subPath: {{ $confSubPath | quote }} + {{- end }} {{- end }} {{- if .Values.persistence.addons.enabled }} - - name: addons + - name: {{ include "openhab.addonsVolumeName" . }} mountPath: /openhab/addons + {{- if $addonsSubPath }} + subPath: {{ $addonsSubPath | quote }} + {{- end }} {{- end }} {{- with .Values.extraVolumeMounts }} {{- toYaml . | nindent 12 }} {{- end }} volumes: + {{- $renderedVolumeNames := dict }} {{- if .Values.persistence.userdata.enabled }} - - name: userdata + {{- $volumeName := include "openhab.userdataVolumeName" . }} + {{- if not (hasKey $renderedVolumeNames $volumeName) }} + {{- $_ := set $renderedVolumeNames $volumeName true }} + - name: {{ $volumeName }} persistentVolumeClaim: claimName: {{ include "openhab.userdataPvcName" . }} {{- end }} + {{- end }} {{- if .Values.persistence.conf.enabled }} - - name: conf + {{- $volumeName := include "openhab.confVolumeName" . }} + {{- if not (hasKey $renderedVolumeNames $volumeName) }} + {{- $_ := set $renderedVolumeNames $volumeName true }} + - name: {{ $volumeName }} persistentVolumeClaim: claimName: {{ include "openhab.confPvcName" . }} {{- end }} + {{- end }} {{- if .Values.persistence.addons.enabled }} - - name: addons + {{- $volumeName := include "openhab.addonsVolumeName" . }} + {{- if not (hasKey $renderedVolumeNames $volumeName) }} + {{- $_ := set $renderedVolumeNames $volumeName true }} + - name: {{ $volumeName }} persistentVolumeClaim: claimName: {{ include "openhab.addonsPvcName" . }} {{- end }} + {{- end }} {{- if $hasSitemaps }} - name: sitemaps configMap: diff --git a/charts/openhab/tests/backup_test.yaml b/charts/openhab/tests/backup_test.yaml index ddf1fe63f..31c56f34f 100644 --- a/charts/openhab/tests/backup_test.yaml +++ b/charts/openhab/tests/backup_test.yaml @@ -1,5 +1,4 @@ # SPDX-License-Identifier: Apache-2.0 ---- suite: Backup CronJob templates: - backup-cronjob.yaml @@ -63,6 +62,31 @@ tests: path: spec.failedJobsHistoryLimit value: 2 + - it: should create selected persistence subpaths before the backup init container + set: + backup.enabled: true + persistence.userdata.existingClaim: openhab-userdata + persistence.userdata.subPath: shared/openhab/userdata + persistence.conf.existingClaim: openhab-conf + persistence.conf.subPath: shared/openhab/conf + asserts: + - equal: + path: spec.jobTemplate.spec.template.spec.initContainers[0].name + value: create-backup-subpaths + - equal: + path: spec.jobTemplate.spec.template.spec.initContainers[0].command + value: ["/bin/mkdir", "-p"] + - contains: + path: spec.jobTemplate.spec.template.spec.initContainers[0].volumeMounts + content: + name: userdata + mountPath: /persistence/userdata + - contains: + path: spec.jobTemplate.spec.template.spec.initContainers[0].volumeMounts + content: + name: conf + mountPath: /persistence/conf + - it: should have backup initContainer using alpine image set: backup.enabled: true diff --git a/charts/openhab/tests/pvc_test.yaml b/charts/openhab/tests/pvc_test.yaml index 0cfc5fed6..ff7260dcd 100644 --- a/charts/openhab/tests/pvc_test.yaml +++ b/charts/openhab/tests/pvc_test.yaml @@ -3,79 +3,95 @@ suite: PersistentVolumeClaims templates: - pvc.yaml tests: - - it: should create 3 PVCs by default + - it: should create the three legacy PVCs by default asserts: - hasDocuments: count: 3 + - equal: + path: metadata.name + value: RELEASE-NAME-openhab-userdata + documentIndex: 0 + - equal: + path: metadata.name + value: RELEASE-NAME-openhab-conf + documentIndex: 1 + - equal: + path: metadata.name + value: RELEASE-NAME-openhab-addons + documentIndex: 2 - - it: should create userdata PVC with correct size - documentIndex: 0 + - it: should create dedicated PVCs with their legacy sizes by default asserts: - - isKind: - of: PersistentVolumeClaim - equal: path: spec.resources.requests.storage value: 5Gi - - equal: - path: spec.accessModes[0] - value: ReadWriteOnce - - - it: should create conf PVC with correct size - documentIndex: 1 - asserts: - - isKind: - of: PersistentVolumeClaim + documentIndex: 0 - equal: path: spec.resources.requests.storage value: 1Gi - - - it: should create addons PVC with correct size - documentIndex: 2 - asserts: - - isKind: - of: PersistentVolumeClaim + documentIndex: 1 - equal: path: spec.resources.requests.storage value: 2Gi + documentIndex: 2 - - it: should not create userdata PVC when existingClaim is set + - it: should create the shared PVC only when explicitly enabled set: - persistence.userdata.existingClaim: my-userdata + persistence.claim.enabled: true asserts: - hasDocuments: - count: 2 + count: 1 + - equal: + path: metadata.name + value: RELEASE-NAME-openhab-data + + - it: should use the configured shared PVC size + set: + persistence.claim.enabled: true + persistence.claim.size: 10Gi + asserts: + - equal: + path: spec.resources.requests.storage + value: 10Gi - - it: should not create conf PVC when existingClaim is set + - it: should not create a PVC when every enabled directory has an existing claim set: - persistence.conf.existingClaim: my-conf + persistence.userdata.existingClaim: openhab-userdata + persistence.conf.existingClaim: openhab-conf + persistence.addons.existingClaim: openhab-addons asserts: - hasDocuments: - count: 2 + count: 0 - - it: should not create addons PVC when existingClaim is set + - it: should use the shared PVC for directories without an existing claim set: - persistence.addons.existingClaim: my-addons + persistence.claim.enabled: true + persistence.userdata.existingClaim: openhab-userdata asserts: - hasDocuments: - count: 2 + count: 1 + - equal: + path: metadata.name + value: RELEASE-NAME-openhab-data - - it: should set custom storageClass for userdata + - it: should set custom storageClass for the shared PVC set: - persistence.userdata.storageClass: fast-ssd - documentIndex: 0 + persistence.claim.enabled: true + persistence.claim.storageClass: fast-ssd asserts: - equal: path: spec.storageClassName value: fast-ssd - - it: should not create userdata PVC when disabled + - it: should create the shared PVC when userdata is disabled set: + persistence.claim.enabled: true persistence.userdata.enabled: false asserts: - hasDocuments: - count: 2 + count: 1 - - it: should create no PVCs when all disabled + - it: should create no PVCs when all directories are disabled set: persistence.userdata.enabled: false persistence.conf.enabled: false diff --git a/charts/openhab/tests/statefulset_test.yaml b/charts/openhab/tests/statefulset_test.yaml index eb8291996..35bd8bdf5 100644 --- a/charts/openhab/tests/statefulset_test.yaml +++ b/charts/openhab/tests/statefulset_test.yaml @@ -85,7 +85,7 @@ tests: name: TZ value: UTC - - it: should mount userdata volume when persistence enabled + - it: should mount userdata from its dedicated PVC by default set: persistence.userdata.enabled: true asserts: @@ -95,7 +95,7 @@ tests: name: userdata mountPath: /openhab/userdata - - it: should mount conf volume when persistence enabled + - it: should mount conf from its dedicated PVC by default set: persistence.conf.enabled: true asserts: @@ -105,7 +105,7 @@ tests: name: conf mountPath: /openhab/conf - - it: should mount addons volume when persistence enabled + - it: should mount addons from its dedicated PVC by default set: persistence.addons.enabled: true asserts: @@ -115,6 +115,115 @@ tests: name: addons mountPath: /openhab/addons + - it: should mount all directories from the shared PVC subpaths when enabled + set: + persistence.claim.enabled: true + asserts: + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + name: openhab-data + mountPath: /openhab/userdata + subPath: userdata + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + name: openhab-data + mountPath: /openhab/conf + subPath: conf + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + name: openhab-data + mountPath: /openhab/addons + subPath: addons + + - it: should mount all data directories from configured PVC subpaths + set: + persistence.userdata.subPath: shared/openhab/userdata + persistence.userdata.existingClaim: smarthome-data + persistence.conf.subPath: shared/openhab/conf + persistence.conf.existingClaim: smarthome-data + persistence.addons.subPath: shared/openhab/addons + persistence.addons.existingClaim: smarthome-data + asserts: + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + name: pvc-426d9f12 + mountPath: /openhab/userdata + subPath: shared/openhab/userdata + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + name: pvc-426d9f12 + mountPath: /openhab/conf + subPath: shared/openhab/conf + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + name: pvc-426d9f12 + mountPath: /openhab/addons + subPath: shared/openhab/addons + - equal: + path: spec.template.spec.volumes + value: + - name: pvc-426d9f12 + persistentVolumeClaim: + claimName: smarthome-data + + - it: should mount data directories from separate PVCs + set: + persistence.userdata.existingClaim: openhab-userdata + persistence.conf.existingClaim: openhab-conf + persistence.addons.existingClaim: openhab-addons + asserts: + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + name: pvc-85697dd9 + mountPath: /openhab/userdata + - notExists: + path: spec.template.spec.containers[0].volumeMounts[0].subPath + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + name: pvc-7bf34568 + mountPath: /openhab/conf + - notExists: + path: spec.template.spec.containers[0].volumeMounts[1].subPath + - contains: + path: spec.template.spec.containers[0].volumeMounts + content: + name: pvc-bfd25939 + mountPath: /openhab/addons + - notExists: + path: spec.template.spec.containers[0].volumeMounts[2].subPath + + - it: should create subpaths before mounting a newly created PVC + set: + persistence.userdata.size: 5Gi + persistence.userdata.subPath: openhab/userdata + persistence.conf.enabled: false + persistence.addons.enabled: false + asserts: + - equal: + path: spec.template.spec.initContainers[0].name + value: create-persistence-subpaths + - equal: + path: spec.template.spec.initContainers[0].command + value: + - /bin/mkdir + - -p + - contains: + path: spec.template.spec.initContainers[0].args + content: /persistence/userdata/openhab/userdata + - contains: + path: spec.template.spec.initContainers[0].volumeMounts + content: + name: userdata + mountPath: /persistence/userdata + - it: should not mount karaf port when karaf disabled asserts: - notContains: diff --git a/charts/openhab/tests/validation_test.yaml b/charts/openhab/tests/validation_test.yaml index 61bfa1f04..70fa83120 100644 --- a/charts/openhab/tests/validation_test.yaml +++ b/charts/openhab/tests/validation_test.yaml @@ -41,7 +41,6 @@ tests: asserts: - isKind: of: StatefulSet - - it: should fail when podLabels override selector name values: - podlabels-selector-name-values.yaml @@ -62,3 +61,72 @@ tests: asserts: - failedTemplate: errorMessage: "podLabels must not override the selector label app.kubernetes.io/instance" + + - it: should fail when a disabled volume has an existing claim + set: + persistence.userdata.existingClaim: openhab-userdata + persistence.conf.enabled: false + persistence.conf.existingClaim: openhab-conf + persistence.addons.existingClaim: openhab-addons + asserts: + - failedTemplate: + errorMessage: "persistence.conf must be enabled when existingClaim is configured." + + - it: should allow a single directory to use an existing claim + set: + persistence.userdata.existingClaim: openhab-userdata + asserts: + - isKind: + of: StatefulSet + + - it: should fail when multiple directories share an existing claim without subpaths + set: + persistence.userdata.existingClaim: openhab-data + persistence.conf.existingClaim: openhab-data + asserts: + - failedTemplate: + errorMessage: "existingClaim \"openhab-data\" is used by multiple directories; set subPath for every directory that uses the same existing PVC." + + - it: should allow multiple directories to share an existing claim when every directory has a subpath + set: + persistence.userdata.existingClaim: openhab-data + persistence.userdata.subPath: userdata + persistence.conf.existingClaim: openhab-data + persistence.conf.subPath: conf + asserts: + - isKind: + of: StatefulSet + + - it: should fail when multiple directories use the same existing claim and subpath + set: + persistence.userdata.existingClaim: openhab-data + persistence.userdata.subPath: openhab + persistence.conf.existingClaim: openhab-data + persistence.conf.subPath: openhab + asserts: + - failedTemplate: + errorMessage: "existingClaim \"openhab-data\" uses subPath \"openhab\" for multiple directories; each directory must use a distinct subPath." + + - it: should allow a subPath in the default dedicated PVC mode + set: + persistence.userdata.storageClass: fast-ssd + persistence.userdata.subPath: openhab/userdata + asserts: + - isKind: + of: StatefulSet + + - it: should fail when subPath is set for the shared PVC + set: + persistence.claim.enabled: true + persistence.userdata.subPath: custom/userdata + asserts: + - failedTemplate: + errorMessage: "persistence.userdata.subPath requires existingClaim when persistence.claim.enabled is true." + + - it: should fail when subPath contains traversal segments + set: + persistence.addons.existingClaim: openhab-addons + persistence.addons.subPath: shared/../addons + asserts: + - failedTemplate: + errorMessage: "persistence.addons.subPath must be a relative path without traversal segments." diff --git a/charts/openhab/values.schema.json b/charts/openhab/values.schema.json index 65c7459d9..f757164bd 100644 --- a/charts/openhab/values.schema.json +++ b/charts/openhab/values.schema.json @@ -211,6 +211,30 @@ "type": "object", "description": "Persistent storage for openHAB data directories", "properties": { + "claim": { + "type": "object", + "description": "Settings for the optional generated shared data PVC", + "properties": { + "enabled": { + "type": "boolean", + "default": false, + "description": "Store userdata, conf, and addons on one shared PVC instead of the legacy three-PVC layout." + }, + "storageClass": { + "type": "string" + }, + "accessMode": { + "type": "string", + "enum": ["ReadWriteOnce", "ReadWriteMany", "ReadOnlyMany"], + "default": "ReadWriteOnce" + }, + "size": { + "type": "string", + "pattern": "^[0-9]+(Mi|Gi|Ti|M|G|T)$", + "default": "5Gi" + } + } + }, "userdata": { "type": "object", "description": "Runtime state, JSONDB, logs", @@ -220,7 +244,8 @@ "default": true }, "storageClass": { - "type": "string" + "type": "string", + "description": "Storage class for the legacy dedicated userdata PVC." }, "accessMode": { "type": "string", @@ -232,8 +257,13 @@ "pattern": "^[0-9]+(Mi|Gi|Ti|M|G|T)$", "default": "5Gi" }, + "subPath": { + "type": "string", + "description": "Optional relative subdirectory within an existing or legacy dedicated PVC" + }, "existingClaim": { - "type": "string" + "type": "string", + "description": "Existing PVC to mount instead of creating one" } } }, @@ -246,7 +276,8 @@ "default": true }, "storageClass": { - "type": "string" + "type": "string", + "description": "Storage class for the legacy dedicated conf PVC." }, "accessMode": { "type": "string", @@ -258,8 +289,13 @@ "pattern": "^[0-9]+(Mi|Gi|Ti|M|G|T)$", "default": "1Gi" }, + "subPath": { + "type": "string", + "description": "Optional relative subdirectory within an existing or legacy dedicated PVC" + }, "existingClaim": { - "type": "string" + "type": "string", + "description": "Existing PVC to mount instead of creating one" } } }, @@ -272,7 +308,8 @@ "default": true }, "storageClass": { - "type": "string" + "type": "string", + "description": "Storage class for the legacy dedicated addons PVC." }, "accessMode": { "type": "string", @@ -284,8 +321,13 @@ "pattern": "^[0-9]+(Mi|Gi|Ti|M|G|T)$", "default": "2Gi" }, + "subPath": { + "type": "string", + "description": "Optional relative subdirectory within an existing or legacy dedicated PVC" + }, "existingClaim": { - "type": "string" + "type": "string", + "description": "Existing PVC to mount instead of creating one" } } } diff --git a/charts/openhab/values.yaml b/charts/openhab/values.yaml index 4d703e9be..14fc60236 100644 --- a/charts/openhab/values.yaml +++ b/charts/openhab/values.yaml @@ -102,6 +102,17 @@ ingress: # -- Persistent storage for openHAB data directories persistence: + # -- Settings for the optional generated shared data PVC + claim: + # -- Store userdata, conf, and addons on one PVC. Disabled by default to retain the legacy three-PVC layout. + enabled: false + # -- Storage class name (empty = cluster default) + storageClass: "" + # -- Access mode + accessMode: ReadWriteOnce + # -- Storage size + size: 5Gi + # -- userdata: Runtime state, JSONDB, logs, persistence data (REQUIRED) userdata: # -- Enable PVC for userdata @@ -112,8 +123,9 @@ persistence: accessMode: ReadWriteOnce # -- Storage size size: 5Gi - # -- Use an existing PVC instead of creating one + # -- Existing PVC for userdata. When persistence.claim.enabled is true, directories without an existingClaim use the shared PVC. existingClaim: "" + # -- Optional subdirectory in an existing or legacy dedicated PVC to mount at /openhab/userdata. # -- conf: Configuration files synced before startup (REQUIRED) conf: @@ -125,8 +137,9 @@ persistence: accessMode: ReadWriteOnce # -- Storage size size: 1Gi - # -- Use an existing PVC instead of creating one + # -- Existing PVC for conf. When persistence.claim.enabled is true, directories without an existingClaim use the shared PVC. existingClaim: "" + # -- Optional subdirectory in an existing or legacy dedicated PVC to mount at /openhab/conf. # -- addons: Drop-in JAR addons not available via marketplace (optional) addons: @@ -138,8 +151,9 @@ persistence: accessMode: ReadWriteOnce # -- Storage size size: 2Gi - # -- Use an existing PVC instead of creating one + # -- Existing PVC for addons. When persistence.claim.enabled is true, directories without an existingClaim use the shared PVC. existingClaim: "" + # -- Optional subdirectory in an existing or legacy dedicated PVC to mount at /openhab/addons. # -- Admin credentials configuration. # openHAB does not support env-var-based admin bootstrap natively.