-
Notifications
You must be signed in to change notification settings - Fork 49
OCPCLOUD-2992: machine update #400
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
WalkthroughAdds a MachineState type and helpers to capture and verify pre/post MAPI/CAPI generations and synchronized time; introduces new end-to-end test suites for MAPI and CAPI machine updates (label/annotation add/modify/delete) and imports Gomega. Duplicate test blocks were added in test files. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant Test as E2E Test
participant Helper as MachineState Helper
participant MAPI as MAPI API
participant CAPI as CAPI API
rect rgba(173,216,230,0.15)
Test->>Helper: captureMachineStateBeforeUpdate(machineName)
Helper->>MAPI: Get Machine, Status (generation, conds)
Helper->>CAPI: Get Mirror Machine, Status (generation)
Helper-->>Test: MachineState{MAPIGeneration, CAPIGeneration, SynchronizedTime}
end
rect rgba(144,238,144,0.12)
Test->>MAPI: Apply change (add/modify/delete labels/annotations)
Note right of MAPI: change may be metadata-only or metadata+generation
MAPI-->>Test: update acknowledged
end
rect rgba(255,228,196,0.12)
Test->>Helper: wait & verify synchronization
Helper->>CAPI: Poll mirror for expected label/annotation state
CAPI-->>Helper: updated state observed
Helper-->>Test: sync confirmed
end
rect rgba(221,160,221,0.08)
Test->>Helper: verifyMachineStateChanged/Unchanged(prevState, authority, op)
Helper->>MAPI: fetch post-op status
Helper->>CAPI: fetch post-op status
Helper-->>Test: verdict (generations/time changed or unchanged)
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes
Poem
Pre-merge checks and finishing touches❌ Failed checks (1 inconclusive)
✅ Passed checks (1 passed)
✨ Finishing touches
🧪 Generate unit tests (beta)
📜 Recent review detailsConfiguration 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 📒 Files selected for processing (3)
🔇 Additional comments (9)
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 golangci-lint (2.5.0)Error: can't load config: unsupported version of the configuration: "" See https://golangci-lint.run/docs/product/migration-guide for migration instructions Comment |
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: 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 |
There was a problem hiding this 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 SynchronizedTimeUsing 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 insteadThis 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 helperBoth 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 stateIf 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 consistencyAlign 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
📒 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)
| // 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)) | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
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: 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:
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. |
|
@huali9: The following test failed, say
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. |
|
@huali9 can we use Komega for Eventually? |
a4dd8b0 to
36d3beb
Compare
Sure, updated, PTAL again @sunzhaohua2 |
|
@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:
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. |
machine update e2e, I tested in my local and works @sunzhaohua2 @miyadav @damdo @theobarberbany PTAL, thanks!
Summary by CodeRabbit