diff --git a/.github/workflows/helm_ci.yml b/.github/workflows/helm_ci.yml index 9ff6705b9..264483409 100644 --- a/.github/workflows/helm_ci.yml +++ b/.github/workflows/helm_ci.yml @@ -942,6 +942,46 @@ jobs: if not failed: print("every workload has a policy covering all of its containerPorts") + # The bucket hook Job and its policy are gated on one shared helper, and + # this pins that down: a Job without its policy hangs under default-deny, + # a policy without its Job is noise. The combinations cover the modes that + # decide it, including the ones where a bucket list is ignored. + hook_cases = { + "nothing": {}, + "s3 without buckets": {"s3.enabled": "true"}, + "s3 with buckets": {"s3.enabled": "true", "s3.createBuckets[0].name": "b"}, + "filer.s3 without buckets": {"filer.s3.enabled": "true"}, + "filer.s3 with buckets": {"filer.s3.enabled": "true", + "filer.s3.createBuckets[0].name": "b"}, + "s3 gateway, buckets on filer.s3": {"s3.enabled": "true", + "filer.s3.createBuckets[0].name": "b"}, + "allInOne without buckets": {"allInOne.enabled": "true", + "allInOne.s3.enabled": "true"}, + "allInOne with buckets": {"allInOne.enabled": "true", + "allInOne.s3.enabled": "true", + "allInOne.s3.createBuckets[0].name": "b"}, + # allInOne reads only its own bucket list, so s3.createBuckets is + # not enough to produce the Job. + "allInOne, buckets on s3": {"allInOne.enabled": "true", + "allInOne.s3.enabled": "true", + "s3.createBuckets[0].name": "b"}, + "master off": {"master.enabled": "false", "s3.enabled": "true", + "s3.createBuckets[0].name": "b"}, + "buckets but no S3 endpoint": {"s3.createBuckets[0].name": "b"}, + } + for label, values in hook_cases.items(): + out = render(dict(values, **{"networkPolicy.enabled": "true"})) + job = any(d.get("kind") == "Job" + and d["metadata"]["name"].endswith("-bucket-hook") + for d in docs(out)) + policy = "bucket-hook" in policies(out) + if job != policy: + failed.append(f"{label}: bucket hook Job={job} but its policy={policy}; " + "the two are gated on seaweedfs.bucketHookEnabled and " + "have to appear together") + if not failed: + print(f"bucket hook Job and policy agree across {len(hook_cases)} modes") + # Egress is its own opt-in: with it off the policies must not constrain # outbound traffic at all, or enabling networkPolicy alone would cut the filer # off from its store. diff --git a/k8s/charts/seaweedfs/templates/shared/_helpers.tpl b/k8s/charts/seaweedfs/templates/shared/_helpers.tpl index de5943a40..a27bb0aa5 100644 --- a/k8s/charts/seaweedfs/templates/shared/_helpers.tpl +++ b/k8s/charts/seaweedfs/templates/shared/_helpers.tpl @@ -344,6 +344,22 @@ true {{- end -}} {{- end -}} +{{/* True when the post-install bucket hook Job renders: an S3 endpoint, plus + buckets to create on it. Read by the Job itself and by its NetworkPolicy, + which has to appear exactly when the Job does - a Job without its policy + hangs in a default-deny namespace. */}} +{{- define "seaweedfs.bucketHookEnabled" -}} +{{- if .Values.allInOne.enabled -}} +{{- if and .Values.allInOne.s3.enabled .Values.allInOne.s3.createBuckets -}} +true +{{- end -}} +{{- else if .Values.master.enabled -}} +{{- if and (or .Values.filer.s3.enabled .Values.s3.enabled) (or .Values.s3.createBuckets .Values.filer.s3.createBuckets) -}} +true +{{- end -}} +{{- end -}} +{{- end -}} + {{/* S3 TLS cert/key arguments, using custom secret if s3.tlsSecret is set */}} {{- define "seaweedfs.s3.tlsArgs" -}} {{- $prefix := .prefix -}} diff --git a/k8s/charts/seaweedfs/templates/shared/networkpolicy.yaml b/k8s/charts/seaweedfs/templates/shared/networkpolicy.yaml index 6b4d5b043..56d565d9c 100644 --- a/k8s/charts/seaweedfs/templates/shared/networkpolicy.yaml +++ b/k8s/charts/seaweedfs/templates/shared/networkpolicy.yaml @@ -112,17 +112,7 @@ then. The resize hook is pre-install weight 0, which runs before the manifest is applied at all, so its policy has to be a pre-install hook itself, at a weight below the Job's. */}} -{{- /* Same condition as the Job in post-install-bucket-hook.yaml: an S3 - endpoint plus buckets to create. Keep the two in step. */}} -{{- $bucketHook := false }} -{{- if .Values.allInOne.enabled }} -{{- $bucketHook = and .Values.allInOne.s3.enabled .Values.allInOne.s3.createBuckets }} -{{- else if .Values.master.enabled }} -{{- if or .Values.filer.s3.enabled .Values.s3.enabled }} -{{- $bucketHook = or .Values.s3.createBuckets .Values.filer.s3.createBuckets }} -{{- end }} -{{- end }} -{{- if $bucketHook }} +{{- if include "seaweedfs.bucketHookEnabled" . }} {{- $targets = append $targets (dict "component" "bucket-hook" "ports" (list)) }} {{- end }} {{- /* Whether the resize hook Job materialises depends on a cluster lookup, so diff --git a/k8s/charts/seaweedfs/templates/shared/post-install-bucket-hook.yaml b/k8s/charts/seaweedfs/templates/shared/post-install-bucket-hook.yaml index 83fab94b3..3cb5bd7e2 100644 --- a/k8s/charts/seaweedfs/templates/shared/post-install-bucket-hook.yaml +++ b/k8s/charts/seaweedfs/templates/shared/post-install-bucket-hook.yaml @@ -1,7 +1,6 @@ {{- include "seaweedfs.compat" . -}} {{- /* Support bucket creation for both standalone filer.s3 and allInOne modes */}} {{- $createBuckets := list }} -{{- $s3Enabled := false }} {{- $enableAuth := false }} {{- $existingConfigSecret := "" }} {{- $bucketsFolder := "/buckets" }} @@ -17,7 +16,6 @@ {{- /* Check allInOne mode first */}} {{- if .Values.allInOne.enabled }} {{- if .Values.allInOne.s3.enabled }} - {{- $s3Enabled = true }} {{- if .Values.allInOne.s3.createBuckets }} {{- $createBuckets = .Values.allInOne.s3.createBuckets }} {{- end }} @@ -27,7 +25,6 @@ {{- else if .Values.master.enabled }} {{- /* Check if embedded (in filer) or standalone S3 gateway is enabled */}} {{- if or .Values.filer.s3.enabled .Values.s3.enabled }} - {{- $s3Enabled = true }} {{- if .Values.s3.createBuckets }} {{- $createBuckets = .Values.s3.createBuckets }} {{- $enableAuth = .Values.s3.enableAuth }} @@ -40,9 +37,9 @@ {{- end }} {{- end }} -{{- /* networkpolicy.yaml decides whether to render this Job's policy off the - same condition. Keep the two in step. */}} -{{- if and $s3Enabled $createBuckets }} +{{- /* Shared with networkpolicy.yaml, which renders this Job's policy exactly + when the Job itself renders. */}} +{{- if include "seaweedfs.bucketHookEnabled" . }} --- apiVersion: batch/v1 kind: Job