Skip to content

fix: auto-cleanup closed AWS accounts and thread-safe STS retry handling - #1061

Merged
openshift-merge-bot[bot] merged 12 commits into
openshift:masterfrom
BATMAN-JD:BATMAN-JD/fix-sts-retry-loop
Aug 4, 2026
Merged

fix: auto-cleanup closed AWS accounts and thread-safe STS retry handling#1061
openshift-merge-bot[bot] merged 12 commits into
openshift:masterfrom
BATMAN-JD:BATMAN-JD/fix-sts-retry-loop

Conversation

@BATMAN-JD

@BATMAN-JD BATMAN-JD commented Aug 2, 2026

Copy link
Copy Markdown
Contributor

Summary

Fixes the burst creation incident where the AWS org grew from 1232 to 1701 accounts in one day. PendingDeletion accounts with STS failures were looping forever, clogging the pool, and the pool controller kept creating replacements.

What it does

Unblocks PendingDeletion accounts stuck on STS failures:

  • Checks AccountClientError condition on the CR (persisted, survives pod restarts) to identify accounts that have exhausted STS retries
  • Calls DescribeAccount to check if the AWS account still exists
  • SUSPENDED/CLOSED → removes finalizer immediately (no resources left to clean up)
  • ACTIVE → falls through to normal STS retry (role should work)
  • Guards DescribeAccount on non-empty AwsAccountID to avoid pointless API calls

Garbage-collects zombie Account CRs:

  • Pool-owned, non-BYOC accounts with no AWS ID that are Failed → deleted immediately
  • Pool-owned, non-BYOC accounts with no AWS ID that are NoState and older than 25 min → deleted
  • Safe because no AWS account exists, nothing to orphan

Thread-safe STS retry with bounded retries:

  • STS retry count map protected by sync.Mutex to prevent Go runtime panics from concurrent reconcile goroutines
  • Bounded to 3 retries with linear backoff (30s, 60s, 90s) before permanently failing the account
  • After exhaustion, account is set to Failed with AccountClientError condition — no elaborate recovery logic

Prevents burst creation from ever recurring:

  • Pool controller creates at most one account per reconcile
  • Pending (NoState) accounts count toward pool satisfaction
  • AWS account limit blocks creation with a 5-minute requeue

Boilerplate sync:

  • UBI base image bump (9.8-17853391179.8-1785777232)

Flow

PendingDeletion + non-BYOC account:
  1. Has AccountClientError condition? → DescribeAccount
     - Closed/Suspended → remove finalizer → done
     - Active → fall through to STS (role should work)
  2. No condition → try STS normally
     - Succeeds → finalizeAccount → remove finalizer → done
     - Fails → handleAWSClientError → sets condition → retry cycle

Zombie GC (early exit, no AWS client needed):
  Pool-owned + non-BYOC + no AWS ID + not PendingDeletion →
    - Failed → delete immediately
    - NoState + older than 25 min → delete

Why is it safe to remove the finalizer for closed accounts?

finalizeAccount cleans up IAM users and roles inside the child AWS account. When the account is SUSPENDED/CLOSED, those resources no longer exist and API calls into the account are impossible. Skipping cleanup of resources that don't exist inside an account we can't reach.

Test plan

  • 16 regression tests covering burst prevention, zombie GC, PendingDeletion STS handling, and account limit requeue
  • Full unit test suite passes (go test ./...)
  • Build and pre-commit hooks pass
  • CI/PROW integration tests

🤖 Generated with Claude Code

@openshift-ci
openshift-ci Bot requested review from AlexSmithGH and eth1030 August 2, 2026 01:51
@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Aug 2, 2026
@coderabbitai

coderabbitai Bot commented Aug 2, 2026

Copy link
Copy Markdown

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

The account controller now removes stale pool-owned zombie accounts, handles pending deletion from persisted AccountClientError conditions, and retains exhausted STS retry state. Tests cover account limits, AWS account status handling, and account-pool burst prevention.

Changes

Account lifecycle safeguards

Layer / File(s) Summary
Stale account cleanup
controllers/account/account_controller.go, controllers/account/account_controller_test.go
The controller deletes eligible pool-owned NoState accounts after the creation timeout. Tests confirm retention of young and BYOC accounts and five-minute requeueing at the AWS account limit.
Pending deletion and STS failure handling
controllers/account/account_controller.go, controllers/account/account_controller_test.go
The controller checks persisted AccountClientError conditions, removes finalizers for inactive accounts, continues STS handling for active or indeterminate accounts, and retains retry state after exhausted failures.
Account-pool creation pacing
controllers/accountpool/accountpool_controller_test.go
Tests verify one account per reconcile, pending-account capacity, AWS account-limit handling, pool-size limits, repeated reconciles, and failed-account replacement.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

Suggested reviewers: eth1030


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 error, 1 warning)

Check name Status Explanation Resolution
Stable And Deterministic Test Names ❌ Error Added titles expose implementation identifiers: createPendTime and poolSize in account and account-pool tests can become stale when code names change. Rename titles to describe stable behavior, such as “after the creation timeout” and “configured pool size,” without private identifier names.
Test Structure And Quality ⚠️ Warning Several new Ginkgo Its do not exercise reconciliation; they only inspect fixtures or assert enum constants. Other added assertions lack messages, and one test discards Reconcile errors. Make each pending-deletion It configure the fake client and invoke Reconcile, check behavior, retain returned errors, and add diagnostic messages to every assertion.
✅ Passed checks (13 passed)
Check name Status Explanation
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.
Microshift Test Compatibility ✅ Passed The PR adds controller unit tests in controllers/account and controllers/accountpool, using fake clients and AWS mocks; no new e2e tests or unavailable MicroShift APIs/features are referenced.
Single Node Openshift (Sno) Test Compatibility ✅ Passed The PR adds controller unit tests only; they use fake Kubernetes clients and mocked AWS clients, with no e2e cluster, node, topology, scheduling, or HA assumptions.
Topology-Aware Scheduling Compatibility ✅ Passed The PR changes only account controller logic and tests; the diff adds no affinity, topology spread, node selectors, tolerations, replica, or PDB scheduling constraints.
Ote Binary Stdout Contract ✅ Passed The PR adds no main, init, TestMain, suite setup, logger redirection, or stdout write; all added output-related code is inside test cases.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed New Ginkgo tests use fake Kubernetes clients and mocked AWS calls; the PR diff adds no IPv4 literals, IP parsing, URL construction, or external connectivity.
No-Weak-Crypto ✅ Passed The PR diff adds no MD5, SHA1, DES, RC4, Blowfish, ECB, custom crypto, or secret/token comparisons; imports are AWS/Kubernetes APIs only.
Container-Privileges ✅ Passed The PR changes only Go controller and test files. The complete patch adds no container/Kubernetes manifests or privilege settings such as privileged, hostPID, hostNetwork, hostIPC, SYS_ADMIN, or al...
No-Sensitive-Data-In-Logs ✅ Passed PR logs contain account names, enum states, retry metadata, error codes, and AWS error text; no passwords, tokens, API keys, emails, or AWS account IDs are logged.
Title check ✅ Passed The title clearly summarizes the main changes: AWS account cleanup and thread-safe STS retry handling.
Description check ✅ Passed The description clearly explains the incident, implementation, safety rationale, affected flows, and test results, but it omits the repository template headings and manual test steps.
✨ 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

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)
controllers/account/account_controller.go (1)

674-674: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Clean up the finalizer-only STS retry entry after deletion.

handleAWSClientError must preserve retry counts through pending deletion, but the finalizer-only non-STS path removes the Account finalizer without a Get() before returning. If Get() returns k8serr.IsNotFound, also delete r.stsRetryCount[currentAcctInstance.Name] there so a reused Account name cannot inherit an exhausted count.

🤖 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 `@controllers/account/account_controller.go` at line 674, Update
handleAWSClientError’s finalizer-only non-STS deletion path to remove
r.stsRetryCount[currentAcctInstance.Name] when the Account Get() returns
k8serr.IsNotFound, before returning. Preserve retry counts during pending
deletion while ensuring a later Account with the same name starts without the
stale exhausted count.
🧹 Nitpick comments (1)
controllers/account/account_controller_test.go (1)

