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
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:
@@ -78,6 +78,54 @@ jobs:
|
|||||||
- name: Format, lint and test
|
- name: Format, lint and test
|
||||||
run: make fmt lint test
|
run: make fmt lint test
|
||||||
|
|
||||||
# No `chart` job yet -- there's no Helm chart until Stage 6 (ROADMAP.md). No
|
# Runs on every push and pull request, unlike the image scan, which needs something
|
||||||
# `security` job yet either (govulncheck/gitleaks, as terdut-server has); add one
|
# published to scan and so lives in release.yaml -- same split as terdut-server's.
|
||||||
# alongside `test` once there's controller code worth scanning.
|
# govulncheck reads the source and its module graph, gitleaks reads the working
|
||||||
|
# tree; neither sees what the other does.
|
||||||
|
security:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: golang:1.26.6-bookworm
|
||||||
|
volumes:
|
||||||
|
- go-mod-cache:/go/pkg/mod
|
||||||
|
- go-build-cache:/root/.cache/go-build
|
||||||
|
- gobin-cache:/go/bin
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
env:
|
||||||
|
REF_NAME: ${{ github.ref_name }}
|
||||||
|
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
||||||
|
run: |
|
||||||
|
if [ -n "$HEAD_SHA" ]; then
|
||||||
|
git clone "$REPO_URL" .
|
||||||
|
git checkout -q "$HEAD_SHA"
|
||||||
|
else
|
||||||
|
git clone --depth=1 --branch "$REF_NAME" "$REPO_URL" .
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Go vulnerability scan (govulncheck)
|
||||||
|
run: make security-go
|
||||||
|
|
||||||
|
- name: Secret scan (gitleaks)
|
||||||
|
run: make security-secrets
|
||||||
|
|
||||||
|
# Host mode, no `container:`: helm is baked into the runner image, and a container
|
||||||
|
# job could not install it -- get.helm.sh is unreachable from the dind bridge, same
|
||||||
|
# reason terdut-server's own chart job runs on the host.
|
||||||
|
chart:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
env:
|
||||||
|
REF_NAME: ${{ github.ref_name }}
|
||||||
|
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
|
||||||
|
run: |
|
||||||
|
if [ -n "$HEAD_SHA" ]; then
|
||||||
|
git clone "$REPO_URL" .
|
||||||
|
git checkout -q "$HEAD_SHA"
|
||||||
|
else
|
||||||
|
git clone --depth=1 --branch "$REF_NAME" "$REPO_URL" .
|
||||||
|
fi
|
||||||
|
|
||||||
|
- name: Lint and render the chart
|
||||||
|
run: make helm-lint
|
||||||
|
|||||||
@@ -0,0 +1,127 @@
|
|||||||
|
name: Release
|
||||||
|
|
||||||
|
# Checkout, interpolation and caching conventions match ci.yaml -- see the header there
|
||||||
|
# for why there are no JS actions and why every `${{ }}` goes through `env:`.
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- 'v*'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
# A tag is not normally re-pushed, so this mostly matters when one is force-moved during
|
||||||
|
# a botched release -- the superseded run stops holding runner slots.
|
||||||
|
concurrency:
|
||||||
|
group: release-${{ github.ref }}
|
||||||
|
cancel-in-progress: true
|
||||||
|
|
||||||
|
env:
|
||||||
|
REPO_URL: https://git.ryuvia.com/niklas/terdut-operator.git
|
||||||
|
REGISTRY: git.ryuvia.com
|
||||||
|
IMAGE: git.ryuvia.com/niklas/terdut-operator
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
# Gates every publishing job below. A tag that fails here publishes nothing: the
|
||||||
|
# image and the chart are both downstream of it. No Postgres service, unlike
|
||||||
|
# terdut-server's: this suite drives envtest (a fake API server), not a real database.
|
||||||
|
test:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
container:
|
||||||
|
image: golang:1.26.6-bookworm
|
||||||
|
volumes:
|
||||||
|
- go-mod-cache:/go/pkg/mod
|
||||||
|
- go-build-cache:/root/.cache/go-build
|
||||||
|
- gobin-cache:/go/bin
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
env:
|
||||||
|
REF_NAME: ${{ github.ref_name }}
|
||||||
|
run: git clone --depth=1 --branch "$REF_NAME" "$REPO_URL" .
|
||||||
|
|
||||||
|
- name: Format, lint and test
|
||||||
|
run: make fmt lint test
|
||||||
|
|
||||||
|
# Host mode on purpose (no `container:`): this is the only context with a Docker CLI
|
||||||
|
# pointed at the dind daemon. A `container:` job would sit on the dind bridge with no
|
||||||
|
# docker socket at all -- same reason terdut-server's image job runs on the host.
|
||||||
|
image:
|
||||||
|
needs: test
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
env:
|
||||||
|
REF_NAME: ${{ github.ref_name }}
|
||||||
|
run: git clone --depth=1 --branch "$REF_NAME" "$REPO_URL" .
|
||||||
|
|
||||||
|
- name: Log in to the registry
|
||||||
|
env:
|
||||||
|
TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
||||||
|
run: echo "$TOKEN" | docker login "$REGISTRY" -u niklas --password-stdin
|
||||||
|
|
||||||
|
# buildx setup, the platform list and why there is no QEMU all live on the `push`
|
||||||
|
# target now, so the same command publishes from a laptop and from here.
|
||||||
|
- name: Build and push
|
||||||
|
env:
|
||||||
|
REF_NAME: ${{ github.ref_name }}
|
||||||
|
run: make push VERSION="$REF_NAME"
|
||||||
|
|
||||||
|
# Also host mode: helm is baked into the runner image, and a `container:` job could
|
||||||
|
# not install it -- get.helm.sh is unreachable from the dind bridge.
|
||||||
|
chart:
|
||||||
|
needs: test
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
env:
|
||||||
|
REF_NAME: ${{ github.ref_name }}
|
||||||
|
run: git clone --depth=1 --branch "$REF_NAME" "$REPO_URL" .
|
||||||
|
|
||||||
|
# One publisher, triggered by the tag -- same reasoning as terdut-server's own
|
||||||
|
# chart job: a workflow triggered by the main push cannot know the version it is
|
||||||
|
# about to be tagged with, so there is no second publisher racing this one.
|
||||||
|
- name: Refuse a non-version tag
|
||||||
|
env:
|
||||||
|
REF_NAME: ${{ github.ref_name }}
|
||||||
|
run: |
|
||||||
|
set -eu
|
||||||
|
if ! echo "$REF_NAME" | grep -qE '^v[0-9]'; then
|
||||||
|
echo "::error::refusing to publish a chart for non-version tag ${REF_NAME}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Render before publishing, so a template that does not compile is found here,
|
||||||
|
# not by Flux after the chart is already in the registry.
|
||||||
|
- name: Lint and render the chart
|
||||||
|
run: make helm-lint
|
||||||
|
|
||||||
|
- name: Package and push
|
||||||
|
env:
|
||||||
|
REF_NAME: ${{ github.ref_name }}
|
||||||
|
TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
||||||
|
run: |
|
||||||
|
set -eu
|
||||||
|
echo "$TOKEN" | helm registry login "$REGISTRY" -u niklas --password-stdin
|
||||||
|
make helm-package helm-push VERSION="$REF_NAME"
|
||||||
|
|
||||||
|
# Host mode, like image and chart: this needs a docker daemon to run trivy in, and a
|
||||||
|
# `container:` job would sit on the dind bridge with none.
|
||||||
|
#
|
||||||
|
# Scans the pushed image, not a local one -- trivy cannot read a locally built image
|
||||||
|
# on this runner (no docker socket in a container job, no shared filesystem with the
|
||||||
|
# dind sidecar), so it pulls from the registry. Runs after `image` rather than gating
|
||||||
|
# it: a red scan does not unpublish anything -- it means do not bump the wrapper
|
||||||
|
# chart in Ryuvia/charts to this version. This pipeline does not deploy.
|
||||||
|
scan-image:
|
||||||
|
needs: image
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
env:
|
||||||
|
REF_NAME: ${{ github.ref_name }}
|
||||||
|
run: git clone --depth=1 --branch "$REF_NAME" "$REPO_URL" .
|
||||||
|
|
||||||
|
- name: Scan the pushed image (trivy)
|
||||||
|
env:
|
||||||
|
TRIVY_USERNAME: niklas
|
||||||
|
TRIVY_PASSWORD: ${{ secrets.REGISTRY_TOKEN }}
|
||||||
|
REF_NAME: ${{ github.ref_name }}
|
||||||
|
run: make security-image VERSION="$REF_NAME"
|
||||||
@@ -13,3 +13,7 @@ bin/
|
|||||||
# local kubeconfig/secrets some workflows write here
|
# local kubeconfig/secrets some workflows write here
|
||||||
*.kubeconfig
|
*.kubeconfig
|
||||||
cover.out
|
cover.out
|
||||||
|
|
||||||
|
# scratch output: build-installer's consolidated manifest and packaged charts
|
||||||
|
# (release-vars' HELM_CHART is charts/terdut-operator, committed; this is not)
|
||||||
|
/dist/
|
||||||
|
|||||||
@@ -0,0 +1,21 @@
|
|||||||
|
# Read by the `release` skill (~/.claude/skills/release).
|
||||||
|
#
|
||||||
|
# Only what the Makefile cannot already say. IMAGE, HELM_CHART and HELM_REPO come from
|
||||||
|
# `make release-vars`, so they have one definition and cannot drift from what is built.
|
||||||
|
#
|
||||||
|
# Defaults, set here only where this repo differs:
|
||||||
|
# CHARTS_REPO=$HOME/git/charts CHARTS_DIR=<image basename>
|
||||||
|
# GITEA_LOGIN=Ryuvia APPVERSION_PREFIX=
|
||||||
|
# PROSE_LANG=en
|
||||||
|
|
||||||
|
# Same as the image basename, so this is only stated to be read rather than derived.
|
||||||
|
CHARTS_DIR=terdut-operator
|
||||||
|
|
||||||
|
# This repo writes appVersion: "v0.1.0" (see charts/terdut-operator/Chart.yaml),
|
||||||
|
# matching terdut-server's own v-prefixed style -- nothing reads the field, but people
|
||||||
|
# do, and it should say the same thing the release tag does.
|
||||||
|
APPVERSION_PREFIX=v
|
||||||
|
|
||||||
|
# English, for the same reason as terdut-server: this is an on-call tool's operator,
|
||||||
|
# and nothing about its labels, API or docs is coupled to Swedish.
|
||||||
|
PROSE_LANG=en
|
||||||
@@ -7,19 +7,40 @@ short pitch.
|
|||||||
|
|
||||||
## Checks
|
## Checks
|
||||||
|
|
||||||
`make fmt lint test` is the CI gate (`.gitea/workflows/ci.yaml` calls these targets
|
`make fmt lint test helm-lint` is the CI gate (`.gitea/workflows/ci.yaml`'s `test`,
|
||||||
rather than restating them, same convention as terdut-server). `test` chains through
|
`security` and `chart` jobs call these targets rather than restating them, same
|
||||||
the Kubebuilder-scaffolded `manifests`/`generate` (`controller-gen`) and `setup-envtest`
|
convention as terdut-server). `test` chains through the Kubebuilder-scaffolded
|
||||||
targets automatically — everything needed lands in `bin/` (gitignored) on first run, no
|
`manifests`/`generate` (`controller-gen`) and `setup-envtest` targets automatically —
|
||||||
separate tool install required beyond Go itself and network access to
|
everything needed lands in `bin/` (gitignored) on first run, no separate tool install
|
||||||
`proxy.golang.org`/`storage.googleapis.com`.
|
required beyond Go itself and network access to `proxy.golang.org`/`storage.googleapis.com`.
|
||||||
|
`security` runs `make security-go`/`security-secrets` (govulncheck/gitleaks), same as
|
||||||
|
terdut-server's own `security` job.
|
||||||
|
|
||||||
`make test-e2e` stands up a real `kind` cluster (`kind`/`docker` must be installed) and
|
The kubebuilder-scaffolded `make test-e2e` (a disposable, generic smoke test) is separate
|
||||||
is not part of the CI gate yet — it has no service-image to test against until later
|
from the real golden-path `kind` e2e pass ROADMAP.md's Stage 5 describes (create every CRD
|
||||||
ROADMAP stages produce one.
|
kind, verify against terdut-server's own API, delete, verify gone) — the latter is a
|
||||||
|
manual pass run and recorded in ROADMAP.md, not a CI job, matching Stage 1-4's own
|
||||||
|
precedent of validating against a real cluster outside CI.
|
||||||
|
|
||||||
## Release
|
## Release
|
||||||
|
|
||||||
Not wired yet. `.release.conf` and the release-vars Makefile target land in ROADMAP.md's
|
Wired as of Stage 5 (ROADMAP.md): `.release.conf`, `make release-vars`/`helm-lint`/
|
||||||
Stage 6, once there's an actual Helm chart to release — see that file before assuming
|
`push`/`helm-package`/`helm-push`/`release`, and `.gitea/workflows/release.yaml`
|
||||||
the `release` skill's terdut-server/terdut-tui conventions already apply here.
|
(`test` → `image`/`chart` → `scan-image`) all follow terdut-server's established shape —
|
||||||
|
see that repo's Makefile/`.release.conf` for the shared reasoning, not restated here.
|
||||||
|
|
||||||
|
The chart is `charts/terdut-operator` (via kubebuilder's own `helm/v2-alpha` plugin,
|
||||||
|
regenerate with `kubebuilder edit --plugins helm.kubebuilder.io/v2-alpha --output-dir
|
||||||
|
charts --force` after `config/` changes, then re-review — `--force` does not touch
|
||||||
|
`Chart.yaml` but does touch `values.yaml`, which carries hand-written additions, most
|
||||||
|
importantly the optional `terdutServer` block, DESIGN.md §10). It installs the operator +
|
||||||
|
CRDs + RBAC, and optionally one `TerdutServer` CR (`terdutServer.enabled`, off by default).
|
||||||
|
|
||||||
|
**One manual step the release skill's own automation does not cover**: `release-preflight`
|
||||||
|
expects an existing `terdut-operator/` entry under `Ryuvia/charts` to bump on release
|
||||||
|
(steps 8-10 of the skill). There is no such entry yet — this repo's first-ever release
|
||||||
|
can publish its own image and chart (the `test`/`image`/`chart`/`scan-image` jobs), but
|
||||||
|
the wrapper-chart bump and PR will fail until someone creates that initial wrapper entry
|
||||||
|
in `Ryuvia/charts` by hand, the same one-time step every other onboarded repo already had
|
||||||
|
done for it before its own first release. That's a deliberate decision to deploy this
|
||||||
|
operator for real, not something to do as a side effect of finishing this stage.
|
||||||
|
|||||||
+6
-1
@@ -1,7 +1,12 @@
|
|||||||
# Build the manager binary
|
# Build the manager binary
|
||||||
# Override BASE_IMAGE to build from another registry, e.g. docker.io/library/golang:1.26
|
# Override BASE_IMAGE to build from another registry, e.g. docker.io/library/golang:1.26
|
||||||
ARG BASE_IMAGE=golang:1.26
|
ARG BASE_IMAGE=golang:1.26
|
||||||
FROM ${BASE_IMAGE} AS builder
|
# --platform=$BUILDPLATFORM pins the builder to the machine doing the building, so a
|
||||||
|
# multi-arch build compiles both targets natively instead of running an emulated arm64
|
||||||
|
# toolchain under QEMU -- same reasoning, and the same fix, as terdut-server's own
|
||||||
|
# Dockerfile: the CI runner has no binfmt registration and no way to get one, so
|
||||||
|
# this is not just an optimization, it is what makes the arm64 image buildable at all.
|
||||||
|
FROM --platform=$BUILDPLATFORM ${BASE_IMAGE} AS builder
|
||||||
ARG TARGETOS
|
ARG TARGETOS
|
||||||
ARG TARGETARCH
|
ARG TARGETARCH
|
||||||
|
|
||||||
|
|||||||
@@ -259,3 +259,190 @@ endef
|
|||||||
define gomodver
|
define gomodver
|
||||||
$(shell go list -m -f '{{if .Replace}}{{.Replace.Version}}{{else}}{{.Version}}{{end}}' $(1) 2>/dev/null)
|
$(shell go list -m -f '{{if .Replace}}{{.Replace.Version}}{{else}}{{.Version}}{{end}}' $(1) 2>/dev/null)
|
||||||
endef
|
endef
|
||||||
|
|
||||||
|
##@ Helm Deployment
|
||||||
|
|
||||||
|
## Helm binary to use for deploying the chart
|
||||||
|
HELM ?= helm
|
||||||
|
## Namespace to deploy the Helm release
|
||||||
|
HELM_NAMESPACE ?= terdut-operator-system
|
||||||
|
## Name of the Helm release
|
||||||
|
HELM_RELEASE ?= terdut-operator
|
||||||
|
## Path to the Helm chart directory. Must stay equal to HELM_CHART below
|
||||||
|
## (the release process's own name for this same path) -- two variables
|
||||||
|
## because this one is kubebuilder's own scaffold and that one is the
|
||||||
|
## release skill's contract, not because the path differs.
|
||||||
|
HELM_CHART_DIR ?= charts/terdut-operator
|
||||||
|
## Additional arguments to pass to helm commands
|
||||||
|
HELM_EXTRA_ARGS ?=
|
||||||
|
|
||||||
|
.PHONY: install-helm
|
||||||
|
install-helm: ## Install the latest version of Helm.
|
||||||
|
@command -v $(HELM) >/dev/null 2>&1 || { \
|
||||||
|
echo "Installing Helm..." && \
|
||||||
|
curl -fsSL https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-4 | bash; \
|
||||||
|
}
|
||||||
|
|
||||||
|
.PHONY: helm-deploy
|
||||||
|
helm-deploy: install-helm ## Deploy manager to the K8s cluster via Helm. Specify an image with IMG.
|
||||||
|
IMG="$(IMG)"; $(HELM) upgrade --install $(HELM_RELEASE) $(HELM_CHART_DIR) \
|
||||||
|
--namespace $(HELM_NAMESPACE) \
|
||||||
|
--create-namespace \
|
||||||
|
--set manager.image.repository=$${IMG%:*} \
|
||||||
|
--set manager.image.tag=$${IMG##*:} \
|
||||||
|
--wait \
|
||||||
|
--timeout 5m \
|
||||||
|
$(HELM_EXTRA_ARGS)
|
||||||
|
|
||||||
|
.PHONY: helm-uninstall
|
||||||
|
helm-uninstall: ## Uninstall the Helm release from the K8s cluster.
|
||||||
|
$(HELM) uninstall $(HELM_RELEASE) --namespace $(HELM_NAMESPACE)
|
||||||
|
|
||||||
|
.PHONY: helm-status
|
||||||
|
helm-status: ## Show Helm release status.
|
||||||
|
$(HELM) status $(HELM_RELEASE) --namespace $(HELM_NAMESPACE)
|
||||||
|
|
||||||
|
.PHONY: helm-history
|
||||||
|
helm-history: ## Show Helm release history.
|
||||||
|
$(HELM) history $(HELM_RELEASE) --namespace $(HELM_NAMESPACE)
|
||||||
|
|
||||||
|
.PHONY: helm-rollback
|
||||||
|
helm-rollback: ## Rollback to previous Helm release.
|
||||||
|
$(HELM) rollback $(HELM_RELEASE) --namespace $(HELM_NAMESPACE)
|
||||||
|
|
||||||
|
##@ Release
|
||||||
|
|
||||||
|
# Everything below is read by the `release` skill (~/.claude/skills/release), not by
|
||||||
|
# anything above it in this file -- mirrors terdut-server's Makefile section for
|
||||||
|
# section, adapted for this repo (no Postgres service for tests, no CLI binaries to
|
||||||
|
# cross-compile, one image + one chart to publish).
|
||||||
|
|
||||||
|
REGISTRY := git.ryuvia.com
|
||||||
|
# The personal namespace, not ryuvia -- same reasoning as terdut-server: Gitea scopes
|
||||||
|
# package visibility to the owner with no per-package override, so publishing here
|
||||||
|
# keeps the image and chart anonymously pullable and Flux needs no registry
|
||||||
|
# credentials to pull them.
|
||||||
|
OWNER := niklas
|
||||||
|
|
||||||
|
IMAGE := $(REGISTRY)/$(OWNER)/terdut-operator
|
||||||
|
HELM_CHART := charts/terdut-operator
|
||||||
|
HELM_REPO := oci://$(REGISTRY)/$(OWNER)
|
||||||
|
|
||||||
|
.PHONY: release-vars
|
||||||
|
release-vars: ## Print the variables the release process reads
|
||||||
|
@printf 'IMAGE=%s\nHELM_CHART=%s\nHELM_REPO=%s\n' '$(IMAGE)' '$(HELM_CHART)' '$(HELM_REPO)'
|
||||||
|
|
||||||
|
# database is required (dsn xor postgresClusterRef, DatabaseSpec's own CEL rule) once
|
||||||
|
# terdutServer.enabled, so the chart's own `required` calls fail a bare
|
||||||
|
# `--set terdutServer.enabled=true` the same way a real install without a database
|
||||||
|
# would be rejected at apply time -- this set gives that path something valid to
|
||||||
|
# render against, the way terdut-server's own HELM_LINT_SET supplies its one
|
||||||
|
# required field (database.dsn) for the same reason.
|
||||||
|
HELM_LINT_SET = --set terdutServer.enabled=true \
|
||||||
|
--set terdutServer.image.tag=v0.0.0 \
|
||||||
|
--set terdutServer.networking.hostname=terdut.example.invalid \
|
||||||
|
--set 'terdutServer.database.dsn=postgres://terdut@terdut-postgres:5432/terdut?sslmode=require'
|
||||||
|
|
||||||
|
.PHONY: helm-lint
|
||||||
|
helm-lint: ## Lint and render the chart
|
||||||
|
helm lint $(HELM_CHART)
|
||||||
|
helm template terdut-operator $(HELM_CHART) --namespace terdut-operator-system >/dev/null
|
||||||
|
# Second pass: the optional TerdutServer CR template (off by default, so the
|
||||||
|
# bare render above never exercises it at all).
|
||||||
|
helm lint $(HELM_CHART) $(HELM_LINT_SET)
|
||||||
|
helm template terdut-operator $(HELM_CHART) --namespace terdut-operator-system \
|
||||||
|
$(HELM_LINT_SET) >/dev/null
|
||||||
|
|
||||||
|
## --- publishing ---
|
||||||
|
#
|
||||||
|
# Exist so .gitea/workflows/release.yaml can call `make push` / `make helm-package
|
||||||
|
# helm-push` instead of restating the build in YAML -- one definition, runnable
|
||||||
|
# locally, reviewable in a diff. Publishing happens by pushing a tag; nothing else.
|
||||||
|
#
|
||||||
|
# VERSION is the git tag, passed in by the workflow. require-version is why a stray
|
||||||
|
# local `make push` cannot publish: dev is not a version anyone releases.
|
||||||
|
|
||||||
|
VERSION ?= dev
|
||||||
|
|
||||||
|
# Helm requires strict SemVer -- strip a leading 'v' if present.
|
||||||
|
CHART_VERSION := $(shell echo "$(VERSION)" | sed 's/^v//')
|
||||||
|
|
||||||
|
# Named RELEASE_PLATFORMS, not PLATFORMS: that name is already taken above by
|
||||||
|
# kubebuilder's own docker-buildx target (a 4-platform list this repo's own release
|
||||||
|
# process doesn't use), and `?=` on an already-set variable is a silent no-op, not an
|
||||||
|
# override -- reusing it here would have quietly built s390x/ppc64le instead of the
|
||||||
|
# two platforms this target actually intends.
|
||||||
|
RELEASE_PLATFORMS ?= linux/amd64,linux/arm64
|
||||||
|
BUILDX_BUILDER ?= terdut-operator-release
|
||||||
|
|
||||||
|
# An isolated repo list, same reasoning as terdut-server's: the machine-wide one is
|
||||||
|
# not this build's business, and one unreachable entry in it aborts otherwise-fine
|
||||||
|
# helm commands. HELM_REPOSITORY_CACHE is deliberately NOT overridden alongside it --
|
||||||
|
# helm writes a refreshed index to the default cache and then looks for it there.
|
||||||
|
HELM_ISOLATED = HELM_REPOSITORY_CONFIG=$(CURDIR)/.helm-repos.yaml
|
||||||
|
|
||||||
|
.PHONY: require-version
|
||||||
|
require-version:
|
||||||
|
@test "$(VERSION)" != "dev" || \
|
||||||
|
(echo "VERSION=dev names no release -- pass VERSION=vX.Y.Z (the workflow passes the tag)" && exit 1)
|
||||||
|
|
||||||
|
# Multi-arch, so this is build-and-push in one step, same reasoning as
|
||||||
|
# terdut-server's own `push`: buildx cannot load a multi-platform result into the
|
||||||
|
# local image store, so there is no separate local-only `build` target here either.
|
||||||
|
#
|
||||||
|
# No QEMU: the Dockerfile's builder stage runs on $$BUILDPLATFORM and cross-compiles
|
||||||
|
# via GOOS/GOARCH, so both platforms build natively -- same fix as terdut-server's
|
||||||
|
# Dockerfile, for the same reason (this CI runner has no binfmt registration).
|
||||||
|
.PHONY: push
|
||||||
|
push: require-version ## Build and publish the multi-arch image
|
||||||
|
docker buildx create --name $(BUILDX_BUILDER) --use 2>/dev/null || docker buildx use $(BUILDX_BUILDER)
|
||||||
|
docker buildx build \
|
||||||
|
--platform $(RELEASE_PLATFORMS) \
|
||||||
|
--tag "$(IMAGE):latest" \
|
||||||
|
--tag "$(IMAGE):$(VERSION)" \
|
||||||
|
--push .
|
||||||
|
|
||||||
|
# --version/--app-version come from the tag, so Chart.yaml's own fields decide
|
||||||
|
# nothing about what gets published -- same as terdut-server's chart.
|
||||||
|
.PHONY: helm-package
|
||||||
|
helm-package: require-version ## Package the chart, versioned from the tag
|
||||||
|
$(HELM_ISOLATED) helm package $(HELM_CHART) \
|
||||||
|
--version $(CHART_VERSION) \
|
||||||
|
--app-version $(VERSION) \
|
||||||
|
--destination dist
|
||||||
|
|
||||||
|
.PHONY: helm-push
|
||||||
|
helm-push: require-version ## Push the packaged chart to the OCI registry
|
||||||
|
$(HELM_ISOLATED) helm push dist/terdut-operator-$(CHART_VERSION).tgz $(HELM_REPO)
|
||||||
|
|
||||||
|
.PHONY: release
|
||||||
|
release: push helm-package helm-push ## Publish image + chart (the workflow's one call)
|
||||||
|
|
||||||
|
## --- security ---
|
||||||
|
|
||||||
|
GOVULNCHECK_VERSION := v1.1.4
|
||||||
|
GITLEAKS_VERSION := v8.30.0
|
||||||
|
TRIVY_VERSION := 0.73.0
|
||||||
|
|
||||||
|
# Symbol-level, not dependency-level, same as terdut-server: govulncheck reports a
|
||||||
|
# vulnerability only when the code can actually reach it.
|
||||||
|
.PHONY: security-go
|
||||||
|
security-go: ## Scan Go deps for known CVEs (govulncheck)
|
||||||
|
go run golang.org/x/vuln/cmd/govulncheck@$(GOVULNCHECK_VERSION) ./...
|
||||||
|
|
||||||
|
# --no-git scans the working tree rather than the history, so this catches a secret
|
||||||
|
# on the way in; it says nothing about what is already committed.
|
||||||
|
.PHONY: security-secrets
|
||||||
|
security-secrets: ## Scan the working tree for committed secrets (gitleaks)
|
||||||
|
go run github.com/zricethezav/gitleaks/v8@$(GITLEAKS_VERSION) detect --no-git \
|
||||||
|
--source . --redact --no-banner --exit-code 1
|
||||||
|
|
||||||
|
# Scans the pushed image, not a local one -- trivy cannot read a locally built image
|
||||||
|
# on this runner, same reasoning as terdut-server. A red scan means: do not bump the
|
||||||
|
# wrapper chart in Ryuvia/charts to this version; it does not unpublish anything.
|
||||||
|
.PHONY: security-image
|
||||||
|
security-image: require-version ## Scan the pushed image for CVEs (needs VERSION)
|
||||||
|
docker run --rm -e TRIVY_USERNAME -e TRIVY_PASSWORD \
|
||||||
|
-v trivy-cache:/root/.cache/trivy \
|
||||||
|
docker.io/aquasec/trivy:$(TRIVY_VERSION) image --severity HIGH,CRITICAL \
|
||||||
|
--ignore-unfixed --exit-code 1 $(IMAGE):$(VERSION)
|
||||||
|
|||||||
@@ -6,6 +6,10 @@ cliVersion: 4.16.0
|
|||||||
domain: ryuvia.com
|
domain: ryuvia.com
|
||||||
layout:
|
layout:
|
||||||
- go.kubebuilder.io/v4
|
- go.kubebuilder.io/v4
|
||||||
|
plugins:
|
||||||
|
helm.kubebuilder.io/v2-alpha:
|
||||||
|
manifests: dist/install.yaml
|
||||||
|
output: charts
|
||||||
projectName: terdut-operator
|
projectName: terdut-operator
|
||||||
repo: git.ryuvia.com/niklas/terdut-operator
|
repo: git.ryuvia.com/niklas/terdut-operator
|
||||||
resources:
|
resources:
|
||||||
|
|||||||
+47
@@ -181,6 +181,53 @@ New commits build forward over the old ones; no git history rewrite.
|
|||||||
→ one of each child kind → verify via terdut-server's own API that each
|
→ one of each child kind → verify via terdut-server's own API that each
|
||||||
object exists with the right shape → delete the CR → verify the
|
object exists with the right shape → delete the CR → verify the
|
||||||
server-side object is gone.
|
server-side object is gone.
|
||||||
|
- Chart built via kubebuilder's own `helm/v2-alpha` plugin from `config/`'s
|
||||||
|
kustomize output (`charts/terdut-operator`), not hand-rolled -- CRDs +
|
||||||
|
manager Deployment/RBAC come from the same markers/manifests every other
|
||||||
|
stage already generates, so there's exactly one source of truth for
|
||||||
|
them. Hand-added on top: the optional `terdutServer` values block (§10's
|
||||||
|
"helm install and get a server" path), `.release.conf`, and the
|
||||||
|
`release-vars`/`helm-lint`/`push`/`helm-package`/`helm-push`/`release`
|
||||||
|
Makefile targets `.gitea/workflows/release.yaml` calls, mirroring
|
||||||
|
terdut-server's own shape end to end (same registry/namespace
|
||||||
|
convention, same multi-arch buildx push, same trivy/govulncheck/gitleaks
|
||||||
|
scans). Also fixed while wiring this: the 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) -- caught before it ever shipped, not discovered mid-release;
|
||||||
|
and govulncheck surfaced 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.
|
||||||
|
- **Done, 2026-10-01**: the full golden-path pass above, run for real
|
||||||
|
against a `kind` cluster, installed via `helm install` (not raw
|
||||||
|
kustomize/kubectl apply -- the first time the chart itself, not just
|
||||||
|
`config/`, was exercised): `TerdutServer` (real terdut-server `v0.33.0`
|
||||||
|
image, bring-your-own DSN against a throwaway in-cluster Postgres) →
|
||||||
|
`TerdutTeam` → one `TerdutEscalationRule` + `TerdutDeadmanSwitch` +
|
||||||
|
`TerdutAlertSource`, each confirmed `Ready` and then confirmed a second
|
||||||
|
way, independent of the operator's own status: a `curl` pod inside the
|
||||||
|
cluster, authenticated with the generated team credential, hit
|
||||||
|
terdut-server's real API directly (`GET /api/teams/{id}/escalation`,
|
||||||
|
`.../deadman/switches`, `.../integrations`) and got back exactly the
|
||||||
|
policy/switch/integration each spec declared. Deleting every CR in
|
||||||
|
reverse order was verified the same way: the escalation policy came back
|
||||||
|
empty (its only available "undo"), the switch and the integration were
|
||||||
|
both gone from their list endpoints, the team no longer resolved by
|
||||||
|
name, and the Deployment/Service/every generated Secret were gone from
|
||||||
|
the cluster. No new bugs found this pass -- Stage 1's own kind e2e pass
|
||||||
|
already caught the two issues (`events.k8s.io` RBAC, the podman
|
||||||
|
`.dockerignore` fix) a real cluster catches and `envtest` can't, and
|
||||||
|
nothing since has touched that surface.
|
||||||
|
- Not done in this pass, deliberately: an actual tagged release. `make
|
||||||
|
release-vars`/`helm-lint`/`push`/`helm-package`/`helm-push` all work
|
||||||
|
locally and `.gitea/workflows/release.yaml` is wired, but
|
||||||
|
`release-preflight` found there is no `terdut-operator/` entry under
|
||||||
|
`Ryuvia/charts` yet to bump -- every other onboarded repo had that
|
||||||
|
one-time wrapper-chart bootstrap done for it before its own first
|
||||||
|
release, and this one doesn't, since deploying this operator for real is
|
||||||
|
a decision for whoever runs the cluster, not a side effect of finishing
|
||||||
|
this stage. Cutting the first real release (and creating that wrapper
|
||||||
|
entry) is therefore the next action, not yet taken.
|
||||||
|
|
||||||
## Deferred (§13, unchanged by this roadmap)
|
## Deferred (§13, unchanged by this roadmap)
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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 }}
|
||||||
@@ -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: {}
|
||||||
|
|
||||||
@@ -1,2 +1,8 @@
|
|||||||
resources:
|
resources:
|
||||||
- manager.yaml
|
- manager.yaml
|
||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
images:
|
||||||
|
- name: controller
|
||||||
|
newName: controller
|
||||||
|
newTag: latest
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ require (
|
|||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cel.dev/expr v0.25.1 // indirect
|
cel.dev/expr v0.25.2 // indirect
|
||||||
github.com/Masterminds/semver/v3 v3.4.0 // indirect
|
github.com/Masterminds/semver/v3 v3.4.0 // indirect
|
||||||
github.com/antlr4-go/antlr/v4 v4.13.1 // indirect
|
github.com/antlr4-go/antlr/v4 v4.13.1 // indirect
|
||||||
github.com/beorn7/perks v1.0.1 // indirect
|
github.com/beorn7/perks v1.0.1 // indirect
|
||||||
@@ -88,7 +88,7 @@ require (
|
|||||||
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
|
gomodules.xyz/jsonpatch/v2 v2.4.0 // indirect
|
||||||
google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa // indirect
|
google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa // indirect
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa // indirect
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa // indirect
|
||||||
google.golang.org/grpc v1.82.1 // indirect
|
google.golang.org/grpc v1.83.1 // indirect
|
||||||
google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af // indirect
|
google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af // indirect
|
||||||
gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
|
gopkg.in/evanphx/json-patch.v4 v4.13.0 // indirect
|
||||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
cel.dev/expr v0.25.1 h1:1KrZg61W6TWSxuNZ37Xy49ps13NUovb66QLprthtwi4=
|
cel.dev/expr v0.25.2 h1:K6j46C81hXtZQfuX60cVWQFBJahKSE2gfRbNuvr5bFs=
|
||||||
cel.dev/expr v0.25.1/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4=
|
cel.dev/expr v0.25.2/go.mod h1:hrXvqGP6G6gyx8UAHSHJ5RGk//1Oj5nXQ2NI02Nrsg4=
|
||||||
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
|
github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0=
|
||||||
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
|
github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM=
|
||||||
github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ=
|
github.com/antlr4-go/antlr/v4 v4.13.1 h1:SqQKkuVZ+zWkMMNkjy5FZe5mr5WURWnlpmOuzYWrPrQ=
|
||||||
@@ -222,8 +222,8 @@ google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa h1:
|
|||||||
google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:q4lMZS6kskjT5HvCPrnnypcDPVJqT/f4nfxmkE7gryY=
|
google.golang.org/genproto/googleapis/api v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:q4lMZS6kskjT5HvCPrnnypcDPVJqT/f4nfxmkE7gryY=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa h1:mZHHdPZl0dbGHCflZgAq/Q468DWVFcU2whhB2KAo8fk=
|
||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
|
google.golang.org/genproto/googleapis/rpc v0.0.0-20260526163538-3dc84a4a5aaa/go.mod h1:4Hqkh8ycfw05ld/3BWL7rJOSfebL2Q+DVDeRgYgxUU8=
|
||||||
google.golang.org/grpc v1.82.1 h1:NnAxzGRA0677vCa4BUkOAnO5+FfQqVl9iUXeD0IqcGE=
|
google.golang.org/grpc v1.83.1 h1:HIO0+BEtBP6soyqvqC8sNUjZ7bTs+0hFQuFF+RAy++Y=
|
||||||
google.golang.org/grpc v1.82.1/go.mod h1:yzTZ1TB1Z3SG+LIYaI+WiE8D5+PZ3ArnrSp8zF3+/ZA=
|
google.golang.org/grpc v1.83.1/go.mod h1:kDyl6SKsiHKt0uylY5gtn5cEjkrIOhQOGDgIc4JGwzQ=
|
||||||
google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af h1:+5/Sw3GsDNlEmu7TfklWKPdQ0Ykja5VEmq2i817+jbI=
|
google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af h1:+5/Sw3GsDNlEmu7TfklWKPdQ0Ykja5VEmq2i817+jbI=
|
||||||
google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
google.golang.org/protobuf v1.36.12-0.20260120151049-f2248ac996af/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
|||||||
Reference in New Issue
Block a user