Skip to content

OCPCLOUD-2995: Machine status conversion and syncing#365

Merged
openshift-merge-bot[bot] merged 1 commit into
openshift:mainfrom
damdo:machine-status-conversion-and-syncing
Oct 10, 2025
Merged

OCPCLOUD-2995: Machine status conversion and syncing#365
openshift-merge-bot[bot] merged 1 commit into
openshift:mainfrom
damdo:machine-status-conversion-and-syncing

Conversation

@damdo
Copy link
Copy Markdown
Member

@damdo damdo commented Sep 19, 2025

This work is the Machine version of #329
It adds Machine status conversion and syncing between MAPI and CAPI.

Summary by CodeRabbit

  • New Features

    • Bidirectional status conversion between Machine/MachineSet representations, including phases, addresses, and failure details.
  • Bug Fixes

    • Condition handling improved: ensure LastTransitionTime is set and avoid duplicating controller-managed MachineSet conditions.
  • Refactor

    • Machine sync reconciler reorganized into staged ensure/patch flows with status-aware diffing and updated reconciliation inputs; multi-version condition diffing added.
  • Tests

    • Expanded unit and fuzz suites for status/address conversion and round-trip scenarios.
  • Chores

    • Renamed MAPI condition utilities for clarity.

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Sep 19, 2025
@openshift-ci-robot
Copy link
Copy Markdown

openshift-ci-robot commented Sep 19, 2025

@damdo: This pull request references OCPCLOUD-2995 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.

Details

In response to this:

WIP

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

openshift-ci Bot commented Sep 19, 2025

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@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 Sep 19, 2025
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Sep 19, 2025

Walkthrough

Adds bidirectional Machine and MachineSet status conversion between CAPI and MAPI, renames MAPI condition helpers and updates their behavior, extends multi-version status/condition diffing, refactors Machine reconciliation into staged ensure/create/update/status flows, updates MachineSet condition conversion, and adds tests and fuzzers for status/address/phase/condition handling.

Changes

Cohort / File(s) Summary
Controllers — Machine sync refactor
pkg/controllers/machinesync/machine_sync_controller.go
Rename reconcile parameters to source*/existing*, introduce staged ensure/create/update flows and many ensure* helpers, add status/spec diffing and patch helpers, propagate ownership/finalizers, and add helpers for detecting/applying spec/status changes.
Controllers — MachineSet status setter rename
pkg/controllers/machinesetsync/machineset_sync_controller.go
Replace util.SetMAPIMachineSetCondition(...) usage with util.SetMAPICondition(...) in setChangedMAPIMachineSetStatusFields.
Conversion — CAPI ➜ MAPI (machine)
pkg/conversion/capi2mapi/machine.go
Add conversion of clusterv1.Machine.Statusmapiv1beta1.Machine.Status with helpers for addresses, phase, failure reason/message; assign computed Status and aggregate conversion errors.
Conversion — MAPI ➜ CAPI (machine)
pkg/conversion/mapi2capi/machine.go
Add conversion of mapiv1beta1.Machine.Statusclusterv1.Machine.Status, many helpers to map addresses, phases, conditions (v1beta1/v1beta2), failure info, and derive readiness flags.
Conversion — MachineSet status
pkg/conversion/capi2mapi/machineset.go
Stop converting CAPI MachineSet Conditions into MAPI (set Conditions to nil) and remove the prior convertCAPIConditionsToMAPI helper.
Utils — Conditions helpers rename & behavior
pkg/util/conditions.go
Rename GetMAPIMachineSetConditionGetMAPICondition and SetMAPIMachineSetConditionSetMAPICondition; preserve signatures and add LastTransitionTime handling for new/existing conditions.
Utils — Sync/diff utilities
pkg/util/sync.go
Add multi-version status diffing helpers (CAPIMachineStatusEqual, MAPIMachineStatusEqual, extended MachineSet status comparisons) and per-version condition comparison functions for v1beta1/v1beta2.
Fuzzing — Conversion round-trips
pkg/conversion/test/fuzz/fuzz.go
Add fuzzers for machine status fields (addresses, phase, v1beta2 status), integrate into fuzzer funcs, and neutralize non-1:1 status fields in round-trip tests.
Tests — CAPI ➜ MAPI
pkg/conversion/capi2mapi/machine_test.go
Add tests validating CAPI→MAPI Machine status conversion: NodeRef, LastUpdated, Addresses, Phase, FailureReason/Message, and empty-status behavior.
Tests — MAPI ➜ CAPI
pkg/conversion/mapi2capi/machine_test.go
Add extensive tests for MAPI→CAPI Machine status conversion covering phases, v1beta1/v1beta2 conditions, NodeReady/Deleting semantics, addresses, and failure mapping.
Controllers tests — Machine sync adjustments
pkg/controllers/machinesync/machine_sync_controller_test.go
Use deterministic naming (WithName), reorder creation/ownership wiring to patch OwnerReferences after creation, and adjust assertions to match new creation/update sequencing.

Sequence Diagram(s)

sequenceDiagram
  autonumber
  actor Reconciler
  participant MS as MachineSync Controller
  participant Conv as Converters
  participant Diff as Diff Utils
  participant API as Kubernetes API

  rect rgb(235,245,255)
    Reconciler->>MS: Reconcile(request)
    MS->>API: Get source objects (CAPI/MAPI)
    MS->>Conv: Convert source ↔ target (spec + status)
    MS->>Diff: Diff(spec/metadata/providerSpec)
    alt spec/meta changed
      MS->>API: Create or Update target spec/metadata
    end
    MS->>Diff: hasStatusChanges?
    alt status changed
      MS->>Conv: setChanged*StatusFields (merge changed fields & use util.SetMAPICondition for MAPI)
      MS->>API: Patch target status
    else
      MS-->>MS: Skip status patch
    end
  end
Loading

Estimated code review effort

🎯 5 (Critical) | ⏱️ ~120 minutes

Poem

I hop through diffs with twitching nose,
I map each status where it grows.
Conditions learn when time has passed,
Converters stitch the future and past.
A rabbit cheers — the sync now flows. 🐇✨

Pre-merge checks and finishing touches

✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title Check ✅ Passed The title concisely references the Jira ticket and clearly summarizes the core change—adding machine status conversion and syncing between MAPI and CAPI—without extraneous details or ambiguity.
Docstring Coverage ✅ Passed Docstring coverage is 98.08% which is sufficient. The required threshold is 80.00%.
✨ 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.

@damdo damdo changed the title OCPCLOUD-2995: Machineset status conversion and syncing OCPCLOUD-2995: Machine status conversion and syncing Sep 19, 2025
@damdo damdo force-pushed the machine-status-conversion-and-syncing branch 3 times, most recently from 20be64f to ef363b0 Compare September 24, 2025 12:43
@openshift-ci-robot
Copy link
Copy Markdown

openshift-ci-robot commented Sep 24, 2025

@damdo: This pull request references OCPCLOUD-2995 which is a valid jira issue.

Details

In response to this:

This work is the Machine version of #329
It adds Machine status conversion and syncing between MAPI and CAPI.

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.

@damdo damdo marked this pull request as ready for review September 24, 2025 13:15
@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 Sep 24, 2025
@openshift-ci-robot
Copy link
Copy Markdown

openshift-ci-robot commented Sep 24, 2025

@damdo: This pull request references OCPCLOUD-2995 which is a valid jira issue.

Details

In response to this:

This work is the Machine version of #329
It adds Machine status conversion and syncing between MAPI and CAPI.

Summary by CodeRabbit

  • New Features

  • More accurate CAPI⇄MAPI Machine status synchronization, including phases, addresses, conditions, and error fields.

  • Selective updates based on status/spec diffs to reduce unnecessary changes and improve stability.

  • Clearer status reporting during sync, including “no changes detected” outcomes.

  • Bug Fixes

  • Corrected condition handling and cross-version condition compatibility (v1beta1/v1beta2).

  • Improved phase and error mapping for consistent status representation.

  • Refactor

  • Staged, helper-driven create/update flow for Machines and MachineSets with enhanced logging.

  • Tests

  • Expanded conversion and fuzz testing for robust status and address 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.

Copy link
Copy Markdown

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pkg/controllers/machinesync/machine_sync_controller.go (1)

1349-1354: Fix copy-paste error in provider spec parsing.

Line 1354 incorrectly parses a.Spec.ProviderSpec.Value twice instead of parsing b.Spec.ProviderSpec.Value for the second machine.

Apply this fix to parse the correct provider spec:

-	ps2, err := mapi2capi.AWSProviderSpecFromRawExtension(a.Spec.ProviderSpec.Value)
+	ps2, err := mapi2capi.AWSProviderSpecFromRawExtension(b.Spec.ProviderSpec.Value)
	if err != nil {
		return nil, fmt.Errorf("unable to parse second Machine API machine set providerSpec: %w", err)
	}
🧹 Nitpick comments (9)
pkg/conversion/mapi2capi/machine.go (1)

220-236: Tune Ready condition severity: Info when not failed; Error only on failure.

Marking Ready with SeverityError for all non-running phases is too aggressive. Suggest Info except when Phase == Failed.

Apply this diff:

-		Severity: func() clusterv1.ConditionSeverity {
-			if mapiMachine.Status.Phase != nil && *mapiMachine.Status.Phase == mapiv1beta1.PhaseRunning {
-				return clusterv1.ConditionSeverityNone
-			}
-
-			return clusterv1.ConditionSeverityError
-		}(),
+		Severity: func() clusterv1.ConditionSeverity {
+			switch {
+			case mapiMachine.Status.Phase != nil && *mapiMachine.Status.Phase == mapiv1beta1.PhaseRunning:
+				return clusterv1.ConditionSeverityNone
+			case mapiMachine.Status.Phase != nil && *mapiMachine.Status.Phase == mapiv1beta1.PhaseFailed:
+				return clusterv1.ConditionSeverityError
+			default:
+				return clusterv1.ConditionSeverityInfo
+			}
+		}(),
pkg/conversion/capi2mapi/machine.go (1)

