Skip to content

OCPBUGS-82191: Surface async GCP instance creation errors - #160

Open
RadekManak wants to merge 6 commits into
openshift:mainfrom
openshift-cloud-team:mapgcp-error-surfacing
Open

OCPBUGS-82191: Surface async GCP instance creation errors#160
RadekManak wants to merge 6 commits into
openshift:mainfrom
openshift-cloud-team:mapgcp-error-surfacing

Conversation

@RadekManak

@RadekManak RadekManak commented Apr 21, 2026

Copy link
Copy Markdown
Contributor

Make provider-side instance creation failures visible during reconciliation by checking the returned insert operation and visible in-flight operations instead of relying only on instance lookup.

Summary by CodeRabbit

  • New Features

    • Improved visibility and handling of asynchronous instance creation operations.
  • Bug Fixes

    • Provider-side creation errors are now surfaced and recorded appropriately.
    • Pending operations and temporary instance lookup failures are retried automatically.
    • Instance creation conflicts are handled gracefully to prevent spurious failures.
  • Tests

    • Expanded coverage for asynchronous creation, retries, conflicts, and provider error handling.

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Apr 21, 2026
@openshift-ci-robot

Copy link
Copy Markdown
Contributor

@RadekManak: This pull request references Jira Issue OCPBUGS-82191, 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:

Make provider-side instance creation failures visible during reconciliation by checking the returned insert operation and visible in-flight operations instead of relying only on instance lookup.

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-robot openshift-ci-robot added the jira/invalid-bug Indicates that a referenced Jira bug is invalid for the branch this PR is targeting. label Apr 21, 2026
@coderabbitai

coderabbitai Bot commented Apr 21, 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 machine reconciler now checks recent GCP insert operations before instance creation, requeues pending and conflict cases, records provider operation failures, and handles creation-time not-found responses as transient. Compute service interfaces, mocks, and tests support these flows.

Changes

GCP asynchronous instance creation

Layer / File(s) Summary
Zone operation service support
pkg/cloud/gcp/actuators/services/compute/computeservice.go, pkg/cloud/gcp/actuators/services/compute/computeservice_mock.go
The compute service exposes ZoneOperationsList. The mock exposes hooks for zone operation and instance retrieval.
Creation operation reconciliation
pkg/cloud/gcp/actuators/machine/reconciler.go
create() finds matching insert operations, requeues pending operations, handles HTTP 409 conflicts, reconciles successful inserts, and records provider-side failures. Creation-time not-found responses are transient, while update-time responses remain non-transient.
Asynchronous creation coverage
pkg/cloud/gcp/actuators/machine/reconciler_test.go
Tests cover pending and failed operations, retries, conflicts, wrapped 404 errors, resource-path matching, transient handling, mock callbacks, and operationError() formatting.

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

Suggested reviewers: damdo, racheljpg

Sequence Diagram(s)

sequenceDiagram
    participant Reconciler
    participant ZoneOperationsList
    participant InstancesInsert
    participant InstanceState

    Reconciler->>ZoneOperationsList: Find latest matching insert operation
    ZoneOperationsList-->>Reconciler: Return operation status and errors
    alt Pending operation
        Reconciler->>Reconciler: Requeue
    else No pending operation
        Reconciler->>InstancesInsert: Insert instance
        InstancesInsert-->>Reconciler: Return operation or 409 conflict
        Reconciler->>InstanceState: Reconcile instance state
    end
Loading

Important

Pre-merge checks failed

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

❌ Failed checks (1 error, 1 warning, 1 inconclusive)

Check name Status Explanation Resolution
No-Sensitive-Data-In-Logs ❌ Error reconciler.go:429 logs the full provider-supplied Error.Errors value; %v includes nested ErrorDetails, messages, and metadata that may contain customer or sensitive data. Log only an allowlisted error code or sanitized message. Do not format the full provider error structs.
Docstring Coverage ⚠️ Warning Docstring coverage is 12.50% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Test Structure And Quality ❓ Inconclusive This codebase uses standard Go testing, not Ginkgo. Custom check requires "Ginkgo test code" review, making most Ginkgo-specific requirements inapplicable. However, TestCreateRetriesAfterPriorAsync... Clarify: Does the check apply only to Ginkgo tests, or to all Go tests? If all Go tests, split TestCreateRetriesAfterPriorAsyncInsertFailure into separate test functions for each behavior.
✅ Passed checks (12 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 main change: surfacing asynchronous GCP instance creation errors.
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 PR adds only literal, static Go test and subtest names; no Ginkgo titles or runtime-derived values appear in the changed tests.
Microshift Test Compatibility ✅ Passed The patch adds only standard Go unit tests in reconciler_test.go; it adds no Ginkgo e2e tests, MicroShift-sensitive APIs, namespaces, or unsupported assumptions.
Single Node Openshift (Sno) Test Compatibility ✅ Passed The pull request adds Go unit tests with testing.T, not Ginkgo e2e tests. No new multi-node assumptions or SNO guards require review.
Topology-Aware Scheduling Compatibility ✅ Passed The changes only handle GCP instance creation and compute operations; they add no pod affinity, topology spread, replica, node selector, toleration, or PDB constraints.
Ote Binary Stdout Contract ✅ Passed The PR adds no OTE binary or process-level stdout code; changes are reconciler/services/tests, and controller klog is configured with logtostderr=true.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed The PR adds standard Go unit tests only; it adds no Ginkgo e2e tests, IPv4 networking assumptions, or external connectivity requirements.
No-Weak-Crypto ✅ Passed The patch adds GCP operation lookup, URL-path matching, and error formatting only; scans found no weak-crypto APIs, algorithms, custom crypto, or secret/token comparisons.
Container-Privileges ✅ Passed The PR changes only four Go files. No container/Kubernetes manifests changed, and added lines contain none of privileged, hostPID, hostNetwork, hostIPC, SYS_ADMIN, or allowPrivilegeEscalation.
✨ 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 requested review from damdo and racheljpg April 21, 2026 14:32
@openshift-ci

openshift-ci Bot commented Apr 21, 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 nrb 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

@RadekManak

Copy link
Copy Markdown
Contributor Author

/jira refresh

@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 Apr 21, 2026
@openshift-ci-robot

Copy link
Copy Markdown
Contributor

@RadekManak: This pull request references Jira Issue OCPBUGS-82191, 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 ASSIGNED, which is one of the valid states (NEW, ASSIGNED, POST)
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.

@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

🧹 Nitpick comments (1)
pkg/cloud/gcp/actuators/machine/reconciler.go (1)

462-470: Record failed-create metrics for async operation failures too.

This new return path updates conditions, but it bypasses metrics.RegisterFailedInstanceCreate, so async provider-side failures won't show up in the existing failed-create metrics/alerts.

📈 Proposed fix
 	if err := operationError(insertOp); err != nil {
+		metrics.RegisterFailedInstanceCreate(&metrics.MachineLabels{
+			Name:      r.machine.Name,
+			Namespace: r.machine.Namespace,
+			Reason:    "failed to create instance via compute service",
+		})
 		r.providerStatus.Conditions = reconcileConditions(r.providerStatus.Conditions, metav1.Condition{
 			Type:    string(machinev1.MachineCreated),
 			Reason:  machineCreationFailedReason,
 			Message: err.Error(),
 			Status:  metav1.ConditionFalse,
 		})
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/cloud/gcp/actuators/machine/reconciler.go` around lines 462 - 470, The
return path when operationError(insertOp) is true updates
r.providerStatus.Conditions but skips recording failed-create metrics; call
metrics.RegisterFailedInstanceCreate (with the same labels/context used
elsewhere for machine failures) immediately before returning from the
operationError(insertOp) branch so async/provider-side failures are counted,
keeping the existing condition update; locate the operationError(insertOp) check
in reconciler.go and add the metrics.RegisterFailedInstanceCreate invocation
prior to the fmt.Errorf return.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/cloud/gcp/actuators/machine/reconciler.go`:
- Around line 423-430: The current logic in reconciler.go's
latestVisibleInsertOperation check only skips re-create when existingOp.Status
!= "DONE" but allows a DONE operation with provider-side errors to fall through
to InstancesInsert; update the check in the reconciler (function
latestVisibleInsertOperation usage) to detect when existingOp.Status == "DONE"
and existingOp.Error != nil && len(existingOp.Error.Errors) > 0 and treat that
as a terminal failure: log the error (including existingOp.Error.Errors and
r.machine.Name), surface or return an appropriate non-retry error instead of
proceeding to InstancesInsert, and ensure any Requeue/Failure state prevents
issuing a new InstancesInsert for that same visible insert operation.

---

Nitpick comments:
In `@pkg/cloud/gcp/actuators/machine/reconciler.go`:
- Around line 462-470: The return path when operationError(insertOp) is true
updates r.providerStatus.Conditions but skips recording failed-create metrics;
call metrics.RegisterFailedInstanceCreate (with the same labels/context used
elsewhere for machine failures) immediately before returning from the
operationError(insertOp) branch so async/provider-side failures are counted,
keeping the existing condition update; locate the operationError(insertOp) check
in reconciler.go and add the metrics.RegisterFailedInstanceCreate invocation
prior to the fmt.Errorf return.
🪄 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: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: d4c33b05-57d3-4057-b16a-74abdfd9d1eb

📥 Commits

Reviewing files that changed from the base of the PR and between 065e2b6 and 3441b64.

📒 Files selected for processing (4)
  • pkg/cloud/gcp/actuators/machine/reconciler.go
  • pkg/cloud/gcp/actuators/machine/reconciler_test.go
  • pkg/cloud/gcp/actuators/services/compute/computeservice.go
  • pkg/cloud/gcp/actuators/services/compute/computeservice_mock.go

Comment thread pkg/cloud/gcp/actuators/machine/reconciler.go
@RadekManak
RadekManak force-pushed the mapgcp-error-surfacing branch from 3441b64 to 8e39814 Compare April 22, 2026 12:03
@openshift-ci-robot

Copy link
Copy Markdown
Contributor

@RadekManak: This pull request references Jira Issue OCPBUGS-82191, which is valid.

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 POST, which is one of the valid states (NEW, ASSIGNED, POST)
Details

In response to this:

Make provider-side instance creation failures visible during reconciliation by checking the returned insert operation and visible in-flight operations instead of relying only on instance lookup.

Summary by CodeRabbit

  • New Features

  • Added compute operations listing support to improve visibility into async instance inserts.

  • Bug Fixes

  • Improved handling of async insert operations, surfacing provider-side errors and requeuing appropriately.

  • Requeued instead of failing when instance lookups are temporarily unavailable.

  • Requeued on instance creation conflicts (409) instead of treating as immediate failures.

  • Tests

  • Expanded tests covering async failures, requeue scenarios, operation-error aggregation, and conflict handling.

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 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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/cloud/gcp/actuators/machine/reconciler.go`:
- Around line 504-506: The current check using isNotFoundError(...) only matches
a bare *googleapi.Error and misses wrapped 404 errors; update the logic so the
code uses errors.As to detect a *googleapi.Error (or modify isNotFoundError to
internally use errors.As) and then checks err.Code == 404 before returning
&machinecontroller.RequeueAfterError{RequeueAfter: requeueAfterSeconds *
time.Second}; apply this change for all spots that currently call
isNotFoundError for requeue handling (the 404 requeue branches in reconciler.go,
e.g., the places around the RequeueAfterError returns) so wrapped errors are
handled consistently like the 409 handling that already uses errors.As.
🪄 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: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 0f81abaf-5607-41b7-b590-375f1cedc8de

📥 Commits

Reviewing files that changed from the base of the PR and between 3441b64 and 8e39814.

📒 Files selected for processing (4)
  • pkg/cloud/gcp/actuators/machine/reconciler.go
  • pkg/cloud/gcp/actuators/machine/reconciler_test.go
  • pkg/cloud/gcp/actuators/services/compute/computeservice.go
  • pkg/cloud/gcp/actuators/services/compute/computeservice_mock.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • pkg/cloud/gcp/actuators/services/compute/computeservice.go
  • pkg/cloud/gcp/actuators/services/compute/computeservice_mock.go
  • pkg/cloud/gcp/actuators/machine/reconciler_test.go

@RadekManak
RadekManak force-pushed the mapgcp-error-surfacing branch from 8e39814 to f5b6f13 Compare April 22, 2026 14:36

@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

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/cloud/gcp/actuators/machine/reconciler.go`:
- Around line 504-506: reconcileMachineWithCloudState currently treats an
InstancesGet 404 as a transient condition and always returns a
RequeueAfterError, which causes endless retries when invoked from update();
change reconcileMachineWithCloudState signature to accept a boolean (e.g.,
treatNotFoundAsTransient bool) and only return
&machinecontroller.RequeueAfterError{...} when isNotFoundError(err) &&
treatNotFoundAsTransient is true; update all call sites so create() invokes
reconcileMachineWithCloudState(..., true) and update() invokes
reconcileMachineWithCloudState(..., false), leaving isNotFoundError and
RequeueAfterError logic intact otherwise.
🪄 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: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: d9048dd5-fbe5-4632-917f-04e678716bbd

📥 Commits

Reviewing files that changed from the base of the PR and between 8e39814 and f5b6f13.

📒 Files selected for processing (4)
  • pkg/cloud/gcp/actuators/machine/reconciler.go
  • pkg/cloud/gcp/actuators/machine/reconciler_test.go
  • pkg/cloud/gcp/actuators/services/compute/computeservice.go
  • pkg/cloud/gcp/actuators/services/compute/computeservice_mock.go

Comment thread pkg/cloud/gcp/actuators/machine/reconciler.go Outdated
@newtonheath

Copy link
Copy Markdown

@RadekManak can we get help getting this reviewed please - its a release blocker

@RadekManak
RadekManak force-pushed the mapgcp-error-surfacing branch from f5b6f13 to 73fee98 Compare April 29, 2026 14:57

@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

🧹 Nitpick comments (1)
pkg/cloud/gcp/actuators/machine/reconciler_test.go (1)

197-203: Assert ZoneOperationsList query arguments to lock behavior.

These mocks drive return shape, but they don’t validate the filter and orderBy inputs. Adding assertions for expected query content would prevent silent regressions in latestVisibleInsertOperation() construction.

Also applies to: 220-224, 1178-1187

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

In `@pkg/cloud/gcp/actuators/machine/reconciler_test.go` around lines 197 - 203,
The mock implementation for mockZoneOperationsList used in tests should assert
the incoming query args (filter and orderBy, and optionally project/zone) to
ensure latestVisibleInsertOperation() constructs the correct query; update the
mock callbacks (mockZoneOperationsList at the instances around the given diffs
and the ones at lines ~220 and ~1178) to check that the received filter string
contains the expected operation type and instance metadata and that orderBy
equals the expected sort (e.g., "insertTime desc") and fail the test (return an
error or call t.Fatalf) when they don’t match so regressions in query
construction are detected.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/cloud/gcp/actuators/machine/reconciler.go`:
- Around line 742-749: The loop over op.Error.Errors panics if any slice element
is nil — modify the block in reconciler.go that iterates "for _, e := range
op.Error.Errors" to skip nil entries (if e == nil continue) and also defensively
ensure op.Error and op.Error.Errors are non-nil before iterating; then build
msgs using e.Code and e.Message as before and return the formatted error string.
This prevents a nil dereference while preserving the existing error-message
aggregation.

---

Nitpick comments:
In `@pkg/cloud/gcp/actuators/machine/reconciler_test.go`:
- Around line 197-203: The mock implementation for mockZoneOperationsList used
in tests should assert the incoming query args (filter and orderBy, and
optionally project/zone) to ensure latestVisibleInsertOperation() constructs the
correct query; update the mock callbacks (mockZoneOperationsList at the
instances around the given diffs and the ones at lines ~220 and ~1178) to check
that the received filter string contains the expected operation type and
instance metadata and that orderBy equals the expected sort (e.g., "insertTime
desc") and fail the test (return an error or call t.Fatalf) when they don’t
match so regressions in query construction are detected.
🪄 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: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 35e9b6bd-5ef3-4114-a95c-fbccf95ed61d

📥 Commits

Reviewing files that changed from the base of the PR and between f5b6f13 and 73fee98.

📒 Files selected for processing (4)
  • pkg/cloud/gcp/actuators/machine/reconciler.go
  • pkg/cloud/gcp/actuators/machine/reconciler_test.go
  • pkg/cloud/gcp/actuators/services/compute/computeservice.go
  • pkg/cloud/gcp/actuators/services/compute/computeservice_mock.go

Comment thread pkg/cloud/gcp/actuators/machine/reconciler.go
@RadekManak
RadekManak force-pushed the mapgcp-error-surfacing branch from 73fee98 to 3326eaf Compare August 5, 2026 14:26
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@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

🧹 Nitpick comments (3)
pkg/cloud/gcp/actuators/machine/reconciler_test.go (3)

68-69: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Build a fresh operation per test case instead of sharing asyncFailureOp.

asyncFailureOp is created once and shared by all TestCreate cases. The case at Line 233 calls withTargetLink(asyncFailureOp, ...), which mutates that shared pointer in place from inside a mock closure. The case at Line 168 returns the same pointer from MockInstancesInsert.

The cases run sequentially today, so the assertions still pass. The coupling is fragile: adding t.Parallel() or reordering the cases changes which subtest observes a mutated TargetLink. Call zoneResourcePoolExhaustedOperation inside each mock, or make withTargetLink copy the operation.

♻️ Proposed change to make `withTargetLink` non-mutating
 func withTargetLink(op *compute.Operation, targetLink string) *compute.Operation {
-	op.TargetLink = targetLink
-	return op
+	copied := *op
+	copied.TargetLink = targetLink
+	return &copied
 }
🤖 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/cloud/gcp/actuators/machine/reconciler_test.go` around lines 68 - 69,
Stop sharing the mutable asyncFailureOp across TestCreate cases: create a fresh
operation with zoneResourcePoolExhaustedOperation inside each mock that returns
or modifies it, including the withTargetLink path, or update withTargetLink to
copy before changing TargetLink. Keep each subtest isolated so
MockInstancesInsert and related assertions never observe another case’s
mutation.

1440-1442: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Use errors.As for the requeue type check.

Line 1440 asserts the concrete type directly. Line 1336 in the same file uses errors.As. Use errors.As here too, so a wrapped *machinecontroller.RequeueAfterError is still detected.

♻️ Proposed change
-	if _, ok := err.(*machinecontroller.RequeueAfterError); ok {
+	var requeueErr *machinecontroller.RequeueAfterError
+	if errors.As(err, &requeueErr) {
 		t.Fatalf("expected non-requeue error, got %v", err)
 	}
🤖 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/cloud/gcp/actuators/machine/reconciler_test.go` around lines 1440 - 1442,
Update the error-type assertion in the test around the requeue check to use
errors.As, matching the existing pattern near the other requeue assertion.
Ensure wrapped *machinecontroller.RequeueAfterError values are detected while
preserving the current failure message and non-requeue expectation.

171-190: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Merge the two identical requeue cases.

"Requeue when returned operation is still RUNNING" and "Requeue when returned operation is not visible yet" use the same mocks and expect the same error. Only the operation name differs, and the reconciler does not read that name. Keep one case.

🤖 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/cloud/gcp/actuators/machine/reconciler_test.go` around lines 171 - 190,
Merge the duplicate requeue cases in reconciler_test.go by keeping a single
table entry around the existing requeue path in the machine reconciler test. The
two cases that cover a RUNNING operation and an operation not yet visible use
the same mockInstancesInsert and mockInstancesGet behavior and assert the same
machinecontroller.RequeueAfterError, so remove one of them and preserve the
shared expectation in the remaining case.
🤖 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 `@pkg/cloud/gcp/actuators/machine/reconciler.go`:
- Around line 726-733: The filter loop in the operation lookup should not return
immediately when ZoneOperationsList fails. Update the logic around
ZoneOperationsList to record the latest error and continue trying subsequent
filters, returning the operation result on success and the last recorded error
only after every filter has failed.

---

Nitpick comments:
In `@pkg/cloud/gcp/actuators/machine/reconciler_test.go`:
- Around line 68-69: Stop sharing the mutable asyncFailureOp across TestCreate
cases: create a fresh operation with zoneResourcePoolExhaustedOperation inside
each mock that returns or modifies it, including the withTargetLink path, or
update withTargetLink to copy before changing TargetLink. Keep each subtest
isolated so MockInstancesInsert and related assertions never observe another
case’s mutation.
- Around line 1440-1442: Update the error-type assertion in the test around the
requeue check to use errors.As, matching the existing pattern near the other
requeue assertion. Ensure wrapped *machinecontroller.RequeueAfterError values
are detected while preserving the current failure message and non-requeue
expectation.
- Around line 171-190: Merge the duplicate requeue cases in reconciler_test.go
by keeping a single table entry around the existing requeue path in the machine
reconciler test. The two cases that cover a RUNNING operation and an operation
not yet visible use the same mockInstancesInsert and mockInstancesGet behavior
and assert the same machinecontroller.RequeueAfterError, so remove one of them
and preserve the shared expectation in the remaining case.
🪄 Autofix

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: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 0042d4f6-7a9f-4de6-b6b2-0a4f59647a8e

📥 Commits

Reviewing files that changed from the base of the PR and between 91033fc and 3326eaf.

📒 Files selected for processing (4)
  • pkg/cloud/gcp/actuators/machine/reconciler.go
  • pkg/cloud/gcp/actuators/machine/reconciler_test.go
  • pkg/cloud/gcp/actuators/services/compute/computeservice.go
  • pkg/cloud/gcp/actuators/services/compute/computeservice_mock.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • pkg/cloud/gcp/actuators/services/compute/computeservice.go
  • pkg/cloud/gcp/actuators/services/compute/computeservice_mock.go

Comment on lines +726 to +733
for _, filter := range []string{
fmt.Sprintf(`targetLink="%s" AND operationType="insert"`, fmtInstanceSelfLink(r.projectID, r.providerSpec.Zone, r.machine.Name)),
fmt.Sprintf(`operationType="insert" AND targetLink:"%s"`, expectedPath),
} {
opList, err := r.computeService.ZoneOperationsList(r.projectID, r.providerSpec.Zone, filter, "creationTimestamp desc")
if err != nil {
return nil, err
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🌐 Web query:

GCP Compute Engine API list filter syntax AND operator colon substring match targetLink zoneOperations

💡 Result:

The Google Cloud Compute Engine API supports filtering list requests using a syntax based on API Improvement Proposal AIP-160 [1][2][3]. Filter Syntax Details: Operators: The API supports the following operators: =,!=, >, <, <=, >=, and: [1][2][3]. AND/OR Logic: Expressions are combined using implicit AND logic when multiple separate expressions are provided within parentheses [1][2][3]. You can also explicitly use the AND and OR operators [1][2][3]. Substring Matching: The colon (:) operator is used for substring matching on string fields [3]. For non-string fields, the: operator functions identically to the = (equality) operator [3]. TargetLink and zoneOperations: When filtering zoneOperations, the targetLink field is commonly used to narrow results to specific resources [4]. Because the: operator performs a substring match, filtering by targetLink often requires extra verification in your code to ensure exact matches, as the filter may return any operation containing that string within the targetLink URL [4]. Example usage for zoneOperations: To filter for specific preempted instances, you might use a filter string such as: 'operationType="compute.instances.preempted" AND targetLink:instances/your-instance-name' [4] Note that because targetLink:instances/your-instance-name matches any targetLink containing that substring, it is recommended to further validate the results in your client-side code if strict matching is required [4].

Citations:


Don't return early on API errors; try the fallback filter.

Both filter operators are valid in the Compute API: AND combines expressions and : performs substring matching on string fields. However, if ZoneOperationsList returns an error on the first filter request—whether due to transient API issues or other reasons—the loop exits immediately. The fallback filter never runs. This causes the async-failure surfacing feature added by this PR to stop working silently. Continue to the next filter on error and return the last error only when all filters fail.

🤖 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/cloud/gcp/actuators/machine/reconciler.go` around lines 726 - 733, The
filter loop in the operation lookup should not return immediately when
ZoneOperationsList fails. Update the logic around ZoneOperationsList to record
the latest error and continue trying subsequent filters, returning the operation
result on success and the last recorded error only after every filter has
failed.

@RadekManak
RadekManak force-pushed the mapgcp-error-surfacing branch 2 times, most recently from ca1f83b to 7b00b61 Compare August 5, 2026 15:10
Make provider-side instance creation failures visible during reconciliation
by inspecting the returned insert operation and the latest visible zone
insert operation, instead of treating a successful InstancesInsert HTTP
response (or a missing instance alone) as enough.

On failed DONE ops (e.g. ZONE_RESOURCE_POOL_EXHAUSTED), record
MachineCreated=False with the provider error and retry create until it
succeeds. Requeue while an insert is still RUNNING; on 409, reconcile
(requeue on transient 404) rather than failing as InvalidMachineConfiguration.
If a prior insert DONE successfully, skip re-insert when the instance
exists, or recreate when it does not. Match operation targetLink by
resource path so www/compute/sovereign-cloud URL hosts still resolve.
@RadekManak
RadekManak force-pushed the mapgcp-error-surfacing branch from 7b00b61 to 72afe38 Compare August 5, 2026 16:37
…y stockout

Extend async insert-op surfacing so providerID, addresses, and MachineCreated=True
are set only when the instance is RUNNING with a clean or absent insert op. Capacity
pool-exhausted failures keep MachineCreated=False with linear backoff and re-insert
from Create after Exists=false, failing terminal after 30 minutes.
…r backoff

MAO ignores InvalidMachineConfiguration from Update, so surface insert-op
failures while the instance is visible via MachineCreated=False + requeue
only. Terminal Failed stays on Create after vanish. Capacity backoff uses
triangular 20s/40s/60s… waits; insert gate shares that schedule.
…rt failures

Create sites that hit capacity via sync InstancesInsert or an immediate insert
op error now share deadline logic with capacityInsertGate so they return
InvalidMachineConfiguration past 30m instead of requeueing forever when no
prior Operation is discoverable. Update still uses recordCapacityAndRequeue
and never surfaces IMC.
Structure-only cleanup: collapse Create/Update capacity wrappers into
evaluateCapacityRetry, share the triangular boundary walker, and merge
duplicate insert-failure handling without changing behavior.
…acity

ZoneOperations.list ignores targetLink HAS/substring (0 items live), so
capacity/quota surfacing never ran. Match full targetLink URLs (www +
compute + BasePath) and order by insertTime. Treat QUOTA_EXCEEDED like
pool-exhausted with the same backoff/deadline, and gate Create/Update
from MachineCreated=False when the op list still misses.
@RadekManak

Copy link
Copy Markdown
Contributor Author

/hold
This is working AI slop tested on live cluster.
I am going on a vacation. Pushing if this needs to be merged sooner than in a week. More details on jira.

@openshift-ci openshift-ci Bot added the do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. label Aug 7, 2026
@openshift-ci

openshift-ci Bot commented Aug 7, 2026

Copy link
Copy Markdown
Contributor

@RadekManak: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/e2e-gcp-ovn 1b0b444 link true /test e2e-gcp-ovn

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

do-not-merge/hold Indicates that a PR should not merge because someone has issued a /hold command. 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