Skip to content

OCPBUGS-77056: Lock DeleteFunc to stop SARCompleted overwriting rejection - #840

Open
bentito wants to merge 1 commit into
openshift:masterfrom
bentito:OCPBUGS-77056-fix-delete-sar-race
Open

OCPBUGS-77056: Lock DeleteFunc to stop SARCompleted overwriting rejection#840
bentito wants to merge 1 commit into
openshift:masterfrom
bentito:OCPBUGS-77056-fix-delete-sar-race

Conversation

@bentito

@bentito bentito commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

What

Fixes a residual race in the merged external-certificate fix (#828) that the Component Readiness / QSE triage bot flagged on OCPBUGS-77056 (re-regression of OCPFeatureGate:RouteExternalCertificate, techpreview variants across 4.22/4.23/5.0/5.1).

The race

On secret deletion, DeleteFunc marks the route in deletedSecrets and records an ExternalCertificateValidationFailed rejection. HandleRoute's tail guards its SARCompleted write with a deletedSecrets.Load() check — but that check and the RecordRouteUpdate(SARCompleted) write are not atomic relative to DeleteFunc's Store + rejection. Losing interleaving:

  1. HandleRoute (Added/registered) loads deletedSecrets → not deleted
  2. DeleteFunc stores deletedSecrets, records rejection [ValidationFailed, False]
  3. HandleRoute writes [SARCompleted, True], overwriting the rejection

Result: after the backing secret is deleted, the route's ingress condition is stuck at [ExternalCertificateSARCompleted, True] instead of flipping to [ExternalCertificateValidationFailed, False], which is what the e2e test (test/extended/router/external_certificate.go, "and the secret is deleted → then routes are not reachable") asserts. It surfaces as a race under the parallel conformance suite's concurrency/API load, not in an isolated single-spec run.

The fix

Every registered path in HandleRoute already holds the per-route lock (routeLocks) through its tail via validateAndRegister's deferred unlock. Having DeleteFunc acquire that same per-route lock around its deletedSecrets.Store + RecordRouteRejection serializes the two paths, so whichever runs second observes the other's write and the rejection stays authoritative in both orderings.

Test

Adds TestDeleteFuncSerializesWithRegistrationLock, which asserts DeleteFunc blocks while the per-route lock is held (fails before this change, passes after). The existing TestInFlightRegistrationDoesNotReAdmitDeletedSecretRoute only covered the fully-sequential ordering the deletedSecrets guard already handled; this covers the interleaving that actually regressed. Full pkg/router/controller suite passes under -race.

🤖 Generated with Claude Code

…tion

On secret deletion, DeleteFunc marks the route in deletedSecrets and records
an ExternalCertificateValidationFailed rejection. HandleRoute's tail guards
its SARCompleted write with a deletedSecrets.Load() check, but that check and
the RecordRouteUpdate(SARCompleted) write are not atomic relative to
DeleteFunc's Store + rejection. An in-flight registration that loaded
deletedSecrets before DeleteFunc stored it can finish afterward and overwrite
the rejection, leaving the route stuck at [ExternalCertificateSARCompleted,
True] with its backing secret already gone.

Every registered path in HandleRoute already holds the per-route lock through
its tail (via validateAndRegister's deferred unlock), so having DeleteFunc
acquire that same lock around its deletedSecrets.Store + RecordRouteRejection
serializes the two paths. Whichever side runs second observes the other's
write, making the rejection authoritative in both orderings.

Adds TestDeleteFuncSerializesWithRegistrationLock, which asserts DeleteFunc
blocks while the per-route lock is held (fails before this change, passes
after), and corrects the overstated comment on the SARCompleted guard.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@openshift-ci-robot openshift-ci-robot added jira/severity-critical Referenced Jira bug's severity is critical 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 Sep 4, 2026
@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Pipeline controller notification
This repo is configured to use the pipeline controller. Second-stage tests will be triggered either automatically or after lgtm label is added, depending on the repository configuration. The pipeline controller will automatically detect which contexts are required and will utilize /test Prow commands to trigger the second stage.

For optional jobs, comment /test ? to see a list of all defined jobs. To trigger manually all jobs from second stage use /pipeline required command.

This repository is configured in: LGTM mode

@openshift-ci-robot

Copy link
Copy Markdown
Contributor

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

  • expected the bug to target either version "5.1.0." or "openshift-5.1.0.", but it targets "5.0.0" instead

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:

What

Fixes a residual race in the merged external-certificate fix (#828) that the Component Readiness / QSE triage bot flagged on OCPBUGS-77056 (re-regression of OCPFeatureGate:RouteExternalCertificate, techpreview variants across 4.22/4.23/5.0/5.1).

The race

On secret deletion, DeleteFunc marks the route in deletedSecrets and records an ExternalCertificateValidationFailed rejection. HandleRoute's tail guards its SARCompleted write with a deletedSecrets.Load() check — but that check and the RecordRouteUpdate(SARCompleted) write are not atomic relative to DeleteFunc's Store + rejection. Losing interleaving:

  1. HandleRoute (Added/registered) loads deletedSecrets → not deleted
  2. DeleteFunc stores deletedSecrets, records rejection [ValidationFailed, False]
  3. HandleRoute writes [SARCompleted, True], overwriting the rejection

Result: after the backing secret is deleted, the route's ingress condition is stuck at [ExternalCertificateSARCompleted, True] instead of flipping to [ExternalCertificateValidationFailed, False], which is what the e2e test (test/extended/router/external_certificate.go, "and the secret is deleted → then routes are not reachable") asserts. It surfaces as a race under the parallel conformance suite's concurrency/API load, not in an isolated single-spec run.

The fix

Every registered path in HandleRoute already holds the per-route lock (routeLocks) through its tail via validateAndRegister's deferred unlock. Having DeleteFunc acquire that same per-route lock around its deletedSecrets.Store + RecordRouteRejection serializes the two paths, so whichever runs second observes the other's write and the rejection stays authoritative in both orderings.

Test

Adds TestDeleteFuncSerializesWithRegistrationLock, which asserts DeleteFunc blocks while the per-route lock is held (fails before this change, passes after). The existing TestInFlightRegistrationDoesNotReAdmitDeletedSecretRoute only covered the fully-sequential ordering the deletedSecrets guard already handled; this covers the interleaving that actually regressed. Full pkg/router/controller suite passes under -race.

🤖 Generated with Claude Code

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 Sep 4, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

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

Review profile: CHILL

Plan: Team

Run ID: bb34854c-22a0-4c78-b6d9-5d58dabdec17

📥 Commits

Reviewing files that changed from the base of the PR and between 3381229 and 46d38f6.

📒 Files selected for processing (2)
  • pkg/router/controller/route_secret_manager.go
  • pkg/router/controller/route_secret_manager_test.go

Included review availability: Your plan provides up to 1 included review per hour; 0 remain after this review.


📝 Walkthrough

Walkthrough

DeleteFunc now acquires the per-route lock before marking a secret deleted and recording the rejection. Registration completion uses the same lock, preventing stale SARCompleted updates from overwriting deletion rejections. A test verifies that deletion blocks during an in-flight registration and records one rejection after lock release.

Suggested reviewers: redhat-chai-bot

Merge Risk: ⚪ Minimal · up to 46d38

Secret deletion now serializes with route registration so deletion rejection status is retained rather than overwritten by a stale registration completion. The focused test covers the lock ordering and resulting rejection behavior; no merge-blocking risk remains.

🚥 Pre-merge checks | ✅ 14 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 66.67% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 3 functions across 2 files. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (14 passed)
Check name Status Explanation
Description check ✅ Passed The description clearly explains the race, the locking fix, and the added test. It is directly related to the changeset.
Title check ✅ Passed The title clearly identifies the Jira issue and the primary change: locking DeleteFunc to prevent SARCompleted from overwriting the rejection.
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 pull request adds the static Go test name TestDeleteFuncSerializesWithRegistrationLock. It contains no pod, node, namespace, IP, UUID, timestamp, or generated value. The changed file uses standa…
Test Structure And Quality ✅ Passed PASS: The added test is a standard Go testing unit test, not Ginkgo test code, and it uses only in-memory fakes. It creates no cluster resources that require cleanup. It tests one behavior: `DeleteF…
Microshift Test Compatibility ✅ Passed The pull request adds a standard Go testing unit test, TestDeleteFuncSerializesWithRegistrationLock, in pkg/router/controller/route_secret_manager_test.go. The changed test file contains no Gink…
Single Node Openshift (Sno) Test Compatibility ✅ Passed PASS: The pull request adds only the standard Go unit test TestDeleteFuncSerializesWithRegistrationLock in pkg/router/controller/route_secret_manager_test.go. It does not add Ginkgo e2e tests, and…
Topology-Aware Scheduling Compatibility ✅ Passed PASS — The PR changes only RouteSecretManager synchronization and its tests. The code adds a per-route mutex around deletedSecrets.Store and route rejection. It adds no deployment, pod, replica, a…
Ote Binary Stdout Contract ✅ Passed PASS: The pull request changes only route locking comments/code and a unit test. The added production code uses lockRoute, deletedSecrets.Store, and RecordRouteRejection; it adds no stdout write…
Ipv6 And Disconnected Network Test Compatibility ✅ Passed The pull request adds a standard Go unit test, TestDeleteFuncSerializesWithRegistrationLock, in pkg/router/controller; it does not add a Ginkgo e2e test. The changed test uses in-memory fakes, cha…
No-Weak-Crypto ✅ Passed PASS: The pull request changes only route locking, deletion-status handling, and tests. The added code introduces no MD5, SHA1, DES, 3DES, RC4, Blowfish, ECB, custom cryptography, or secret/token comp…
Container-Privileges ✅ Passed PASS. The pull request changes only pkg/router/controller/route_secret_manager.go and its Go test. The added code contains no privileged, hostPID, hostNetwork, hostIPC, SYS_ADMIN, or `allo…
No-Sensitive-Data-In-Logs ✅ Passed PASS. The source diff adds only per-route locking and comments in DeleteFunc; it does not add or modify a logging call. The existing log.V(4).Info(msg) line for deleted secrets is unchanged from t…
  • Fix all pre-merge checks with AI
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@openshift-ci openshift-ci Bot added the ready-for-human-review Indicates a PR has been reviewed by automated tools and is ready for human review label Sep 4, 2026
@openshift-ci
openshift-ci Bot requested review from Miciah and frobware September 4, 2026 15:28
@openshift-ci

openshift-ci Bot commented Sep 4, 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 ironcladlou 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

@melvinjoseph86

Copy link
Copy Markdown

/pipeline required

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Scheduling tests matching the pipeline_run_if_changed or not excluded by pipeline_skip_if_only_changed parameters:
/test e2e-agnostic
/test e2e-aws-fips
/test e2e-aws-serial-1of2
/test e2e-aws-serial-2of2
/test e2e-upgrade

@openshift-ci

openshift-ci Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

@melvinjoseph86: it appears that you have attempted to use some version of the payload command, but your comment was incorrectly formatted and cannot be acted upon. See the docs for usage info.

@melvinjoseph86

Copy link
Copy Markdown

/payload-job periodic-ci-openshift-release-main-nightly-5.1-e2e-vsphere-ovn-rhcos10-techpreview periodic-ci-openshift-release-main-nightly-5.1-e2e-vsphere-ovn-techpreview

@openshift-ci

openshift-ci Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

@melvinjoseph86: trigger 2 job(s) for the /payload-(with-prs|job|aggregate|job-with-prs|aggregate-with-prs) command

  • periodic-ci-openshift-release-main-nightly-5.1-e2e-vsphere-ovn-rhcos10-techpreview
  • periodic-ci-openshift-release-main-nightly-5.1-e2e-vsphere-ovn-techpreview

See details on https://pr-payload-tests.ci.openshift.org/runs/ci/1fd0aed0-a886-11f1-9087-6fdd89bb05a9-0

@melvinjoseph86

Copy link
Copy Markdown

one more time
/payload-job periodic-ci-openshift-release-main-nightly-5.1-e2e-vsphere-ovn-rhcos10-techpreview periodic-ci-openshift-release-main-nightly-5.1-e2e-vsphere-ovn-techpreview

@openshift-ci

openshift-ci Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

@melvinjoseph86: trigger 2 job(s) for the /payload-(with-prs|job|aggregate|job-with-prs|aggregate-with-prs) command

  • periodic-ci-openshift-release-main-nightly-5.1-e2e-vsphere-ovn-rhcos10-techpreview
  • periodic-ci-openshift-release-main-nightly-5.1-e2e-vsphere-ovn-techpreview

See details on https://pr-payload-tests.ci.openshift.org/runs/ci/5700df00-a8c3-11f1-886d-470f4a308805-0

@melvinjoseph86

Copy link
Copy Markdown

/retest-required

@melvinjoseph86

Copy link
Copy Markdown

/payload-job periodic-ci-openshift-release-main-nightly-5.0-e2e-vsphere-ovn-rhcos10-techpreview periodic-ci-openshift-release-main-nightly-5.0-e2e-vsphere-ovn-techpreview

@openshift-ci

openshift-ci Bot commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

@melvinjoseph86: trigger 2 job(s) for the /payload-(with-prs|job|aggregate|job-with-prs|aggregate-with-prs) command

  • periodic-ci-openshift-release-main-nightly-5.0-e2e-vsphere-ovn-rhcos10-techpreview
  • periodic-ci-openshift-release-main-nightly-5.0-e2e-vsphere-ovn-techpreview

See details on https://pr-payload-tests.ci.openshift.org/runs/ci/fb7abc90-a8c3-11f1-8313-a8eedcd57e02-0

@openshift-ci

openshift-ci Bot commented Sep 5, 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.

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

Labels

jira/invalid-bug Indicates that a referenced Jira bug is invalid for the branch this PR is targeting. jira/severity-critical Referenced Jira bug's severity is critical for the branch this PR is targeting. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. ready-for-human-review Indicates a PR has been reviewed by automated tools and is ready for human review

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants