helm: label the hook Job pods so selectors can reach them

The bucket hook pod carries only managed-by/instance and the volume
resize hook pod carries no labels at all, so nothing keyed on the
standard app.kubernetes.io set can address either of them. Give both
the same name/chart/managed-by/instance/component labels the other
workloads use, with the component naming each hook.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Sebastian Preisner
2026-07-29 11:15:04 +02:00
co-authored by Claude Opus 5
parent 13176b4edd
commit 900e409f5d
3 changed files with 105 additions and 0 deletions
+86
View File
@@ -697,6 +697,92 @@ jobs:
echo "$BOOL_FALSE" | grep -q -- '-status Suspended' || { echo "FAIL: bool false versioning did not Suspend the bucket"; exit 1; }
echo "Bucket versioning: YAML bool false suspends consistently with string \"false\""
echo ""
echo "=== Testing hook Job labels ==="
# The hook Jobs were the only pods in the chart without the standard
# app.kubernetes.io label set, so nothing label-based could target
# them - NetworkPolicy podSelectors, monitoring, kubectl -l. Assert
# both the Job and its pod template carry the same name/instance/
# component triple the other components use, and that the triple is
# the hook's own so a per-component selector cannot match it too.
#
# Only the bucket hook is covered: the volume resize hook is gated on
# lookup finding a StatefulSet with a smaller PVC than requested, and
# lookup returns nothing under helm template, so it never renders here.
python3 - "$CHART_DIR" <<'PYEOF'
import subprocess, sys, yaml
chart = sys.argv[1]
TRIPLE = ("app.kubernetes.io/name", "app.kubernetes.io/instance",
"app.kubernetes.io/component")
def render(values):
args = ["helm", "template", "test", chart]
for k, v in values.items():
args += ["--set", f"{k}={v}"]
return subprocess.check_output(args, text=True)
def docs(manifest):
return [d for d in yaml.safe_load_all(manifest) if d]
def hook_job(manifest):
for d in docs(manifest):
if d.get("kind") == "Job" and d["metadata"]["name"].endswith("-bucket-hook"):
return d
return None
def triple(labels):
return {k: labels.get(k) for k in TRIPLE}
modes = {
"s3": {"s3.enabled": "true",
"s3.createBuckets[0].name": "b"},
"filer.s3": {"filer.s3.enabled": "true",
"filer.s3.createBuckets[0].name": "b"},
"allInOne": {"allInOne.enabled": "true",
"allInOne.s3.enabled": "true",
"allInOne.s3.createBuckets[0].name": "b"},
}
failed = []
for mode, values in modes.items():
before = len(failed)
out = render(values)
job = hook_job(out)
if job is None:
failed.append(f"{mode}: bucket hook Job not rendered")
continue
pod_labels = job["spec"]["template"]["metadata"].get("labels", {})
for where, labels in (("Job", job["metadata"].get("labels", {})),
("pod", pod_labels)):
missing = [k for k in TRIPLE if not labels.get(k)]
if missing:
failed.append(f"{mode}: bucket hook {where} has no {missing}, "
"nothing can select it")
component = pod_labels.get("app.kubernetes.io/component")
if component != "bucket-hook":
failed.append(f"{mode}: bucket hook pod component is {component!r}, "
"expected 'bucket-hook'")
# The triple must not also match another component's pods, or a
# selector meant for that component would pull the hook pod in.
for d in docs(out):
if d.get("kind") not in ("Deployment", "StatefulSet"):
continue
other = d["spec"]["template"]["metadata"].get("labels", {})
if triple(other) == triple(pod_labels):
failed.append(f"{mode}: bucket hook pod shares its label triple "
f"with {d['metadata']['name']}")
if len(failed) == before:
print(f"{mode}: bucket hook Job and pod carry a distinct label triple")
if failed:
print("\nFAIL:", file=sys.stderr)
for f in failed:
print(f" - {f}", file=sys.stderr)
sys.exit(1)
PYEOF
echo "Hook Job label tests passed"
echo "All template rendering tests passed!"
- name: Create kind cluster
@@ -47,8 +47,11 @@ kind: Job
metadata:
name: "{{ $.Release.Name }}-bucket-hook"
labels:
app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
app.kubernetes.io/instance: {{ .Release.Name | quote }}
app.kubernetes.io/component: bucket-hook
annotations:
"helm.sh/hook": post-install,post-upgrade
"helm.sh/hook-weight": "-5"
@@ -58,8 +61,11 @@ spec:
metadata:
name: "{{ .Release.Name }}"
labels:
app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
app.kubernetes.io/managed-by: {{ .Release.Service | quote }}
app.kubernetes.io/instance: {{ .Release.Name | quote }}
app.kubernetes.io/component: bucket-hook
spec:
restartPolicy: Never
{{- if .Values.filer.podSecurityContext.enabled }}
@@ -53,6 +53,12 @@ apiVersion: batch/v1
kind: Job
metadata:
name: "{{ $seaweedfsName }}-volume-resize-hook"
labels:
app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: volume-resize-hook
annotations:
helm.sh/hook: pre-install,pre-upgrade
helm.sh/hook-weight: "0"
@@ -60,6 +66,13 @@ metadata:
spec:
backoffLimit: 1
template:
metadata:
labels:
app.kubernetes.io/name: {{ template "seaweedfs.name" . }}
helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: volume-resize-hook
spec:
serviceAccountName: {{ $seaweedfsName }}-volume-resize-hook
restartPolicy: Never