Files
terdut-operator/charts/terdut-operator/templates/terdutserver/terdutserver.yaml
T
Niklas Ye 6a699d4341 Let TerdutServer customize its pod, and never manage its own ingress
spec.pod (api/v1alpha1/terdutserver_types.go): annotations, nodeSelector,
tolerations, affinity, topologySpreadConstraints, resources, pod and
container securityContext, serviceAccountName, extraEnv/extraEnvFrom,
extraVolumes/extraVolumeMounts, imagePullSecrets, and an optional
disruptionBudget. All direct corev1 passthrough -- no wrapper types buy
anything for any of these, matching how CloudNativePG and the Zalando
postgres-operator both expose the same knobs, and matching this repo's
own SweeperSpec precedent ("wrap only when a round-trip through a
different type buys something"). affinity is pure user-supplied
passthrough, not a toggle-plus-generated-default the way a multi-replica
cluster operator's pod anti-affinity usually is: this operator never
auto-generates one, since spec.replicas above 1 isn't a supported
topology (the sweeper/notifier singleton constraint). Considered and
declined for this round: priorityClassName, pod labels beyond
annotations, and a HorizontalPodAutoscaler -- the last of those would
directly contradict the singleton constraint above.

disruptionBudget is the one field here that isn't a plain PodTemplateSpec
knob: when set, the controller now reconciles a PodDisruptionBudget
selecting the TerdutServer's own pods (new terdutserver_pdb.go); clearing
it deletes any it previously created. New RBAC marker on
poddisruptionbudgets to match.

Driven by a public-release pass: looking past this project's own use case
at what a mature, general-purpose operator CRD exposes here (researched
against Zalando postgres-operator and CloudNativePG specifically), not
just the fields this install happened to need.

Separately, and found while answering a question about exposing
TerdutServer through Istio instead of Gateway API: spec.networking's own
doc comment quietly promised a Gateway API HTTPRoute this operator would
build eventually ("a near-term follow-up, not deferred"). That promise is
wrong for a public release -- an operator managing someone's ingress
mechanism for them is a worse default than not touching it at all, and a
surprise HTTPRoute appearing once that follow-up eventually landed would
have been exactly backwards for an Istio (or plain-Ingress, or
intentionally-unexposed) install. Made the non-goal explicit and
permanent instead (DESIGN.md §1), removed the dead `gatewayListener`
field it was the only consumer of (zero runtime call sites anywhere --
setting it already had no effect, so this is a schema cleanup, not a
behavior change), and corrected ROADMAP.md's framing. hostname/servicePort
stay: both are live (TERDUT_PUBLIC_URL, container/Service port), this
operator just never acts on hostname for exposure. Added
examples/networking (Gateway API HTTPRoute, Istio VirtualService) showing
how to expose the plain ClusterIP Service the operator already creates --
outside the operator itself, as illustrations, not as something
examples/demo applies automatically.

No new terdut-server version requirement: both changes are CRD/controller-
only, nothing about the API this operator's bootstrap flow depends on
changed.
2026-10-02 18:50:38 +02:00

59 lines
2.4 KiB
YAML

{{/*
Optional: one TerdutServer CR from values.yaml (DESIGN.md §10's "helm
install and get a server" path). Off by default -- see values.yaml's own
terdutServer block for the full shape and api/v1alpha1/terdutserver_types.go
for what each field validates.
*/}}
{{- if .Values.terdutServer.enabled }}
apiVersion: terdut.ryuvia.com/v1alpha1
kind: TerdutServer
metadata:
name: {{ .Values.terdutServer.name | default (include "terdut-operator.fullname" .) }}
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/name: {{ include "terdut-operator.name" . }}
helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
app.kubernetes.io/instance: {{ .Release.Name }}
spec:
image:
repository: {{ required "terdutServer.image.repository is required when terdutServer.enabled" .Values.terdutServer.image.repository }}
tag: {{ required "terdutServer.image.tag is required when terdutServer.enabled" .Values.terdutServer.image.tag | quote }}
replicas: {{ .Values.terdutServer.replicas }}
networking:
hostname: {{ required "terdutServer.networking.hostname is required when terdutServer.enabled" .Values.terdutServer.networking.hostname | quote }}
servicePort: {{ .Values.terdutServer.networking.servicePort }}
# Not re-validated here as dsn-xor-postgresClusterRef (api/v1alpha1's own
# CEL rule on DatabaseSpec is the authority, same v1 stance as every
# other cross-field check in this operator -- DESIGN.md §13: no
# admission webhooks, CEL-only validation). This chart just has to pass
# the block through faithfully.
database:
{{- required "terdutServer.database (dsn or postgresClusterRef) is required when terdutServer.enabled" .Values.terdutServer.database | toYaml | nindent 4 }}
{{- with .Values.terdutServer.sweeper }}
sweeper:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.terdutServer.deadman }}
deadman:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.terdutServer.notify }}
notify:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.terdutServer.oidc }}
oidc:
{{- toYaml . | nindent 4 }}
{{- end }}
passwordLogin: {{ .Values.terdutServer.passwordLogin }}
{{- with .Values.terdutServer.allowedTeams }}
allowedTeams:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.terdutServer.pod }}
pod:
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}