Files
jklein 40289a2e67 zipline: strict values.schema.json, ingress gate and null-safe hardening
Three changes, all about values that do not do what they promise:

1. values.schema.json (#68): additionalProperties: false on every
   chart-owned object level, so a key the chart does not read is rejected
   at render time instead of being silently ignored.

2. Ingress gate (#93): the Ingress template is wrapped in
   {{- if .Values.ingress.enabled }} and the key is added to values.yaml
   with default true, so behaviour is unchanged.

   As in rallly, ingress.domain is not a pure Ingress value: the
   StatefulSet also feeds it to CORE_DEFAULT_DOMAIN, the app's default
   domain for generated share links, and did so without required(). The
   guarantee only came from the ungated Ingress template, so the gate
   would have handed out unusable links silently. That read is now
   required() as well; only clusterIssuer becomes unnecessary.

3. Null-safety for hardening, probes and resources (#99): an erased block
   fell back to "securityContext: null" (unhardened), a vanished probe or
   a container without resource accounting. The rebuilt liveness probe
   keeps "/" rather than /api/healthcheck, so a database outage still does
   not restart the pod.

config stays deliberately not null-safe: storage and storageClass are
required(), which puts an erased block in the loud class #99 excludes.

Apart from an added comment, the rendered manifest is unchanged.
2026-08-23 21:07:11 +02:00

95 lines
4.0 KiB
YAML

apiVersion: apps/v1
kind: StatefulSet
metadata:
name: "{{ .Release.Name }}-{{ .Chart.Name }}-sfs"
spec:
selector:
matchLabels:
app: "{{ .Release.Name }}-{{ .Chart.Name }}-sfs"
serviceName: "{{ .Release.Name }}-{{ .Chart.Name }}-service"
replicas: {{ include "zipline.replicas" (dict "scaleDown" .Values.scaleDown "replicas" .Values.zipline.replicas) }}
template:
metadata:
labels:
app: "{{ .Release.Name }}-{{ .Chart.Name }}-sfs"
spec:
securityContext:
{{- include "zipline.podSecurityContext" .Values.zipline.securityContext | nindent 8 }}
containers:
- name: "{{ .Release.Name }}-{{ .Chart.Name }}-sfs"
image: "ghcr.io/diced/zipline:{{ .Chart.AppVersion }}"
securityContext:
{{- include "zipline.containerSecurityContext" .Values.zipline.securityContext | nindent 12 }}
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: {{ .Release.Name }}-{{ .Chart.Name }}-db-secret
key: connection-url
# ingress.domain is not a pure Ingress value: it is also the app's
# default domain for generated share links, so it stays required
# even when the Ingress is switched off (an empty value would hand
# out unusable links silently).
- name: CORE_DEFAULT_DOMAIN
value: "{{ required "A Domain/Host must be provided (ingress.domain)" .Values.ingress.domain }}"
- name: CORE_SECRET
valueFrom:
secretKeyRef:
name: {{ .Release.Name }}-{{ .Chart.Name }}-secret
key: server-secret
- name: UPLOADER_ADMIN_LIMIT
value: 500mb
{{- range $value := .Values.zipline.env }}
{{- if $value.value }}
- name: {{ $value.name | quote }}
value: {{ tpl $value.value $ | quote }}
{{- else if $value.valueFrom }}
{{- if $value.valueFrom.secretKeyRef }}
- name: {{ $value.name }}
valueFrom:
secretKeyRef:
name: {{ tpl $value.valueFrom.secretKeyRef.name $ | quote }}
key: {{ tpl $value.valueFrom.secretKeyRef.key $ | quote }}
{{- else if $value.valueFrom.configMapKeyRef }}
- name: {{ $value.name }}
valueFrom:
configMapKeyRef:
name: {{ tpl $value.valueFrom.configMapKeyRef.name $ | quote }}
key: {{ tpl $value.valueFrom.configMapKeyRef.key $ | quote }}
{{- end }}
{{- end }}
{{- end }}
resources:
{{- include "zipline.effectiveResources" .Values.zipline.resources | nindent 12 }}
ports:
- name: "zipline-server"
containerPort: 3000
protocol: TCP
livenessProbe:
{{- include "zipline.livenessProbe" .Values.zipline.livenessProbe | nindent 12 }}
readinessProbe:
{{- include "zipline.readinessProbe" .Values.zipline.readinessProbe | nindent 12 }}
startupProbe:
{{- include "zipline.startupProbe" .Values.zipline.startupProbe | nindent 12 }}
volumeMounts:
- name: zipline-volume
mountPath: /zipline/uploads
subPath: uploads/
- name: zipline-volume
mountPath: /zipline/public
subPath: public/
- name: zipline-volume
mountPath: /zipline/themes
subPath: themes/
# Zipline writes temporary chunks/files below /tmp; with a
# read-only root filesystem this must be a writable emptyDir.
- name: tmp
mountPath: /tmp
automountServiceAccountToken: false
volumes:
- name: tmp
emptyDir: {}
- name: zipline-volume
persistentVolumeClaim:
claimName: {{ .Release.Name }}-{{ .Chart.Name }}-vc