2868-2876: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Cover the finalizer-removal path through Reconcile.

This test calls handleAWSClientError directly and checks only the retained retry count. It does not verify the behavior added at Lines 326-334: skipping the STS role-assumption call and removing awsv1alpha1.AccountFinalizer for a pending-deletion Account. Add a focused Reconcile test with an exhausted retry count and assertions for both outcomes.

🤖 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 `@controllers/account/account_controller_test.go` around lines 2868 - 2876,
Extend the account controller tests with a focused Reconcile scenario for a
pending-deletion Account whose stsRetryCount is already
maxSTSClientErrorRetries. Assert that Reconcile skips the STS role-assumption
call and removes awsv1alpha1.AccountFinalizer, covering the finalizer-removal
behavior rather than only the direct handleAWSClientError retry-count check.
🤖 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 `@controllers/account/account_controller.go`:
- Around line 326-334: Ensure the account controller enforces max concurrent
reconciles of 1 before any access to r.stsRetryCount, preventing operator
configuration from enabling concurrent reconciles; alternatively, protect every
read and write of r.stsRetryCount with a mutex. Update the controller setup
symbol that applies maxReconciles while preserving the existing retry and
finalizer behavior.

---

Outside diff comments:
In `@controllers/account/account_controller.go`:
- Line 674: Update handleAWSClientError’s finalizer-only non-STS deletion path
to remove r.stsRetryCount[currentAcctInstance.Name] when the Account Get()
returns k8serr.IsNotFound, before returning. Preserve retry counts during
pending deletion while ensuring a later Account with the same name starts
without the stale exhausted count.

---

Nitpick comments:
In `@controllers/account/account_controller_test.go`:
- Around line 2868-2876: Extend the account controller tests with a focused
Reconcile scenario for a pending-deletion Account whose stsRetryCount is already
maxSTSClientErrorRetries. Assert that Reconcile skips the STS role-assumption
call and removes awsv1alpha1.AccountFinalizer, covering the finalizer-removal
behavior rather than only the direct handleAWSClientError retry-count check.
🪄 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: Pro Plus

Run ID: d1830987-0a10-425c-828b-3f4e2ad0a3ea

📥 Commits

Reviewing files that changed from the base of the PR and between f7af817 and 0c38bed.

📒 Files selected for processing (2)
  • controllers/account/account_controller.go
  • controllers/account/account_controller_test.go

Comment thread controllers/account/account_controller.go Outdated
@codecov-commenter

codecov-commenter commented Aug 2, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 60.00000% with 22 lines in your changes missing coverage. Please review.
✅ Project coverage is 47.85%. Comparing base (f7af817) to head (436fe25).

Files with missing lines Patch % Lines
controllers/account/account_controller.go 60.00% 17 Missing and 5 partials ⚠️
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master    #1061      +/-   ##
==========================================
+ Coverage   47.31%   47.85%   +0.54%     
==========================================
  Files          46       46              
  Lines        7177     7217      +40     
==========================================
+ Hits         3396     3454      +58     
+ Misses       3429     3406      -23     
- Partials      352      357       +5     
Files with missing lines Coverage Δ
controllers/account/account_controller.go 46.77% <60.00%> (+3.06%) ⬆️

... and 3 files with indirect coverage changes

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

@BATMAN-JD
BATMAN-JD marked this pull request as draft August 3, 2026 14:09
@openshift-ci openshift-ci Bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Aug 3, 2026
Three fixes for the STS retry counter bug that caused infinite queue
congestion for Failed+PendingDeletion accounts:

1. Remove `delete(r.stsRetryCount, ...)` from handleAWSClientError that
   reset the counter after exhaustion, causing an infinite 3-retry loop
2. Add 6-hour requeue for exhausted PendingDeletion accounts instead of
   removing the finalizer, so AAO retains awareness and can clean up
   when the underlying issue (e.g. missing OrganizationAccountAccessRole)
   is resolved
3. Pre-fill retry counter from existing AccountClientError condition on
   pod restart to prevent queue storm from re-doing rapid retries on
   known-bad accounts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@BATMAN-JD
BATMAN-JD force-pushed the BATMAN-JD/fix-sts-retry-loop branch from 0c38bed to 9956ce7 Compare August 3, 2026 14:37
@BATMAN-JD BATMAN-JD changed the title fix: stop STS retry counter reset causing infinite queue congestion fix: stop STS retry loop and add long-backoff for unreachable accounts Aug 3, 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: 2

🤖 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 `@controllers/account/account_controller_test.go`:
- Around line 2880-2939: Replace the three tests’ duplicated stsRetryCount map
logic with integration-style cases that construct a pending-deletion Account
containing AccountClientError and invoke AccountReconciler.Reconcile. Assert the
result requeues after six hours, stsRetryCount is maxSTSClientErrorRetries - 1,
and the STS AssumeRole mock is not called; retain coverage for the no-condition
and existing-count scenarios only where they are exercised through Reconcile.

In `@controllers/account/account_controller.go`:
- Around line 340-346: Remove the awsAccountID field from the retry log in
controllers/account/account_controller.go lines 340-346 within the STS
retries-exhausted logging block, and remove the same field from the retry log at
lines 689-695. Leave the remaining retry context and behavior unchanged.
🪄 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: Pro Plus

Run ID: 37dcac77-5c8d-446e-80d2-05fe74e9e8fc

📥 Commits

Reviewing files that changed from the base of the PR and between 0c38bed and 9956ce7.

📒 Files selected for processing (2)
  • controllers/account/account_controller.go
  • controllers/account/account_controller_test.go

Comment thread controllers/account/account_controller_test.go Outdated
Comment thread controllers/account/account_controller.go Outdated
Comment thread controllers/account/account_controller.go Outdated
@BATMAN-JD

Copy link
Copy Markdown
Contributor Author

/label tide/merge-method-squash

@openshift-ci openshift-ci Bot added the tide/merge-method-squash Denotes a PR that should be squashed by tide when it merges. label Aug 3, 2026
BATMAN-JD and others added 3 commits August 3, 2026 10:50
When STS retries are exhausted for a pending-deletion account, call
DescribeAccount to check if the AWS account is still active. If it's
SUSPENDED or CLOSED, remove the finalizer since there are no AWS
resources left to clean up. If still active, fall through to the
6-hour long-backoff retry.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…logs

- Remove pod-restart pre-fill logic per Alex's feedback: DescribeAccount
  auto-cleanup makes it unnecessary, and in-memory state hacks are not
  appropriate for controllers
- Remove awsAccountID from STS exhaustion log lines (security concern)
- Remove 3 associated pre-fill tests

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…STS check

Replace stsRetryCount map lookup with AccountClientError condition check
in the PendingDeletion path. The condition is already persisted on the CR
by handleAWSClientError, so it survives pod restarts — no ephemeral state
needed, no retry storm on restart, no external cache required.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@BATMAN-JD BATMAN-JD changed the title fix: stop STS retry loop and add long-backoff for unreachable accounts fix: auto-cleanup closed AWS accounts and use CR-persisted state for STS retries Aug 3, 2026
BATMAN-JD and others added 4 commits August 3, 2026 11:32
Remove the 6h backoff for active-but-unreachable accounts. If
DescribeAccount shows the account is active, fall through to the
normal STS attempt — the role should work. If it doesn't,
handleAWSClientError handles retries and failure as usual.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Widen the zombie GC to also catch NoState accounts (not just Failed)
that are pool-owned and have no AWS account ID. These CRs were created
during burst incidents but never provisioned — they sit on the limit
requeue loop forever as dead weight. NoState accounts are only GC'd
after createPendTime (25 min) to avoid racing with initial processing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…ention

Cover three defense layers that prevent the org from growing unchecked:
- Pool controller: one account per reconcile, pending accounts satisfy pool,
  AWS limit blocking, rapid reconcile capping, failed account replacement
- Account controller: zombie GC for pool-owned accounts with no AWS ID,
  PendingDeletion finalizer removal for SUSPENDED/PendingClosure accounts,
  condition persistence across pod restarts, account limit requeue
- 13 new tests total, all using existing fake client and mock patterns

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

@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: 4

🧹 Nitpick comments (2)
controllers/account/account_controller_test.go (2)

2977-3001: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove the tautological specs; the new Reconcile tests now cover this behavior. These specs assert on test-local fixtures and on constants compared to themselves, so they execute no controller code and cannot fail for a production reason. The specs at Lines 3004-3105 already drive the same pending-deletion branch through Reconcile with a mocked DescribeAccount.

  • controllers/account/account_controller_test.go#L2977-L3001: delete the three specs, or replace them with Reconcile invocations. Expect(organizationstypes.AccountStatusActive).To(Equal(organizationstypes.AccountStatusActive)) is always true, and GetCondition here reads a condition the test itself just assigned.
  • controllers/account/account_controller_test.go#L3107-L3133: delete this spec. It asserts that a map created by make(map[string]int) on the previous line is empty, and that a condition assigned in the fixture is present.
🤖 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 `@controllers/account/account_controller_test.go` around lines 2977 - 3001,
Remove the three tautological specs at
controllers/account/account_controller_test.go:2977-3001, since they only
inspect test-local fixtures; retain coverage through the existing
Reconcile-based tests. Also delete the spec at
controllers/account/account_controller_test.go:3107-3133, which only verifies an
immediately created empty map and an explicitly assigned condition; make no
production-code changes.

1758-1785: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Derive these offsets from createPendTime instead of hardcoding minutes.

createPendTime is utils.WaitTime * time.Minute, currently 25 minutes. The -30 * time.Minute and -5 * time.Minute offsets assume that 25-minute boundary, so changing utils.WaitTime would silently invert one assertion. Use fixed fractions of createPendTime, such as -2 * createPendTime and -createPendTime / 2.

🤖 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 `@controllers/account/account_controller_test.go` around lines 1758 - 1785,
Update the account age setup in the zombie-account tests around the relevant
Reconcile cases to derive timestamps from createPendTime rather than hardcoded
minute values. Replace the -30-minute and -5-minute offsets with fixed fractions
such as -2*createPendTime and -createPendTime/2, preserving the intended
older-than and newer-than boundary assertions when utils.WaitTime changes.
🤖 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 `@controllers/account/account_controller_test.go`:
- Around line 1814-1838: Update the zombie BYOC test around
newTestAccountBuilder so the fixture sets Spec.AccountPool and includes the
corresponding AccountPool owner reference, ensuring IsOwnedByAccountPool() is
true; also update the controller condition handling the zombie branch to require
!currentAcctInstance.IsBYOC(). Keep the existing non-deletion assertion so the
test verifies BYOC protection for pool-owned accounts.
- Around line 3160-3191: Make the “account limit requeue” test explicitly
control and restore the process-wide watcher and FedRAMP state used by
AccountReconciler.Reconcile. Initialize the relevant TotalAccountWatcher and
config.isFedramp values in test setup, then restore their original values in
teardown so the test does not depend on or leak global state; preserve the
existing requeue and account-status assertions.

In `@controllers/account/account_controller.go`:
- Around line 331-337: Guard the DescribeAccount call in the AccountClientError
handling branch by checking that currentAcctInstance.Spec.AwsAccountID is
non-empty first. Skip the Organizations request and continue the existing
fallback flow when the AWS account ID is empty, while preserving the current
DescribeAccount behavior for valid IDs.
- Around line 133-151: Update the zombie-account deletion condition in the
reconciliation flow to require feature.validation_delete_account before removing
the finalizer or calling Delete, and require zombieAge > createPendTime for both
Failed and NoState cases. Preserve the existing pool-owned and no-AWS-account
checks, and use the existing feature flag symbol and age threshold.

---

Nitpick comments:
In `@controllers/account/account_controller_test.go`:
- Around line 2977-3001: Remove the three tautological specs at
controllers/account/account_controller_test.go:2977-3001, since they only
inspect test-local fixtures; retain coverage through the existing
Reconcile-based tests. Also delete the spec at
controllers/account/account_controller_test.go:3107-3133, which only verifies an
immediately created empty map and an explicitly assigned condition; make no
production-code changes.
- Around line 1758-1785: Update the account age setup in the zombie-account
tests around the relevant Reconcile cases to derive timestamps from
createPendTime rather than hardcoded minute values. Replace the -30-minute and
-5-minute offsets with fixed fractions such as -2*createPendTime and
-createPendTime/2, preserving the intended older-than and newer-than boundary
assertions when utils.WaitTime changes.
🪄 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: Pro Plus

Run ID: b2234552-8c9b-4007-931a-2cbe3a9c85bd

📥 Commits

Reviewing files that changed from the base of the PR and between db5d836 and 3d3d589.

📒 Files selected for processing (3)
  • controllers/account/account_controller.go
  • controllers/account/account_controller_test.go
  • controllers/accountpool/accountpool_controller_test.go

Comment thread controllers/account/account_controller_test.go Outdated
Comment thread controllers/account/account_controller_test.go
Comment thread controllers/account/account_controller.go
Comment thread controllers/account/account_controller.go Outdated
- Add !IsBYOC() guard to zombie GC condition for defense-in-depth
- Update BYOC test to set AccountPool so it tests BYOC protection specifically
- Save/restore TotalAccountWatcher global in account limit test
- Guard DescribeAccount call on non-empty AwsAccountID

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@BATMAN-JD
BATMAN-JD marked this pull request as ready for review August 3, 2026 19:45
@openshift-ci openshift-ci Bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Aug 3, 2026
@BATMAN-JD
BATMAN-JD requested a review from AlexSmithGH August 3, 2026 19:45
@openshift-ci
openshift-ci Bot requested review from dakotalongRH and reedcort August 3, 2026 19:45
BATMAN-JD and others added 2 commits August 3, 2026 15:07
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace the in-memory stsRetryCount map with a CR annotation
(aws.managed.openshift.io/aao-sts-retry-count) to eliminate shared
mutable state across concurrent reconcile goroutines. The plain Go map
could cause a runtime panic when accessed concurrently.

Also adds a 1-hour requeue interval after retries are exhausted to
prevent clogging the reconcile queue when many accounts are stuck.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@BATMAN-JD

Copy link
Copy Markdown
Contributor Author

/retest

@BATMAN-JD

Copy link
Copy Markdown
Contributor Author

Container test exited with code 137, reason OOMKilled for lint test. Very frustrating. Will try in a little bit

@BATMAN-JD

Copy link
Copy Markdown
Contributor Author

/retest

@BATMAN-JD

Copy link
Copy Markdown
Contributor Author

Container test exited with code 137, reason OOMKilled for lint test. Still seeing this. Will try in another hour or so

@BATMAN-JD BATMAN-JD changed the title fix: auto-cleanup closed AWS accounts and use CR-persisted state for STS retries fix: auto-cleanup closed AWS accounts and thread-safe STS retry handling Aug 4, 2026
Replace annotation-based approach with a mutex-protected in-memory map
per Alex's feedback. The mutex prevents Go runtime panics from concurrent
map access across reconcile goroutines while keeping the implementation
simple — no new code paths or business logic for failed states.

Lock/unlock is encapsulated in helper methods (incrementSTSRetry,
getSTSRetry, clearSTSRetry) with defer-based unlock so callers never
touch the mutex directly.

After retries are exhausted the account is failed with no requeue,
consistent with core controller design.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@BATMAN-JD
BATMAN-JD force-pushed the BATMAN-JD/fix-sts-retry-loop branch from ad44750 to 436fe25 Compare August 4, 2026 20:05
@openshift-ci

openshift-ci Bot commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

@BATMAN-JD: 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.

@AlexSmithGH

Copy link
Copy Markdown
Contributor

/lgtm

@openshift-ci openshift-ci Bot added the lgtm Indicates that a PR is ready to be merged. label Aug 4, 2026
@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: AlexSmithGH, BATMAN-JD

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:
  • OWNERS [AlexSmithGH,BATMAN-JD]

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 ddd0db1 into openshift:master Aug 4, 2026
14 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. lgtm Indicates that a PR is ready to be merged. tide/merge-method-squash Denotes a PR that should be squashed by tide when it merges.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants