Stage 5: installer chart + release infra, kind e2e pass through the chart
Release / test (push) Successful in 2m48s
CI / chart (push) Successful in 1s
CI / security (push) Successful in 1m3s
CI / test (push) Successful in 2m5s
Release / chart (push) Successful in 4s
Release / image (push) Successful in 7m6s
Release / scan-image (push) Failing after 33s

Chart (charts/terdut-operator) generated via kubebuilder's own helm/v2-alpha
plugin from config/'s kustomize output -- CRDs + manager Deployment/RBAC
come from the same markers every other stage already generates, one source
of truth. Hand-added on top: the optional terdutServer values block
(DESIGN.md §10's "helm install and get a server" path, off by default) and
the release-skill plumbing -- .release.conf, release-vars/helm-lint/push/
helm-package/helm-push/release Makefile targets, .gitea/workflows/release.yaml
(test -> image/chart -> scan-image) -- mirroring terdut-server's own shape
(registry/namespace convention, multi-arch buildx push, trivy/govulncheck/
gitleaks scans). ci.yaml gains security and chart jobs to match.

Two real issues caught while wiring this, fixed before either shipped:
- Dockerfile's builder stage didn't pin --platform=$BUILDPLATFORM, which
  would have made a multi-arch release build fail outright on this org's
  runners (no binfmt registration) -- same fix terdut-server's own
  Dockerfile already needed for the same reason.
- govulncheck found one real, reachable finding: google.golang.org/grpc
  v1.82.1 (transitive via controller-runtime's otel exporter), fixed by
  bumping to v1.83.1.

Full golden-path kind e2e pass, this time through `helm install` rather than
raw kustomize: TerdutServer (real terdut-server v0.33.0 image) -> TerdutTeam
-> one of each child kind, each confirmed Ready and then independently
confirmed against terdut-server's own API from inside the cluster (not just
the operator's own status). Deleted every CR in reverse order and confirmed
server-side cleanup the same independent way for all three child kinds, the
team, and the server. No new bugs found -- Stage 1's own kind pass already
caught what a real cluster catches that envtest can't.

Also dropped the kubebuilder helm plugin's default .github/workflows/
scaffold, same as Stage 0 already did for the main scaffold: this org runs
on Gitea, not GitHub.

Not done here, deliberately: an actual tagged release. release-preflight
found no terdut-operator/ entry under Ryuvia/charts yet to bump -- that
one-time wrapper bootstrap is a decision about deploying this operator for
real, not a side effect of finishing this stage.

make fmt lint test helm-lint build all clean.
This commit is contained in:
Niklas Ye
2026-10-01 14:47:10 +02:00
parent 048f4448c4
commit b4ccdb09d5
50 changed files with 3190 additions and 22 deletions
+25
View File
@@ -0,0 +1,25 @@
# Patterns to ignore when building Helm packages.
# Operating system files
.DS_Store
# Version control directories
.git/
.gitignore
.bzr/
.hg/
.hgignore
.svn/
# Backup and temporary files
*.swp
*.tmp
*.bak
*.orig
*~
# IDE and editor-related files
.idea/
.vscode/
# Helm chart artifacts
dist/chart/*.tgz
+20
View File
@@ -0,0 +1,20 @@
apiVersion: v2
name: terdut-operator
description: Installs terdut-operator (CRDs + controller) for terdut-server, and optionally one TerdutServer CR
type: application
# These fields decide nothing: `make helm-package` passes --version and
# --app-version from the release tag (same reasoning as terdut-server's own
# chart). They're for whoever reads the tree before a tag exists.
version: 0.1.0
appVersion: "v0.1.0"
keywords:
- kubernetes
- operator
- terdut
home: https://git.ryuvia.com/niklas/terdut-operator
annotations:
kubebuilder.io/generated-by: kubebuilder
@@ -0,0 +1,15 @@
Thank you for installing {{ .Chart.Name }}.
Your release is named {{ .Release.Name }}.
The controller and CRDs have been installed in namespace {{ .Release.Namespace }}.
To verify the installation:
kubectl get pods -n {{ .Release.Namespace }}
kubectl get customresourcedefinitions
To learn more about the release, try:
$ helm status {{ .Release.Name }} -n {{ .Release.Namespace }}
$ helm get all {{ .Release.Name }} -n {{ .Release.Namespace }}
@@ -0,0 +1,63 @@
{{/*
Expand the name of the chart.
*/}}
{{- define "terdut-operator.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
If release name contains chart name it will be used as a full name.
*/}}
{{- define "terdut-operator.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Namespace for generated references.
Always uses the Helm release namespace.
*/}}
{{- define "terdut-operator.namespaceName" -}}
{{- .Release.Namespace }}
{{- end }}
{{/*
Resource name with proper truncation for Kubernetes 63-character limit.
Takes a dict with:
- .suffix: Resource name suffix (e.g., "metrics", "webhook")
- .context: Template context (root context with .Values, .Release, etc.)
Dynamically calculates safe truncation to ensure total name length <= 63 chars.
*/}}
{{- define "terdut-operator.resourceName" -}}
{{- $fullname := include "terdut-operator.fullname" .context }}
{{- $suffix := .suffix }}
{{- $maxLen := sub 62 (len $suffix) | int }}
{{- if gt (len $fullname) $maxLen }}
{{- printf "%s-%s" (trunc $maxLen $fullname | trimSuffix "-") $suffix | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" $fullname $suffix | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{/*
ServiceAccount name to use.
When enabled, use the chart's ServiceAccount name.
When disabled, serviceAccount.name must be set; use "default" to pick the namespace default ServiceAccount.
*/}}
{{- define "terdut-operator.serviceAccountName" -}}
{{- if .Values.serviceAccount.enabled }}
{{- include "terdut-operator.resourceName" (dict "suffix" "controller-manager" "context" .) }}
{{- else }}
{{- required "serviceAccount.name is required when serviceAccount.enabled=false (set name: default explicitly to use the namespace default ServiceAccount)" .Values.serviceAccount.name }}
{{- end }}
{{- end }}
@@ -0,0 +1,198 @@
{{- if .Values.crd.enabled }}
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
{{- if .Values.crd.keep }}
"helm.sh/resource-policy": keep
{{- end }}
controller-gen.kubebuilder.io/version: v0.22.0
name: terdutalertsources.terdut.ryuvia.com
spec:
group: terdut.ryuvia.com
names:
kind: TerdutAlertSource
listKind: TerdutAlertSourceList
plural: terdutalertsources
singular: terdutalertsource
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .spec.teamRef.name
name: Team
type: string
- jsonPath: .status.integrationID
name: IntegrationID
type: integer
- jsonPath: .status.conditions[?(@.type=="Ready")].status
name: Ready
type: string
- jsonPath: .status.conditions[?(@.type=="Ready")].reason
name: Reason
type: string
name: v1alpha1
schema:
openAPIV3Schema:
description: TerdutAlertSource is the Schema for the terdutalertsources API
properties:
apiVersion:
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
spec:
description: spec defines the desired state of TerdutAlertSource
properties:
kind:
default: alertmanager
description: |-
kind is the alert source type. Only "alertmanager" is supported
today, mirroring terdut-server's own CHECK constraint on
integrations.kind (internal/db/migrations/003_teams.sql) --
confirmed against source, not assumed. Changing it after the
integration already exists rotates the webhook key (DESIGN.md §5's
reconciliation table): the old one is deleted and a fresh one
created, which breaks whatever sends to the old URL until the new
Secret is picked up.
enum:
- alertmanager
type: string
name:
description: |-
name is this source's own display name server-side -- distinct from
this object's own metadata.name. POST
/api/teams/{teamID}/integrations {"name": ...} at creation, and what
PATCH renames thereafter; renaming never rotates the webhook key.
minLength: 1
type: string
teamRef:
description: |-
TerdutTeamRef names the TerdutTeam this resource belongs to. Always
same-namespace as the CR itself (DESIGN.md §1: only TerdutTeam.spec.serverRef
crosses namespaces in v1) -- no namespace field, unlike TerdutServerRef.
properties:
name:
minLength: 1
type: string
required:
- name
type: object
required:
- name
- teamRef
type: object
status:
description: status defines the observed state of TerdutAlertSource
properties:
conditions:
items:
description: Condition contains details for one aspect of the current
state of this API Resource.
properties:
lastTransitionTime:
description: |-
lastTransitionTime is the last time the condition transitioned from one status to another.
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
format: date-time
type: string
message:
description: |-
message is a human readable message indicating details about the transition.
This may be an empty string.
maxLength: 32768
type: string
observedGeneration:
description: |-
observedGeneration represents the .metadata.generation that the condition was set based upon.
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
with respect to the current state of the instance.
format: int64
minimum: 0
type: integer
reason:
description: |-
reason contains a programmatic identifier indicating the reason for the condition's last transition.
Producers of specific condition types may define expected values and meanings for this field,
and whether the values are considered a guaranteed API.
The value should be a CamelCase string.
This field may not be empty.
maxLength: 1024
minLength: 1
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
type: string
status:
description: status of the condition, one of True, False, Unknown.
enum:
- "True"
- "False"
- Unknown
type: string
type:
description: type of condition in CamelCase or in foo.example.com/CamelCase.
maxLength: 316
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
type: string
required:
- lastTransitionTime
- message
- reason
- status
- type
type: object
type: array
x-kubernetes-list-map-keys:
- type
x-kubernetes-list-type: map
integrationID:
description: integrationID is the server-side id.
format: int64
type: integer
lastAppliedKind:
description: |-
lastAppliedKind is the kind the currently-live integration was
actually created with -- compared against spec.kind on every
reconcile to detect the one spec change that requires
delete-and-recreate (DESIGN.md §5), since terdut-server's own API has
no way to read a live integration's kind back for comparison.
type: string
observedGeneration:
format: int64
type: integer
webhookURLSecretRef:
description: |-
webhookURLSecretRef names the generated Secret holding "url" and
"key" -- the integration's webhook address and credential, shown by
terdut-server's API exactly once, at creation (DESIGN.md §4.5), and
never re-readable afterward, including from this status. Lives in
this CR's own namespace with a plain OwnerReference (§7) -- unlike
TerdutServer/TerdutTeam's credential Secrets, this one never crosses
namespaces, so no finalizer cleanup is needed for it specifically.
properties:
name:
description: name is the Secret's name.
minLength: 1
type: string
required:
- name
type: object
type: object
required:
- spec
type: object
served: true
storage: true
subresources:
status: {}
{{- end }}
@@ -0,0 +1,184 @@
{{- if .Values.crd.enabled }}
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
{{- if .Values.crd.keep }}
"helm.sh/resource-policy": keep
{{- end }}
controller-gen.kubebuilder.io/version: v0.22.0
name: terdutdeadmanswitches.terdut.ryuvia.com
spec:
group: terdut.ryuvia.com
names:
kind: TerdutDeadmanSwitch
listKind: TerdutDeadmanSwitchList
plural: terdutdeadmanswitches
singular: terdutdeadmanswitch
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .spec.teamRef.name
name: Team
type: string
- jsonPath: .status.switchID
name: SwitchID
type: integer
- jsonPath: .status.conditions[?(@.type=="Ready")].status
name: Ready
type: string
- jsonPath: .status.conditions[?(@.type=="Ready")].reason
name: Reason
type: string
name: v1alpha1
schema:
openAPIV3Schema:
description: TerdutDeadmanSwitch is the Schema for the terdutdeadmanswitches
API
properties:
apiVersion:
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
spec:
description: spec defines the desired state of TerdutDeadmanSwitch
properties:
matcher:
description: |-
matcher names the alerts this switch watches, e.g.
"alertname=Watchdog,cluster=prod". One matcher per switch -- add
another TerdutDeadmanSwitch instead of separating with ";"
(terdut-server's own restriction, mirrored here so a bad spec is
rejected at apply time).
minLength: 1
type: string
x-kubernetes-validations:
- message: 'one matcher per switch: add another TerdutDeadmanSwitch
instead of separating with ;'
rule: '!self.contains('';'')'
name:
description: |-
name is optional, same as the API: left empty, terdut-server derives
it from matcher's own canonical form, and that's what the
idempotent-create lookup matches against too.
type: string
severity:
default: critical
enum:
- critical
- error
- warning
- info
type: string
teamRef:
description: |-
TerdutTeamRef names the TerdutTeam this resource belongs to. Always
same-namespace as the CR itself (DESIGN.md §1: only TerdutTeam.spec.serverRef
crosses namespaces in v1) -- no namespace field, unlike TerdutServerRef.
properties:
name:
minLength: 1
type: string
required:
- name
type: object
timeout:
description: timeout is a Go duration string, e.g. "15m".
minLength: 1
type: string
required:
- matcher
- teamRef
- timeout
type: object
status:
description: status defines the observed state of TerdutDeadmanSwitch
properties:
conditions:
items:
description: Condition contains details for one aspect of the current
state of this API Resource.
properties:
lastTransitionTime:
description: |-
lastTransitionTime is the last time the condition transitioned from one status to another.
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
format: date-time
type: string
message:
description: |-
message is a human readable message indicating details about the transition.
This may be an empty string.
maxLength: 32768
type: string
observedGeneration:
description: |-
observedGeneration represents the .metadata.generation that the condition was set based upon.
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
with respect to the current state of the instance.
format: int64
minimum: 0
type: integer
reason:
description: |-
reason contains a programmatic identifier indicating the reason for the condition's last transition.
Producers of specific condition types may define expected values and meanings for this field,
and whether the values are considered a guaranteed API.
The value should be a CamelCase string.
This field may not be empty.
maxLength: 1024
minLength: 1
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
type: string
status:
description: status of the condition, one of True, False, Unknown.
enum:
- "True"
- "False"
- Unknown
type: string
type:
description: type of condition in CamelCase or in foo.example.com/CamelCase.
maxLength: 316
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
type: string
required:
- lastTransitionTime
- message
- reason
- status
- type
type: object
type: array
x-kubernetes-list-map-keys:
- type
x-kubernetes-list-type: map
observedGeneration:
format: int64
type: integer
switchID:
description: switchID is the server-side id.
format: int64
type: integer
type: object
required:
- spec
type: object
served: true
storage: true
subresources:
status: {}
{{- end }}
@@ -0,0 +1,195 @@
{{- if .Values.crd.enabled }}
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
{{- if .Values.crd.keep }}
"helm.sh/resource-policy": keep
{{- end }}
controller-gen.kubebuilder.io/version: v0.22.0
name: terdutescalationrules.terdut.ryuvia.com
spec:
group: terdut.ryuvia.com
names:
kind: TerdutEscalationRule
listKind: TerdutEscalationRuleList
plural: terdutescalationrules
singular: terdutescalationrule
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .spec.teamRef.name
name: Team
type: string
- jsonPath: .status.conditions[?(@.type=="Ready")].status
name: Ready
type: string
- jsonPath: .status.conditions[?(@.type=="Ready")].reason
name: Reason
type: string
name: v1alpha1
schema:
openAPIV3Schema:
description: TerdutEscalationRule is the Schema for the terdutescalationrules
API
properties:
apiVersion:
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
spec:
description: spec defines the desired state of TerdutEscalationRule
properties:
fallbackTopic:
type: string
levels:
items:
description: |-
EscalationLevel is one rung of the ladder: how long to wait, and who to
page if nobody's acknowledged by then.
properties:
targets:
items:
description: |-
EscalationTarget is one page within a level. username is required iff
kind is "user" (terdut-server's own validation, internal/api/escalation.go's
handleSetEscalation -- mirrored here as a CEL rule so a bad spec is
rejected at apply time, not discovered on the next failed PUT).
properties:
kind:
description: EscalationTargetKind is who one rung of the
ladder pages.
enum:
- oncall
- user
type: string
username:
type: string
required:
- kind
type: object
x-kubernetes-validations:
- message: username is required when kind is user
rule: self.kind != 'user' || has(self.username)
- message: username must not be set when kind is oncall
rule: self.kind != 'oncall' || !has(self.username)
minItems: 1
type: array
timeout:
description: timeout is a Go duration string, e.g. "5m".
minLength: 1
type: string
required:
- targets
- timeout
type: object
minItems: 1
type: array
repeatCount:
format: int64
maximum: 10
minimum: 0
type: integer
teamRef:
description: |-
TerdutTeamRef names the TerdutTeam this resource belongs to. Always
same-namespace as the CR itself (DESIGN.md §1: only TerdutTeam.spec.serverRef
crosses namespaces in v1) -- no namespace field, unlike TerdutServerRef.
properties:
name:
minLength: 1
type: string
required:
- name
type: object
required:
- levels
- teamRef
type: object
status:
description: status defines the observed state of TerdutEscalationRule
properties:
conditions:
items:
description: Condition contains details for one aspect of the current
state of this API Resource.
properties:
lastTransitionTime:
description: |-
lastTransitionTime is the last time the condition transitioned from one status to another.
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
format: date-time
type: string
message:
description: |-
message is a human readable message indicating details about the transition.
This may be an empty string.
maxLength: 32768
type: string
observedGeneration:
description: |-
observedGeneration represents the .metadata.generation that the condition was set based upon.
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
with respect to the current state of the instance.
format: int64
minimum: 0
type: integer
reason:
description: |-
reason contains a programmatic identifier indicating the reason for the condition's last transition.
Producers of specific condition types may define expected values and meanings for this field,
and whether the values are considered a guaranteed API.
The value should be a CamelCase string.
This field may not be empty.
maxLength: 1024
minLength: 1
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
type: string
status:
description: status of the condition, one of True, False, Unknown.
enum:
- "True"
- "False"
- Unknown
type: string
type:
description: type of condition in CamelCase or in foo.example.com/CamelCase.
maxLength: 316
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
type: string
required:
- lastTransitionTime
- message
- reason
- status
- type
type: object
type: array
x-kubernetes-list-map-keys:
- type
x-kubernetes-list-type: map
observedGeneration:
format: int64
type: integer
type: object
required:
- spec
type: object
served: true
storage: true
subresources:
status: {}
{{- end }}
@@ -0,0 +1,457 @@
{{- if .Values.crd.enabled }}
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
{{- if .Values.crd.keep }}
"helm.sh/resource-policy": keep
{{- end }}
controller-gen.kubebuilder.io/version: v0.22.0
name: terdutservers.terdut.ryuvia.com
spec:
group: terdut.ryuvia.com
names:
kind: TerdutServer
listKind: TerdutServerList
plural: terdutservers
singular: terdutserver
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .spec.replicas
name: Replicas
type: integer
- jsonPath: .status.conditions[?(@.type=="Ready")].status
name: Ready
type: string
- jsonPath: .status.conditions[?(@.type=="Ready")].reason
name: Reason
type: string
name: v1alpha1
schema:
openAPIV3Schema:
description: TerdutServer is the Schema for the terdutservers API
properties:
apiVersion:
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
spec:
description: spec defines the desired state of TerdutServer
properties:
allowedTeams:
description: |-
allowedTeams gates cross-namespace TerdutTeams (DESIGN.md §4.6).
Unused until TerdutTeam exists (ROADMAP.md Stage 2); present now so
this CRD's schema doesn't need a breaking change to grow it later.
properties:
namespaces:
description: |-
AllowedTeamsNamespaces gates which namespaces a TerdutTeam may resolve a
cross-namespace serverRef into this TerdutServer from (DESIGN.md §4.6).
Same-namespace TerdutTeams are always allowed, regardless of this field.
Modeled on Gateway API's Gateway.spec.allowedListeners.namespaces.
properties:
from:
default: None
description: |-
from selects which namespaces may attach. Same is equivalent to None in
effect (same-namespace is unrestricted either way) but kept for parity
with the upstream enum this mirrors, and to make the policy
self-documenting in a diff.
enum:
- None
- Same
- All
- Selector
type: string
selector:
description: |-
selector is required, and only meaningful, when from is Selector: a
standard label selector over Namespace objects.
properties:
matchExpressions:
description: matchExpressions is a list of label selector
requirements. The requirements are ANDed.
items:
description: |-
A label selector requirement is a selector that contains values, a key, and an operator that
relates the key and values.
properties:
key:
description: key is the label key that the selector
applies to.
type: string
operator:
description: |-
operator represents a key's relationship to a set of values.
Valid operators are In, NotIn, Exists and DoesNotExist.
type: string
values:
description: |-
values is an array of string values. If the operator is In or NotIn,
the values array must be non-empty. If the operator is Exists or DoesNotExist,
the values array must be empty. This array is replaced during a strategic
merge patch.
items:
type: string
type: array
x-kubernetes-list-type: atomic
required:
- key
- operator
type: object
type: array
x-kubernetes-list-type: atomic
matchLabels:
additionalProperties:
type: string
description: |-
matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
map is equivalent to an element of matchExpressions, whose key field is "key", the
operator is "In", and the values array contains only "value". The requirements are ANDed.
type: object
type: object
x-kubernetes-map-type: atomic
type: object
type: object
database:
description: |-
DatabaseSpec is the Postgres connection this TerdutServer uses. Exactly
one of dsn or postgresClusterRef must be set (DESIGN.md §8) — this
operator provisions no database either way, only wires up one that
exists.
properties:
dsn:
description: |-
dsn is a DSN with no password in it, e.g.
"postgres://terdut@terdut-postgres:5432/terdut?sslmode=require" --
mutually exclusive with postgresClusterRef.
type: string
passwordSecretRef:
description: |-
passwordSecretRef is where PGPASSWORD comes from for the dsn path.
pgx falls back to libpq's environment variables for anything the DSN
omits, so the password never appears in the DSN string itself. Unused
on the postgresClusterRef path -- the Zalando-generated Secret is
wired in directly instead.
properties:
key:
description: key is the data key inside the Secret holding
the raw value.
minLength: 1
type: string
name:
description: name is the Secret's name.
minLength: 1
type: string
required:
- key
- name
type: object
postgresClusterRef:
description: |-
postgresClusterRef names a Zalando postgres-operator CR instead of a
plain DSN -- mutually exclusive with dsn.
properties:
name:
minLength: 1
type: string
required:
- name
type: object
type: object
x-kubernetes-validations:
- message: exactly one of dsn or postgresClusterRef must be set
rule: '(has(self.dsn) ? 1 : 0) + (has(self.postgresClusterRef) ?
1 : 0) == 1'
deadman:
description: |-
DeadmanSpec controls dead man's switch alerts. Matchers/Timeout/Severity
map straight to TERDUT_DEADMAN_MATCHERS/TERDUT_DEADMAN_TIMEOUT/
TERDUT_DEADMAN_SEVERITY.
properties:
matchers:
type: string
severity:
type: string
timeout:
type: string
type: object
image:
description: ImageSpec is the terdut-server image to run.
properties:
repository:
minLength: 1
type: string
tag:
minLength: 1
type: string
required:
- repository
- tag
type: object
networking:
description: |-
NetworkingSpec is how this TerdutServer is reached from outside the
cluster.
hostname/gatewayListener describe the intended Gateway API HTTPRoute
(matching charts/terdut-server's own templates/httpproxy.yaml, despite its
name — that chart carries a Gateway API HTTPRoute, not a Contour
HTTPProxy), but creating that HTTPRoute isn't implemented yet: it needs
the Gateway API types as a new dependency, and nothing about proving a
TerdutServer boots and bootstraps a real server depends on external
ingress existing. Tracked as a near-term follow-up, not deferred to a
later ROADMAP.md stage the way Deployment/database/bootstrap once were.
properties:
gatewayListener:
description: |-
gatewayListener is the HTTPRoute's sectionName once it exists. Empty
attaches to every matching listener, including plaintext HTTP.
type: string
hostname:
description: hostname the HTTPRoute will carry once it exists.
type: string
servicePort:
default: 8080
description: |-
servicePort is both the Service's port and the HTTPRoute's backend
port once it exists. Defaults to 8080, matching the chart's own
service.port default.
format: int32
type: integer
type: object
notify:
description: |-
NotifySpec controls push notifications via ntfy. Empty ntfyURL disables
notifications entirely (matches the chart's own default).
properties:
fallbackTopic:
type: string
ntfyURL:
type: string
repeatEvery:
type: string
tokenSecretRef:
description: |-
tokenSecretRef is an optional bearer token for an access-controlled
ntfy. Leave unset for an open ntfy.
properties:
key:
description: key is the data key inside the Secret holding
the raw value.
minLength: 1
type: string
name:
description: name is the Secret's name.
minLength: 1
type: string
required:
- key
- name
type: object
type: object
oidc:
description: |-
OIDCSpec controls single sign-on. Fields the chart also exposes but
DESIGN.md's spec doesn't (usernameClaim, emailClaim, groupsClaim,
trustEmail) use terdut-server's own defaults
(preferred_username/email/groups/false) rather than being added here
speculatively.
properties:
adminGroup:
type: string
allowedGroups:
items:
type: string
type: array
clientID:
type: string
clientSecretRef:
description: |-
SecretKeyRef names one data key inside a Secret. Every use of this type in
TerdutServerSpec resolves in the TerdutServer's own namespace (it's wired
straight into the Deployment's pod spec as a secretKeyRef env source,
which Kubernetes itself only allows same-namespace) -- unlike the
generated credentials Secret (DESIGN.md §6), which always lives in the
operator's own namespace and is never referenced through this type.
properties:
key:
description: key is the data key inside the Secret holding
the raw value.
minLength: 1
type: string
name:
description: name is the Secret's name.
minLength: 1
type: string
required:
- key
- name
type: object
enabled:
type: boolean
issuer:
type: string
name:
default: SSO
type: string
scopes:
default: openid profile email
type: string
sessionMaxAge:
default: 12h
type: string
type: object
passwordLogin:
default: true
description: |-
passwordLogin: whether a user may sign in, or sign up, with a
password.
type: boolean
replicas:
default: 1
description: |-
replicas. terdut-server is not horizontally-scale-tested; keep this
at its default of 1 unless you've verified otherwise -- the sweeper
and the notifier are unsynchronised singletons.
format: int32
type: integer
sweeper:
description: |-
SweeperSpec controls incident auto-resolve/archive timing. Values are
Go duration strings (e.g. "6h"), passed straight through to the
TERDUT_STALE_AFTER/TERDUT_ARCHIVE_AFTER env vars exactly as written --
not a structured metav1.Duration, since terdut-server parses them itself
and a round-trip through a different type would buy nothing.
properties:
archiveAfter:
type: string
staleAfter:
type: string
type: object
required:
- database
- image
- networking
type: object
status:
description: status defines the observed state of TerdutServer
properties:
conditions:
description: conditions represent the current state of the TerdutServer
resource.
items:
description: Condition contains details for one aspect of the current
state of this API Resource.
properties:
lastTransitionTime:
description: |-
lastTransitionTime is the last time the condition transitioned from one status to another.
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
format: date-time
type: string
message:
description: |-
message is a human readable message indicating details about the transition.
This may be an empty string.
maxLength: 32768
type: string
observedGeneration:
description: |-
observedGeneration represents the .metadata.generation that the condition was set based upon.
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
with respect to the current state of the instance.
format: int64
minimum: 0
type: integer
reason:
description: |-
reason contains a programmatic identifier indicating the reason for the condition's last transition.
Producers of specific condition types may define expected values and meanings for this field,
and whether the values are considered a guaranteed API.
The value should be a CamelCase string.
This field may not be empty.
maxLength: 1024
minLength: 1
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
type: string
status:
description: status of the condition, one of True, False, Unknown.
enum:
- "True"
- "False"
- Unknown
type: string
type:
description: type of condition in CamelCase or in foo.example.com/CamelCase.
maxLength: 316
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
type: string
required:
- lastTransitionTime
- message
- reason
- status
- type
type: object
type: array
x-kubernetes-list-map-keys:
- type
x-kubernetes-list-type: map
credentialsSecretRef:
description: |-
credentialsSecretRef is the generated instance-scoped credential
(DESIGN.md §6) -- pure output, always in the operator's own
namespace, under a fixed data key ("token"). Set only once
Bootstrapped is True.
properties:
key:
description: key is the data key inside the Secret holding the
raw value.
minLength: 1
type: string
name:
description: name is the Secret's name.
minLength: 1
type: string
required:
- key
- name
type: object
observedGeneration:
description: |-
observedGeneration is the .metadata.generation this status was last
computed against — the standard way a client (or `kubectl wait`)
tells "applied" from "seen" (DESIGN.md §7).
format: int64
type: integer
serviceName:
description: |-
serviceName is the Service this controller created for the
Deployment, so other objects can reference it without recomputing the
naming convention.
type: string
type: object
required:
- spec
type: object
served: true
storage: true
subresources:
status: {}
{{- end }}
@@ -0,0 +1,198 @@
{{- if .Values.crd.enabled }}
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
{{- if .Values.crd.keep }}
"helm.sh/resource-policy": keep
{{- end }}
controller-gen.kubebuilder.io/version: v0.22.0
name: terdutteams.terdut.ryuvia.com
spec:
group: terdut.ryuvia.com
names:
kind: TerdutTeam
listKind: TerdutTeamList
plural: terdutteams
singular: terdutteam
scope: Namespaced
versions:
- additionalPrinterColumns:
- jsonPath: .spec.serverRef.name
name: Server
type: string
- jsonPath: .status.teamID
name: TeamID
type: integer
- jsonPath: .status.conditions[?(@.type=="Ready")].status
name: Ready
type: string
- jsonPath: .status.conditions[?(@.type=="Ready")].reason
name: Reason
type: string
name: v1alpha1
schema:
openAPIV3Schema:
description: TerdutTeam is the Schema for the terdutteams API
properties:
apiVersion:
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
spec:
description: spec defines the desired state of TerdutTeam
properties:
displayName:
description: |-
displayName is this team's name, both in terdut-server's own data
(POST /api/teams {"name": ...}) and as the identity POST /api/teams
and GET /api/teams?name= correlate on (DESIGN.md §5's idempotent-
create rule, via TEAM-LOOKUP.md).
minLength: 1
type: string
oidc:
description: |-
TerdutTeamOIDC binds which identity-provider groups grant membership and
ownership of this team (DESIGN.md §4.2). Both empty means no group grants
either role here — matches terdut-server's own NULLIF-on-empty-string
handling (internal/api/oidc_teams.go).
properties:
memberGroup:
type: string
ownerGroup:
type: string
type: object
serverRef:
description: serverRef names the TerdutServer this team belongs to.
properties:
name:
minLength: 1
type: string
namespace:
type: string
required:
- name
type: object
required:
- displayName
- serverRef
type: object
status:
description: status defines the observed state of TerdutTeam
properties:
conditions:
items:
description: Condition contains details for one aspect of the current
state of this API Resource.
properties:
lastTransitionTime:
description: |-
lastTransitionTime is the last time the condition transitioned from one status to another.
This should be when the underlying condition changed. If that is not known, then using the time when the API field changed is acceptable.
format: date-time
type: string
message:
description: |-
message is a human readable message indicating details about the transition.
This may be an empty string.
maxLength: 32768
type: string
observedGeneration:
description: |-
observedGeneration represents the .metadata.generation that the condition was set based upon.
For instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date
with respect to the current state of the instance.
format: int64
minimum: 0
type: integer
reason:
description: |-
reason contains a programmatic identifier indicating the reason for the condition's last transition.
Producers of specific condition types may define expected values and meanings for this field,
and whether the values are considered a guaranteed API.
The value should be a CamelCase string.
This field may not be empty.
maxLength: 1024
minLength: 1
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
type: string
status:
description: status of the condition, one of True, False, Unknown.
enum:
- "True"
- "False"
- Unknown
type: string
type:
description: type of condition in CamelCase or in foo.example.com/CamelCase.
maxLength: 316
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
type: string
required:
- lastTransitionTime
- message
- reason
- status
- type
type: object
type: array
x-kubernetes-list-map-keys:
- type
x-kubernetes-list-type: map
credentialsSecretRef:
description: |-
credentialsSecretRef is this team's own scoped credential
(DESIGN.md §6 point 3) -- pure output, always in the operator's own
namespace, under a fixed data key ("token").
properties:
key:
description: key is the data key inside the Secret holding the
raw value.
minLength: 1
type: string
name:
description: name is the Secret's name.
minLength: 1
type: string
required:
- key
- name
type: object
observedGeneration:
format: int64
type: integer
serverEndpoint:
description: |-
serverEndpoint is the resolved TerdutServer's base URL, resolved once
here so no child controller (TerdutEscalationRule, TerdutDeadmanSwitch,
TerdutAlertSource) ever needs its own RBAC on terdutservers just to
find out where to send a request (DESIGN.md §5).
type: string
teamID:
description: |-
teamID is the server-side id -- needed by every child object's
controller (DESIGN.md §4.2).
format: int64
type: integer
type: object
required:
- spec
type: object
served: true
storage: true
subresources:
status: {}
{{- end }}
@@ -0,0 +1,161 @@
{{- if or (not (hasKey .Values.manager "enabled")) (.Values.manager.enabled) }}
apiVersion: apps/v1
kind: Deployment
metadata:
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 }}
control-plane: controller-manager
{{- with .Values.manager.labels }}
{{- with omit . "app.kubernetes.io/managed-by" "app.kubernetes.io/name" "helm.sh/chart" "app.kubernetes.io/instance" "control-plane" }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
name: {{ include "terdut-operator.resourceName" (dict "suffix" "controller-manager" "context" $) }}
namespace: {{ .Release.Namespace }}
{{- if .Values.manager.annotations }}
annotations:
{{- toYaml .Values.manager.annotations | nindent 4 }}
{{- end }}
spec:
{{- with .Values.manager.strategy }}
strategy: {{ toYaml . | nindent 6 }}
{{- end }}
replicas: {{ .Values.manager.replicas }}
selector:
matchLabels:
app.kubernetes.io/name: {{ include "terdut-operator.name" . }}
control-plane: controller-manager
template:
metadata:
annotations:
kubectl.kubernetes.io/default-container: manager
{{- with .Values.manager.pod }}
{{- with .annotations }}
{{- with omit . "kubectl.kubernetes.io/default-container" }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- end }}
{{- end }}
labels:
app.kubernetes.io/name: {{ include "terdut-operator.name" . }}
helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
control-plane: controller-manager
{{- with .Values.manager.pod }}
{{- with .labels }}
{{- with omit . "app.kubernetes.io/name" "helm.sh/chart" "app.kubernetes.io/instance" "app.kubernetes.io/managed-by" "control-plane" }}
{{- toYaml . | nindent 8 }}
{{- end }}
{{- end }}
{{- end }}
spec:
{{- with .Values.manager.topologySpreadConstraints }}
topologySpreadConstraints: {{ toYaml . | nindent 10 }}
{{- end }}
{{- with .Values.manager.priorityClassName }}
priorityClassName: {{ . | quote }}
{{- end }}
{{- with .Values.manager.tolerations }}
tolerations: {{ toYaml . | nindent 10 }}
{{- end }}
{{- with .Values.manager.affinity }}
affinity: {{ toYaml . | nindent 10 }}
{{- end }}
{{- with .Values.manager.nodeSelector }}
nodeSelector: {{ toYaml . | nindent 10 }}
{{- end }}
{{- with .Values.manager.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- args:
{{- if .Values.metrics.enabled }}
- --metrics-bind-address=:{{ .Values.metrics.port }}
{{- if not .Values.metrics.secure }}
- --metrics-secure=false
{{- end }}
{{- else }}
# Bind to :0 to disable the controller-runtime managed metrics server
- --metrics-bind-address=0
{{- end }}
- --health-probe-bind-address=:{{ .Values.manager.healthProbe.port }}
{{- range .Values.manager.args }}
- {{ tpl . $ }}
{{- end }}
command:
- /manager
env:
{{- if or .Values.manager.env (and (kindIs "map" .Values.manager.envOverrides) (not (empty .Values.manager.envOverrides))) }}
{{- if .Values.manager.env }}
{{- toYaml .Values.manager.env | nindent 10 }}
{{- end }}
{{- if kindIs "map" .Values.manager.envOverrides }}
{{- range $k, $v := .Values.manager.envOverrides }}
- name: {{ $k }}
value: {{ $v | quote }}
{{ end }}
{{- end }}
{{- else }}
[]
{{- end }}
image: "{{ .Values.manager.image.repository | default "controller" }}{{- if not (contains "@" (.Values.manager.image.repository | default "controller")) }}:{{ .Values.manager.image.tag | default .Chart.AppVersion }}{{- end }}"
{{- with .Values.manager.image.pullPolicy }}
imagePullPolicy: {{ . }}
{{- end }}
livenessProbe:
httpGet:
path: /healthz
port: {{ .Values.manager.healthProbe.port }}
initialDelaySeconds: 15
periodSeconds: 20
name: manager
ports:
- containerPort: {{ .Values.manager.healthProbe.port }}
name: health
protocol: TCP
readinessProbe:
httpGet:
path: /readyz
port: {{ .Values.manager.healthProbe.port }}
initialDelaySeconds: 5
periodSeconds: 10
resources:
{{- if .Values.manager.resources }}
{{- toYaml .Values.manager.resources | nindent 10 }}
{{- else }}
{}
{{- end }}
securityContext:
{{- if .Values.manager.securityContext }}
{{- toYaml .Values.manager.securityContext | nindent 10 }}
{{- else }}
{}
{{- end }}
volumeMounts:
{{- if .Values.manager.extraVolumeMounts }}
{{- toYaml .Values.manager.extraVolumeMounts | nindent 10 }}
{{- else }}
[]
{{- end }}
securityContext:
{{- if .Values.manager.podSecurityContext }}
{{- toYaml .Values.manager.podSecurityContext | nindent 8 }}
{{- else }}
{}
{{- end }}
serviceAccountName: {{ include "terdut-operator.serviceAccountName" . }}
{{- if and (hasKey .Values.manager "terminationGracePeriodSeconds") (ne .Values.manager.terminationGracePeriodSeconds nil) }}
terminationGracePeriodSeconds: {{ .Values.manager.terminationGracePeriodSeconds }}
{{- end }}
volumes:
{{- if .Values.manager.extraVolumes }}
{{- toYaml .Values.manager.extraVolumes | nindent 8 }}
{{- else }}
[]
{{- end }}
{{- end }}
@@ -0,0 +1,22 @@
{{- if .Values.metrics.enabled }}
apiVersion: v1
kind: Service
metadata:
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 }}
control-plane: controller-manager
name: {{ include "terdut-operator.resourceName" (dict "suffix" "controller-manager-metrics-service" "context" $) }}
namespace: {{ .Release.Namespace }}
spec:
ports:
- name: {{ if .Values.metrics.secure }}https{{ else }}http{{ end }}
port: {{ .Values.metrics.port }}
protocol: TCP
targetPort: {{ .Values.metrics.port }}
selector:
app.kubernetes.io/name: {{ include "terdut-operator.name" . }}
control-plane: controller-manager
{{- end }}
@@ -0,0 +1,25 @@
{{- if and .Values.networkPolicy.enabled .Values.metrics.enabled }}
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
labels:
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/name: {{ include "terdut-operator.name" . }}
name: {{ include "terdut-operator.resourceName" (dict "suffix" "allow-metrics-traffic" "context" $) }}
namespace: {{ .Release.Namespace }}
spec:
podSelector:
matchLabels:
control-plane: controller-manager
app.kubernetes.io/name: {{ include "terdut-operator.name" . }}
policyTypes:
- Ingress
ingress:
- from:
- namespaceSelector:
matchLabels:
metrics: enabled
ports:
- port: {{ .Values.metrics.port }}
protocol: TCP
{{- end }}
@@ -0,0 +1,53 @@
{{- if .Values.prometheus.enabled }}
apiVersion: monitoring.coreos.com/v1
kind: ServiceMonitor
metadata:
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 }}
control-plane: controller-manager
{{- with .Values.prometheus.labels }}
{{- with omit . "app.kubernetes.io/managed-by" "app.kubernetes.io/name" "helm.sh/chart" "app.kubernetes.io/instance" "control-plane" }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
{{- with .Values.prometheus.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
name: {{ include "terdut-operator.resourceName" (dict "suffix" "controller-manager-metrics-monitor" "context" $) }}
namespace: {{ .Release.Namespace }}
spec:
endpoints:
- {{- if .Values.metrics.secure }}
bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token
{{- end }}
path: /metrics
port: {{ if .Values.metrics.secure }}https{{ else }}http{{ end }}
scheme: {{ if .Values.metrics.secure }}https{{ else }}http{{ end }}
{{- if .Values.metrics.secure }}
tlsConfig:
serverName: {{ include "terdut-operator.resourceName" (dict "suffix" "controller-manager-metrics-service" "context" $) }}.{{ .Release.Namespace }}.svc
{{- if .Values.certManager.enabled }}
ca:
secret:
name: metrics-server-cert
key: ca.crt
cert:
secret:
name: metrics-server-cert
key: tls.crt
keySecret:
name: metrics-server-cert
key: tls.key
{{- else }}
insecureSkipVerify: true
{{- end }}
{{- end }}
selector:
matchLabels:
app.kubernetes.io/name: {{ include "terdut-operator.name" . }}
control-plane: controller-manager
{{- end }}
@@ -0,0 +1,21 @@
{{- if .Values.serviceAccount.enabled }}
apiVersion: v1
kind: ServiceAccount
metadata:
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 }}
{{- with .Values.serviceAccount.labels }}
{{- with omit . "app.kubernetes.io/managed-by" "app.kubernetes.io/name" "helm.sh/chart" "app.kubernetes.io/instance" }}
{{- toYaml . | nindent 4 }}
{{- end }}
{{- end }}
{{- with .Values.serviceAccount.annotations }}
annotations:
{{- toYaml . | nindent 4 }}
{{- end }}
name: {{ include "terdut-operator.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
{{- end }}
@@ -0,0 +1,42 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
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 }}
name: {{ include "terdut-operator.resourceName" (dict "suffix" "leader-election-role" "context" $) }}
namespace: {{ .Release.Namespace }}
rules:
- apiGroups:
- ""
resources:
- configmaps
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
- apiGroups:
- coordination.k8s.io
resources:
- leases
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
- apiGroups:
- ""
resources:
- events
verbs:
- create
- patch
@@ -0,0 +1,18 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
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 }}
name: {{ include "terdut-operator.resourceName" (dict "suffix" "leader-election-rolebinding" "context" $) }}
namespace: {{ .Release.Namespace }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ include "terdut-operator.resourceName" (dict "suffix" "leader-election-role" "context" $) }}
subjects:
- kind: ServiceAccount
name: {{ include "terdut-operator.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
@@ -0,0 +1,98 @@
apiVersion: rbac.authorization.k8s.io/v1
{{- if .Values.rbac.namespaced }}
kind: Role
{{- else }}
kind: ClusterRole
{{- end }}
metadata:
{{- if .Values.rbac.namespaced }}
namespace: {{ .Release.Namespace }}
{{- end }}
name: {{ include "terdut-operator.resourceName" (dict "suffix" "manager-role" "context" $) }}
rules:
- apiGroups:
- ""
resources:
- namespaces
verbs:
- get
- list
- watch
- apiGroups:
- ""
resources:
- secrets
- services
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- acid.zalan.do
resources:
- postgresqls
verbs:
- get
- list
- watch
- apiGroups:
- apps
resources:
- deployments
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- events.k8s.io
resources:
- events
verbs:
- create
- patch
- apiGroups:
- terdut.ryuvia.com
resources:
- terdutalertsources
- terdutdeadmanswitches
- terdutescalationrules
- terdutservers
- terdutteams
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- terdut.ryuvia.com
resources:
- terdutalertsources/finalizers
- terdutdeadmanswitches/finalizers
- terdutescalationrules/finalizers
- terdutservers/finalizers
- terdutteams/finalizers
verbs:
- update
- apiGroups:
- terdut.ryuvia.com
resources:
- terdutalertsources/status
- terdutdeadmanswitches/status
- terdutescalationrules/status
- terdutservers/status
- terdutteams/status
verbs:
- get
- patch
- update
@@ -0,0 +1,28 @@
apiVersion: rbac.authorization.k8s.io/v1
{{- if .Values.rbac.namespaced }}
kind: RoleBinding
{{- else }}
kind: ClusterRoleBinding
{{- end }}
metadata:
{{- if .Values.rbac.namespaced }}
namespace: {{ .Release.Namespace }}
{{- end }}
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 }}
name: {{ include "terdut-operator.resourceName" (dict "suffix" "manager-rolebinding" "context" $) }}
roleRef:
apiGroup: rbac.authorization.k8s.io
{{- if .Values.rbac.namespaced }}
kind: Role
{{- else }}
kind: ClusterRole
{{- end }}
name: {{ include "terdut-operator.resourceName" (dict "suffix" "manager-role" "context" $) }}
subjects:
- kind: ServiceAccount
name: {{ include "terdut-operator.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
@@ -0,0 +1,19 @@
{{- if and .Values.metrics.enabled .Values.metrics.secure }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ include "terdut-operator.resourceName" (dict "suffix" "metrics-auth-role" "context" $) }}
rules:
- apiGroups:
- authentication.k8s.io
resources:
- tokenreviews
verbs:
- create
- apiGroups:
- authorization.k8s.io
resources:
- subjectaccessreviews
verbs:
- create
{{- end }}
@@ -0,0 +1,14 @@
{{- if and .Values.metrics.enabled .Values.metrics.secure }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: {{ include "terdut-operator.resourceName" (dict "suffix" "metrics-auth-rolebinding" "context" $) }}
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: {{ include "terdut-operator.resourceName" (dict "suffix" "metrics-auth-role" "context" $) }}
subjects:
- kind: ServiceAccount
name: {{ include "terdut-operator.serviceAccountName" . }}
namespace: {{ .Release.Namespace }}
{{- end }}
@@ -0,0 +1,11 @@
{{- if and .Values.metrics.enabled .Values.metrics.secure }}
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: {{ include "terdut-operator.resourceName" (dict "suffix" "metrics-reader" "context" $) }}
rules:
- nonResourceURLs:
- /metrics
verbs:
- get
{{- end }}
@@ -0,0 +1,31 @@
{{- if .Values.rbac.helpers.enabled }}
apiVersion: rbac.authorization.k8s.io/v1
{{- if .Values.rbac.namespaced }}
kind: Role
{{- else }}
kind: ClusterRole
{{- end }}
metadata:
{{- if .Values.rbac.namespaced }}
namespace: {{ .Release.Namespace }}
{{- end }}
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 }}
name: {{ include "terdut-operator.resourceName" (dict "suffix" "terdutalertsource-admin-role" "context" $) }}
rules:
- apiGroups:
- terdut.ryuvia.com
resources:
- terdutalertsources
verbs:
- '*'
- apiGroups:
- terdut.ryuvia.com
resources:
- terdutalertsources/status
verbs:
- get
{{- end }}
@@ -0,0 +1,37 @@
{{- if .Values.rbac.helpers.enabled }}
apiVersion: rbac.authorization.k8s.io/v1
{{- if .Values.rbac.namespaced }}
kind: Role
{{- else }}
kind: ClusterRole
{{- end }}
metadata:
{{- if .Values.rbac.namespaced }}
namespace: {{ .Release.Namespace }}
{{- end }}
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 }}
name: {{ include "terdut-operator.resourceName" (dict "suffix" "terdutalertsource-editor-role" "context" $) }}
rules:
- apiGroups:
- terdut.ryuvia.com
resources:
- terdutalertsources
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- terdut.ryuvia.com
resources:
- terdutalertsources/status
verbs:
- get
{{- end }}
@@ -0,0 +1,33 @@
{{- if .Values.rbac.helpers.enabled }}
apiVersion: rbac.authorization.k8s.io/v1
{{- if .Values.rbac.namespaced }}
kind: Role
{{- else }}
kind: ClusterRole
{{- end }}
metadata:
{{- if .Values.rbac.namespaced }}
namespace: {{ .Release.Namespace }}
{{- end }}
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 }}
name: {{ include "terdut-operator.resourceName" (dict "suffix" "terdutalertsource-viewer-role" "context" $) }}
rules:
- apiGroups:
- terdut.ryuvia.com
resources:
- terdutalertsources
verbs:
- get
- list
- watch
- apiGroups:
- terdut.ryuvia.com
resources:
- terdutalertsources/status
verbs:
- get
{{- end }}
@@ -0,0 +1,31 @@
{{- if .Values.rbac.helpers.enabled }}
apiVersion: rbac.authorization.k8s.io/v1
{{- if .Values.rbac.namespaced }}
kind: Role
{{- else }}
kind: ClusterRole
{{- end }}
metadata:
{{- if .Values.rbac.namespaced }}
namespace: {{ .Release.Namespace }}
{{- end }}
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 }}
name: {{ include "terdut-operator.resourceName" (dict "suffix" "terdutdeadmanswitch-admin-role" "context" $) }}
rules:
- apiGroups:
- terdut.ryuvia.com
resources:
- terdutdeadmanswitches
verbs:
- '*'
- apiGroups:
- terdut.ryuvia.com
resources:
- terdutdeadmanswitches/status
verbs:
- get
{{- end }}
@@ -0,0 +1,37 @@
{{- if .Values.rbac.helpers.enabled }}
apiVersion: rbac.authorization.k8s.io/v1
{{- if .Values.rbac.namespaced }}
kind: Role
{{- else }}
kind: ClusterRole
{{- end }}
metadata:
{{- if .Values.rbac.namespaced }}
namespace: {{ .Release.Namespace }}
{{- end }}
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 }}
name: {{ include "terdut-operator.resourceName" (dict "suffix" "terdutdeadmanswitch-editor-role" "context" $) }}
rules:
- apiGroups:
- terdut.ryuvia.com
resources:
- terdutdeadmanswitches
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- terdut.ryuvia.com
resources:
- terdutdeadmanswitches/status
verbs:
- get
{{- end }}
@@ -0,0 +1,33 @@
{{- if .Values.rbac.helpers.enabled }}
apiVersion: rbac.authorization.k8s.io/v1
{{- if .Values.rbac.namespaced }}
kind: Role
{{- else }}
kind: ClusterRole
{{- end }}
metadata:
{{- if .Values.rbac.namespaced }}
namespace: {{ .Release.Namespace }}
{{- end }}
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 }}
name: {{ include "terdut-operator.resourceName" (dict "suffix" "terdutdeadmanswitch-viewer-role" "context" $) }}
rules:
- apiGroups:
- terdut.ryuvia.com
resources:
- terdutdeadmanswitches
verbs:
- get
- list
- watch
- apiGroups:
- terdut.ryuvia.com
resources:
- terdutdeadmanswitches/status
verbs:
- get
{{- end }}
@@ -0,0 +1,31 @@
{{- if .Values.rbac.helpers.enabled }}
apiVersion: rbac.authorization.k8s.io/v1
{{- if .Values.rbac.namespaced }}
kind: Role
{{- else }}
kind: ClusterRole
{{- end }}
metadata:
{{- if .Values.rbac.namespaced }}
namespace: {{ .Release.Namespace }}
{{- end }}
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 }}
name: {{ include "terdut-operator.resourceName" (dict "suffix" "terdutescalationrule-admin-role" "context" $) }}
rules:
- apiGroups:
- terdut.ryuvia.com
resources:
- terdutescalationrules
verbs:
- '*'
- apiGroups:
- terdut.ryuvia.com
resources:
- terdutescalationrules/status
verbs:
- get
{{- end }}
@@ -0,0 +1,37 @@
{{- if .Values.rbac.helpers.enabled }}
apiVersion: rbac.authorization.k8s.io/v1
{{- if .Values.rbac.namespaced }}
kind: Role
{{- else }}
kind: ClusterRole
{{- end }}
metadata:
{{- if .Values.rbac.namespaced }}
namespace: {{ .Release.Namespace }}
{{- end }}
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 }}
name: {{ include "terdut-operator.resourceName" (dict "suffix" "terdutescalationrule-editor-role" "context" $) }}
rules:
- apiGroups:
- terdut.ryuvia.com
resources:
- terdutescalationrules
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- terdut.ryuvia.com
resources:
- terdutescalationrules/status
verbs:
- get
{{- end }}
@@ -0,0 +1,33 @@
{{- if .Values.rbac.helpers.enabled }}
apiVersion: rbac.authorization.k8s.io/v1
{{- if .Values.rbac.namespaced }}
kind: Role
{{- else }}
kind: ClusterRole
{{- end }}
metadata:
{{- if .Values.rbac.namespaced }}
namespace: {{ .Release.Namespace }}
{{- end }}
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 }}
name: {{ include "terdut-operator.resourceName" (dict "suffix" "terdutescalationrule-viewer-role" "context" $) }}
rules:
- apiGroups:
- terdut.ryuvia.com
resources:
- terdutescalationrules
verbs:
- get
- list
- watch
- apiGroups:
- terdut.ryuvia.com
resources:
- terdutescalationrules/status
verbs:
- get
{{- end }}
@@ -0,0 +1,31 @@
{{- if .Values.rbac.helpers.enabled }}
apiVersion: rbac.authorization.k8s.io/v1
{{- if .Values.rbac.namespaced }}
kind: Role
{{- else }}
kind: ClusterRole
{{- end }}
metadata:
{{- if .Values.rbac.namespaced }}
namespace: {{ .Release.Namespace }}
{{- end }}
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 }}
name: {{ include "terdut-operator.resourceName" (dict "suffix" "terdutserver-admin-role" "context" $) }}
rules:
- apiGroups:
- terdut.ryuvia.com
resources:
- terdutservers
verbs:
- '*'
- apiGroups:
- terdut.ryuvia.com
resources:
- terdutservers/status
verbs:
- get
{{- end }}
@@ -0,0 +1,37 @@
{{- if .Values.rbac.helpers.enabled }}
apiVersion: rbac.authorization.k8s.io/v1
{{- if .Values.rbac.namespaced }}
kind: Role
{{- else }}
kind: ClusterRole
{{- end }}
metadata:
{{- if .Values.rbac.namespaced }}
namespace: {{ .Release.Namespace }}
{{- end }}
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 }}
name: {{ include "terdut-operator.resourceName" (dict "suffix" "terdutserver-editor-role" "context" $) }}
rules:
- apiGroups:
- terdut.ryuvia.com
resources:
- terdutservers
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- terdut.ryuvia.com
resources:
- terdutservers/status
verbs:
- get
{{- end }}
@@ -0,0 +1,33 @@
{{- if .Values.rbac.helpers.enabled }}
apiVersion: rbac.authorization.k8s.io/v1
{{- if .Values.rbac.namespaced }}
kind: Role
{{- else }}
kind: ClusterRole
{{- end }}
metadata:
{{- if .Values.rbac.namespaced }}
namespace: {{ .Release.Namespace }}
{{- end }}
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 }}
name: {{ include "terdut-operator.resourceName" (dict "suffix" "terdutserver-viewer-role" "context" $) }}
rules:
- apiGroups:
- terdut.ryuvia.com
resources:
- terdutservers
verbs:
- get
- list
- watch
- apiGroups:
- terdut.ryuvia.com
resources:
- terdutservers/status
verbs:
- get
{{- end }}
@@ -0,0 +1,31 @@
{{- if .Values.rbac.helpers.enabled }}
apiVersion: rbac.authorization.k8s.io/v1
{{- if .Values.rbac.namespaced }}
kind: Role
{{- else }}
kind: ClusterRole
{{- end }}
metadata:
{{- if .Values.rbac.namespaced }}
namespace: {{ .Release.Namespace }}
{{- end }}
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 }}
name: {{ include "terdut-operator.resourceName" (dict "suffix" "terdutteam-admin-role" "context" $) }}
rules:
- apiGroups:
- terdut.ryuvia.com
resources:
- terdutteams
verbs:
- '*'
- apiGroups:
- terdut.ryuvia.com
resources:
- terdutteams/status
verbs:
- get
{{- end }}
@@ -0,0 +1,37 @@
{{- if .Values.rbac.helpers.enabled }}
apiVersion: rbac.authorization.k8s.io/v1
{{- if .Values.rbac.namespaced }}
kind: Role
{{- else }}
kind: ClusterRole
{{- end }}
metadata:
{{- if .Values.rbac.namespaced }}
namespace: {{ .Release.Namespace }}
{{- end }}
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 }}
name: {{ include "terdut-operator.resourceName" (dict "suffix" "terdutteam-editor-role" "context" $) }}
rules:
- apiGroups:
- terdut.ryuvia.com
resources:
- terdutteams
verbs:
- create
- delete
- get
- list
- patch
- update
- watch
- apiGroups:
- terdut.ryuvia.com
resources:
- terdutteams/status
verbs:
- get
{{- end }}
@@ -0,0 +1,33 @@
{{- if .Values.rbac.helpers.enabled }}
apiVersion: rbac.authorization.k8s.io/v1
{{- if .Values.rbac.namespaced }}
kind: Role
{{- else }}
kind: ClusterRole
{{- end }}
metadata:
{{- if .Values.rbac.namespaced }}
namespace: {{ .Release.Namespace }}
{{- end }}
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 }}
name: {{ include "terdut-operator.resourceName" (dict "suffix" "terdutteam-viewer-role" "context" $) }}
rules:
- apiGroups:
- terdut.ryuvia.com
resources:
- terdutteams
verbs:
- get
- list
- watch
- apiGroups:
- terdut.ryuvia.com
resources:
- terdutteams/status
verbs:
- get
{{- end }}
@@ -0,0 +1,54 @@
{{/*
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 }}
{{- end }}
+272
View File
@@ -0,0 +1,272 @@
## String to partially override chart.fullname template (will maintain the release name)
##
# nameOverride: ""
## String to fully override chart.fullname template
##
# fullnameOverride: ""
## Configure the controller manager deployment
##
manager:
## Set to false to skip manager installation
##
enabled: true
replicas: 1
image:
repository: git.ryuvia.com/niklas/terdut-operator
## Image tag (defaults to Chart.appVersion if not set) -- the release
## process (`make helm-package`) always passes --app-version from the
## tag, so leaving this unset here is what tracks a release correctly.
##
# tag: ""
pullPolicy: IfNotPresent
## Arguments
##
args:
- --leader-elect
## Health probes.
## The manager serves the liveness (/healthz) and readiness (/readyz) endpoints on this port.
##
healthProbe:
# Health probe server port
port: 8081
## Environment variables
##
env:
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
## Env overrides (--set manager.envOverrides.VAR=value)
## Same name in env above: this value takes precedence.
##
envOverrides: {}
## Image pull secrets
##
# imagePullSecrets:
# - name: myregistrykey
## Pod-level security settings
##
podSecurityContext:
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
## Container-level security settings
##
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
readOnlyRootFilesystem: true
## Resource limits and requests
##
resources:
limits:
cpu: 500m
memory: 128Mi
requests:
cpu: 10m
memory: 64Mi
## Manager pod's affinity
##
affinity: {}
## Manager pod's node selector
##
nodeSelector: {}
## Manager pod's tolerations
##
tolerations: []
## Deployment strategy
##
# strategy:
# type: RollingUpdate
# rollingUpdate:
# maxSurge: 25%
# maxUnavailable: 25%
## Priority class name
##
# priorityClassName: ""
## Topology spread constraints
##
# topologySpreadConstraints: []
## Termination grace period seconds
##
terminationGracePeriodSeconds: 10
## Custom Deployment labels
##
# labels: {}
## Custom Deployment annotations
##
# annotations: {}
## Custom Pod labels and annotations
##
# pod:
# labels: {}
# annotations: {}
## RBAC configuration
##
rbac:
## RBAC resource scope
## - false (default): ClusterRole/ClusterRoleBinding (all namespaces)
## - true: Role/RoleBinding (release namespace only)
##
namespaced: false
## Helper roles for CRD management (admin/editor/viewer)
##
helpers:
## Install convenience admin/editor/viewer roles for CRDs
##
enabled: false
## ServiceAccount configuration
##
serviceAccount:
# Install default ServiceAccount provided
enabled: true
## Existing ServiceAccount name (required when enabled=false)
## Set to "default" to use the namespace default ServiceAccount
## Note: When enabled=true, respects nameOverride/fullnameOverride
##
# name: ""
## Custom ServiceAccount annotations
##
# annotations: {}
## Custom ServiceAccount labels
##
# labels: {}
## Custom Resource Definitions
##
crd:
# Install CRDs with the chart
enabled: true
# Keep CRDs when uninstalling
keep: true
## Controller metrics endpoint.
## Enable to expose /metrics endpoint
##
metrics:
enabled: true
# Metrics server port
port: 8443
# Enable secure metrics: HTTPS with certs/auth (true) or HTTP (false).
# Note: Metrics authn/authz needs ClusterRole access.
secure: true
## Cert-manager integration for TLS certificates.
## Required for webhook certificates and metrics endpoint certificates.
##
certManager:
enabled: false
## Webhook server configuration
##
webhook:
enabled: false
# Webhook server port
port: 9443
## Prometheus ServiceMonitor for metrics scraping.
## Requires prometheus-operator to be installed in the cluster.
##
prometheus:
enabled: false
## Custom ServiceMonitor labels
##
# labels: {}
## Custom ServiceMonitor annotations
##
# annotations: {}
## Network policies for controlling traffic flow.
## Enable to restrict ingress to the controller manager.
##
networkPolicy:
enabled: false
## Optionally render one TerdutServer CR from this chart -- "helm install
## and get a server" without hand-writing a CR (DESIGN.md §10). Off by
## default: most installs only want the operator and CRDs here, then apply
## their own TerdutServer (and TerdutTeam, and so on) separately. The shape
## below mirrors api/v1alpha1/terdutserver_types.go's TerdutServerSpec
## directly -- see that file for what each field means and which are
## required.
##
terdutServer:
enabled: false
## This CR's own metadata.name. Defaults to the chart's own fullname if unset.
# name: ""
image:
repository: git.ryuvia.com/niklas/terdut-server
## Required when terdutServer.enabled.
# tag: ""
replicas: 1
networking:
## Required when terdutServer.enabled -- the hostname a future
## HTTPRoute will carry (see NetworkingSpec's own doc comment: creating
## that HTTPRoute isn't implemented yet).
# hostname: ""
servicePort: 8080
## Exactly one of dsn or postgresClusterRef, matching DatabaseSpec's own
## CEL rule -- required when terdutServer.enabled. Bring-your-own DSN:
## database:
## dsn: "postgres://terdut@terdut-postgres:5432/terdut?sslmode=require"
## passwordSecretRef:
## name: terdut-postgres-password
## key: password
## Zalando postgres-operator instead:
## database:
## postgresClusterRef:
## name: terdut-postgres
database: {}
## All optional -- omit entirely for their terdut-server defaults.
# sweeper:
# staleAfter: 6h
# archiveAfter: 168h
# deadman:
# matchers: "alertname=Watchdog"
# timeout: 15m
# severity: critical
# notify: {}
# oidc: {}
passwordLogin: true
# allowedTeams: {}