178-196: Prefer using MAPI phase constant for “Deleting” mapping.

Avoid hard-coded string to reduce typos.

Apply this diff:

-	case "Deleted":
-		return ptr.To("Deleting") // Deleted is not supported in MAPI but we can stay in Deleting until the machine is fully removed.
+	case "Deleted":
+		return ptr.To(string(mapiv1.PhaseDeleting)) // Deleted is not supported in MAPI; approximate with Deleting.
pkg/conversion/capi2mapi/machine_test.go (1)

118-132: Add coverage for HostName/Hostname mapping and DNS-type filtering.

Strengthen the status conversion test to:

  • Include a HostName address and assert NodeHostName in MAPI.
  • Include an ExternalDNS and assert it is filtered out.

Apply this diff:

-			capiMachine := capibuilder.Machine().
+			capiMachine := capibuilder.Machine().
 				WithName("test-machine").
 				WithNamespace("test-namespace").
 				WithNodeRef(nodeRef).
 				WithLastUpdated(lastUpdated).
 				WithAddresses(clusterv1.MachineAddresses{
-					{Type: clusterv1.MachineAddressType(corev1.NodeInternalIP), Address: "10.0.0.1"},
-					{Type: clusterv1.MachineAddressType(corev1.NodeExternalIP), Address: "203.0.113.1"},
+					{Type: clusterv1.MachineHostName, Address: "ip-10-0-0-1"},
+					{Type: clusterv1.MachineInternalIP, Address: "10.0.0.1"},
+					{Type: clusterv1.MachineExternalIP, Address: "203.0.113.1"},
+					{Type: clusterv1.MachineExternalDNS, Address: "node.example.com"},
 				}).
 				WithPhase("Running").
 				WithFailureReason(ptr.To(capierrors.MachineStatusError("InvalidConfiguration"))).
 				WithFailureMessage(ptr.To(string("Test failure message"))).
 				WithConditions([]clusterv1.Condition{condition}).
 				Build()
@@
-			Expect(mapiStatus.Addresses).To(SatisfyAll(
-				HaveLen(2),
-				ContainElement(SatisfyAll(HaveField("Type", corev1.NodeInternalIP), HaveField("Address", "10.0.0.1"))),
-				ContainElement(SatisfyAll(HaveField("Type", corev1.NodeExternalIP), HaveField("Address", "203.0.113.1"))),
-			))
+			Expect(mapiStatus.Addresses).To(SatisfyAll(
+				HaveLen(3),
+				ContainElement(SatisfyAll(HaveField("Type", corev1.NodeHostName), HaveField("Address", "ip-10-0-0-1"))),
+				ContainElement(SatisfyAll(HaveField("Type", corev1.NodeInternalIP), HaveField("Address", "10.0.0.1"))),
+				ContainElement(SatisfyAll(HaveField("Type", corev1.NodeExternalIP), HaveField("Address", "203.0.113.1"))),
+			))
+			Expect(mapiStatus.Addresses).NotTo(ContainElement(HaveField("Type", corev1.NodeExternalDNS)))

Also applies to: 136-150

pkg/conversion/test/fuzz/fuzz.go (2)

298-303: TODO comment needs tracking.

The TODO comment indicates that ProviderStatus conversion is not yet implemented. This should be tracked formally.

Would you like me to create a GitHub issue to track the implementation of CAPI InfraMachine to MAPI Machine ProviderStatus conversion?


767-802: Consider extracting address generation logic to reduce duplication.

The address fuzzing functions have similar IP generation logic that could be extracted to helper functions for better maintainability.

Consider extracting IP address generation into helper functions:

+func generatePrivateIP(c randfill.Continue) string {
+    switch c.Int31n(3) {
+    case 0:
+        // 10.0.0.0/8
+        return fmt.Sprintf("10.%d.%d.%d",
+            c.Int31n(256), c.Int31n(256), c.Int31n(254)+1)
+    case 1:
+        // 172.16.0.0/12
+        return fmt.Sprintf("172.%d.%d.%d",
+            c.Int31n(16)+16, c.Int31n(256), c.Int31n(254)+1)
+    case 2:
+        // 192.168.0.0/16
+        return fmt.Sprintf("192.168.%d.%d",
+            c.Int31n(256), c.Int31n(254)+1)
+    }
+    return ""
+}

+func generatePublicIP(c randfill.Continue) string {
+    return fmt.Sprintf("%d.%d.%d.%d",
+        c.Int31n(223)+1, // 1-223 (avoid 0.x.x.x and 224+ multicast)
+        c.Int31n(256),   // 0-255
+        c.Int31n(256),   // 0-255
+        c.Int31n(254)+1) // 1-254 (avoid .0 and .255)
+}

 func fuzzMAPIMachineStatusAddress(address *corev1.NodeAddress, c randfill.Continue) {
     // ... existing switch logic ...
     case 1:
         address.Type = corev1.NodeExternalIP
-        address.Address = fmt.Sprintf("%d.%d.%d.%d",
-            c.Int31n(223)+1,
-            c.Int31n(256),
-            c.Int31n(256),
-            c.Int31n(254)+1)
+        address.Address = generatePublicIP(c)
     case 2:
         address.Type = corev1.NodeInternalIP
-        // ... existing IP generation logic ...
+        address.Address = generatePrivateIP(c)
pkg/util/sync.go (1)

266-279: Consider extracting common condition comparison logic.

The v1beta1 condition comparison logic is duplicated across CAPI and MAPI versions with only type differences.

Consider using generics to reduce duplication:

// compareConditions compares conditions of type T
func compareConditions[T any](a, b []T, getFields func(T) (string, string, string, string, string)) []string {
    diff := []string{}
    // Common comparison logic here
    return diff
}
pkg/controllers/machinesync/machine_sync_controller.go (2)

606-607: Remove unnecessary unparam lint directive.

The unparam directive appears to be no longer needed since the function now returns three values including the boolean syncronizationIsProgressing.

-//nolint:funlen,unparam
+//nolint:funlen
 func (r *MachineSyncReconciler) createOrUpdateCAPIInfraMachine(ctx context.Context, mapiMachine *machinev1beta1.Machine, infraMachine client.Object, newCAPIInfraMachine client.Object) (ctrl.Result, bool, error) {

809-810: Remove outdated unparam lint directive.

Similar to the previous comment, this unparam directive appears unnecessary.

-//nolint:unparam
 func (r *MachineSyncReconciler) createOrUpdateMAPIMachine(ctx context.Context, existingMAPIMachine *machinev1beta1.Machine, convertedMAPIMachine *machinev1beta1.Machine) (ctrl.Result, error) {
pkg/conversion/mapi2capi/machine_test.go (1)

261-271: Add tests for Provisioned, Failed, and Deleting phases

Conversion already maps phases — add tests asserting these expectations:

  • Provisioned: InfrastructureReady = true; Ready = false; BootstrapReady = false.
  • Deleting (phase): BootstrapReady = true; InfrastructureReady = true; Ready = false. v1beta2 "Deleting" condition is driven by DeletionTimestamp (test both phase-only and with DeletionTimestamp); NodeReady is true only if NodeRef is present.
  • Failed: Ready, BootstrapReady, InfrastructureReady should all be false.

Suggested location: pkg/conversion/mapi2capi/machine_test.go (near existing Running/Provisioning tests).

📜 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 a18e6a8 and ef363b0.

📒 Files selected for processing (9)
  • pkg/controllers/machinesetsync/machineset_sync_controller.go (1 hunks)
  • pkg/controllers/machinesync/machine_sync_controller.go (7 hunks)
  • pkg/conversion/capi2mapi/machine.go (5 hunks)
  • pkg/conversion/capi2mapi/machine_test.go (3 hunks)
  • pkg/conversion/mapi2capi/machine.go (3 hunks)
  • pkg/conversion/mapi2capi/machine_test.go (2 hunks)
  • pkg/conversion/test/fuzz/fuzz.go (7 hunks)
  • pkg/util/conditions.go (2 hunks)
  • pkg/util/sync.go (5 hunks)
🔇 Additional comments (15)
pkg/conversion/mapi2capi/machine.go (2)

65-66: Status construction LGTM; verify LastTransitionTime is managed upstream.

The conversion sets Condition structs directly; ensure the writer uses conditions.Set(...) when patching to populate LastTransitionTime consistently.

Also applies to: 85-105


198-202: Explicit skips for NodeInfo and clean v1beta2 population LGTM.

No further action.

Also applies to: 205-209

pkg/util/conditions.go (2)

116-125: Helper rename and behavior: LGTM.

Signature and behavior unchanged; safe migration for callers.


127-160: Condition upsert semantics look correct.

  • Updates LTT only on state change or preserves existing when unchanged.
  • Uses UTC and second precision.
pkg/conversion/capi2mapi/machine.go (1)

40-63: Status conversion integration: LGTM.

Errors are plumbed and status is assigned early; downstream errs are aggregated.

Also applies to: 73-76

pkg/controllers/machinesetsync/machineset_sync_controller.go (1)

1074-1076: Renamed helper usage LGTM.

Switch to util.SetMAPICondition is correct and matches the helper rename.

pkg/conversion/mapi2capi/machine_test.go (2)

146-514: Comprehensive test coverage for MAPI to CAPI Machine status conversion.

The test suite provides excellent coverage of status conversion scenarios including phase transitions, conditions, addresses, and error states. The test structure follows best practices with clear test names and proper assertions.


441-459: Good test coverage for NodeRef conditional logic.

The tests properly verify that NodeReady condition depends on both the phase being "Running" and NodeRef being set, which matches the expected behavior.

pkg/conversion/test/fuzz/fuzz.go (1)

127-136: Status field exclusions are correctly handled for round-trip testing.

The exclusion of non-mappable fields (CertificatesExpiryDate, Deletion, NodeInfo) from CAPI to MAPI conversion is appropriate since these fields don't exist in MAPI.

pkg/util/sync.go (2)

84-137: Good implementation of status comparison with v1beta2 support.

The function properly handles nil checks for V1Beta2 status before comparison and includes all relevant status fields.


237-282: Efficient condition comparison implementation.

The condition comparison functions correctly ignore LastTransitionTime differences and only compare meaningful fields. The early break optimization is good.

pkg/controllers/machinesync/machine_sync_controller.go (4)

712-736: Clean separation of concerns in ensureCAPIMachine.

The function follows single responsibility principle by only handling creation logic.


1472-1520: Good implementation of conditional status updates.

The function correctly checks for synchronized generation before updating status, preventing race conditions. The use of patch operations with proper error handling is appropriate.


1619-1647: Comprehensive status field updates.

The function correctly updates all relevant status fields including v1beta2 conditions with proper nil checks.


1484-1488: SynchronizedGeneration is updated by applySynchronizedConditionWithPatch—each “true” condition call passes &…Generation (both CAPI→MAPI and MAPI→CAPI flows)—so the generation check in ensureCAPIMachineStatusUpdated is correctly gated.

Comment thread pkg/conversion/capi2mapi/machine.go
Comment thread pkg/conversion/mapi2capi/machine.go Outdated
Comment thread pkg/conversion/test/fuzz/fuzz.go
Copy link
Copy Markdown
Contributor

@theobarberbany theobarberbany left a comment

Choose a reason for hiding this comment

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

Initial review of just the controller changes (so everything under pkg/controllers). I think the approach is good, so mainly comment / style nits and one part around using SSA

Comment thread pkg/controllers/machinesync/machine_sync_controller.go Outdated
Comment thread pkg/controllers/machinesync/machine_sync_controller.go
Comment thread pkg/controllers/machinesync/machine_sync_controller.go Outdated
Comment thread pkg/controllers/machinesync/machine_sync_controller.go Outdated
Comment thread pkg/controllers/machinesync/machine_sync_controller.go Outdated
Comment thread pkg/controllers/machinesync/machine_sync_controller.go Outdated
Comment thread pkg/controllers/machinesync/machine_sync_controller.go Outdated
Comment thread pkg/controllers/machinesync/machine_sync_controller.go
Comment thread pkg/controllers/machinesync/machine_sync_controller.go Outdated
Comment thread pkg/controllers/machinesync/machine_sync_controller.go Outdated
@damdo damdo marked this pull request as draft September 25, 2025 12:21
@damdo
Copy link
Copy Markdown
Member Author

damdo commented Sep 25, 2025

Moving to draft to address the review

@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 Sep 25, 2025
Comment thread pkg/controllers/machinesync/machine_sync_controller.go Outdated
Comment thread pkg/controllers/machinesync/machine_sync_controller.go Outdated
Comment thread pkg/conversion/capi2mapi/machine.go Outdated
Comment thread pkg/conversion/mapi2capi/machine.go Outdated
Comment thread pkg/conversion/mapi2capi/machine.go Outdated
Comment thread pkg/conversion/mapi2capi/machine.go Outdated
Comment thread pkg/conversion/mapi2capi/machine.go Outdated
Comment thread pkg/util/sync.go
Comment thread pkg/conversion/capi2mapi/machine.go
Comment thread pkg/conversion/capi2mapi/machine_test.go Outdated
Comment thread pkg/util/conditions.go Outdated
Comment thread pkg/conversion/capi2mapi/machine.go Outdated
Comment thread pkg/conversion/capi2mapi/machine.go
@damdo
Copy link
Copy Markdown
Member Author

damdo commented Sep 25, 2025

Addressed all review comments. LMK if you are happy with that. TY

@damdo damdo marked this pull request as ready for review September 26, 2025 09:05
Copy link
Copy Markdown

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

♻️ Duplicate comments (4)
pkg/conversion/mapi2capi/machine.go (4)

358-397: Address mapping now robust and safe

Explicit mapping (including HostName) and skipping unknown types resolves the earlier issue of malformed entries.


399-407: Simple, correct phase mapping

Using ptr.Deref is concise and matches prior suggestion.


409-416: Correct error reason mapping

ptr.To(capierrors.MachineStatusError(*mapiErrorReason)) is the right conversion.


418-421: Trivial pass-through is fine

Returning the pointer directly keeps this helper minimal as suggested.

🧹 Nitpick comments (3)
pkg/conversion/mapi2capi/machine.go (2)

168-186: Precompute derived flags to reduce repeated calls

You call deriveCAPIBootstrapReadyFromMAPI/deriveCAPIInfrastructureReadyFromMAPI multiple times inside closures. Precompute once (e.g., br := …, ir := …) and reuse for Status/Severity/Reason. Improves readability and avoids redundant work.

Also applies to: 187-211, 268-286, 289-306


329-334: Fix typos in comments

“We don't ned” → “We don't need”; “tt require” → “it requires”.

pkg/conversion/mapi2capi/machine_test.go (1)

535-565: Add small tests for HostName mapping and nil addresses

Consider:

  • HostName mapping: corev1.NodeHostName (“Hostname”) should convert to clusterv1.MachineHostName (“HostName”).
  • Nil addresses: ensure nil-in → nil-out without errors.

Example snippets you can add:

It("converts Hostname to HostName", func() {
  m := machinebuilder.Machine().
    WithAddresses([]corev1.NodeAddress{{Type: corev1.NodeHostName, Address: "node-1"}}).
    Build()
  s, errs := convertMAPIMachineToCAPIMachineStatus(m)
  Expect(errs).To(BeEmpty())
  Expect(s.Addresses).To(ContainElement(SatisfyAll(
    HaveField("Type", BeEquivalentTo(clusterv1.MachineHostName)),
    HaveField("Address", Equal("node-1")),
  )))
})

It("returns nil addresses when input is nil", func() {
  m := machinebuilder.Machine().Build()
  m.Status.Addresses = nil
  s, errs := convertMAPIMachineToCAPIMachineStatus(m)
  Expect(errs).To(BeEmpty())
  Expect(s.Addresses).To(BeNil())
})
📜 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 cf50170 and 16aeac1.

📒 Files selected for processing (2)
  • pkg/conversion/mapi2capi/machine.go (4 hunks)
  • pkg/conversion/mapi2capi/machine_test.go (2 hunks)
🔇 Additional comments (2)
pkg/conversion/mapi2capi/machine.go (1)

39-43: Status conversion wired correctly

Status is computed once, errors are aggregated, and assigned to the CAPI Machine. Looks good.

Also applies to: 71-71

pkg/conversion/mapi2capi/machine_test.go (1)

147-259: Comprehensive status/conditions coverage

Solid end-to-end assertions for fields and both v1beta1/v1beta2 conditions. Nice.

@chrischdi
Copy link
Copy Markdown
Contributor

/lgtm

@openshift-ci openshift-ci Bot added the lgtm Indicates that a PR is ready to be merged. label Oct 8, 2025
@openshift-ci-robot
Copy link
Copy Markdown

Scheduling tests matching the pipeline_run_if_changed or not excluded by pipeline_skip_if_only_changed parameters:
/test e2e-aws-capi-techpreview
/test e2e-aws-ovn
/test e2e-aws-ovn-serial-1of2
/test e2e-aws-ovn-serial-2of2
/test e2e-aws-ovn-techpreview
/test e2e-aws-ovn-techpreview-upgrade
/test e2e-azure-capi-techpreview
/test e2e-azure-ovn-techpreview
/test e2e-azure-ovn-techpreview-upgrade
/test e2e-gcp-capi-techpreview
/test e2e-gcp-ovn-techpreview
/test e2e-metal3-capi-techpreview
/test e2e-openstack-capi-techpreview
/test e2e-openstack-ovn-techpreview
/test e2e-vsphere-capi-techpreview
/test regression-clusterinfra-aws-ipi-techpreview-capi

@damdo damdo force-pushed the machine-status-conversion-and-syncing branch from 16aeac1 to 737e205 Compare October 9, 2025 15:42
@openshift-ci openshift-ci Bot removed the lgtm Indicates that a PR is ready to be merged. label Oct 9, 2025
@openshift-ci-robot
Copy link
Copy Markdown

openshift-ci-robot commented Oct 9, 2025

@damdo: This pull request references OCPCLOUD-2995 which is a valid jira issue.

Details

In response to this:

This work is the Machine version of #329
It adds Machine status conversion and syncing between MAPI and CAPI.

Summary by CodeRabbit

  • New Features

  • Bidirectional status conversion between Machine/MachineSet representations, including phases, addresses, and failure details.

  • Bug Fixes

  • Condition handling improved: ensure LastTransitionTime is set and avoid duplicating controller-managed MachineSet conditions.

  • Refactor

  • Machine sync reconciler reorganized into staged ensure/patch flows with status-aware diffing and updated reconciliation inputs; multi-version condition diffing added.

  • Tests

  • Expanded unit and fuzz suites for status/address conversion and round-trip scenarios.

  • Chores

  • Renamed MAPI condition utilities for clarity.

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.

Copy link
Copy Markdown

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
pkg/util/sync.go (2)

237-257: Condition adds in desired set are ignored; may skip required status updates

compareCAPIV1Beta1Conditions only checks types present in 'a'. If 'b' introduces a new condition, diff stays empty and status update may be skipped.

Apply symmetric comparison to catch additions:

 func compareCAPIV1Beta1Conditions(a, b []clusterv1.Condition) []string {
   diff := []string{}
   // Compare the conditions one by one.
   // Ignore the differences in LastTransitionTime.
   for _, condition := range a {
     for _, conditionB := range b {
       if condition.Type == conditionB.Type {
         if condition.Status != conditionB.Status ||
           condition.Severity != conditionB.Severity ||
           condition.Reason != conditionB.Reason ||
           condition.Message != conditionB.Message {
           diff = append(diff, deep.Equal(condition, conditionB)...)
         }
         break // Break out of the inner loop once we have found a match.
       }
     }
   }
+  // Also detect additions in b not present in a.
+  for _, conditionB := range b {
+    found := false
+    for _, condition := range a {
+      if condition.Type == conditionB.Type {
+        found = true
+        break
+      }
+    }
+    if !found {
+      diff = append(diff, "missing condition type in source: "+string(conditionB.Type))
+    }
+  }
   return diff
 }

263-282: Same issue for MAPI v1beta1 condition comparison

Add symmetric check to catch conditions present only in 'b'.

 func compareMAPIV1Beta1Conditions(a, b []mapiv1beta1.Condition) []string {
   diff := []string{}
   // Compare the conditions one by one.
   // Ignore the differences in LastTransitionTime.
   for _, condition := range a {
     for _, conditionB := range b {
       if condition.Type == conditionB.Type {
         if condition.Status != conditionB.Status ||
           condition.Severity != conditionB.Severity ||
           condition.Reason != conditionB.Reason ||
           condition.Message != conditionB.Message {
           diff = append(diff, deep.Equal(condition, conditionB)...)
         }
         break // Break out of the inner loop once we have found a match.
       }
     }
   }
+  // Also detect additions in b not present in a.
+  for _, conditionB := range b {
+    found := false
+    for _, condition := range a {
+      if condition.Type == conditionB.Type {
+        found = true
+        break
+      }
+    }
+    if !found {
+      diff = append(diff, "missing condition type in source: "+string(conditionB.Type))
+    }
+  }
   return diff
 }
♻️ Duplicate comments (2)
pkg/conversion/mapi2capi/machine.go (2)

399-407: YAGNI: inline phase conversion

This wrapper only calls ptr.Deref; consider inlining at call sites to reduce surface.

-func convertMAPIMachinePhaseToCAPI(mapiPhase *string) string {
-  // ...
-  return ptr.Deref(mapiPhase, "")
-}
+// Inline ptr.Deref(mapiPhase, "") at call sites and drop this helper.

418-421: Trivial passthrough helper can be removed

Function returns its input unmodified; suggest inlining to simplify.

-func convertMAPIMachineErrorMessageToCAPIFailureMessage(mapiErrorMessage *string) *string {
-  return mapiErrorMessage
-}
+// Inline the pointer directly at call sites and remove this helper.
📜 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 16aeac1 and 737e205.

📒 Files selected for processing (11)
  • pkg/controllers/machinesetsync/machineset_sync_controller.go (1 hunks)
  • pkg/controllers/machinesync/machine_sync_controller.go (13 hunks)
  • pkg/controllers/machinesync/machine_sync_controller_test.go (5 hunks)
  • pkg/conversion/capi2mapi/machine.go (4 hunks)
  • pkg/conversion/capi2mapi/machine_test.go (2 hunks)
  • pkg/conversion/capi2mapi/machineset.go (1 hunks)
  • pkg/conversion/mapi2capi/machine.go (4 hunks)
  • pkg/conversion/mapi2capi/machine_test.go (2 hunks)
  • pkg/conversion/test/fuzz/fuzz.go (7 hunks)
  • pkg/util/conditions.go (3 hunks)
  • pkg/util/sync.go (5 hunks)
🚧 Files skipped from review as they are similar to previous changes (5)
  • pkg/conversion/capi2mapi/machineset.go
  • pkg/conversion/test/fuzz/fuzz.go
  • pkg/controllers/machinesetsync/machineset_sync_controller.go
  • pkg/conversion/capi2mapi/machine.go
  • pkg/conversion/capi2mapi/machine_test.go
🔇 Additional comments (4)
pkg/conversion/mapi2capi/machine.go (1)

372-388: Address conversion: good filtering and diagnostics

Unknown types are skipped and surfaced via field.Invalid; no malformed entries emitted. LGTM.

pkg/conversion/mapi2capi/machine_test.go (1)

535-564: Good coverage for address filtering and error reporting

Test correctly asserts we emit a single field.Invalid and drop the unrecognized address.

pkg/util/conditions.go (1)

158-165: LastTransitionTime handling fixed

New conditions now get LTT set (UTC, truncated). Matches intent and prevents churn.

pkg/controllers/machinesync/machine_sync_controller.go (1)

273-282: Nil dereference risk in log path

If sourceCAPIMachine were nil, existingMAPIMachine may also be nil; dereferencing Name would panic. Log safely without dereferencing.

- if sourceCAPIMachine == nil {
-   logger.Error(errCAPIMachineNotFound, "machine", existingMAPIMachine.Name)
+ if sourceCAPIMachine == nil {
+   logger.Error(errCAPIMachineNotFound, "Cluster API machine is nil")

Likely an incorrect or invalid review comment.

Comment thread pkg/controllers/machinesync/machine_sync_controller.go
Comment thread pkg/util/sync.go
@damdo
Copy link
Copy Markdown
Member Author

damdo commented Oct 9, 2025

/assign @JoelSpeed @chrischdi

For approve/lgtm

@chrischdi
Copy link
Copy Markdown
Contributor

/lgtm

@openshift-ci openshift-ci Bot added the lgtm Indicates that a PR is ready to be merged. label Oct 10, 2025
@openshift-ci-robot
Copy link
Copy Markdown

Scheduling tests matching the pipeline_run_if_changed or not excluded by pipeline_skip_if_only_changed parameters:
/test e2e-aws-capi-techpreview
/test e2e-aws-ovn
/test e2e-aws-ovn-serial-1of2
/test e2e-aws-ovn-serial-2of2
/test e2e-aws-ovn-techpreview
/test e2e-aws-ovn-techpreview-upgrade
/test e2e-azure-capi-techpreview
/test e2e-azure-ovn-techpreview
/test e2e-azure-ovn-techpreview-upgrade
/test e2e-gcp-capi-techpreview
/test e2e-gcp-ovn-techpreview
/test e2e-metal3-capi-techpreview
/test e2e-openstack-capi-techpreview
/test e2e-openstack-ovn-techpreview
/test e2e-vsphere-capi-techpreview
/test regression-clusterinfra-aws-ipi-techpreview-capi

@JoelSpeed
Copy link
Copy Markdown
Contributor

/approve

@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented Oct 10, 2025

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: JoelSpeed

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:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Oct 10, 2025
@damdo
Copy link
Copy Markdown
Member Author

damdo commented Oct 10, 2025

ci/prow/e2e-openstack-capi-techpreview passed the testing phase but failed on gathering/post phase.

Hence overriding
/override ci/prow/e2e-openstack-capi-techpreview

@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented Oct 10, 2025

@damdo: Overrode contexts on behalf of damdo: ci/prow/e2e-openstack-capi-techpreview

Details

In response to this:

ci/prow/e2e-openstack-capi-techpreview passed the testing phase but failed on gathering/post phase.

Hence overriding
/override ci/prow/e2e-openstack-capi-techpreview

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.

@damdo
Copy link
Copy Markdown
Member Author

damdo commented Oct 10, 2025

ci/prow/e2e-openstack-ovn-techpreview passed but timed out during the gathering/post phase

/override ci/prow/e2e-openstack-ovn-techpreview

@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented Oct 10, 2025

@damdo: Overrode contexts on behalf of damdo: ci/prow/e2e-openstack-ovn-techpreview

Details

In response to this:

ci/prow/e2e-openstack-ovn-techpreview passed but timed out during the gathering/post phase

/override ci/prow/e2e-openstack-ovn-techpreview

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.

@damdo
Copy link
Copy Markdown
Member Author

damdo commented Oct 10, 2025

ci/prow/e2e-gcp-ovn-techpreview timedout, but I have manually verified the CCAPIO controllers are ok
(see here)

Also the CAPI GCP e2e test passed here.

Hence overriding it

/override ci/prow/e2e-gcp-ovn-techpreview

@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented Oct 10, 2025

@damdo: Overrode contexts on behalf of damdo: ci/prow/e2e-gcp-ovn-techpreview

Details

In response to this:

ci/prow/e2e-gcp-ovn-techpreview timedout, but I have manually verified the CCAPIO controllers are ok
(see here)

Also the CAPI GCP e2e test passed here.

Hence overriding it

/override ci/prow/e2e-gcp-ovn-techpreview

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.

@openshift-ci
Copy link
Copy Markdown
Contributor

openshift-ci Bot commented Oct 10, 2025

@damdo: 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-azure-ovn-techpreview 737e205 link false /test e2e-azure-ovn-techpreview

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.

@damdo
Copy link
Copy Markdown
Member Author

damdo commented Oct 10, 2025

/verified later @sunzhaohua2

To verify the machine status is synced over correctly we also need the infra machine's status to be correctly converted. So it is better to verify everything at the end once both are present.

@openshift-ci-robot openshift-ci-robot added verified-later verified Signifies that the PR passed pre-merge verification criteria labels Oct 10, 2025
@openshift-ci-robot
Copy link
Copy Markdown

@damdo: This PR has been marked to be verified later by @sunzhaohua2.

Details

In response to this:

/verified later @sunzhaohua2

To verify the machine status is synced over correctly we also need the infra machine's status to be correctly converted. So it is better to verify everything at the end once both are present.

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-merge-bot openshift-merge-bot Bot merged commit eea205c into openshift:main Oct 10, 2025
25 of 26 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. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. lgtm Indicates that a PR is ready to be merged. verified Signifies that the PR passed pre-merge verification criteria verified-later

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants