template-chart + README: values.schema.json, gate and null-safe helpers
Closes out the schema programme (#68) by moving what the 18 charts taught into the reference implementation and the binding guidelines. template-chart: - values.schema.json as the reference schema: additionalProperties false on every chart-owned level, pod-spec passthrough left open, and the reasoning inline in the descriptions so a copy carries it along. - defaultedDict and subBlock plus the per-block fallbacks for both security contexts, the three probes and resources, wired into both the Deployment and the StatefulSet. - the reference itself violated guideline 1: its env block reads ingress.domain, so with the Ingress gated off it rendered an empty value. That read is now required(), and the comment says why - the template is what people copy, so it has to teach the guard, not the hole. README, new section "Values that must not lie" with the five rules: 1. a value read outside its obvious template needs its own guard (matrix-synapse published '{"m.server": ":443"}' to federation without it, rendering cleanly and reporting healthy) 2. probes, contexts and resources through the null-safe helper, never behind an "if" - a guard removes the probe instead of showing a null 3. no liveness on an external dependency where a dependency-free path exists, otherwise document why on the helper 4. a fallback reproduces THIS chart's defaults, not the repo standard - calibre's readOnlyRootFilesystem: false is what keeps the runtime uid at 1000 instead of 911 and existing volume data readable 5. a probe default carries its context - port name, Host header, exec command - or the probe vanishes (teamspeak) or gets 403 (patchmon) Plus the two mechanics that are easiest to lose: null reaches schema validation only for keys WITHOUT a chart default (which is why the helper and the ["object","null"] types each cover a case the other cannot), and schemas must be validated against real bundle values - that step caught a draft of mine that would have broken three live paperless releases. CLAUDE.md: the new-chart checklist now names the schema and the adaptation step, since the copied file is chart-specific and wrong until it is adapted. freesailarr is not covered: it is not on main yet (#59).
This commit is contained in:
8 files changed
+424
-18
No files matched your search
@@ -5,7 +5,7 @@ icon: https://helm.sh/img/helm.svg
|
||||
|
||||
type: application
|
||||
|
||||
version: 2.0.0+upxxx
|
||||
version: 3.0.0+upxxx
|
||||
appVersion: "xxx"
|
||||
|
||||
maintainers:
|
||||
|
||||
@@ -114,3 +114,171 @@ template-chart is the reference implementation.
|
||||
1
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Merge a user-supplied values sub-tree onto a dict of chart defaults so that a
|
||||
null / empty override falls back to the defaults instead of erasing them.
|
||||
|
||||
Input: dict "defaults" <dict> "given" <dict|nil> "path" <string, optional
|
||||
values path used in error messages>. Output: YAML of the merged dict (consume
|
||||
it with fromYaml).
|
||||
|
||||
Why this exists (issues #61 and #99): Helm merges values maps recursively, but
|
||||
an override key written without children — e.g. a leftover
|
||||
|
||||
securityContext:
|
||||
|
||||
after deleting its last remaining sub-key — is YAML null. Where the chart
|
||||
defines a default, Helm treats that null as a deletion of the default; the
|
||||
template then renders "securityContext: null": no readOnlyRootFilesystem, no
|
||||
dropped capabilities, no allowPrivilegeEscalation: false. The workload starts
|
||||
and reports healthy while being unhardened, so nothing points at the mistake.
|
||||
The same shape erases a probe (it disappears) or the resources block (no
|
||||
requests, no computed limits). This helper defines the opposite semantics: an
|
||||
empty block means "chart defaults apply".
|
||||
|
||||
Rules:
|
||||
- a nil "given" is treated as an empty dict (all defaults apply).
|
||||
- a key whose override value is null keeps the default (nulls never delete).
|
||||
- a key present in both as a map is merged recursively, so a partially
|
||||
filled block only overrides the keys it actually sets.
|
||||
- a scalar override for a key the defaults define as a map is rejected with
|
||||
a message naming the values path, instead of failing later with a template
|
||||
field error.
|
||||
- any other set value wins as given, including an explicit false or 0 —
|
||||
Helm's "default" and sprig's "mergeOverwrite" would both swallow those
|
||||
zero values, hence the explicit kindIs "invalid" nil check.
|
||||
- keys only present in the override are passed through unchanged.
|
||||
|
||||
NOTE: like the helpers above, this is duplicated into every chart's
|
||||
templates/_helpers.tpl with the chart's name as define prefix, because charts
|
||||
in this repo deliberately have no dependencies. This file is the reference
|
||||
implementation.
|
||||
*/}}
|
||||
{{- define "xxx.defaultedDict" -}}
|
||||
{{- $defaults := .defaults | default dict -}}
|
||||
{{- $given := .given -}}
|
||||
{{- $path := .path | default "value" -}}
|
||||
{{- if kindIs "invalid" $given -}}
|
||||
{{- $given = dict -}}
|
||||
{{- end -}}
|
||||
{{- if not (kindIs "map" $given) -}}
|
||||
{{- fail (printf "%s must be a mapping or null, got %s (%v)" $path (kindOf $given) $given) -}}
|
||||
{{- end -}}
|
||||
{{- $out := deepCopy $defaults -}}
|
||||
{{- range $key, $value := $given -}}
|
||||
{{- if not (kindIs "invalid" $value) -}}
|
||||
{{- $default := index $defaults $key -}}
|
||||
{{- if and (kindIs "map" $value) (kindIs "map" $default) -}}
|
||||
{{- $_ := set $out $key (fromYaml (include "xxx.defaultedDict" (dict "defaults" $default "given" $value "path" (printf "%s.%s" $path $key)))) -}}
|
||||
{{- else if kindIs "map" $default -}}
|
||||
{{- fail (printf "%s.%s must be a mapping or null, got %s (%v)" $path $key (kindOf $value) $value) -}}
|
||||
{{- else -}}
|
||||
{{- $_ := set $out $key $value -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- end -}}
|
||||
{{- toYaml $out -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
Pick one sub-block out of a values block that may itself be null.
|
||||
|
||||
Input: dict "block" <dict|nil> "key" <string> "path" <string>.
|
||||
Returns YAML of dict "value" <the sub-block, may be nil>, after rejecting a
|
||||
non-mapping block with a message that names the values path. Needed because
|
||||
".Values.<app>.securityContext" can itself be erased, and indexing into nil
|
||||
inside a template is not an error but silently yields nothing.
|
||||
*/}}
|
||||
{{- define "xxx.subBlock" -}}
|
||||
{{- $block := .block -}}
|
||||
{{- if kindIs "invalid" $block -}}
|
||||
{{- $block = dict -}}
|
||||
{{- end -}}
|
||||
{{- if not (kindIs "map" $block) -}}
|
||||
{{- fail (printf "%s must be a mapping or null, got %s (%v)" .path (kindOf $block) $block) -}}
|
||||
{{- end -}}
|
||||
{{- toYaml (dict "value" (index $block .key)) -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
The effective security contexts, probes and resources (issue #99).
|
||||
|
||||
The defaults below MUST stay in sync with the corresponding blocks in
|
||||
values.yaml, which stays the documented, user-facing place for them; this copy
|
||||
is only the fallback for the case where an override has erased the block.
|
||||
|
||||
Two rules that these fallbacks exist to demonstrate (README, "Chart style
|
||||
guidelines"):
|
||||
|
||||
- Reproduce THIS chart's defaults, not the repo standard. Where a chart
|
||||
deviates on purpose (a root-starting image, a non-default limitFactor, a
|
||||
pinned uid), the fallback must reproduce the deviation. Restoring the
|
||||
"clean" standard here is not tidying, it is an outage - in one chart it
|
||||
would move the runtime uid from 1000 to 911 and make existing volume data
|
||||
inaccessible.
|
||||
- Carry the probe's CONTEXT, not just its timings. A probe default without
|
||||
its port name, Host header or exec command is worse than useless: in one
|
||||
chart the probe vanished entirely, in another it answered 403 and the pod
|
||||
never became Ready.
|
||||
*/}}
|
||||
{{- define "xxx.podSecurityContext" -}}
|
||||
{{- $given := (fromYaml (include "xxx.subBlock" (dict "block" . "key" "pod" "path" "xxx.securityContext"))).value -}}
|
||||
{{- $defaults := dict
|
||||
"runAsNonRoot" true
|
||||
"runAsUser" 20000
|
||||
"runAsGroup" 1000
|
||||
"fsGroup" 1000
|
||||
"fsGroupChangePolicy" "Always" -}}
|
||||
{{- include "xxx.defaultedDict" (dict "defaults" $defaults "given" $given "path" "xxx.securityContext.pod") -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "xxx.containerSecurityContext" -}}
|
||||
{{- $given := (fromYaml (include "xxx.subBlock" (dict "block" . "key" "container" "path" "xxx.securityContext"))).value -}}
|
||||
{{- $defaults := dict
|
||||
"allowPrivilegeEscalation" false
|
||||
"readOnlyRootFilesystem" true
|
||||
"runAsNonRoot" true
|
||||
"capabilities" (dict "drop" (list "ALL") "add" (list)) -}}
|
||||
{{- include "xxx.defaultedDict" (dict "defaults" $defaults "given" $given "path" "xxx.securityContext.container") -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "xxx.livenessProbe" -}}
|
||||
{{- $defaults := dict
|
||||
"httpGet" (dict "path" "/" "port" "http")
|
||||
"periodSeconds" 10
|
||||
"timeoutSeconds" 5
|
||||
"failureThreshold" 3 -}}
|
||||
{{- include "xxx.defaultedDict" (dict "defaults" $defaults "given" . "path" "xxx.livenessProbe") -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "xxx.readinessProbe" -}}
|
||||
{{- $defaults := dict
|
||||
"httpGet" (dict "path" "/" "port" "http")
|
||||
"periodSeconds" 10
|
||||
"timeoutSeconds" 5
|
||||
"failureThreshold" 3 -}}
|
||||
{{- include "xxx.defaultedDict" (dict "defaults" $defaults "given" . "path" "xxx.readinessProbe") -}}
|
||||
{{- end -}}
|
||||
|
||||
{{- define "xxx.startupProbe" -}}
|
||||
{{- $defaults := dict
|
||||
"httpGet" (dict "path" "/" "port" "http")
|
||||
"periodSeconds" 5
|
||||
"timeoutSeconds" 5
|
||||
"failureThreshold" 30 -}}
|
||||
{{- include "xxx.defaultedDict" (dict "defaults" $defaults "given" . "path" "xxx.startupProbe") -}}
|
||||
{{- end -}}
|
||||
|
||||
{{/*
|
||||
The effective resources block, fed into the resources helper above so that an
|
||||
erased "resources:" still yields the chart's requests and computed limits
|
||||
instead of a container without any resource accounting.
|
||||
*/}}
|
||||
{{- define "xxx.effectiveResources" -}}
|
||||
{{- $defaults := dict
|
||||
"limitFactor" 3
|
||||
"requests" (dict "cpu" 0.1 "memory" "512Mi" "ephemeral-storage" "10Mi") -}}
|
||||
{{- $merged := fromYaml (include "xxx.defaultedDict" (dict "defaults" $defaults "given" . "path" "xxx.resources")) -}}
|
||||
{{- include "xxx.resources" $merged -}}
|
||||
{{- end -}}
|
||||
@@ -24,7 +24,7 @@ spec:
|
||||
spec:
|
||||
automountServiceAccountToken: false
|
||||
securityContext:
|
||||
{{- toYaml .Values.xxx.securityContext.pod | nindent 8 }}
|
||||
{{- include "xxx.podSecurityContext" .Values.xxx.securityContext | nindent 8 }}
|
||||
containers:
|
||||
- name: {{ .Release.Name }}-{{ .Chart.Name }}-deployment
|
||||
image: "registry/image:{{ .Chart.AppVersion }}"
|
||||
@@ -52,14 +52,19 @@ spec:
|
||||
{{- end }}
|
||||
ports:
|
||||
{{- toYaml .Values.xxx.ports | nindent 12 }}
|
||||
# Probes, resources and both security contexts go through the
|
||||
# null-safe helpers (#99): an erased block means "chart defaults
|
||||
# apply" instead of a vanished probe or an unhardened container.
|
||||
# Never wrap these in an "if" - a guard hides the erased case
|
||||
# completely instead of rendering a visible null.
|
||||
livenessProbe:
|
||||
{{- toYaml .Values.xxx.livenessProbe | nindent 12 }}
|
||||
{{- include "xxx.livenessProbe" .Values.xxx.livenessProbe | nindent 12 }}
|
||||
readinessProbe:
|
||||
{{- toYaml .Values.xxx.readinessProbe | nindent 12 }}
|
||||
{{- include "xxx.readinessProbe" .Values.xxx.readinessProbe | nindent 12 }}
|
||||
startupProbe:
|
||||
{{- toYaml .Values.xxx.startupProbe | nindent 12 }}
|
||||
{{- include "xxx.startupProbe" .Values.xxx.startupProbe | nindent 12 }}
|
||||
resources:
|
||||
{{- include "xxx.resources" .Values.xxx.resources | nindent 12 }}
|
||||
{{- include "xxx.effectiveResources" .Values.xxx.resources | nindent 12 }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.xxx.securityContext.container | nindent 12 }}
|
||||
{{- include "xxx.containerSecurityContext" .Values.xxx.securityContext | nindent 12 }}
|
||||
restartPolicy: Always
|
||||
@@ -25,7 +25,7 @@ spec:
|
||||
spec:
|
||||
automountServiceAccountToken: false
|
||||
securityContext:
|
||||
{{- toYaml .Values.xxx.securityContext.pod | nindent 8 }}
|
||||
{{- include "xxx.podSecurityContext" .Values.xxx.securityContext | nindent 8 }}
|
||||
containers:
|
||||
- name: {{ .Release.Name }}-{{ .Chart.Name }}-sfs
|
||||
image: "registry/image:{{ .Chart.AppVersion }}"
|
||||
@@ -53,14 +53,19 @@ spec:
|
||||
{{- end }}
|
||||
ports:
|
||||
{{- toYaml .Values.xxx.ports | nindent 12 }}
|
||||
# Probes, resources and both security contexts go through the
|
||||
# null-safe helpers (#99): an erased block means "chart defaults
|
||||
# apply" instead of a vanished probe or an unhardened container.
|
||||
# Never wrap these in an "if" - a guard hides the erased case
|
||||
# completely instead of rendering a visible null.
|
||||
livenessProbe:
|
||||
{{- toYaml .Values.xxx.livenessProbe | nindent 12 }}
|
||||
{{- include "xxx.livenessProbe" .Values.xxx.livenessProbe | nindent 12 }}
|
||||
readinessProbe:
|
||||
{{- toYaml .Values.xxx.readinessProbe | nindent 12 }}
|
||||
{{- include "xxx.readinessProbe" .Values.xxx.readinessProbe | nindent 12 }}
|
||||
startupProbe:
|
||||
{{- toYaml .Values.xxx.startupProbe | nindent 12 }}
|
||||
{{- include "xxx.startupProbe" .Values.xxx.startupProbe | nindent 12 }}
|
||||
resources:
|
||||
{{- include "xxx.resources" .Values.xxx.resources | nindent 12 }}
|
||||
{{- include "xxx.effectiveResources" .Values.xxx.resources | nindent 12 }}
|
||||
securityContext:
|
||||
{{- toYaml .Values.xxx.securityContext.container | nindent 12 }}
|
||||
{{- include "xxx.containerSecurityContext" .Values.xxx.securityContext | nindent 12 }}
|
||||
restartPolicy: Always
|
||||
@@ -0,0 +1,192 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft-07/schema#",
|
||||
"title": "xxx values",
|
||||
"description": "Reference values schema (issue #68). Copy this file alongside the rest of template-chart and replace every xxx. Two rules carry the whole idea: additionalProperties is 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; and the objects that go verbatim into the Kubernetes pod spec (probes, security contexts, global, free-form annotations) stay open, because the chart does not interpret their contents and cannot judge which keys are meaningful. The hardening, probe and resources blocks additionally accept null - see the note on that in the definitions below.",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"global": {
|
||||
"description": "Helm's conventional cross-chart values. Unused by this chart, kept open so an umbrella install cannot break on it.",
|
||||
"type": "object"
|
||||
},
|
||||
"scaleDown": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"secrets": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"xxxSecretRef": {
|
||||
"description": "op:// item path. Name the key exactly as the template reads it - a plausible abbreviation is a dead key, and this schema is what turns it into a named error instead of a missing secret.",
|
||||
"type": ["string", "null"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"xxx": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"replicas": {
|
||||
"type": "integer",
|
||||
"minimum": 0
|
||||
},
|
||||
"resources": {
|
||||
"$ref": "#/definitions/resources"
|
||||
},
|
||||
"livenessProbe": {
|
||||
"$ref": "#/definitions/probe"
|
||||
},
|
||||
"readinessProbe": {
|
||||
"$ref": "#/definitions/probe"
|
||||
},
|
||||
"startupProbe": {
|
||||
"$ref": "#/definitions/probe"
|
||||
},
|
||||
"securityContext": {
|
||||
"$ref": "#/definitions/securityContext"
|
||||
},
|
||||
"ports": {
|
||||
"description": "Rendered verbatim as the container's ports list; kept open because the chart does not interpret the entries.",
|
||||
"type": ["array", "null"]
|
||||
},
|
||||
"env": {
|
||||
"$ref": "#/definitions/env"
|
||||
}
|
||||
}
|
||||
},
|
||||
"storage": {
|
||||
"description": "The data PVC. Deliberately NOT null-safe: an erased block yields an invalid PVC, which fails loudly. Issue #99 covers only the silent class - an error that shows itself needs no fallback, and every extra bit of template logic has to be read by someone.",
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"amount": {
|
||||
"type": ["string", "null"]
|
||||
},
|
||||
"storageClass": {
|
||||
"type": ["string", "null"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"ingress": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"enabled": {
|
||||
"description": "Gates the whole Ingress template (issue #93). Whether switching it off also frees domain depends on the chart: if anything outside the Ingress template reads ingress.domain, that read needs its own required() and the value stays mandatory. Check, do not assume (guideline 1).",
|
||||
"type": "boolean"
|
||||
},
|
||||
"clusterIssuer": {
|
||||
"type": ["string", "null"]
|
||||
},
|
||||
"domain": {
|
||||
"type": ["string", "null"]
|
||||
},
|
||||
"className": {
|
||||
"type": ["string", "null"]
|
||||
},
|
||||
"annotations": {
|
||||
"description": "Extra Ingress annotations, merged with the cert-manager annotation the chart always sets. Free-form keys by nature, so this object stays open.",
|
||||
"type": "object"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"definitions": {
|
||||
"resources": {
|
||||
"description": "May be null / empty: the chart then falls back to its default requests and computed limits (issue #99) instead of rendering a container without resource accounting.",
|
||||
"type": ["object", "null"],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"limitFactor": {
|
||||
"type": "number",
|
||||
"exclusiveMinimum": 0
|
||||
},
|
||||
"requests": {
|
||||
"$ref": "#/definitions/resourceList"
|
||||
},
|
||||
"limits": {
|
||||
"$ref": "#/definitions/resourceList"
|
||||
}
|
||||
}
|
||||
},
|
||||
"resourceList": {
|
||||
"description": "Both spellings of the ephemeral-storage key are accepted because the resources helper normalizes camelCase to the Kubernetes key.",
|
||||
"type": ["object", "null"],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"cpu": {
|
||||
"type": ["string", "number", "null"]
|
||||
},
|
||||
"memory": {
|
||||
"type": ["string", "number", "null"]
|
||||
},
|
||||
"ephemeral-storage": {
|
||||
"type": ["string", "number", "null"]
|
||||
},
|
||||
"ephemeralStorage": {
|
||||
"type": ["string", "number", "null"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"env": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["name"],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"value": {
|
||||
"type": "string"
|
||||
},
|
||||
"valueFrom": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"secretKeyRef": {
|
||||
"$ref": "#/definitions/keyRef"
|
||||
},
|
||||
"configMapKeyRef": {
|
||||
"$ref": "#/definitions/keyRef"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"keyRef": {
|
||||
"type": "object",
|
||||
"additionalProperties": false,
|
||||
"required": ["name", "key"],
|
||||
"properties": {
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"key": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"securityContext": {
|
||||
"description": "May be null / empty at any level: the chart then falls back to its hardening defaults (issue #99) instead of rendering an unhardened workload. Where a chart deviates from the repo hardening standard on purpose, its fallback reproduces the DEVIATION, not the standard (guideline 4).",
|
||||
"type": ["object", "null"],
|
||||
"additionalProperties": false,
|
||||
"properties": {
|
||||
"pod": {
|
||||
"description": "Merged onto the chart's pod hardening defaults and rendered as the pod's securityContext; kept open because the chart does not interpret the individual fields.",
|
||||
"type": ["object", "null"]
|
||||
},
|
||||
"container": {
|
||||
"description": "Merged onto the chart's container hardening defaults and rendered as the container's securityContext; kept open because the chart does not interpret the individual fields.",
|
||||
"type": ["object", "null"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"probe": {
|
||||
"description": "Merged onto the chart's probe defaults and rendered as a container probe; kept open because the chart does not interpret the individual fields. May be null / empty, which means the defaults apply (issue #99) rather than the probe disappearing. The chart's default MUST carry the probe's context - port name, Host header, exec command - not just its timings (guideline 5).",
|
||||
"type": ["object", "null"]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -63,8 +63,13 @@ xxx:
|
||||
protocol: TCP
|
||||
name: http
|
||||
env:
|
||||
# Reference for guideline 1: ingress.domain is read HERE, outside the
|
||||
# Ingress template, so it needs its own required(). Without it, switching
|
||||
# the Ingress off via ingress.enabled would render an empty value and the
|
||||
# workload would start with a broken address - silently. Copy this shape
|
||||
# whenever a chart uses the domain for anything but the Ingress host.
|
||||
- name: NORMAL_ENV
|
||||
value: "{{ .Values.ingress.domain }}"
|
||||
value: '{{ required "A Domain/Host must be provided (ingress.domain)" .Values.ingress.domain }}'
|
||||
- name: ENV_FROM_SECRET
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
@@ -81,6 +86,10 @@ storage:
|
||||
storageClass: null
|
||||
|
||||
ingress:
|
||||
# Gates the whole Ingress template. Note that ingress.domain is ALSO read by
|
||||
# the env block above, so it stays required even with the Ingress switched
|
||||
# off; only clusterIssuer becomes unnecessary. Check this per chart instead
|
||||
# of assuming either way (guideline 1).
|
||||
enabled: true
|
||||
clusterIssuer: null
|
||||
domain: null
|
||||
|
||||
Reference in new issue
Block a user