helm: add namespaceOverride to deploy into another namespace (#12256)

* helm: add namespaceOverride to deploy into another namespace

When the chart is a subchart of an umbrella chart, every object lands in
the umbrella's release namespace, with no way to give SeaweedFS its own.

namespaceOverride, empty by default, now sets the namespace of every
object through a new seaweedfs.namespace helper, which falls back to the
release namespace. All uses of .Release.Namespace go through it, so the
in-cluster addresses, certificate SANs, ClusterRoleBinding subjects,
HTTPRoute backendRefs and lookups follow the override too. The
self-signed Issuer, the bucket hook Job and the volume resize hook
objects, which had no metadata.namespace, now set it.

With namespaceOverride unset the default render is unchanged. Adds a
helm_ci check that renders with an override and asserts nothing is left
in the release namespace.

* ci: cover the bucket hook Job in the all-in-one namespace test

The all-in-one render set s3.createBuckets, which bucketHookEnabled
ignores in allInOne mode, so the Job never rendered and the namespace
check could not see it. Use allInOne.s3.createBuckets and assert the
Job is present.

* helm: fail on an invalid namespaceOverride instead of reshaping it

Truncating and trimming could silently map an override onto a different
existing namespace and deploy into it. Validate against the DNS-1123
namespace rules and fail the render instead.

* helm: bound the master data volume name at 63 characters

data-<namespace> can exceed the Kubernetes name limit when the release
or override namespace is near 63 characters; truncate the composed name
and trim a trailing hyphen like the other name helpers.

* helm: quote the rendered namespace in YAML fields

* helm: warn that changing namespaceOverride strands claims and data

* helm: say namespaceOverride only moves namespaced objects

* helm: retrigger the PR head sync (no changes)

* helm: warn that secrets and hook resources do not follow namespaceOverride

* helm: warn that hostPath data does not follow namespaceOverride

---------

Co-authored-by: jeffWild <20067853+jeffWild@users.noreply.github.com>
Co-authored-by: chrislusf <chrislusf@users.noreply.github.com>
This commit is contained in:
authored and GitHub committed 2026-10-30 11:24:36 -07:00
1 parent 816f9356b4
commit b7bfbaf9eb
70 files changed
+224 -138

No files matched your search

+55
View File
@@ -1934,6 +1934,61 @@ jobs:
PYEOF
echo "License + master persistence tests passed"
echo ""
echo "=== Testing namespaceOverride ==="
NS_ARGS=(
--set s3.enabled=true --set s3.enableAuth=true
--set 's3.createBuckets[0].name=data'
--set sftp.enabled=true --set sftp.enableAuth=true
--set admin.enabled=true --set admin.secret.adminPassword=ci
--set worker.enabled=true
--set cosi.enabled=true --set cosi.bucketClassName=seaweedfs
--set global.seaweedfs.enableSecurity=true
--set global.seaweedfs.monitoring.enabled=true
--set networkPolicy.enabled=true
--set volumes.extra.replicas=1
)
helm template test $CHART_DIR --namespace release-ns "${NS_ARGS[@]}" \
--set namespaceOverride=other-ns > /tmp/ns-override.yaml
helm template test $CHART_DIR --namespace release-ns \
--set allInOne.enabled=true --set allInOne.s3.enabled=true \
--set master.enabled=false --set volume.enabled=false --set filer.enabled=false \
--set 'allInOne.s3.createBuckets[0].name=data' \
--set global.seaweedfs.enableSecurity=true \
--set namespaceOverride=other-ns > /tmp/ns-override-aio.yaml
grep -q 'kind: Job' /tmp/ns-override-aio.yaml
python3 - /tmp/ns-override.yaml /tmp/ns-override-aio.yaml <<'PYEOF'
import sys, yaml
CLUSTER_SCOPED = {"ClusterRole", "ClusterRoleBinding", "BucketClass", "BucketAccessClass"}
failed = []
for path in sys.argv[1:]:
text = open(path).read()
if "release-ns" in text:
failed.append(f"{path}: release namespace still rendered")
for d in yaml.safe_load_all(text):
if not d:
continue
kind, md = d["kind"], d["metadata"]
if kind in CLUSTER_SCOPED:
for s in d.get("subjects") or []:
if s.get("namespace") != "other-ns":
failed.append(f"{path}: {kind}/{md['name']} subject in {s.get('namespace')!r}")
elif md.get("namespace") != "other-ns":
failed.append(f"{path}: {kind}/{md['name']} in {md.get('namespace')!r}")
if failed:
print("\n".join(failed), file=sys.stderr)
sys.exit(1)
PYEOF
grep -q -- '-filer=test-seaweedfs-filer-client.other-ns:' /tmp/ns-override.yaml
grep -q 'test-seaweedfs-master-0.test-seaweedfs-master.other-ns:' /tmp/ns-override.yaml
grep -qF "'*.other-ns.svc.cluster.local'" /tmp/ns-override.yaml
# Setting it to the release namespace changes nothing.
helm template test $CHART_DIR --namespace release-ns > /tmp/ns-default.yaml
helm template test $CHART_DIR --namespace release-ns \
--set namespaceOverride=release-ns > /tmp/ns-same.yaml
diff /tmp/ns-default.yaml /tmp/ns-same.yaml
echo "namespaceOverride moves every namespaced object and address"
echo "All template rendering tests passed!"
- name: Resolve an image tag that is published