Skip to content

feat: allow ArgoCD Image Updater to watch specific namespaces#1488

Open
grahamalama wants to merge 3 commits intoargoproj-labs:masterfrom
grahamalama:limit-application-namespace
Open

feat: allow ArgoCD Image Updater to watch specific namespaces#1488
grahamalama wants to merge 3 commits intoargoproj-labs:masterfrom
grahamalama:limit-application-namespace

Conversation

@grahamalama
Copy link
Copy Markdown
Contributor

@grahamalama grahamalama commented Feb 11, 2026

In this PR, I'm essentially trying to re-enable what was introduced in #1112.

Adds configuration to scope the controller to specific namespaces, enabling use of namespace-scoped Roles instead of ClusterRoles. Useful for multi-tenant environments where cluster-wide RBAC is not desired.

Summary by CodeRabbit

  • New Features

    • Namespace-scoped operation mode allowing the controller to watch only specified namespaces.
    • New CLI flag (--watch-namespaces) and environment variable (IMAGE_UPDATER_WATCH_NAMESPACES) to configure watched namespaces; controller enforces valid, non-empty namespace lists.
  • Documentation

    • Added docs and installation guide for namespace-scoped setup, RBAC adjustments, examples, and usage notes.

@grahamalama grahamalama changed the title feat: allow Argo Image Updater to watch specific namespaces feat: allow ArgoCD Image Updater to watch specific namespaces Feb 11, 2026
@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Feb 11, 2026

Walkthrough

Adds namespace-scoped operation via a new --watch-namespaces flag and IMAGE_UPDATER_WATCH_NAMESPACES env var, configures controller-runtime Manager with cache.Options{DefaultNamespaces: ...}, extends ImageUpdaterConfig with WatchNamespaces, and updates deployment config and docs.

Changes

Cohort / File(s) Summary
Runtime / CLI
cmd/run.go
Adds --watch-namespaces flag, parses comma-separated namespaces, validates entries, builds cache.Options{DefaultNamespaces: ...}, and passes it to ctrl.NewManager; errors if no valid namespaces provided.
Kubernetes manifests
config/install.yaml, config/manager/manager.yaml
Adds IMAGE_UPDATER_WATCH_NAMESPACES env var sourced from argocd-image-updater-config ConfigMap key watch-namespaces (optional) to the controller Deployment.
Controller config
internal/controller/imageupdater_controller.go
Adds WatchNamespaces string field to ImageUpdaterConfig.
Documentation
docs/install/cmd/run.md, docs/install/installation.md
Documents --watch-namespaces flag, env var alias, and provides namespace-scoped installation and RBAC guidance.
sequenceDiagram
    participant Operator as Operator (CLI / Deployment)
    participant Controller as argocd-image-updater (cmd/run)
    participant Manager as controller-runtime Manager
    participant K8s as Kubernetes API Server

    Operator->>Controller: start with --watch-namespaces / env var
    Controller->>Controller: parse CSV, validate namespaces
    Controller->>Manager: provide cache.Options(DefaultNamespaces)
    Manager->>K8s: initialize cache scoped to specified namespaces
    Manager->>Controller: start controllers using scoped cache
Loading
🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title accurately and concisely describes the main feature: allowing ArgoCD Image Updater to watch specific namespaces, which directly aligns with the primary purpose of enabling namespace-scoped operation.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

Tip

Issue Planner is now in beta. Read the docs and try it out! Share your feedback on Discord.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Add configuration to scope the controller to specific namespaces,
enabling use of namespace-scoped Roles instead of ClusterRoles.
Useful for multi-tenant environments where cluster-wide RBAC is
not permitted.

Signed-off-by: Graham Beckley <gbeckley@mozilla.com>
@grahamalama grahamalama force-pushed the limit-application-namespace branch from 8e5d73e to cf636b0 Compare February 11, 2026 16:25
@codecov-commenter
Copy link
Copy Markdown

codecov-commenter commented Feb 11, 2026

Codecov Report

❌ Patch coverage is 7.14286% with 13 lines in your changes missing coverage. Please review.
✅ Project coverage is 72.33%. Comparing base (c1674be) to head (3bce3aa).
⚠️ Report is 38 commits behind head on master.

Files with missing lines Patch % Lines
cmd/run.go 7.14% 13 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##           master    #1488      +/-   ##
==========================================
+ Coverage   71.48%   72.33%   +0.85%     
==========================================
  Files          50       51       +1     
  Lines        4667     4906     +239     
==========================================
+ Hits         3336     3549     +213     
- Misses       1133     1156      +23     
- Partials      198      201       +3     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@cmd/run.go`:
- Around line 184-192: Add a startup validation before creating the manager
(before ctrl.NewManager) that checks if leaderElectionNamespace is non-empty and
leader election is enabled and the controller is running in namespace-scoped
watch mode (i.e., the configured watched namespaces are a restricted set rather
than all namespaces); if so, verify the leaderElectionNamespace is included in
the watched namespace set (or warn/error if not) and fail fast or log a clear
warning explaining the RBAC lease restriction; update docs/install/cmd/run.md to
state that --leader-election-namespace must be inside the --watch-namespaces set
for namespace-scoped deployments (or be left empty to use the pod namespace) as
an alternative to runtime validation.

In `@docs/install/installation.md`:
- Line 199: The sentence containing the log message "Configuring
namespace-scoped operation" in the installation documentation is missing a
trailing period; edit the sentence to add a period at the end so it reads
"Configuring namespace-scoped operation." to match punctuation style.
🧹 Nitpick comments (1)
docs/install/cmd/run.md (1)

176-188: Flag documentation is placed between the two --metrics-* flags.

The --watch-namespaces block splits --metrics-bind-address and --metrics-secure. Consider moving it to maintain grouping of related flags (e.g., after --metrics-secure or in alphabetical order with the other flags).

Comment on lines 184 to 192
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
Scheme: scheme,
Metrics: metricsServerOptions,
HealthProbeBindAddress: probeAddr,
LeaderElection: enableLeaderElection,
LeaderElectionID: "c21b75f2.argoproj.io",
LeaderElectionNamespace: leaderElectionNamespace,
Cache: cacheOptions,
})
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Check docs and config for leader election lease permissions
rg -n "leases" docs/ config/rbac/ --type md --type yaml 2>/dev/null || true

# Check for coordination.k8s.io API group
rg -n "coordination" docs/ config/rbac/ --type md --type yaml 2>/dev/null || true

Repository: argoproj-labs/argocd-image-updater

Length of output: 1547


🏁 Script executed:

# View the leader election role file
cat config/rbac/leader_election_role.yaml

# List all RBAC files
echo "=== All RBAC files ===" 
fd . config/rbac/ --type f

# Check for any role bindings
rg -n "roleRef\|RoleBinding\|ClusterRoleBinding" config/rbac/ --type yaml

Repository: argoproj-labs/argocd-image-updater

Length of output: 1153


🏁 Script executed:

# Check the leader election role binding
cat config/rbac/leader_election_role_binding.yaml

# Look at cmd/run.go to see how leaderElectionNamespace is handled
head -250 cmd/run.go | tail -100

# Search for namespace validation logic
rg -n "leaderElectionNamespace\|--leader-election-namespace" cmd/ --type go -A 3

Repository: argoproj-labs/argocd-image-updater

Length of output: 4226


🏁 Script executed:

# Find where leaderElectionNamespace is defined as a flag
rg -n "leader-election-namespace\|leaderElectionNamespace" cmd/ --type go -B 2 -A 2

# Search for any validation that compares leaderElectionNamespace with watchNamespaces
rg -n "leaderElectionNamespace.*watchNamespaces\|watchNamespaces.*leaderElectionNamespace" --type go

Repository: argoproj-labs/argocd-image-updater

Length of output: 60


🏁 Script executed:

# Let's look at a broader section of cmd/run.go to find flag definitions
cat cmd/run.go | head -100

# Also search for how leaderElectionNamespace is declared/used
rg -n "leaderElectionNamespace" . --type go

# Search for flag setup patterns
rg -n "flag\|Flag" cmd/run.go --type go | head -20

Repository: argoproj-labs/argocd-image-updater

Length of output: 3690


🏁 Script executed:

# Look at the full flag definitions section around line 312
sed -n '290,320p' cmd/run.go

# Search for any validation logic after flag parsing that might check leaderElectionNamespace
rg -n "leaderElectionNamespace\|watchNamespaces\|WatchNamespaces" cmd/run.go --type go -A 2 -B 2

# Check if there are any error checks or warnings about namespace mismatches
rg -n "namespace.*mismatch\|lease.*permission\|RBAC\|error" cmd/run.go --type go | grep -i "leader\|election\|namespace"

Repository: argoproj-labs/argocd-image-updater

Length of output: 2715


🏁 Script executed:

# Get the full section from flag parsing to manager start to check for any validation
sed -n '70,220p' cmd/run.go

# Also check if there's any validation in the controller itself
rg -n "DefaultNamespaces\|leaderElection\|lease" cmd/ --type go -B 3 -A 3

Repository: argoproj-labs/argocd-image-updater

Length of output: 5908


🏁 Script executed:

# Search documentation for any mention of leader election namespace requirements
rg -n "leader" docs/ --type md -i -B 2 -A 2

# Check if there's any README or installation guide mentioning this
cat README.md 2>/dev/null | grep -i "leader\|election\|namespace" || echo "Not found in README"

# Check installation or deployment docs
find docs/ -type f \( -name "*.md" -o -name "*.yaml" \) | xargs rg -l "install\|deploy" 2>/dev/null | head -5

Repository: argoproj-labs/argocd-image-updater

Length of output: 832


🏁 Script executed:

# Check if there's documentation about namespace-scoped RBAC requirements
rg -n "namespace.*scoped\|RBAC\|role.*binding" docs/install/ --type md -B 2 -A 2

# Look at the full installation doc
cat docs/install/cmd/run.md | head -150

Repository: argoproj-labs/argocd-image-updater

Length of output: 4938


Add validation or warning when leader election namespace differs from watched namespaces.

With namespace-scoped RBAC, the leader-election-role Role only applies permissions in its bound namespace. If --leader-election-namespace is set to a namespace outside --watch-namespaces, the controller will fail to acquire the leadership lease due to missing RBAC permissions.

Add either:

  1. A startup validation that warns or errors if --leader-election-namespace is set and not included in --watch-namespaces (when namespace-scoped mode is enabled)
  2. Documentation in docs/install/cmd/run.md clarifying that --leader-election-namespace must be included in the watched set for namespace-scoped deployments, or left empty to use the controller pod's namespace
🤖 Prompt for AI Agents
In `@cmd/run.go` around lines 184 - 192, Add a startup validation before creating
the manager (before ctrl.NewManager) that checks if leaderElectionNamespace is
non-empty and leader election is enabled and the controller is running in
namespace-scoped watch mode (i.e., the configured watched namespaces are a
restricted set rather than all namespaces); if so, verify the
leaderElectionNamespace is included in the watched namespace set (or warn/error
if not) and fail fast or log a clear warning explaining the RBAC lease
restriction; update docs/install/cmd/run.md to state that
--leader-election-namespace must be inside the --watch-namespaces set for
namespace-scoped deployments (or be left empty to use the pod namespace) as an
alternative to runtime validation.


Alternatively, you can add the `--watch-namespaces=argocd,team-a` flag to the container's `command` arguments in the deployment manifest, or set the `IMAGE_UPDATER_WATCH_NAMESPACES` environment variable.

The controller logs `Configuring namespace-scoped operation` on startup when this mode is active
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Missing period at end of sentence.

Line 199 is missing a trailing period.

-The controller logs `Configuring namespace-scoped operation` on startup when this mode is active
+The controller logs `Configuring namespace-scoped operation` on startup when this mode is active.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
The controller logs `Configuring namespace-scoped operation` on startup when this mode is active
The controller logs `Configuring namespace-scoped operation` on startup when this mode is active.
🤖 Prompt for AI Agents
In `@docs/install/installation.md` at line 199, The sentence containing the log
message "Configuring namespace-scoped operation" in the installation
documentation is missing a trailing period; edit the sentence to add a period at
the end so it reads "Configuring namespace-scoped operation." to match
punctuation style.

Signed-off-by: Graham Beckley <gbeckley@mozilla.com>
@dkarpele dkarpele added the hold label Feb 11, 2026
@grahamalama
Copy link
Copy Markdown
Contributor Author

@dkarpele what does the hold label mean?

@chengfang
Copy link
Copy Markdown
Collaborator

Does #1490 addresses your requirements and concerns?

@chengfang
Copy link
Copy Markdown
Collaborator

@grahamalama thanks for your contribution. As we're working on high-priority features and fixes, issues and pr labelled hold will take a backseat in the near term. But we'll get to it as soon as we can.

@grahamalama
Copy link
Copy Markdown
Contributor Author

Does #1490 addresses your requirements and concerns?

I'm not exactly sure, but I don't think so. Even with this change, I think the controller will still search across all namespaces and as a result, require a ClusterRole. We'd like to limit the namespaces the controller searches so we only need Roles

Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
config/install.yaml (1)

618-664: Consider documenting RBAC implications for namespace-scoped installs.

The PR's goal is to let operators use namespace-scoped Roles instead of ClusterRoles, but this install.yaml still ships ClusterRole / ClusterRoleBinding for the manager (lines 618-664, 725-739). Users enabling --watch-namespaces will need to manually replace these with per-namespace Role/RoleBinding resources.

It would be helpful to either:

  • Add a comment in this file near the ClusterRole noting it can be replaced with Roles when watch-namespaces is configured, or
  • Provide a separate overlay/example for namespace-scoped installs.

This isn't blocking, just a usability improvement for the feature's target audience.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@config/install.yaml` around lines 618 - 664, The ClusterRole
"argocd-image-updater-manager-role" is shipped for the manager but the PR
enables namespace-scoped installs; update the install.yaml to document this by
adding a clear comment immediately above the ClusterRole (and corresponding
ClusterRoleBinding) stating that these ClusterRole/ClusterRoleBinding resources
can be replaced with per-namespace Role/RoleBinding when using the
--watch-namespaces option, and optionally add or reference a separate
example/overlay for namespace-scoped installation so operators have a ready
template to copy.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@config/install.yaml`:
- Around line 618-664: The ClusterRole "argocd-image-updater-manager-role" is
shipped for the manager but the PR enables namespace-scoped installs; update the
install.yaml to document this by adding a clear comment immediately above the
ClusterRole (and corresponding ClusterRoleBinding) stating that these
ClusterRole/ClusterRoleBinding resources can be replaced with per-namespace
Role/RoleBinding when using the --watch-namespaces option, and optionally add or
reference a separate example/overlay for namespace-scoped installation so
operators have a ready template to copy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants