Compare commits

...

3 Commits

Author SHA1 Message Date
Niklas Ye 36468a68ed chart: add bootstrap job (v0.2.0)
Post-install/post-upgrade Job that calls /api/bootstrap on first deploy
and stores the admin API key in a Secret (<release>-admin-key by default).
Exits cleanly on subsequent upgrades when bootstrap is already complete.
Adds ServiceAccount, Role (secrets:create), and RoleBinding as hook resources.
2026-05-22 10:11:30 +02:00
Niklas Ye 885ba73d12 chart: guard version sed behind tag pattern check 2026-05-21 18:14:09 +02:00
Niklas Ye 1451682cdd chart: add skip_existing and workflow_dispatch trigger 2026-05-21 18:08:30 +02:00
6 changed files with 161 additions and 4 deletions
+8 -3
View File
@@ -4,6 +4,7 @@ on:
push:
tags:
- 'v*'
workflow_dispatch:
jobs:
build:
@@ -94,12 +95,16 @@ jobs:
- name: Update chart versions
run: |
VERSION="${{ github.ref_name }}"
CHART_VERSION="${VERSION#v}"
sed -i "s/^version:.*/version: ${CHART_VERSION}/" charts/terdut-server/Chart.yaml
sed -i "s/^appVersion:.*/appVersion: \"${VERSION}\"/" charts/terdut-server/Chart.yaml
if [[ "$VERSION" =~ ^v[0-9] ]]; then
CHART_VERSION="${VERSION#v}"
sed -i "s/^version:.*/version: ${CHART_VERSION}/" charts/terdut-server/Chart.yaml
sed -i "s/^appVersion:.*/appVersion: \"${VERSION}\"/" charts/terdut-server/Chart.yaml
fi
- name: Run chart-releaser
uses: helm/chart-releaser-action@v1.6.0
with:
skip_existing: true
env:
CR_TOKEN: "${{ secrets.GITHUB_TOKEN }}"
+1 -1
View File
@@ -2,5 +2,5 @@ apiVersion: v2
name: terdut-server
description: A Helm chart for Terminal Duty — on-call alert management server
type: application
version: 0.1.0
version: 0.2.0
appVersion: "latest"
@@ -32,3 +32,7 @@ app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/name: {{ include "terdut-server.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{- define "terdut-server.bootstrapSecretName" -}}
{{- .Values.bootstrap.secretName | default (printf "%s-admin-key" (include "terdut-server.fullname" .)) }}
{{- end }}
@@ -0,0 +1,91 @@
{{- if .Values.bootstrap.enabled }}
---
apiVersion: batch/v1
kind: Job
metadata:
name: {{ include "terdut-server.fullname" . }}-bootstrap
namespace: {{ .Release.Namespace }}
labels:
{{- include "terdut-server.labels" . | nindent 4 }}
annotations:
helm.sh/hook: post-install,post-upgrade
helm.sh/hook-weight: "0"
helm.sh/hook-delete-policy: before-hook-creation,hook-succeeded
spec:
backoffLimit: 3
template:
metadata:
labels:
{{- include "terdut-server.selectorLabels" . | nindent 8 }}
app.kubernetes.io/component: bootstrap
spec:
restartPolicy: OnFailure
serviceAccountName: {{ include "terdut-server.fullname" . }}-bootstrap
containers:
- name: bootstrap
image: alpine:3
command:
- /bin/sh
- -c
- |
apk add --no-cache curl > /dev/null 2>&1
SERVICE_URL="http://{{ include "terdut-server.fullname" . }}:{{ .Values.service.port }}"
SECRET_NAME="{{ include "terdut-server.bootstrapSecretName" . }}"
K8S_API="https://kubernetes.default.svc"
SA_TOKEN="$(cat /var/run/secrets/kubernetes.io/serviceaccount/token)"
CA_CERT="/var/run/secrets/kubernetes.io/serviceaccount/ca.crt"
NAMESPACE="$(cat /var/run/secrets/kubernetes.io/serviceaccount/namespace)"
echo "Waiting for terdut-server to be ready..."
RETRIES=60
while [ "$RETRIES" -gt 0 ]; do
curl -sf "$SERVICE_URL/healthz" > /dev/null 2>&1 && break
RETRIES=$((RETRIES - 1))
sleep 2
done
if [ "$RETRIES" -eq 0 ]; then
echo "Timed out waiting for server to be ready."
exit 1
fi
echo "Server is ready."
RESPONSE=$(curl -s -w "\n%{http_code}" -X POST "$SERVICE_URL/api/bootstrap" \
-H "Content-Type: application/json" \
-d '{"username":"{{ .Values.bootstrap.username }}","email":"{{ .Values.bootstrap.email }}"}')
HTTP_CODE=$(echo "$RESPONSE" | tail -1)
BODY=$(echo "$RESPONSE" | head -1)
if [ "$HTTP_CODE" = "403" ]; then
echo "Server already bootstrapped, nothing to do."
exit 0
fi
if [ "$HTTP_CODE" != "201" ]; then
echo "Bootstrap failed (HTTP $HTTP_CODE): $BODY"
exit 1
fi
API_KEY=$(echo "$BODY" | grep -o '"key":"[^"]*"' | cut -d'"' -f4)
if [ -z "$API_KEY" ]; then
echo "Failed to extract API key from response."
exit 1
fi
echo "Bootstrap succeeded. Storing API key in secret '$SECRET_NAME'."
HTTP_CODE=$(curl -s -o /dev/null -w "%{http_code}" \
-X POST "$K8S_API/api/v1/namespaces/$NAMESPACE/secrets" \
--cacert "$CA_CERT" \
-H "Authorization: Bearer $SA_TOKEN" \
-H "Content-Type: application/json" \
-d "$(printf '{"apiVersion":"v1","kind":"Secret","metadata":{"name":"%s"},"stringData":{"api-key":"%s"}}' "$SECRET_NAME" "$API_KEY")")
if [ "$HTTP_CODE" != "201" ]; then
echo "Failed to create secret (HTTP $HTTP_CODE)."
exit 1
fi
echo "Secret '$SECRET_NAME' created successfully."
{{- end }}
@@ -0,0 +1,50 @@
{{- if .Values.bootstrap.enabled }}
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: {{ include "terdut-server.fullname" . }}-bootstrap
namespace: {{ .Release.Namespace }}
labels:
{{- include "terdut-server.labels" . | nindent 4 }}
annotations:
helm.sh/hook: post-install,post-upgrade
helm.sh/hook-weight: "-1"
helm.sh/hook-delete-policy: before-hook-creation
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: {{ include "terdut-server.fullname" . }}-bootstrap
namespace: {{ .Release.Namespace }}
labels:
{{- include "terdut-server.labels" . | nindent 4 }}
annotations:
helm.sh/hook: post-install,post-upgrade
helm.sh/hook-weight: "-1"
helm.sh/hook-delete-policy: before-hook-creation
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["create"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: {{ include "terdut-server.fullname" . }}-bootstrap
namespace: {{ .Release.Namespace }}
labels:
{{- include "terdut-server.labels" . | nindent 4 }}
annotations:
helm.sh/hook: post-install,post-upgrade
helm.sh/hook-weight: "-1"
helm.sh/hook-delete-policy: before-hook-creation
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: {{ include "terdut-server.fullname" . }}-bootstrap
subjects:
- kind: ServiceAccount
name: {{ include "terdut-server.fullname" . }}-bootstrap
namespace: {{ .Release.Namespace }}
{{- end }}
+7
View File
@@ -14,3 +14,10 @@ storage:
service:
type: ClusterIP
port: 8080
bootstrap:
enabled: true
username: admin
email: admin@example.com
# secretName overrides the default of <fullname>-admin-key
secretName: ""