Files
Michał MarszałekandClaude Opus 4.8 50153d05ea feat: scoped multi-namespace mode (Role per namespace, no ClusterRole)
Add a third RBAC posture between watch-globally (ClusterRole) and single
namespace: give Reloader an explicit list of namespaces to watch. The chart
creates a namespace-scoped Role + RoleBinding in each listed namespace (no
ClusterRole), and one install covers them all.

Go:
- new --namespaces flag / options.Namespaces
- resolveWatchNamespaces() picks list -> KUBERNETES_NAMESPACE -> all
- controller creation loops over the watched namespaces
- namespaces-to-ignore is now only honored in global mode (watchGlobally=true);
  in single-namespace and scoped modes the watched set is already explicit

Helm:
- new reloader.namespaces value (active when watchGlobally=false); accepts either
  a YAML list or a comma-separated string for consistency with the sibling
  namespace options
- reloader-watchNamespaces helper (release ns always auto-included, deduped)
- shared reloader-namespaced-rules template reused per namespace
- role.yaml/rolebinding.yaml range over the list; deployment passes --namespaces
- --namespaces-to-ignore only rendered when watchGlobally=true
- fail guard for watchGlobally=true + namespaces set

Tests: unit test for resolveWatchNamespaces; scoped-namespaces e2e case.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-26 15:48:38 +02:00

80 lines
2.5 KiB
YAML

{{- if and .Values.reloader.watchGlobally .Values.reloader.namespaces }}
{{- fail "reloader.namespaces is set but reloader.watchGlobally is true; set reloader.watchGlobally=false to use scoped namespace mode." }}
{{- end }}
{{- if and (not (.Values.reloader.watchGlobally)) (.Values.reloader.rbac.enabled) }}
{{- $apiVersion := "rbac.authorization.k8s.io/v1" }}
{{- if not (.Capabilities.APIVersions.Has "rbac.authorization.k8s.io/v1") }}
{{- $apiVersion = "rbac.authorization.k8s.io/v1beta1" }}
{{- end }}
{{- if .Values.reloader.namespaces }}
{{- range $ns := (include "reloader-watchNamespaces" . | mustFromJson) }}
apiVersion: {{ $apiVersion }}
kind: Role
metadata:
annotations:
{{ include "reloader-helm3.annotations" $ | indent 4 }}
labels:
{{ include "reloader-labels.chart" $ | indent 4 }}
{{- if $.Values.reloader.rbac.labels }}
{{ tpl (toYaml $.Values.reloader.rbac.labels) $ | indent 4 }}
{{- end }}
{{- if $.Values.reloader.matchLabels }}
{{ tpl (toYaml $.Values.reloader.matchLabels) $ | indent 4 }}
{{- end }}
name: {{ template "reloader-fullname" $ }}-role
namespace: {{ $ns }}
rules:
{{- include "reloader-namespaced-rules" $ }}
---
{{- end }}
{{- else }}
apiVersion: {{ $apiVersion }}
kind: Role
metadata:
annotations:
{{ include "reloader-helm3.annotations" . | indent 4 }}
labels:
{{ include "reloader-labels.chart" . | indent 4 }}
{{- if .Values.reloader.rbac.labels }}
{{ tpl (toYaml .Values.reloader.rbac.labels) . | indent 4 }}
{{- end }}
{{- if .Values.reloader.matchLabels }}
{{ tpl (toYaml .Values.reloader.matchLabels) . | indent 4 }}
{{- end }}
name: {{ template "reloader-fullname" . }}-role
namespace: {{ .Values.namespace | default .Release.Namespace }}
rules:
{{- include "reloader-namespaced-rules" . }}
{{- end }}
{{- end }}
---
{{- if .Values.reloader.rbac.enabled }}
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
annotations:
{{ include "reloader-helm3.annotations" . | indent 4 }}
labels:
{{ include "reloader-labels.chart" . | indent 4 }}
{{- if .Values.reloader.rbac.labels }}
{{ tpl (toYaml .Values.reloader.rbac.labels) . | indent 4 }}
{{- end }}
{{- if .Values.reloader.matchLabels }}
{{ tpl (toYaml .Values.reloader.matchLabels) . | indent 4 }}
{{- end }}
name: {{ template "reloader-fullname" . }}-metadata-role
namespace: {{ .Values.namespace | default .Release.Namespace }}
rules:
- apiGroups:
- ""
resources:
- configmaps
verbs:
- list
- get
- watch
- create
- update
{{- end }}