mirror of
https://github.com/cozystack/cozystack.git
synced 2026-11-09 05:25:14 +09:00
fix(harbor): preserve jobservice and trivy storageClass on upgrade
The cozy-harbor wrapper never passed storageClass to the jobservice jobLog PVC, so it was created without a storageClassName and the default-StorageClass admission stamped the cluster default. Because PVC storageClassName is immutable, this caused rendered-vs-live drift on upgrade. Preserve an existing PVC's class via lookup and fall back to the configured storageClass for fresh installs. The trivy StatefulSet's volumeClaimTemplate had the same latent drift -- .Values.storageClass was forwarded blindly into a VCT that cannot be patched at all -- so it gets the same lookup-preserve treatment, keyed off data-<release>-trivy-0. A live object pinned to an explicit "" (no dynamic provisioning) now round-trips through upstream's "-" sentinel instead of collapsing to an omitted storageClassName, and the spec lookup is guarded with `| default dict` so a PVC carrying no storageClassName key stays omitted. Adds a helm-unittest regression suite and wires a test target so make unit-tests stops skipping packages/apps/harbor. Fixes #2368 Assisted-By: Claude <noreply@anthropic.com> Signed-off-by: Myasnikov Daniil <myasnikovdaniil2001@gmail.com>
This commit is contained in:
2 files changed
+114
-3
No files matched your search
@@ -23,6 +23,46 @@
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- /*
|
||||
storageClassName on a PVC is immutable, and a StatefulSet's volumeClaimTemplate
|
||||
cannot be patched at all. The upstream chart renders both the jobservice PVC and
|
||||
the trivy VCT without a storageClassName unless one is passed, so on first install
|
||||
the default-StorageClass admission stamps the cluster default onto the live object.
|
||||
To avoid an immutable-field rejection on upgrade we keep the rendered value equal
|
||||
to the live one: preserve an existing object's storageClassName, and only fall back
|
||||
to the configured storageClass for a fresh install. See issue #2368.
|
||||
|
||||
A live object pinned to an explicit "" (no dynamic provisioning) must round-trip
|
||||
too: upstream maps the "-" sentinel back to storageClassName: "", so forward "-"
|
||||
rather than letting "" collapse to an omitted field. An object carrying no
|
||||
storageClassName key at all keeps the empty fallback so the field stays omitted,
|
||||
matching the live object.
|
||||
*/}}
|
||||
{{- $jobservicePvc := lookup "v1" "PersistentVolumeClaim" .Release.Namespace (printf "%s-jobservice" .Release.Name) }}
|
||||
{{- $jobserviceStorageClass := .Values.storageClass }}
|
||||
{{- if $jobservicePvc }}
|
||||
{{- $jobserviceSpec := $jobservicePvc.spec | default dict }}
|
||||
{{- if hasKey $jobserviceSpec "storageClassName" }}
|
||||
{{- $jobserviceStorageClass = $jobserviceSpec.storageClassName | default "-" }}
|
||||
{{- else }}
|
||||
{{- $jobserviceStorageClass = "" }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
{{- /* The trivy StatefulSet's VCT is named "data", so its PVCs are
|
||||
data-<release>-trivy-0..N; the class is identical across ordinals, so the
|
||||
first ordinal is representative. */}}
|
||||
{{- $trivyPvc := lookup "v1" "PersistentVolumeClaim" .Release.Namespace (printf "data-%s-trivy-0" .Release.Name) }}
|
||||
{{- $trivyStorageClass := .Values.storageClass }}
|
||||
{{- if $trivyPvc }}
|
||||
{{- $trivySpec := $trivyPvc.spec | default dict }}
|
||||
{{- if hasKey $trivySpec "storageClassName" }}
|
||||
{{- $trivyStorageClass = $trivySpec.storageClassName | default "-" }}
|
||||
{{- else }}
|
||||
{{- $trivyStorageClass = "" }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
@@ -108,13 +148,20 @@ spec:
|
||||
bucket: {{ .Release.Name }}-registry
|
||||
secure: false
|
||||
v4auth: true
|
||||
{{- if .Values.trivy.enabled }}
|
||||
{{- if or $jobserviceStorageClass .Values.trivy.enabled }}
|
||||
persistentVolumeClaim:
|
||||
{{- with $jobserviceStorageClass }}
|
||||
jobservice:
|
||||
jobLog:
|
||||
storageClass: {{ . | quote }}
|
||||
{{- end }}
|
||||
{{- if .Values.trivy.enabled }}
|
||||
trivy:
|
||||
size: {{ .Values.trivy.size }}
|
||||
{{- with .Values.storageClass }}
|
||||
storageClass: {{ . }}
|
||||
{{- with $trivyStorageClass }}
|
||||
storageClass: {{ . | quote }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
portal:
|
||||
resources: {{- include "cozy-lib.resources.defaultingSanitize" (list "t1.nano" (dict) $) | nindent 10 }}
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
suite: jobservice storageClass propagation
|
||||
|
||||
release:
|
||||
name: harbor
|
||||
namespace: tenant-test
|
||||
|
||||
# Regression test for issue #2368: the jobservice PVC must receive the
|
||||
# configured storageClass so it is created with an explicit storageClassName
|
||||
# instead of relying on the default-StorageClass admission. Because PVC
|
||||
# storageClassName is immutable, the template preserves an existing PVC's
|
||||
# class when one is found; under `helm template`/unittest the cluster lookup
|
||||
# returns empty, so these cases exercise the fresh-install fallback path.
|
||||
#
|
||||
# The rendered HelmRelease (documentIndex 1) carries the values that the
|
||||
# cozy-harbor chart forwards to the upstream harbor subchart.
|
||||
# helm-unittest renders every template in the chart, so the platform-injected
|
||||
# globals consumed by the ingress/httproute/bucket templates must be supplied
|
||||
# even though only templates/harbor.yaml is asserted on.
|
||||
set:
|
||||
_namespace:
|
||||
host: example.org
|
||||
ingress: nginx
|
||||
gateway: ""
|
||||
seaweedfs: seaweedfs
|
||||
_cluster:
|
||||
solver: http01
|
||||
|
||||
tests:
|
||||
- it: forwards storageClass to jobservice jobLog on a fresh install
|
||||
template: templates/harbor.yaml
|
||||
documentIndex: 1
|
||||
set:
|
||||
storageClass: local-3rep
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.values.harbor.persistence.persistentVolumeClaim.jobservice.jobLog.storageClass
|
||||
value: local-3rep
|
||||
|
||||
- it: still forwards storageClass to trivy alongside jobservice
|
||||
template: templates/harbor.yaml
|
||||
documentIndex: 1
|
||||
set:
|
||||
storageClass: local-3rep
|
||||
asserts:
|
||||
- equal:
|
||||
path: spec.values.harbor.persistence.persistentVolumeClaim.trivy.storageClass
|
||||
value: local-3rep
|
||||
|
||||
- it: omits the jobservice block when storageClass is unset
|
||||
template: templates/harbor.yaml
|
||||
documentIndex: 1
|
||||
asserts:
|
||||
- notExists:
|
||||
path: spec.values.harbor.persistence.persistentVolumeClaim.jobservice
|
||||
|
||||
- it: emits no persistentVolumeClaim block when storageClass is unset and trivy is disabled
|
||||
template: templates/harbor.yaml
|
||||
documentIndex: 1
|
||||
set:
|
||||
trivy:
|
||||
enabled: false
|
||||
asserts:
|
||||
- notExists:
|
||||
path: spec.values.harbor.persistence.persistentVolumeClaim
|
||||
Reference in new issue
Block a user