Third change of the same class (#99): an override written without children is YAML null and replaced the whole default sub-tree, rendering "securityContext: null" (unhardened container), a vanished probe or a container without resource accounting - silently, while the workload reports healthy. The defaultedDict helper from #96 is adopted for both workloads, so an empty block means "chart defaults apply" while an explicitly set value still wins, including false and 0. The server probes rebuild their Host header from ingress.domain via the passed-in root context, because the 2.x server rejects requests whose Host is neither loopback nor a CORS_ORIGIN host. The schema types allow null for exactly these blocks, so schema and helper agree instead of the schema rejecting what the helper absorbs. Rendering with normal values is byte-identical to the previous version, with and without the guacd sidecar.
234 lines
10 KiB
YAML
234 lines
10 KiB
YAML
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: {{ .Release.Name }}-{{ .Chart.Name }}-deployment
|
|
labels:
|
|
app: {{ .Release.Name }}-{{ .Chart.Name }}
|
|
spec:
|
|
replicas: {{ include "patchmon.replicas" (dict "scaleDown" .Values.scaleDown "replicas" .Values.patchmon.server.replicas) }}
|
|
selector:
|
|
matchLabels:
|
|
app: {{ .Release.Name }}-{{ .Chart.Name }}
|
|
template:
|
|
metadata:
|
|
name: {{ .Release.Name }}-{{ .Chart.Name }}
|
|
labels:
|
|
app: {{ .Release.Name }}-{{ .Chart.Name }}
|
|
spec:
|
|
automountServiceAccountToken: false
|
|
# Pin a stable pod hostname: the server identifies itself in the agent
|
|
# presence registry (Redis) by hostname, and a Deployment pod's default
|
|
# hostname changes on every rollout, which would leave stale presence
|
|
# records behind (upstream pins "patchmon-server" in its compose file
|
|
# for the same reason).
|
|
hostname: {{ .Release.Name }}-{{ .Chart.Name }}-server
|
|
securityContext:
|
|
{{- include "patchmon.server.podSecurityContext" .Values.patchmon.server.securityContext | nindent 8 }}
|
|
containers:
|
|
- name: {{ .Release.Name }}-{{ .Chart.Name }}-server
|
|
image: "ghcr.io/patchmon/patchmon-server:{{ .Chart.AppVersion }}"
|
|
imagePullPolicy: IfNotPresent
|
|
securityContext:
|
|
{{- include "patchmon.server.containerSecurityContext" .Values.patchmon.server.securityContext | nindent 12 }}
|
|
ports:
|
|
- containerPort: 3000
|
|
protocol: TCP
|
|
name: http
|
|
env:
|
|
- name: DATABASE_URL
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: {{ .Release.Name }}-{{ .Chart.Name }}-postgres-secret
|
|
key: database-url
|
|
- name: REDIS_HOST
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: {{ .Release.Name }}-{{ .Chart.Name }}-redis-secret
|
|
key: host
|
|
- name: REDIS_PORT
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: {{ .Release.Name }}-{{ .Chart.Name }}-redis-secret
|
|
key: port
|
|
- name: REDIS_USER
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: {{ .Release.Name }}-{{ .Chart.Name }}-redis-secret
|
|
key: username
|
|
- name: REDIS_PASSWORD
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: {{ .Release.Name }}-{{ .Chart.Name }}-redis-secret
|
|
key: password
|
|
- name: REDIS_DB
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: {{ .Release.Name }}-{{ .Chart.Name }}-redis-secret
|
|
key: db
|
|
- name: JWT_SECRET
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: {{ .Release.Name }}-{{ .Chart.Name }}-patchmon-secret
|
|
key: jwt-secret
|
|
- name: AI_ENCRYPTION_KEY
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: {{ .Release.Name }}-{{ .Chart.Name }}-patchmon-secret
|
|
key: encryption-key
|
|
- name: SESSION_SECRET
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: {{ .Release.Name }}-{{ .Chart.Name }}-patchmon-secret
|
|
key: session-secret
|
|
- name: OIDC_ENABLED
|
|
value: "true"
|
|
- name: OIDC_ISSUER_URL
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: {{ .Release.Name }}-{{ .Chart.Name }}-oidc-secret
|
|
key: issuer-url
|
|
- name: OIDC_CLIENT_ID
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: {{ .Release.Name }}-{{ .Chart.Name }}-oidc-secret
|
|
key: client-id
|
|
- name: OIDC_CLIENT_SECRET
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: {{ .Release.Name }}-{{ .Chart.Name }}-oidc-secret
|
|
key: client-secret
|
|
- name: OIDC_REDIRECT_URI
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: {{ .Release.Name }}-{{ .Chart.Name }}-oidc-secret
|
|
key: redirect-uri
|
|
- name: OIDC_SCOPES
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: {{ .Release.Name }}-{{ .Chart.Name }}-oidc-secret
|
|
key: requested-scopes
|
|
- name: OIDC_AUTO_CREATE_USERS
|
|
value: "true"
|
|
# 2.x role vocabulary: superadmin, admin, host_manager, readonly,
|
|
# user. "viewer" (the 1.x default of this chart) no longer exists;
|
|
# readonly is its least-privilege equivalent.
|
|
- name: OIDC_DEFAULT_ROLE
|
|
value: "readonly"
|
|
- name: OIDC_DISABLE_LOCAL_AUTH
|
|
value: "true"
|
|
- name: OIDC_BUTTON_TEXT
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: {{ .Release.Name }}-{{ .Chart.Name }}-oidc-secret
|
|
key: button-text
|
|
- name: OIDC_SYNC_ROLES
|
|
value: "true"
|
|
- name: OIDC_USER_GROUP
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: {{ .Release.Name }}-{{ .Chart.Name }}-oidc-secret
|
|
key: user-group-name
|
|
- name: OIDC_ADMIN_GROUP
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: {{ .Release.Name }}-{{ .Chart.Name }}-oidc-secret
|
|
key: admin-group-name
|
|
- name: CORS_ORIGIN
|
|
value: "https://{{ required "A Domain/Host must be provided" .Values.ingress.domain }}"
|
|
# Renamed upstream in 2.x (was TRUST_PROXIES=<count> in 1.x): the
|
|
# server sits behind the ingress-nginx reverse proxy.
|
|
- name: TRUST_PROXY
|
|
value: "true"
|
|
{{- if .Values.patchmon.guacd.enabled }}
|
|
- name: GUACD_ADDRESS
|
|
value: "127.0.0.1:4822"
|
|
{{- end }}
|
|
{{- range $value := .Values.patchmon.server.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 }}
|
|
# Probe values are rendered through tpl (see values.yaml for the
|
|
# defaults and why the probes send a Host header).
|
|
livenessProbe:
|
|
{{- tpl (include "patchmon.server.livenessProbe" (dict "given" .Values.patchmon.server.livenessProbe "root" $)) . | nindent 12 }}
|
|
readinessProbe:
|
|
{{- tpl (include "patchmon.server.readinessProbe" (dict "given" .Values.patchmon.server.readinessProbe "root" $)) . | nindent 12 }}
|
|
startupProbe:
|
|
{{- tpl (include "patchmon.server.startupProbe" (dict "given" .Values.patchmon.server.startupProbe "root" $)) . | nindent 12 }}
|
|
resources:
|
|
{{- include "patchmon.server.effectiveResources" .Values.patchmon.server.resources | nindent 12 }}
|
|
volumeMounts:
|
|
# The image is stateless, but the Go server needs a writable /tmp
|
|
# for scratch files with a read-only root filesystem.
|
|
- name: tmp
|
|
mountPath: /tmp
|
|
{{- if .Values.patchmon.guacd.enabled }}
|
|
- name: {{ .Release.Name }}-{{ .Chart.Name }}-guacd
|
|
image: {{ .Values.patchmon.guacd.image }}
|
|
imagePullPolicy: IfNotPresent
|
|
{{- if .Values.patchmon.guacd.env }}
|
|
env:
|
|
{{- range $value := .Values.patchmon.guacd.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 }}
|
|
{{- end }}
|
|
securityContext:
|
|
{{- include "patchmon.guacd.containerSecurityContext" .Values.patchmon.guacd.securityContext | nindent 12 }}
|
|
ports:
|
|
- containerPort: 4822
|
|
protocol: TCP
|
|
name: guacd
|
|
livenessProbe:
|
|
{{- tpl (include "patchmon.guacd.livenessProbe" .Values.patchmon.guacd.livenessProbe) . | nindent 12 }}
|
|
readinessProbe:
|
|
{{- tpl (include "patchmon.guacd.readinessProbe" .Values.patchmon.guacd.readinessProbe) . | nindent 12 }}
|
|
startupProbe:
|
|
{{- tpl (include "patchmon.guacd.startupProbe" .Values.patchmon.guacd.startupProbe) . | nindent 12 }}
|
|
resources:
|
|
{{- include "patchmon.guacd.effectiveResources" .Values.patchmon.guacd.resources | nindent 12 }}
|
|
volumeMounts:
|
|
- name: guacd-tmp
|
|
mountPath: /tmp
|
|
{{- end }}
|
|
restartPolicy: Always
|
|
volumes:
|
|
- name: tmp
|
|
emptyDir: {}
|
|
{{- if .Values.patchmon.guacd.enabled }}
|
|
- name: guacd-tmp
|
|
emptyDir: {}
|
|
{{- end }}
|