Skip to content

OCPBUGS-97605: Use static ServiceAccount for operand#535

Open
bentito wants to merge 3 commits into
openshift:mainfrom
bentito:OCPBUGS-97605-static-operand-sa
Open

OCPBUGS-97605: Use static ServiceAccount for operand#535
bentito wants to merge 3 commits into
openshift:mainfrom
bentito:OCPBUGS-97605-static-operand-sa

Conversation

@bentito

@bentito bentito commented Jul 17, 2026

Copy link
Copy Markdown

When the operator is installed in a custom namespace, OLM fails to rewrite Group subjects in the ClusterRoleBinding. By standardizing the operand to use a single static ServiceAccount ('external-dns') and referencing it as a ServiceAccount subject, OLM successfully dynamically rewrites the namespace field during custom namespace installs, allowing operand pods to function correctly.

This aligns with Red Hat's philosophy that operators should be namespace-agnostic and resolves the issue where OLM fails to rewrite Group subjects for custom namespace installations.

Includes a build fix to allow the golangci-lint script to run on Apple Silicon.

Resolves: https://issues.redhat.com/browse/OCPBUGS-97605

@openshift-ci-robot openshift-ci-robot added jira/severity-low Referenced Jira bug's severity is low for the branch this PR is targeting. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. jira/invalid-bug Indicates that a referenced Jira bug is invalid for the branch this PR is targeting. labels Jul 17, 2026
@openshift-ci-robot

Copy link
Copy Markdown

@bentito: This pull request references Jira Issue OCPBUGS-97605, which is invalid:

  • expected the bug to target the "5.0.0" version, but no target version was set

Comment /jira refresh to re-evaluate validity if changes to the Jira bug are made, or edit the title of this pull request to link to a different bug.

The bug has been updated to refer to the pull request using the external bug tracker.

Details

In response to this:

When the operator is installed in a custom namespace, OLM fails to rewrite Group subjects in the ClusterRoleBinding. By standardizing the operand to use a single static ServiceAccount ('external-dns') and referencing it as a ServiceAccount subject, OLM successfully dynamically rewrites the namespace field during custom namespace installs, allowing operand pods to function correctly.

This aligns with Red Hat's philosophy that operators should be namespace-agnostic and resolves the issue where OLM fails to rewrite Group subjects for custom namespace installations.

Includes a build fix to allow the golangci-lint script to run on Apple Silicon.

Resolves: https://issues.redhat.com/browse/OCPBUGS-97605

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@bentito, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 45 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 270c2c72-2e99-4d70-9dbc-da57fe927c26

📥 Commits

Reviewing files that changed from the base of the PR and between 84d558d and 0e98973.

📒 Files selected for processing (7)
  • bundle/manifests/external-dns_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml
  • config/rbac/operand_rolebinding.yaml
  • hack/golangci-lint.sh
  • pkg/operator/controller/externaldns/controller_test.go
  • pkg/operator/controller/externaldns/service_account.go
  • pkg/operator/controller/externaldns/service_account_test.go
  • pkg/operator/controller/names.go
📝 Walkthrough

Walkthrough

The ExternalDNS controller now uses a fixed operand ServiceAccount name for lookups and desired resources. Tests, source RBAC, and generated RBAC manifests reflect the explicit ServiceAccount subject in the external-dns-operator namespace. The golangci-lint script adds macOS architecture support and selects platform-specific checksum verification commands.

🚥 Pre-merge checks | ✅ 14 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (14 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly summarizes the main change: switching the operand to a static ServiceAccount.
Description check ✅ Passed The description accurately describes the ServiceAccount change and the golangci-lint build fix in the patch.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Stable And Deterministic Test Names ✅ Passed The touched tests use only static case names (e.g. "Bootstrap", "Exists"); no dynamic IDs, timestamps, namespaces, or other unstable title text appears.
Test Structure And Quality ✅ Passed PASS: The changed tests are simple table-driven unit tests; they add no new setup/cleanup, timeouts, or multi-behavior assertions, and they match existing repo patterns.
Microshift Test Compatibility ✅ Passed The changed test files use plain Go unit tests (t.Run), not new Ginkgo e2e specs, so the MicroShift check is not applicable.
Single Node Openshift (Sno) Test Compatibility ✅ Passed No new Ginkgo/e2e tests were added; the touched tests are unit tests using t.Run and contain no multi-node or SNO-unsafe assumptions.
Topology-Aware Scheduling Compatibility ✅ Passed Touched files only change RBAC, service-account naming, tests, and linting; no new affinity, selectors, tolerations, replicas, or PDBs were added.
Ote Binary Stdout Contract ✅ Passed The PR only changes RBAC, a shell script, and ordinary reconciler/unit-test code; no main/init/TestMain/suite-setup stdout writes were added.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed No new Ginkgo e2e tests were added; changed tests are unit tests using testing.T and show no IPv4-only or external-network assumptions.
No-Weak-Crypto ✅ Passed No weak crypto, custom crypto, or secret comparisons were introduced; the shell change only uses SHA256 checksum verification.
Container-Privileges ✅ Passed PR changes only RBAC subjects, tests, and a lint script; no modified manifest adds privileged, hostPID/hostNetwork/hostIPC, SYS_ADMIN, or allowPrivilegeEscalation.
No-Sensitive-Data-In-Logs ✅ Passed Changed code only logs the created ServiceAccount namespace/name; no passwords, tokens, PII, or other sensitive data are logged.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@openshift-ci openshift-ci Bot added the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jul 17, 2026
@openshift-ci
openshift-ci Bot requested review from alebedev87 and jcmoraisjr July 17, 2026 14:11
@openshift-ci

openshift-ci Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign miciah for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@bentito

bentito commented Jul 17, 2026

Copy link
Copy Markdown
Author

/jira refresh

When the operator is installed in a custom namespace, OLM fails to rewrite
Group subjects in the ClusterRoleBinding. By standardizing the operand to use
a single static ServiceAccount ('external-dns') and referencing it as a
ServiceAccount subject, OLM successfully dynamically rewrites the namespace
field during custom namespace installs, allowing operand pods to function correctly.
@openshift-ci-robot openshift-ci-robot added jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. and removed jira/invalid-bug Indicates that a referenced Jira bug is invalid for the branch this PR is targeting. labels Jul 17, 2026
@openshift-ci-robot

Copy link
Copy Markdown

@bentito: This pull request references Jira Issue OCPBUGS-97605, which is valid. The bug has been moved to the POST state.

3 validation(s) were run on this bug
  • bug is open, matching expected state (open)
  • bug target version (5.0.0) matches configured target version for branch (5.0.0)
  • bug is in the state New, which is one of the valid states (NEW, ASSIGNED, POST)

Requesting review from QA contact:
/cc @melvinjoseph86

Details

In response to this:

/jira refresh

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-ci
openshift-ci Bot requested a review from melvinjoseph86 July 17, 2026 14:12
@bentito
bentito force-pushed the OCPBUGS-97605-static-operand-sa branch from 84d558d to 80a5ece Compare July 17, 2026 14:12
@openshift-ci openshift-ci Bot removed the needs-rebase Indicates a PR cannot be merged because it has merge conflicts with HEAD. label Jul 17, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pkg/operator/controller/externaldns/service_account.go (1)

35-40: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Avoid controller ownership on the shared ServiceAccount. ExternalDNSOperandServiceAccountName() is static across all ExternalDNS instances, but this path still sets the current CR as the controller owner. If more than one ExternalDNS exists, deleting one can garbage-collect the shared ServiceAccount and break the others. Use shared ownership semantics or enforce a singleton CR.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pkg/operator/controller/externaldns/service_account.go` around lines 35 - 40,
The service account identified by ExternalDNSOperandServiceAccountName is shared
across ExternalDNS instances, so do not assign the current CR as its controller
owner in the reconcile path. Update the ownership handling around
SetControllerReference to use shared, non-controller ownership semantics, or
enforce a singleton ExternalDNS resource before applying controller ownership.
🧹 Nitpick comments (1)
hack/golangci-lint.sh (1)

40-44: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win

Ensure temporary directory is cleaned up on verification failure.

If the checksum verification fails, the script will exit immediately due to the set -e directive, bypassing the manual rm -rf "$TEMPDIR" command at the end of the script. This will result in a leaked temporary directory. Consider using a trap to guarantee cleanup regardless of how the script terminates.

Add a trap immediately after the temporary directory is created, and remove the manual cleanup at the bottom of the script:

TEMPDIR=$(mktemp -d)
trap 'rm -rf "$TEMPDIR"' EXIT
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@hack/golangci-lint.sh` around lines 40 - 44, Add an EXIT trap immediately
after TEMPDIR is created to remove the temporary directory on all termination
paths, including checksum verification failures. Remove the manual rm -rf
cleanup at the script’s end while preserving the existing verification logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@config/rbac/operand_rolebinding.yaml`:
- Around line 11-13: The ClusterRoleBinding still grants access to every
ServiceAccount in the external-dns-operator namespace, defeating the fixed
least-privilege ServiceAccount subject. Remove or explicitly justify the
system:serviceaccounts:external-dns-operator Group in
config/rbac/operand_rolebinding.yaml (anchor, lines 11-13), then apply the same
RBAC correction in
bundle/manifests/external-dns_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml
(sibling, lines 11-13), preserving access only for the intended external-dns
ServiceAccount.

---

Outside diff comments:
In `@pkg/operator/controller/externaldns/service_account.go`:
- Around line 35-40: The service account identified by
ExternalDNSOperandServiceAccountName is shared across ExternalDNS instances, so
do not assign the current CR as its controller owner in the reconcile path.
Update the ownership handling around SetControllerReference to use shared,
non-controller ownership semantics, or enforce a singleton ExternalDNS resource
before applying controller ownership.

---

Nitpick comments:
In `@hack/golangci-lint.sh`:
- Around line 40-44: Add an EXIT trap immediately after TEMPDIR is created to
remove the temporary directory on all termination paths, including checksum
verification failures. Remove the manual rm -rf cleanup at the script’s end
while preserving the existing verification logic.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: eb9949b5-ae8b-48e9-ad24-76669777d883

📥 Commits

Reviewing files that changed from the base of the PR and between f3977d3 and 84d558d.

📒 Files selected for processing (7)
  • bundle/manifests/external-dns_rbac.authorization.k8s.io_v1_clusterrolebinding.yaml
  • config/rbac/operand_rolebinding.yaml
  • hack/golangci-lint.sh
  • pkg/operator/controller/externaldns/controller_test.go
  • pkg/operator/controller/externaldns/service_account.go
  • pkg/operator/controller/externaldns/service_account_test.go
  • pkg/operator/controller/names.go

Comment thread config/rbac/operand_rolebinding.yaml
@openshift-ci

openshift-ci Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

@bentito: all tests passed!

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

@alebedev87

alebedev87 commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

@bentito: We never really declared (== tested) the support of the installation of EDO outside of the suggested namespace. The install mode is own and single namespace and we always suggested external-dns-operator in the CSV. Is the need for this change driven by the OLM console dropdown list which allows selection of a different namespace?

@bentito

bentito commented Jul 23, 2026

Copy link
Copy Markdown
Author

@bentito: We never really declared (== tested) the support of the installation of EDO outside of the suggested namespace. The install mode is own and single namespace and we always suggested external-dns-operator in the CSV. Is the need for this change driven by the OLM console dropdown list which allows selection of a different namespace?

Sorry about delayed response. @alebedev87 so are you suggesting just reject the bug as not a bug?

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

Labels

jira/severity-low Referenced Jira bug's severity is low for the branch this PR is targeting. jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants