Skip to content

Conversation

@huali9
Copy link
Contributor

@huali9 huali9 commented Oct 28, 2025

machine update e2e, I tested in my local and works @sunzhaohua2 @miyadav @damdo @theobarberbany PTAL, thanks!

Summary by CodeRabbit

  • Tests
    • Expanded end-to-end test coverage for machine migration scenarios, including MAPI machine updates with metadata changes.
    • Introduced new test helpers to track and validate machine state transitions and synchronization status before and after operations.
    • Enhanced verification that generation metadata and synchronized conditions remain consistent during expected update operations.

@coderabbitai
Copy link

coderabbitai bot commented Oct 28, 2025

Walkthrough

Adds machine state-tracking helpers to validate MAPI/CAPI synchronization during updates, including capture and verification functions. Introduces comprehensive end-to-end tests for MAPI machine update operations with label/annotation changes and synchronization validation. Adds Gomega import to test files. Note: duplicate test suites appear in both test files.

Changes

Cohort / File(s) Summary
Machine State Helpers
e2e/machine_migration_helpers.go
Introduces MachineState struct and helpers: captureMachineStateBeforeUpdate to capture MAPI/CAPI generations and synchronized condition time, and verifyMachineStateChanged/verifyMachineStateUnchanged to assert generation and synchronization time transitions. Enables validation of metadata-driven vs. metadata-only updates.
MAPI Machine Update Tests
e2e/machine_migration_mapi_authoritative_test.go
Adds new "Update MAPI Machine" test suite with operations on MAPI machines (add/modify/delete labels and annotations), synchronization verification to CAPI, and validation that synchronized state remains unchanged for non-mutating operations. Suite includes setup, teardown, and multiple test cases. Duplicated test block present. Adds Gomega import.
CAPI Machine Update Tests
e2e/machine_migration_capi_authoritative_test.go
Adds duplicate "Update CAPI Machine" test suite (identical to existing suite). Adds Gomega import.

Sequence Diagram(s)

sequenceDiagram
    participant Test as Test Case
    participant Helper as State Helper
    participant MAPI as MAPI Machine
    participant CAPI as CAPI Machine
    
    Test->>Helper: captureMachineStateBeforeUpdate
    Helper->>MAPI: fetch machine & status
    Helper->>CAPI: fetch machine & status
    Helper->>Test: return MachineState (pre-op)
    
    Test->>MAPI: perform operation (label/annotation change)
    Test->>Helper: wait & verify synchronization
    Helper->>CAPI: check synchronized to CAPI
    Helper->>Test: sync confirmed
    
    Test->>Helper: verifyMachineStateChanged/Unchanged
    Helper->>MAPI: fetch post-op status
    Helper->>CAPI: fetch post-op status
    Helper->>Helper: compare generations & times
    Helper->>Test: validation result (pass/fail)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • Duplicate test suites: Both MAPI and CAPI test files contain duplicate/identical test blocks that need clarification or removal
  • State helper complexity: New MachineState struct and validation logic verify generation counters and synchronization timestamps—logic requires careful review to ensure correctness
  • Test case coverage: Multiple label/annotation operations across add/modify/delete scenarios need verification that test assertions align with expected behavior
  • Synchronization timing: State capture and verification functions handle timing-dependent operations that may be environment-sensitive

Poem

🐰 New states we track, through migrations we hop,
MAPI meets CAPI, the syncs never stop,
Labels and annotations in dance do they sway,
But why test it twice? A duplicate play!

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The pull request title "machine update" is directly related to the main changes in the changeset. The primary modifications consist of adding end-to-end test suites for machine update operations—specifically introducing tests for MAPI and CAPI machine updates, along with supporting helper functions for state tracking and validation. The title accurately captures the core theme of the changes, aligning with the PR description which mentions "adding 'machine update e2e'". While the title could be more descriptive by explicitly mentioning "e2e tests," it is sufficiently specific within the project context and conveys meaningful information about the changeset. The title is not misleading, off-topic, or vague to the point of being uninformative.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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 and usage tips.

@openshift-ci openshift-ci bot requested review from chrischdi and mdbooth October 28, 2025 04:53
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Oct 28, 2025

[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 theobarberbany for approval. For more information see the Code Review Process.

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

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

Copy link

@coderabbitai coderabbitai bot left a comment

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 (5)
e2e/machine_migration_helpers.go (3)

328-333: Prefer value + presence flag over pointer for SynchronizedTime

Using a pointer here (and later taking an address of a range copy) is fragile. Store the time value and a boolean presence flag instead; it’s simpler and avoids accidental aliasing.

 type MachineState struct {
   MAPIGeneration   int64
   CAPIGeneration   int64
-  SynchronizedTime *metav1.Time
+  SynchronizedTime metav1.Time
+  HasSynchronizedTime bool
 }

Follow-ups (outside this hunk):

  • In captureMachineStateBeforeUpdate: set both SynchronizedTime and HasSynchronizedTime when the condition is found.
  • In verify helpers: gate temporal assertions on HasSynchronizedTime and use SynchronizedTime directly.

339-356: Don’t take the address of a for-range copy; capture the value instead

This loop takes the address of condition.LastTransitionTime where condition is a copy. Prefer copying the value into state (or use the boolean flag from the previous comment).

- for _, condition := range currentMAPIMachine.Status.Conditions {
+ for _, condition := range currentMAPIMachine.Status.Conditions {
     if condition.Type == SynchronizedCondition {
-      state.SynchronizedTime = &condition.LastTransitionTime
+      // value copy; no pointer to range variable
+      state.SynchronizedTime = condition.LastTransitionTime
+      state.HasSynchronizedTime = true
       break
     }
   }

408-419: DRY the “find synchronized time” scan into a tiny helper

Both verify functions repeat the same loop. Extract a small helper to read the synchronized condition’s LastTransitionTime and reuse it. Keeps tests terse and less error-prone.

// outside: helpers.go
func getSynchronizedLastTransitionTime(m *mapiv1beta1.Machine) (*metav1.Time, bool) {
  for _, c := range m.Status.Conditions {
    if c.Type == SynchronizedCondition {
      t := c.LastTransitionTime
      return &t, true
    }
  }
  return nil, false
}

Then replace the loops with getSynchronizedLastTransitionTime(mapiMachine).

e2e/machine_migration_capi_authoritative_test.go (1)

325-341: Stabilize capture: wait for Synchronized condition before recording previous state

If the synchronized condition isn’t set yet, previousState.SynchronizedTime may be nil and downstream assertions may skip/flake. Ensure it’s True before capture.

 It("should add labels/annotations on CAPI machine", func() {
-  // Capture state before the update
-  previousState = captureMachineStateBeforeUpdate(cl, newMapiMachine.Name)
+  // Ensure sync condition is present, then capture state
+  verifyMAPIMachineSynchronizedCondition(newMapiMachine, mapiv1beta1.MachineAuthorityClusterAPI)
+  previousState = captureMachineStateBeforeUpdate(cl, newMapiMachine.Name)
   Eventually(func() error {

Please run this suite once locally to confirm reduced flakes in the first “Update CAPI Machine” block.

e2e/machine_migration_mapi_authoritative_test.go (1)

229-248: Optional: add the same precondition before capture for consistency

Align with the CAPI suite by waiting for the Synchronized condition before capturing; reduces any timing window variability.

 It("should add labels/annotations on MAPI machine", func() {
-  // Capture state before the update
+  // Optional: ensure sync condition is present, then capture state
+  verifyMAPIMachineSynchronizedCondition(newMapiMachine, mapiv1beta1.MachineAuthorityMachineAPI)
   previousState = captureMachineStateBeforeUpdate(cl, newMapiMachine.Name)
📜 Review details

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to data retention organization setting

📥 Commits

Reviewing files that changed from the base of the PR and between a1a97d6 and a4dd8b0.

📒 Files selected for processing (3)
  • e2e/machine_migration_capi_authoritative_test.go (2 hunks)
  • e2e/machine_migration_helpers.go (1 hunks)
  • e2e/machine_migration_mapi_authoritative_test.go (2 hunks)

Comment on lines +375 to +386
// Verify synchronized time is updated
var currentSynchronizedTime *metav1.Time
for _, condition := range mapiMachine.Status.Conditions {
if condition.Type == SynchronizedCondition {
currentSynchronizedTime = &condition.LastTransitionTime
break
}
}
Expect(currentSynchronizedTime).ToNot(BeNil(), "Synchronized condition should exist")
By(fmt.Sprintf("Verifying synchronized time changed after %s (previous: %v, current: %v)", operation, previousState.SynchronizedTime.Time, currentSynchronizedTime.Time))
Expect(currentSynchronizedTime.Time).To(BeTemporally(">", previousState.SynchronizedTime.Time), fmt.Sprintf("Synchronized time should change when syncing %s metadata to spec", operation))

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Nil-deref risk: previousState.SynchronizedTime can be nil

If the synchronized condition wasn’t present when captured, this dereferences a nil pointer (both in By() and BeTemporally(">")). Guard it and still assert that current sync time is set.

- // Verify synchronized time is updated
- var currentSynchronizedTime *metav1.Time
+ // Verify synchronized time is updated
+ var currentSynchronizedTime *metav1.Time
   for _, condition := range mapiMachine.Status.Conditions {
     if condition.Type == SynchronizedCondition {
       currentSynchronizedTime = &condition.LastTransitionTime
       break
     }
   }
   Expect(currentSynchronizedTime).ToNot(BeNil(), "Synchronized condition should exist")
- By(fmt.Sprintf("Verifying synchronized time changed after %s (previous: %v, current: %v)", operation, previousState.SynchronizedTime.Time, currentSynchronizedTime.Time))
- Expect(currentSynchronizedTime.Time).To(BeTemporally(">", previousState.SynchronizedTime.Time), fmt.Sprintf("Synchronized time should change when syncing %s metadata to spec", operation))
+ if previousState.SynchronizedTime != nil {
+   By(fmt.Sprintf(
+     "Verifying synchronized time changed after %s (previous: %v, current: %v)",
+     operation, previousState.SynchronizedTime.Time, currentSynchronizedTime.Time))
+   Expect(currentSynchronizedTime.Time).
+     To(BeTemporally(">", previousState.SynchronizedTime.Time),
+        fmt.Sprintf("Synchronized time should change when syncing %s metadata to spec", operation))
+ } else {
+   By(fmt.Sprintf("Previous synchronized time missing; asserting current time is set after %s", operation))
+   Expect(currentSynchronizedTime.Time.IsZero()).To(BeFalse(), "Synchronized time should be set after synchronization")
+ }

Optional hardening: re-fetch mapiMachine at the start of this function to reduce reliance on the caller providing a fresh object.

@huali9 huali9 changed the title machine update OCPCLOUD-2992: machine update Oct 28, 2025
@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Oct 28, 2025
@openshift-ci-robot
Copy link

openshift-ci-robot commented Oct 28, 2025

@huali9: This pull request references OCPCLOUD-2992 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 story to target the "4.21.0" version, but no target version was set.

In response to this:

machine update e2e, I tested in my local and works @sunzhaohua2 @miyadav @damdo @theobarberbany PTAL, thanks!

Summary by CodeRabbit

  • Tests
  • Expanded end-to-end test coverage for machine migration scenarios, including MAPI machine updates with metadata changes.
  • Introduced new test helpers to track and validate machine state transitions and synchronization status before and after operations.
  • Enhanced verification that generation metadata and synchronized conditions remain consistent during expected update operations.

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
Copy link
Contributor

openshift-ci bot commented Oct 28, 2025

@huali9: 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/okd-scos-e2e-aws-ovn a4dd8b0 link false /test okd-scos-e2e-aws-ovn

Full PR test history. Your PR dashboard.

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.

@sunzhaohua2
Copy link
Contributor

@huali9 can we use Komega for Eventually?

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

Labels

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