Skip to content

OSAC-3132: migrate ExternalIP and ExternalIPAttachment feedback controllers to Bridge - #121

Merged
openshift-merge-bot[bot] merged 2 commits into
osac-project:mainfrom
vladikr:refactor/OSAC-3132-migrate-externalip-feedback
Aug 4, 2026
Merged

openshift-merge-bot[bot] merged 2 commits into
osac-project:mainfrom
vladikr:refactor/OSAC-3132-migrate-externalip-feedback

Conversation

@vladikr

@vladikr vladikr commented Aug 3, 2026 •

Copy link
Copy Markdown
Contributor

Summary

Final migration PR — ExternalIP and ExternalIPAttachment feedback controllers now use the feedback.Bridge. This completes the migration of all feedback controllers (excluding BareMetalInstance, which is a fundamentally different signal-only pattern).

Ported from osac-operator PR #403 to the monorepo.

Commit Controller Notes
1 ExternalIP Uses IsNotFound for sentinel ErrExternalIPNotFound
2 ExternalIPAttachment Uses IsNotFound, PostSaveOnDelete, and two gRPC clients

Bridge API change

PostSaveOnDelete signature updated from func(ctx, obj O) error to func(ctx, obj O, remote R) error. The remote proto is now passed so callbacks can reference proto spec fields — ExternalIPAttachment needs the parent ExternalIP ID from remote.GetSpec().GetExternalIp() to clear the parent's attached flag.

Bridge tests updated to match.

Cleanup

Removed the clone[M]/equal[M] generic helpers from feedback_controller.go — no remaining callers now that all feedback controllers use the Bridge.

Migration complete

All feedback controllers now use feedback.Bridge:

Controller PR Extension points used
Subnet osac-operator#387 —
VirtualNetwork osac-operator#401 —
SecurityGroup osac-operator#401 —
NATGateway osac-operator#401 —
ExternalIPPool osac-operator#401 —
ComputeInstance osac-operator#402 —
ClusterOrder osac-operator#402 —
ExternalIP this PR IsNotFound
ExternalIPAttachment this PR IsNotFound, PostSaveOnDelete
BareMetalInstance N/A Signal-only, stays standalone

Test plan

  • make lint — 0 issues
  • make test — all pass (controller coverage 72.2%, bridge coverage 94.0%)

Jira: https://redhat.atlassian.net/browse/OSAC-3132

Summary by CodeRabbit

  • Bug Fixes
    • Improved synchronization of external IPs and attachments with their corresponding network resources.
    • Preserved accurate attachment, address, and deletion statuses during reconciliation.
    • Improved handling of failed or in-progress deletions and missing resources.
    • Ensured resource state remains consistent when specifications or statuses are incomplete.
    • Improved deletion processing and error propagation for more reliable cleanup.

vladikr added 2 commits August 3, 2026 11:15
Delegates to feedback.Bridge with IsNotFound set to match the
sentinel ErrExternalIPNotFound error. The Fetch callback preserves
the original error-wrapping behavior (gRPC NotFound and nil object
both wrap into ErrExternalIPNotFound).

Assisted-by: Claude Code <noreply@anthropic.com>
Signed-off-by: Vladik Romanovsky <vromanso@redhat.com>
Delegates to feedback.Bridge with IsNotFound for the sentinel error,
and PostSaveOnDelete for clearing the parent ExternalIP's attached
flag after the attachment's DELETING state is persisted.

SyncUpdate captures eipClient for setting attached=true on Ready and
syncing the parent's address to the attachment.

Bridge API change: PostSaveOnDelete now receives the remote proto in
addition to the K8s object, so callbacks can reference proto spec
fields (e.g. the parent ExternalIP ID).

Also removes the clone/equal generic helpers from feedback_controller.go
since all feedback controllers now use the Bridge (which calls
proto.Clone/proto.Equal directly).

Assisted-by: Claude Code <noreply@anthropic.com>
Signed-off-by: Vladik Romanovsky <vromanso@redhat.com>
@openshift-ci-robot

openshift-ci-robot commented Aug 3, 2026 •

Copy link
Copy Markdown

@vladikr: This pull request references OSAC-3132 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the task to target the "5.0.0" version, but no target version was set.

Details

In response to this:

Summary

Final migration PR — ExternalIP and ExternalIPAttachment feedback controllers now use the feedback.Bridge. This completes the migration of all feedback controllers (excluding BareMetalInstance, which is a fundamentally different signal-only pattern).

Ported from osac-operator PR #403 to the monorepo.

Commit Controller Notes
1 ExternalIP Uses IsNotFound for sentinel ErrExternalIPNotFound
2 ExternalIPAttachment Uses IsNotFound, PostSaveOnDelete, and two gRPC clients

Bridge API change

PostSaveOnDelete signature updated from func(ctx, obj O) error to func(ctx, obj O, remote R) error. The remote proto is now passed so callbacks can reference proto spec fields — ExternalIPAttachment needs the parent ExternalIP ID from remote.GetSpec().GetExternalIp() to clear the parent's attached flag.

Bridge tests updated to match.

Cleanup

Removed the clone[M]/equal[M] generic helpers from feedback_controller.go — no remaining callers now that all feedback controllers use the Bridge.

Migration complete

All feedback controllers now use feedback.Bridge:

Controller PR Extension points used
Subnet osac-operator#387 —
VirtualNetwork osac-operator#401 —
SecurityGroup osac-operator#401 —
NATGateway osac-operator#401 —
ExternalIPPool osac-operator#401 —
ComputeInstance osac-operator#402 —
ClusterOrder osac-operator#402 —
ExternalIP this PR IsNotFound
ExternalIPAttachment this PR IsNotFound, PostSaveOnDelete
BareMetalInstance N/A Signal-only, stays standalone

Test plan

  • make lint — 0 issues
  • make test — all pass (controller coverage 72.2%, bridge coverage 94.0%)

Jira: https://redhat.atlassian.net/browse/OSAC-3132

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 review from larsks and trewest August 3, 2026 15:32
@openshift-ci openshift-ci Bot added the approved label Aug 3, 2026
@coderabbitai

coderabbitai Bot commented Aug 3, 2026 •

Copy link
Copy Markdown
Contributor

Review Change Stack

Walkthrough

Changes

Feedback bridge migration

Layer / File(s) Summary
Shared bridge callback contract
osac-operator/internal/controller/feedback/bridge.go, osac-operator/internal/controller/feedback/bridge_test.go, osac-operator/internal/controller/feedback_controller.go
PostSaveOnDelete now receives the remote record. Tests validate the argument and deletion behavior. Unused protobuf helpers were removed.
ExternalIP bridge reconciliation
osac-operator/internal/controller/externalip_feedback_controller.go
The controller configures and invokes the shared bridge. Synchronization preserves remote state, address, and deletion status.
ExternalIPAttachment bridge reconciliation
osac-operator/internal/controller/externalipattachment_feedback_controller.go
The controller delegates reconciliation to the bridge. Callbacks synchronize attachment state, address, deletion, and parent detachment.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Reconciler
  participant Bridge
  participant ExternalIPAttachmentAPI
  participant ExternalIPAPI
  Reconciler->>Bridge: Reconcile request
  Bridge->>ExternalIPAttachmentAPI: Fetch attachment
  Bridge->>ExternalIPAttachmentAPI: Save synchronized state and address
  Bridge->>ExternalIPAPI: Detach parent ExternalIP after deletion
Loading
🚥 Pre-merge checks | ✅ 11
✅ Passed checks (11 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely describes the migration of the ExternalIP and ExternalIPAttachment feedback controllers to Bridge.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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.
No-Hardcoded-Secrets ✅ Passed The complete PR diff adds no API keys, tokens, passwords, private keys, credential URLs, or encoded secret blobs; literals are controller identifiers, errors, and log messages.
No-Weak-Crypto ✅ Passed The full PR diff adds no MD5, SHA1, DES, RC4, Blowfish, ECB, custom crypto, or secret/token comparisons; added comparisons are only gRPC status and resource-state checks.
No-Injection-Vectors ✅ Passed The complete two-commit diff contains no SQL, shell, eval/exec, pickle, unsafe YAML, os.system, jq, or dangerouslySetInnerHTML sinks; identifiers go only to typed gRPC requests.
Container-Privileges ✅ Passed The PR changes only five Go files. It adds no container or Kubernetes manifests and no prohibited privilege settings.
No-Sensitive-Data-In-Logs ✅ Passed Changed logs contain only state, phase, resource IDs, and control metadata; no credentials, tokens, payloads, addresses, hostnames, or customer fields are logged.
Ai-Attribution ✅ Passed AI use is attributed in both PR commits with Assisted-by: Claude Code <noreply@anthropic.com>; no AI Co-Authored-By trailer appears.
✨ 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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

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)
osac-operator/internal/controller/externalipattachment_feedback_controller.go (1)

185-219: 🩺 Stability & Availability | 🟠 Major | 🏗️ Heavy lift

Use an UpdateMask for status field updates.

ExternalIPsUpdateRequest supports UpdateMask, but these controllers send the full Object without it. Add an update_mask: ["status.attached", "status.state", "status.address"] field mask for the fields this sync writes so concurrent reconciles do not overwrite each other.

🤖 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
`@osac-operator/internal/controller/externalipattachment_feedback_controller.go`
around lines 185 - 219, Update syncAttachedOnParentExternalIP to include an
UpdateMask in the ExternalIPsUpdateRequest, covering status.attached,
status.state, and status.address. Keep the existing Object payload and
attached-state synchronization unchanged, using the request’s field-mask builder
or established API pattern.
🤖 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
`@osac-operator/internal/controller/externalipattachment_feedback_controller.go`:
- Around line 113-126: Update syncExternalIPAttachmentAddress to return an
error, propagating non-NotFound Get failures while preserving nil for missing
IDs, NotFound responses, and incomplete objects. In
newExternalIPAttachmentSyncUpdate, handle and return this error before
continuing so transient address-fetch failures trigger the existing retry
behavior.

---

Outside diff comments:
In
`@osac-operator/internal/controller/externalipattachment_feedback_controller.go`:
- Around line 185-219: Update syncAttachedOnParentExternalIP to include an
UpdateMask in the ExternalIPsUpdateRequest, covering status.attached,
status.state, and status.address. Keep the existing Object payload and
attached-state synchronization unchanged, using the request’s field-mask builder
or established API pattern.
🪄 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: osac-project/coderabbit/.coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 371fc806-f709-4cbc-9fd3-2bccdfedf301

📥 Commits

Reviewing files that changed from the base of the PR and between 9102124 and 44f77cd.

📒 Files selected for processing (5)
  • osac-operator/internal/controller/externalip_feedback_controller.go
  • osac-operator/internal/controller/externalipattachment_feedback_controller.go
  • osac-operator/internal/controller/feedback/bridge.go
  • osac-operator/internal/controller/feedback/bridge_test.go
  • osac-operator/internal/controller/feedback_controller.go
💤 Files with no reviewable changes (1)
  • osac-operator/internal/controller/feedback_controller.go

@vladikr

vladikr commented Aug 3, 2026

Copy link
Copy Markdown
Contributor Author

@tzvatot can you please take a look?
It migrated from osac-project/osac-operator#403

@vladikr
vladikr requested a review from tzvatot August 3, 2026 17:08

@tzvatot tzvatot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Clean 1:1 migration of the last two feedback controllers to Bridge. Logic preserved faithfully, delete/update path ordering matches the original, PostSaveOnDelete API change is safe (no prior callers), test coverage updated.

LGTM.

@openshift-ci

openshift-ci Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: tzvatot, vladikr

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

The pull request process is described 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

@openshift-merge-bot
openshift-merge-bot Bot merged commit c8ef391 into osac-project:main Aug 4, 2026
31 checks passed
eliorerz pushed a commit that referenced this pull request Sep 18, 2026

This branch was previously deployed

1 inactive deployment
e2e-test — 44f77cd0 Deployed Aug 3, 2026 by vladikr via e2e-bmaas-full-install / e2e #375
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants