-
Notifications
You must be signed in to change notification settings - Fork 52
OCPBUGS-63411: machinesync: Create Cluster API InfraMachine if not exists while Cluster API Machine exists #402
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
|
@chrischdi: This pull request references Jira Issue OCPBUGS-63411, which is invalid:
Comment The bug has been updated to refer to the pull request using the external bug tracker. DetailsIn 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. |
📝 WalkthroughWalkthroughAdds private helpers to fetch and check existence of Cluster API infra Machines and updates MachineSyncReconciler.Reconcile to route synchronization either MAPI→CAPI when a CAPI infra Machine is absent (and timing permits) or retain the existing CAPI→MAPI flow. Tests updated and new unit tests added for infra-resource fetch logic. Changes
Sequence Diagram(s)sequenceDiagram
participant Reconciler as MachineSyncReconciler
participant MAPI as MAPI Machine
participant CAPI as CAPI Machine
participant Infra as CAPI InfraMachine
participant Cluster as CAPI Cluster
Reconciler->>MAPI: fetch mapped MAPI Machine
Reconciler->>CAPI: fetch corresponding CAPI Machine
Reconciler->>Cluster: fetch CAPI infra Cluster (via fetchCAPIInfraResources)
alt InfraMachine exists
Reconciler->>Infra: fetch infra Machine
Reconciler->>CAPI: reconcile CAPI→MAPI sync flow
CAPI-->>Reconciler: status/result
Reconciler-->>MAPI: update synchronization condition
else InfraMachine missing
Reconciler->>Reconciler: doesCAPIInfraMachineExist -> false
Reconciler->>CAPI: initiate MAPI→CAPI reconciliation (create InfraMachine)
CAPI-->>Infra: create InfraMachine
Infra-->>Reconciler: created
Reconciler-->>MAPI: update synchronization condition (ResourceSynchronized)
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Areas requiring extra attention:
Poem
🚥 Pre-merge checks | ✅ 3✅ Passed checks (3 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
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 |
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: 0
🧹 Nitpick comments (1)
pkg/controllers/machinesync/machine_sync_controller.go (1)
246-246: Fix typo in comment."existense" should be "existence".
Apply this diff:
- // Check for existense of the Cluster API Infrastructure Machine or if it needs to get created from MAPI first. + // Check for existence of the Cluster API Infrastructure Machine or if it needs to get created from MAPI first.
📜 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 (2)
pkg/controllers/machinesync/machine_sync_controller.go(4 hunks)pkg/controllers/machinesync/machine_sync_controller_test.go(1 hunks)
🔇 Additional comments (5)
pkg/controllers/machinesync/machine_sync_controller_test.go (1)
782-795: LGTM! Test correctly validates the new InfraMachine creation behavior.The test expectations have been properly updated to reflect the new functionality where the Cluster API InfraMachine is now created successfully when it doesn't exist, rather than failing. The test now:
- Expects successful synchronization (Status=True, Reason=ResourceSynchronized)
- Verifies the InfraMachine is actually created
This aligns well with the implementation changes.
pkg/controllers/machinesync/machine_sync_controller.go (4)
258-262: Good timestamp-based precedence logic.The condition correctly creates the InfraMachine from MAPI only when:
- Cluster API is authoritative
- CAPI Machine exists but InfraMachine doesn't
- MAPI machine was created first (or simultaneously)
The timestamp comparison (
mapiMachine.CreationTimestamp.Equal(&capiMachine.CreationTimestamp) || mapiMachine.CreationTimestamp.Before(&capiMachine.CreationTimestamp)) ensures MAPI-originated configuration takes precedence only when appropriate, preventing overwriting of potentially newer CAPI-originated state.
950-974: Clean refactoring that improves modularity.The refactored
fetchCAPIInfraResourcesnow properly separates InfraCluster and InfraMachine retrieval, delegating the latter to the dedicatedfetchCAPIInfraMachinehelper. This improves code reusability and maintains clear separation of concerns.
976-994: Well-implemented helper function.The
fetchCAPIInfraMachinehelper is cleanly designed with:
- Focused responsibility (fetch infrastructure machine by name/namespace)
- Proper NotFound handling (returns nil rather than error)
- Appropriate error wrapping for clarity
- Platform-agnostic initialization
996-1012: Solid existence check implementation with proper nil handling.The
doesCAPIInfraMachineExisthelper correctly:
- Handles nil
capiMachineby falling back tomapiMachine.Name- Uses
capiMachine.Spec.InfrastructureRefwhen available for accurate lookup- Returns a clear boolean result rather than requiring nil checks
- Wraps errors appropriately for context
|
/jira refresh |
|
@chrischdi: This pull request references Jira Issue OCPBUGS-63411, which is valid. 3 validation(s) were run on this bug
Requesting review from QA contact: DetailsIn 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. |
|
/lgtm |
|
Scheduling tests matching the |
|
[APPROVALNOTIFIER] This PR is APPROVED This pull-request has been approved by: nrb The full list of commands accepted by this bot can be found here. The pull request process is described here DetailsNeeds approval from an approver in each of these files:
Approvers can indicate their approval by writing |
|
Hi @chrischdi I tried to test this, follow below steps:
result: FailedToConvertCAPIMachineToMAPI, awsmachine was not created. |
|
/hold For checking issue |
|
I think this is the expected behavior for the code: I did it this way assuming the scenarios are:
Not sure if it is right to "just create" the InfraMachine from the MAPI Machine in case the CAPI Machine was created first. WDYT @damdo? |
|
/retest |
|
Looks like Have we impacted the deletion logic with this change? |
Fun... yeah that could actually be true. Have to check on this. |
Happy to pair some time this week if you fancy :) |
ebbcf2d to
debacfc
Compare
|
New changes are detected. LGTM label has been removed. |
|
/retest |
|
/pipeline required |
|
Scheduling tests matching the |
|
/retest |
b635f0b to
b6333ab
Compare
|
Rebased to main /pipeline required |
|
Scheduling tests matching the |
|
@chrischdi: This pull request references Jira Issue OCPBUGS-63411, which is valid. 3 validation(s) were run on this bug
Requesting review from QA contact: DetailsIn 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. |
|
/pipeline required |
|
Scheduling tests matching the |
7df1c6a to
df25ead
Compare
|
@chrischdi: This pull request references Jira Issue OCPBUGS-63411, which is invalid:
Comment DetailsIn 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. |
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: 11
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
e2e/machineset_migration_mapi_authoritative_test.go (1)
296-306: Fix assertion on line 305 to check the correct v1beta2 field.The code updates
Spec.Deletion.Orderon the v1beta2 CAPI MachineSet (correct), but then asserts onSpec.DeletePolicywhich was replaced by theDeletionstruct in v1beta2. Line 305 should checkSpec.Deletion.Orderinstead ofSpec.DeletePolicyforcapiMachineSet.pkg/controllers/corecluster/corecluster_controller_test.go (1)
170-177: Incorrect condition constant name.The condition constant should be
ClusterControlPlaneInitializedV1Beta2Condition, notControlPlaneInitializedV1Beta1Condition. The status path change toStatus.Deprecated.V1Beta1.Conditionscorrectly reflects the v1beta2 backward compatibility structure where v1beta1 conditions are maintained under theDeprecatedpath.pkg/util/sync.go (1)
119-126: Duplicate diff checks for ReadyReplicas and AvailableReplicas.Lines 119-125 already check
ReadyReplicasandAvailableReplicas, then lines 164-170 check them again. This results in redundant work and potentially overwriting the diff keys with identical values.Remove the duplicate checks at lines 164-170:
if diffUpToDateReplicas := deep.Equal(a.UpToDateReplicas, b.UpToDateReplicas); len(diffUpToDateReplicas) > 0 { diff[".upToDateReplicas"] = diffUpToDateReplicas } - if diffAvailableReplicas := deep.Equal(a.AvailableReplicas, b.AvailableReplicas); len(diffAvailableReplicas) > 0 { - diff[".availableReplicas"] = diffAvailableReplicas - } - - if diffReadyReplicas := deep.Equal(a.ReadyReplicas, b.ReadyReplicas); len(diffReadyReplicas) > 0 { - diff[".readyReplicas"] = diffReadyReplicas - } - if diffConditions := compareCAPIV1Beta2Conditions(a.Conditions, b.Conditions); len(diffConditions) > 0 { diff[".conditions"] = diffConditions }Also applies to: 160-174
♻️ Duplicate comments (1)
pkg/controllers/machinesync/machine_sync_controller.go (1)
256-273: Timestamp gate still blocks InfraMachine creation for certain scenarios.The condition at line 271
!mapiMachine.CreationTimestamp.After(capiMachine.CreationTimestamp.Time)prevents InfraMachine creation when the MAPI Machine is created after the CAPI Machine. This matches the QA-reported failure where creating a CAPI Machine first, then a MAPI Machine withauthoritativeAPI: ClusterAPI, did not result in InfraMachine creation.Per the author's comment, the intended flow is:
- MAPI Machine (with CAPI authoritative) → creates CAPI Machine + InfraMachine
- CAPI Machine + InfraMachine → creates MAPI Machine
The current logic intentionally restricts scenario where CAPI Machine exists without InfraMachine and MAPI Machine arrives later. Given the
/holdand ongoing discussion, verify this is the desired behavior.
🧹 Nitpick comments (6)
pkg/controllers/machinemigration/machine_migration_controller.go (1)
227-244: Condition status type usage appears inconsistent but functionally correct.The code compares
machinePausedCondition.Status(typemetav1.ConditionStatus) againstmetav1.ConditionTrue, andinfraMachinePausedConditionStatus(typecorev1.ConditionStatus) againstcorev1.ConditionTrue. While both are ultimately string types with the same value"True", consider using consistent types for clarity.- return (machinePausedCondition.Status == metav1.ConditionTrue) && (infraMachinePausedConditionStatus == corev1.ConditionTrue), nil + return (machinePausedCondition.Status == metav1.ConditionTrue) && (string(infraMachinePausedConditionStatus) == string(corev1.ConditionTrue)), nilAlternatively, refactor
util.GetConditionStatusto returnmetav1.ConditionStatusfor consistency with the new v1beta2 conditions API.e2e/framework/machine.go (1)
88-102: Unusedclparameter in GetMachineWithError.The
cl client.Clientparameter is declared but never used in the function body. This appears to be for API consistency with other helper functions but should either be used or documented.Consider one of these options:
-// GetMachine gets a machine by its name. +// GetMachineWithError gets a machine by its name and returns an error if not found. +// The cl parameter is unused but kept for API consistency with other helpers. func GetMachineWithError(cl client.Client, name string, namespace string) (*clusterv1.Machine, error) {Or remove the unused parameter if API consistency is not required:
-func GetMachineWithError(cl client.Client, name string, namespace string) (*clusterv1.Machine, error) { +func GetMachineWithError(name string, namespace string) (*clusterv1.Machine, error) {pkg/controllers/machinesync/machine_sync_controller_test.go (1)
950-964: New ClusterAPI‑authoritative test for missing InfraMachine matches PR intentThe “when the CAPI machine exists and the InfraMachine does not exist” test verifies:
SynchronizedConditionbecomes True with a “Successfully synchronized CAPI Machine to MAPI” message.- An AWSMachine is eventually created in the CAPI namespace with the mirrored name.
This directly exercises the new behavior described in the PR and should catch regressions in infra‑machine creation when only the CAPI Machine exists.
You might also consider asserting the infra-machine’s OwnerReferences point at the v1beta2 Machine (kind and APIVersion) to fully validate the new flow, but that’s optional here.
pkg/controllers/machinesetsync/machineset_sync_controller_test.go (1)
406-413: Status.Replicas expectation uses nil for zero; verify intent vs conversion helperThis assertion treats a zero
mapiMachineSet.Status.Replicasas implying a nilStatus.Replicaspointer on the CAPI MachineSet:var expectedValue *int32 if mapiMachineSet.Status.Replicas != 0 { expectedValue = ptr.To(mapiMachineSet.Status.Replicas) } Eventually(k.Object(capiMachineSet), timeout).Should( HaveField("Status.Replicas", BeEquivalentTo(expectedValue)), )However,
convertMAPIMachineSetToCAPIMachineSetStatusinpkg/conversion/mapi2capi/machineset.gocurrently setsReplicas: ptr.To(mapiMachineSet.Status.Replicas)unconditionally, which would yield a non‑nil pointer even when the value is 0.If the sync controller reuses that helper for initial/status updates, this test may not match the actual behavior. Either:
- adjust the conversion to use
nilIfZerofor.Status.Replicasas well, or- update this expectation to always compare against
ptr.To(mapiMachineSet.Status.Replicas).pkg/conversion/mapi2capi/machineset.go (1)
85-145: MachineSetStatus conversion populates both Deprecated.V1Beta1 and v1beta2 status correctly
convertMAPIMachineSetToCAPIMachineSetStatus:
- fills
Deprecated.V1Beta1replicas, readiness, availability, and conditions,- sets pointer fields
Replicas,ReadyReplicas,AvailableReplicas(usingnilIfZerofor the latter two),- initializes v1beta2
ConditionsviaconvertMAPIMachineSetConditionsToCAPIMachineSetV1Beta2StatusConditions,- always sets
UpToDateReplicasto0as per the in‑code comment and linked CAPI controller logic,- moves ErrorReason/ErrorMessage into
Deprecated.V1Beta1.FailureReason/FailureMessage,- best‑effort populates
Selector.All of that is in line with the referenced CAPI status proposal.
You might consider using
nilIfZeroforReplicasas well for symmetry withReadyReplicas/AvailableReplicas, unless the v1beta2 contract explicitly prefers a non‑nilReplicaspointer even when zero.pkg/controllers/machinesetsync/machineset_sync_controller.go (1)
239-255: InfrastructureRef validation should also check Kind and APIGroup.The validation at line 252 only checks if
infraMachineTemplateRef.Nameis empty. SinceContractVersionedObjectReferencerequiresAPIGroup,Kind, andName, consider validating all required fields to catch misconfigured MachineSet resources early.if capiMachineSet.Spec.ClusterName == "" { return nil, nil, fmt.Errorf("machine set %s/%s: %w", capiMachineSet.Namespace, capiMachineSet.Name, errInvalidInfraClusterReference) } - if infraMachineTemplateRef.Name == "" { + if infraMachineTemplateRef.Name == "" || infraMachineTemplateRef.Kind == "" || infraMachineTemplateRef.APIGroup == "" { return nil, nil, fmt.Errorf("machine %s/%s: %w", capiMachineSet.Namespace, capiMachineSet.Name, errInvalidInfraMachineTemplateReference) }
📜 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 ignored due to path filters (62)
e2e/go.sumis excluded by!**/*.sumgo.sumis excluded by!**/*.sumgo.workis excluded by!**/*.workgo.work.sumis excluded by!**/*.sumvendor/github.com/openshift/cluster-api-actuator-pkg/testutils/resourcebuilder/cluster-api/core/v1beta1/cluster.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/cluster-api-actuator-pkg/testutils/resourcebuilder/cluster-api/core/v1beta1/machine.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/cluster-api-actuator-pkg/testutils/resourcebuilder/cluster-api/core/v1beta1/machineset.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/cluster-api-actuator-pkg/testutils/resourcebuilder/cluster-api/core/v1beta2/cluster.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/cluster-api-actuator-pkg/testutils/resourcebuilder/cluster-api/core/v1beta2/machine.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/cluster-api-actuator-pkg/testutils/resourcebuilder/cluster-api/core/v1beta2/machineset.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/cluster-api-actuator-pkg/testutils/resourcebuilder/cluster-api/infrastructure/v1beta1/openstackcluster.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/cluster-api-actuator-pkg/testutils/resourcebuilder/cluster-api/infrastructure/v1beta1/openstackmachine.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/cluster-api-actuator-pkg/testutils/resourcebuilder/cluster-api/infrastructure/v1beta2/awscluster.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/cluster-api-actuator-pkg/testutils/resourcebuilder/cluster-api/infrastructure/v1beta2/awsmachine.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/cluster-api-actuator-pkg/testutils/resourcebuilder/cluster-api/infrastructure/v1beta2/powervscluster.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/cluster-api-actuator-pkg/testutils/resourcebuilder/cluster-api/infrastructure/v1beta2/powervsmachine.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/cluster-api-actuator-pkg/testutils/tools.gois excluded by!**/vendor/**,!vendor/**vendor/modules.txtis excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/controllers/external/doc.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/controllers/external/tracker.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/controllers/external/types.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/controllers/external/util.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/internal/contract/bootstrap.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/internal/contract/bootstrap_config_template.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/internal/contract/controlplane.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/internal/contract/controlplane_template.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/internal/contract/doc.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/internal/contract/infrastructure_cluster.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/internal/contract/infrastructure_cluster_template.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/internal/contract/infrastructure_machine.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/internal/contract/infrastructure_machine_template.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/internal/contract/infrastructure_machinepool_template.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/internal/contract/metadata.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/internal/contract/references.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/internal/contract/types.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/internal/contract/version.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/aggregate.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/deprecated/v1beta1/doc.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/deprecated/v1beta1/getter.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/deprecated/v1beta1/matcher.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/deprecated/v1beta1/matchers.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/deprecated/v1beta1/merge.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/deprecated/v1beta1/merge_strategies.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/deprecated/v1beta1/patch.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/deprecated/v1beta1/setter.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/deprecated/v1beta1/unstructured.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/doc.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/getter.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/matcher.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/merge_strategies.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/mirror.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/options.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/patch.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/setter.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/sort.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/summary.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/contract/contract.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/contract/doc.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/labels/helpers.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/predicates/cluster_predicates.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/predicates/generic_predicates.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/version/version.gois excluded by!**/vendor/**,!vendor/**
📒 Files selected for processing (87)
.golangci.yml(1 hunks)cmd/cluster-capi-operator/main.go(3 hunks)cmd/machine-api-migration/main.go(2 hunks)e2e/aws_test.go(2 hunks)e2e/azure_test.go(3 hunks)e2e/baremetal_test.go(3 hunks)e2e/e2e_common.go(3 hunks)e2e/framework/cluster.go(3 hunks)e2e/framework/machine.go(6 hunks)e2e/framework/machineset.go(13 hunks)e2e/framework/node.go(1 hunks)e2e/gcp_test.go(3 hunks)e2e/go.mod(1 hunks)e2e/machine_migration_capi_authoritative_test.go(9 hunks)e2e/machine_migration_helpers.go(7 hunks)e2e/machine_migration_mapi_authoritative_test.go(8 hunks)e2e/machineset_migration_capi_authoritative_test.go(8 hunks)e2e/machineset_migration_helpers.go(10 hunks)e2e/machineset_migration_mapi_authoritative_test.go(10 hunks)e2e/migration_common.go(2 hunks)e2e/openstack_test.go(3 hunks)e2e/powervs_test.go(3 hunks)e2e/vsphere_test.go(5 hunks)go.mod(1 hunks)manifests/0000_30_cluster-api_09_admission-policies.yaml(7 hunks)manifests/0000_30_cluster-api_10_webhooks.yaml(1 hunks)pkg/controllers/corecluster/corecluster_controller.go(11 hunks)pkg/controllers/corecluster/corecluster_controller_test.go(6 hunks)pkg/controllers/infracluster/aws.go(2 hunks)pkg/controllers/infracluster/azure.go(3 hunks)pkg/controllers/infracluster/gcp.go(2 hunks)pkg/controllers/infracluster/infracluster_controller.go(2 hunks)pkg/controllers/infracluster/infracluster_controller_test.go(9 hunks)pkg/controllers/infracluster/metal3.go(2 hunks)pkg/controllers/infracluster/powervs.go(2 hunks)pkg/controllers/infracluster/vsphere.go(2 hunks)pkg/controllers/kubeconfig/kubeconfig.go(2 hunks)pkg/controllers/machinemigration/machine_migration_controller.go(8 hunks)pkg/controllers/machinemigration/machine_migration_controller_test.go(12 hunks)pkg/controllers/machinesetmigration/machineset_migration_controller.go(6 hunks)pkg/controllers/machinesetmigration/machineset_migration_controller_test.go(11 hunks)pkg/controllers/machinesetsync/machineset_sync_controller.go(34 hunks)pkg/controllers/machinesetsync/machineset_sync_controller_test.go(15 hunks)pkg/controllers/machinesetsync/machineset_sync_controller_unit_test.go.bak(1 hunks)pkg/controllers/machinesetsync/machineset_vap_test.go(10 hunks)pkg/controllers/machinesync/aws_test.go(4 hunks)pkg/controllers/machinesync/machine_sync_controller.go(34 hunks)pkg/controllers/machinesync/machine_sync_controller_test.go(39 hunks)pkg/controllers/machinesync/machine_sync_controller_unit_test.go(1 hunks)pkg/controllers/machinesync/machine_sync_mapi2capi_infrastructure.go(3 hunks)pkg/conversion/capi2mapi/aws.go(5 hunks)pkg/conversion/capi2mapi/aws_fuzz_test.go(4 hunks)pkg/conversion/capi2mapi/aws_test.go(1 hunks)pkg/conversion/capi2mapi/common.go(4 hunks)pkg/conversion/capi2mapi/machine.go(8 hunks)pkg/conversion/capi2mapi/machine_test.go(4 hunks)pkg/conversion/capi2mapi/machineset.go(4 hunks)pkg/conversion/capi2mapi/machineset_test.go(3 hunks)pkg/conversion/capi2mapi/openstack.go(4 hunks)pkg/conversion/capi2mapi/openstack_fuzz_test.go(4 hunks)pkg/conversion/capi2mapi/openstack_test.go(1 hunks)pkg/conversion/capi2mapi/powervs.go(3 hunks)pkg/conversion/capi2mapi/powervs_fuzz_test.go(4 hunks)pkg/conversion/capi2mapi/powervs_test.go(2 hunks)pkg/conversion/capi2mapi/suite_test.go(2 hunks)pkg/conversion/mapi2capi/aws.go(9 hunks)pkg/conversion/mapi2capi/aws_fuzz_test.go(3 hunks)pkg/conversion/mapi2capi/interface.go(1 hunks)pkg/conversion/mapi2capi/machine.go(15 hunks)pkg/conversion/mapi2capi/machine_test.go(24 hunks)pkg/conversion/mapi2capi/machineset.go(8 hunks)pkg/conversion/mapi2capi/machineset_test.go(9 hunks)pkg/conversion/mapi2capi/openstack.go(8 hunks)pkg/conversion/mapi2capi/openstack_fuzz_test.go(3 hunks)pkg/conversion/mapi2capi/powervs.go(7 hunks)pkg/conversion/mapi2capi/powervs_fuzz_test.go(3 hunks)pkg/conversion/mapi2capi/util.go(6 hunks)pkg/conversion/test/fuzz/fuzz.go(19 hunks)pkg/conversion/test/matchers/capi_condition.go(3 hunks)pkg/conversion/util/util.go(1 hunks)pkg/test/crdbuilder.go(4 hunks)pkg/test/envtest.go(2 hunks)pkg/util/conditions.go(3 hunks)pkg/util/sync.go(8 hunks)pkg/util/sync_test.go(5 hunks)pkg/util/watch_filters.go(2 hunks)pkg/webhook/cluster.go(6 hunks)
🧰 Additional context used
🧬 Code graph analysis (42)
e2e/machineset_migration_capi_authoritative_test.go (1)
pkg/conversion/mapi2capi/interface.go (1)
MachineSet(29-31)
e2e/framework/node.go (1)
pkg/conversion/mapi2capi/interface.go (1)
Machine(24-26)
e2e/azure_test.go (1)
pkg/conversion/mapi2capi/interface.go (1)
MachineSet(29-31)
e2e/machine_migration_capi_authoritative_test.go (1)
pkg/conversion/mapi2capi/interface.go (1)
Machine(24-26)
pkg/controllers/machinesync/machine_sync_controller_test.go (3)
pkg/conversion/mapi2capi/interface.go (2)
Machine(24-26)MachineSet(29-31)e2e/migration_common.go (1)
SynchronizedCondition(10-10)pkg/controllers/common_consts.go (1)
SynchronizedCondition(41-41)
pkg/controllers/machinesync/machine_sync_mapi2capi_infrastructure.go (1)
pkg/util/conditions.go (1)
EnsureCAPIV1Beta1Conditions(222-231)
pkg/controllers/machinesetmigration/machineset_migration_controller.go (2)
pkg/conversion/mapi2capi/interface.go (1)
MachineSet(29-31)e2e/framework/framework.go (1)
CAPINamespace(14-14)
pkg/conversion/capi2mapi/machineset.go (1)
pkg/conversion/mapi2capi/interface.go (1)
MachineSet(29-31)
e2e/gcp_test.go (1)
pkg/conversion/mapi2capi/interface.go (1)
MachineSet(29-31)
e2e/openstack_test.go (1)
pkg/conversion/mapi2capi/interface.go (1)
MachineSet(29-31)
e2e/powervs_test.go (1)
pkg/conversion/mapi2capi/interface.go (1)
MachineSet(29-31)
pkg/conversion/mapi2capi/aws_fuzz_test.go (2)
pkg/conversion/mapi2capi/interface.go (2)
Machine(24-26)MachineSet(29-31)pkg/conversion/capi2mapi/interface.go (2)
MachineAndInfrastructureMachine(21-23)MachineSetAndMachineTemplate(26-28)
e2e/machine_migration_mapi_authoritative_test.go (1)
pkg/conversion/mapi2capi/interface.go (1)
Machine(24-26)
pkg/conversion/capi2mapi/powervs_fuzz_test.go (3)
pkg/conversion/mapi2capi/interface.go (2)
Machine(24-26)MachineSet(29-31)pkg/conversion/capi2mapi/interface.go (1)
MachineAndInfrastructureMachine(21-23)pkg/conversion/test/fuzz/fuzz.go (2)
CAPIMachineFuzzerFuncs(475-546)CAPIMachineSetFuzzerFuncs(549-626)
pkg/conversion/mapi2capi/machineset_test.go (1)
pkg/conversion/test/matchers/capi_condition.go (1)
MatchCAPICondition(51-55)
e2e/machine_migration_helpers.go (2)
pkg/conversion/mapi2capi/interface.go (1)
Machine(24-26)e2e/framework/machine.go (2)
GetMachineWithError(89-102)GetMachine(75-86)
pkg/controllers/machinesync/machine_sync_controller_unit_test.go (2)
pkg/controllers/machinesync/machine_sync_controller.go (1)
MachineSyncReconciler(138-147)pkg/conversion/mapi2capi/interface.go (1)
Machine(24-26)
pkg/conversion/mapi2capi/util.go (1)
pkg/conversion/mapi2capi/interface.go (1)
Machine(24-26)
pkg/conversion/capi2mapi/openstack_fuzz_test.go (1)
pkg/conversion/test/fuzz/fuzz.go (2)
CAPIMachineFuzzerFuncs(475-546)CAPIMachineSetFuzzerFuncs(549-626)
e2e/vsphere_test.go (1)
pkg/conversion/mapi2capi/interface.go (1)
MachineSet(29-31)
pkg/conversion/mapi2capi/machineset.go (1)
pkg/conversion/mapi2capi/interface.go (1)
MachineSet(29-31)
pkg/controllers/machinemigration/machine_migration_controller_test.go (1)
pkg/conversion/mapi2capi/interface.go (2)
Machine(24-26)MachineSet(29-31)
pkg/conversion/capi2mapi/powervs.go (3)
pkg/conversion/mapi2capi/interface.go (2)
Machine(24-26)MachineSet(29-31)pkg/conversion/capi2mapi/interface.go (2)
MachineAndInfrastructureMachine(21-23)MachineSetAndMachineTemplate(26-28)pkg/conversion/consts/consts.go (1)
MAPIMachineMetadataLabelZone(26-26)
e2e/aws_test.go (1)
pkg/conversion/mapi2capi/interface.go (1)
MachineSet(29-31)
e2e/framework/machineset.go (2)
pkg/conversion/mapi2capi/interface.go (2)
MachineSet(29-31)Machine(24-26)e2e/framework/machine.go (1)
GetMachines(18-44)
pkg/conversion/mapi2capi/powervs.go (1)
pkg/conversion/mapi2capi/interface.go (2)
Machine(24-26)MachineSet(29-31)
pkg/conversion/mapi2capi/openstack_fuzz_test.go (2)
pkg/conversion/mapi2capi/interface.go (2)
Machine(24-26)MachineSet(29-31)pkg/conversion/capi2mapi/interface.go (2)
MachineAndInfrastructureMachine(21-23)MachineSetAndMachineTemplate(26-28)
e2e/machineset_migration_helpers.go (2)
pkg/conversion/mapi2capi/interface.go (1)
MachineSet(29-31)e2e/framework/framework.go (2)
WaitOverLong(26-26)RetryLong(19-19)
e2e/baremetal_test.go (1)
pkg/conversion/mapi2capi/interface.go (1)
MachineSet(29-31)
pkg/controllers/machinesync/aws_test.go (1)
pkg/conversion/mapi2capi/interface.go (1)
Machine(24-26)
pkg/conversion/capi2mapi/aws_fuzz_test.go (1)
pkg/conversion/test/fuzz/fuzz.go (2)
CAPIMachineFuzzerFuncs(475-546)CAPIMachineSetFuzzerFuncs(549-626)
pkg/conversion/mapi2capi/machine.go (1)
pkg/conversion/mapi2capi/interface.go (1)
Machine(24-26)
pkg/conversion/capi2mapi/machine_test.go (2)
pkg/conversion/mapi2capi/interface.go (1)
Machine(24-26)pkg/util/annotations.go (1)
MapiDeleteMachineAnnotation(24-24)
pkg/conversion/mapi2capi/aws.go (1)
pkg/conversion/mapi2capi/interface.go (2)
Machine(24-26)MachineSet(29-31)
pkg/conversion/capi2mapi/machine.go (1)
pkg/conversion/mapi2capi/interface.go (1)
Machine(24-26)
pkg/conversion/capi2mapi/openstack.go (3)
pkg/conversion/mapi2capi/interface.go (2)
Machine(24-26)MachineSet(29-31)pkg/conversion/capi2mapi/interface.go (2)
MachineAndInfrastructureMachine(21-23)MachineSetAndMachineTemplate(26-28)pkg/conversion/consts/consts.go (1)
MAPIMachineMetadataLabelZone(26-26)
pkg/conversion/mapi2capi/machine_test.go (1)
pkg/conversion/test/matchers/capi_condition.go (1)
MatchCAPICondition(51-55)
pkg/conversion/mapi2capi/openstack.go (1)
pkg/conversion/mapi2capi/interface.go (2)
Machine(24-26)MachineSet(29-31)
pkg/conversion/capi2mapi/aws.go (2)
pkg/conversion/consts/consts.go (1)
MAPIMachineMetadataLabelZone(26-26)third_party/sigs.k8s.io/cluster-api/util/util.go (1)
IsControlPlaneMachine(25-28)
pkg/conversion/capi2mapi/powervs_test.go (1)
pkg/conversion/mapi2capi/interface.go (2)
Machine(24-26)MachineSet(29-31)
pkg/controllers/machinesetmigration/machineset_migration_controller_test.go (1)
pkg/conversion/mapi2capi/interface.go (2)
MachineSet(29-31)Machine(24-26)
pkg/controllers/machinesetsync/machineset_sync_controller.go (3)
pkg/conversion/mapi2capi/interface.go (1)
MachineSet(29-31)pkg/util/conditions.go (2)
EnsureCAPIDeprecatedV1Beta1Conditions(246-255)EnsureCAPIConditions(258-267)pkg/util/finalizer.go (1)
RemoveFinalizer(60-85)
| openstackv1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" | ||
| vspherev1 "sigs.k8s.io/cluster-api-provider-vsphere/apis/v1beta1" | ||
| clusterv1beta1 "sigs.k8s.io/cluster-api/api/core/v1beta1" | ||
| clusterv1 "sigs.k8s.io/cluster-api/api/core/v1beta2" |
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.
🧩 Analysis chain
🏁 Script executed:
rg -n 'infraAPIVersion' --type go
Repository: openshift/cluster-capi-operator
Length of output: 191
Remove unused infraAPIVersion constant.
The import and scheme registration updates to v1beta2 are correct. However, infraAPIVersion (defined on line 34) is no longer used—ContractVersionedObjectReference uses only APIGroup. Remove the unused constant on line 34.
🤖 Prompt for AI Agents
In e2e/e2e_common.go around lines 22–34, remove the unused infraAPIVersion
constant declaration (the constant defined on line 34) since
ContractVersionedObjectReference now only uses APIGroup; delete the unused
constant and any trailing comma/blank line left behind so the file compiles and
imports remain correct.
| clusterv1beta1 "sigs.k8s.io/cluster-api/api/core/v1beta1" | ||
| clusterv1 "sigs.k8s.io/cluster-api/api/core/v1beta2" |
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.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Inspect the specific lines and usage in powervs.go
echo "=== Lines 30-40 (around imports) ==="
sed -n '30,40p' pkg/controllers/infracluster/powervs.go
echo -e "\n=== Lines 100-110 (around ManagedByAnnotation and APIEndpoint usage) ==="
sed -n '100,110p' pkg/controllers/infracluster/powervs.go
echo -e "\n=== Check all usages of APIEndpoint and ManagedByAnnotation ==="
rg -n "APIEndpoint|ManagedByAnnotation" pkg/controllers/infracluster/powervs.go
echo -e "\n=== Check all clusterv1beta1 usage in the file ==="
rg -n "clusterv1beta1\." pkg/controllers/infracluster/powervs.go
echo -e "\n=== Check all clusterv1 usage in the file (v1beta2) ==="
rg -n "clusterv1\." pkg/controllers/infracluster/powervs.go
Repository: openshift/cluster-capi-operator
Length of output: 1548
Complete v1beta2 Cluster API migration by using APIEndpoint from v1beta2 package.
The file uses both v1beta1 and v1beta2 imports, but only one v1beta1 usage remains: line 107 uses clusterv1beta1.APIEndpoint. Line 103 successfully uses clusterv1.ManagedByAnnotation from v1beta2. Since APIEndpoint is defined identically in v1beta2 with the same structure (Host string, Port int32), update line 107 to use clusterv1.APIEndpoint and remove the v1beta1 import.
🤖 Prompt for AI Agents
In pkg/controllers/infracluster/powervs.go around lines 32-33 and 107, replace
the remaining usage of clusterv1beta1.APIEndpoint with clusterv1.APIEndpoint and
remove the unused import of clusterv1beta1; ensure the import block only
includes clusterv1 ("sigs.k8s.io/cluster-api/api/core/v1beta2") and update the
type reference at line ~107 to clusterv1.APIEndpoint so the file consistently
uses v1beta2.
| /* | ||
| Copyright 2025 Red Hat, Inc. | ||
|
|
||
| Licensed under the Apache License, Version 2.0 (the "License"); | ||
| you may not use this file except in compliance with the License. | ||
| You may obtain a copy of the License at | ||
|
|
||
| http://www.apache.org/licenses/LICENSE-2.0 | ||
|
|
||
| Unless required by applicable law or agreed to in writing, software | ||
| distributed under the License is distributed on an "AS IS" BASIS, | ||
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| See the License for the specific language governing permissions and | ||
| limitations under the License. | ||
| */ | ||
| package machinesetsync | ||
|
|
||
| import ( | ||
| "time" | ||
|
|
||
| . "github.com/onsi/ginkgo/v2" | ||
| . "github.com/onsi/gomega" | ||
| corev1 "k8s.io/api/core/v1" | ||
| metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
| "k8s.io/utils/ptr" | ||
|
|
||
| clusterv1beta1 "sigs.k8s.io/cluster-api/api/core/v1beta1" | ||
| ) |
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.
File has .bak extension - tests won't execute.
This file has a .bak extension which means it won't be picked up by the Go test runner. If these tests are intended to be part of the test suite, rename the file to machineset_sync_controller_unit_test.go.
Additionally, this file imports clusterv1beta1 (v1beta1) while the rest of the PR migrates to v1beta2. If this is intentional for testing v1beta1 compatibility, consider adding a comment explaining the purpose. Otherwise, update imports and types to v1beta2 for consistency.
#!/bin/bash
# Check if there's already a non-.bak version of this file
fd -t f "machineset_sync_controller_unit_test.go" pkg/controllers/machinesetsync/
# Check for other .bak files that might be accidentally committed
fd -e bak .
🤖 Prompt for AI Agents
In pkg/controllers/machinesetsync/machineset_sync_controller_unit_test.go.bak
lines 1-28, the file has a .bak extension so Go test runner will ignore it;
rename the file to machineset_sync_controller_unit_test.go so it runs as part of
the test suite, and also update the Cluster API import and used types from
clusterv1beta1 to clusterv1beta2 to match the PR migration (or if you
intentionally test v1beta1, keep the import but add a short clarifying comment
at the top explaining this backward-compatibility test).
| if capiMachine.Status.Deprecated.V1Beta1.FailureReason == nil && | ||
| capiMachine.Status.Deprecated.V1Beta1.FailureMessage == nil && | ||
| len(capiMachine.Status.Deprecated.V1Beta1.Conditions) == 0 { | ||
| capiMachine.Status.Deprecated = nil | ||
| } |
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.
Add nil checks before accessing nested Deprecated fields.
Lines 140-143 access capiMachine.Status.Deprecated.V1Beta1 fields without checking if Deprecated or V1Beta1 are nil. Based on line 588 which checks if m.Deprecated != nil && m.Deprecated.V1Beta1 != nil, these appear to be pointers. This could cause a nil pointer panic during fuzz tests.
Apply this diff to add proper nil guards:
- if capiMachine.Status.Deprecated.V1Beta1.FailureReason == nil &&
- capiMachine.Status.Deprecated.V1Beta1.FailureMessage == nil &&
- len(capiMachine.Status.Deprecated.V1Beta1.Conditions) == 0 {
+ if capiMachine.Status.Deprecated != nil &&
+ capiMachine.Status.Deprecated.V1Beta1 != nil &&
+ capiMachine.Status.Deprecated.V1Beta1.FailureReason == nil &&
+ capiMachine.Status.Deprecated.V1Beta1.FailureMessage == nil &&
+ len(capiMachine.Status.Deprecated.V1Beta1.Conditions) == 0 {
capiMachine.Status.Deprecated = nil
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if capiMachine.Status.Deprecated.V1Beta1.FailureReason == nil && | |
| capiMachine.Status.Deprecated.V1Beta1.FailureMessage == nil && | |
| len(capiMachine.Status.Deprecated.V1Beta1.Conditions) == 0 { | |
| capiMachine.Status.Deprecated = nil | |
| } | |
| if capiMachine.Status.Deprecated != nil && | |
| capiMachine.Status.Deprecated.V1Beta1 != nil && | |
| capiMachine.Status.Deprecated.V1Beta1.FailureReason == nil && | |
| capiMachine.Status.Deprecated.V1Beta1.FailureMessage == nil && | |
| len(capiMachine.Status.Deprecated.V1Beta1.Conditions) == 0 { | |
| capiMachine.Status.Deprecated = nil | |
| } |
🤖 Prompt for AI Agents
In pkg/conversion/test/fuzz/fuzz.go around lines 140 to 144, the code accesses
capiMachine.Status.Deprecated.V1Beta1 fields without guarding that Deprecated
and V1Beta1 are non-nil; update the conditional to first check that
capiMachine.Status.Deprecated != nil && capiMachine.Status.Deprecated.V1Beta1 !=
nil before evaluating FailureReason, FailureMessage, and Conditions, and only
then set capiMachine.Status.Deprecated = nil when those inner fields are all
empty/nil.
| // fakeAzureClusterKind is the Kind for the AWSCluster. | ||
| fakeAzureClusterKind = "AzureCluster" | ||
|
|
||
| // fakeAWSClusterCRD is a fake AzureCluster CRD. |
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.
Fix comment typo.
The comment incorrectly refers to "fakeAWSClusterCRD" instead of "fakeAzureClusterCRD".
Apply this diff to fix the comment:
- // fakeAWSClusterCRD is a fake AzureCluster CRD.
+ // fakeAzureClusterCRD is a fake AzureCluster CRD.
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // fakeAWSClusterCRD is a fake AzureCluster CRD. | |
| // fakeAzureClusterCRD is a fake AzureCluster CRD. |
🤖 Prompt for AI Agents
In pkg/test/crdbuilder.go around line 113, the comment above the AzureCluster
fake is incorrectly labeled "fakeAWSClusterCRD"; update the comment text to
correctly read "fakeAzureClusterCRD" so it matches the variable/name and
describes the AzureCluster CRD accurately.
a8d9b03 to
e00163b
Compare
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: 5
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (3)
pkg/controllers/corecluster/corecluster_controller_test.go (1)
170-177: Add assertions for the newerClusterControlPlaneInitializedConditioncondition.The controller sets both the deprecated v1beta1 condition and the newer condition type (
clusterv1.ClusterControlPlaneInitializedCondition), but the tests only verify the deprecated path. Add assertions to verify thatStatus.Conditionscontains the newer condition with the correct type and status.Also applies to: 231-238
pkg/conversion/mapi2capi/openstack.go (1)
121-126: Avoid nil dereference wheninfrastructureis nilBoth in
ToMachineAndInfrastructureMachineandToMachineSetAndMachineTemplateyou guard with:if m.infrastructure == nil || m.infrastructure.Status.InfrastructureName == "" { errors = append(errors, field.Invalid( field.NewPath("infrastructure", "status", "infrastructureName"), m.infrastructure.Status.InfrastructureName, "infrastructure cannot be nil and infrastructure.Status.InfrastructureName cannot be empty")) }If
m.infrastructureis actuallynil, this will panic when evaluatingm.infrastructure.Status.InfrastructureNamefor theBadValue.Safer pattern that keeps behavior identical on valid inputs:
- if m.infrastructure == nil || m.infrastructure.Status.InfrastructureName == "" { - errors = append(errors, field.Invalid( - field.NewPath("infrastructure", "status", "infrastructureName"), - m.infrastructure.Status.InfrastructureName, - "infrastructure cannot be nil and infrastructure.Status.InfrastructureName cannot be empty")) - } else { - capiMachine.Spec.ClusterName = m.infrastructure.Status.InfrastructureName - capiMachine.Labels[clusterv1.ClusterNameLabel] = m.infrastructure.Status.InfrastructureName - } + infraName := "" + if m.infrastructure != nil { + infraName = m.infrastructure.Status.InfrastructureName + } + if infraName == "" { + errors = append(errors, field.Invalid( + field.NewPath("infrastructure", "status", "infrastructureName"), + infraName, + "infrastructure cannot be nil and infrastructure.Status.InfrastructureName cannot be empty")) + } else { + capiMachine.Spec.ClusterName = infraName + capiMachine.Labels[clusterv1.ClusterNameLabel] = infraName + }Apply the same pattern in the MachineSet path.
Also applies to: 187-193
pkg/conversion/mapi2capi/aws.go (1)
143-148: Guard against nilinfrastructurein AWS convertersAs in the OpenStack path, both AWS converters use:
if m.infrastructure == nil || m.infrastructure.Status.InfrastructureName == "" { errs = append(errs, field.Invalid( field.NewPath("infrastructure", "status", "infrastructureName"), m.infrastructure.Status.InfrastructureName, "infrastructure cannot be nil and infrastructure.Status.InfrastructureName cannot be empty")) } else { // use m.infrastructure.Status.InfrastructureName }If
m.infrastructureisnil, this will panic while building the error (due tom.infrastructure.Status...).Safer, without changing behavior for valid inputs:
- if m.infrastructure == nil || m.infrastructure.Status.InfrastructureName == "" { - errs = append(errs, field.Invalid( - field.NewPath("infrastructure", "status", "infrastructureName"), - m.infrastructure.Status.InfrastructureName, - "infrastructure cannot be nil and infrastructure.Status.InfrastructureName cannot be empty")) - } else { - capiMachine.Spec.ClusterName = m.infrastructure.Status.InfrastructureName - capiMachine.Labels[clusterv1.ClusterNameLabel] = m.infrastructure.Status.InfrastructureName - } + infraName := "" + if m.infrastructure != nil { + infraName = m.infrastructure.Status.InfrastructureName + } + if infraName == "" { + errs = append(errs, field.Invalid( + field.NewPath("infrastructure", "status", "infrastructureName"), + infraName, + "infrastructure cannot be nil and infrastructure.Status.InfrastructureName cannot be empty")) + } else { + capiMachine.Spec.ClusterName = infraName + capiMachine.Labels[clusterv1.ClusterNameLabel] = infraName + }and analogously in
ToMachineSetAndMachineTemplate.Also applies to: 211-217
♻️ Duplicate comments (7)
e2e/go.mod (1)
7-8: Duplicate: Version mismatch already flagged in past review.This concern was already raised in a prior review. The versions in the replace block for
cluster-api-actuator-pkgmodules remain out of sync with the root go.mod. If this is still unresolved, please address it by synchronizing the dependency versions.pkg/test/crdbuilder.go (1)
113-113: Comment typo already flagged.This typo ("fakeAWSClusterCRD" → "fakeAzureClusterCRD") was identified in a previous review.
pkg/conversion/test/fuzz/fuzz.go (2)
140-144: Add nil checks before accessing nested Deprecated fields.Lines 140-143 access
capiMachine.Status.Deprecated.V1Beta1fields without checking ifDeprecatedorV1Beta1are nil. This pattern at line 588 shows the proper guard:if m.Deprecated != nil && m.Deprecated.V1Beta1 != nil. This could cause a nil pointer panic during fuzz tests.- if capiMachine.Status.Deprecated.V1Beta1.FailureReason == nil && - capiMachine.Status.Deprecated.V1Beta1.FailureMessage == nil && - len(capiMachine.Status.Deprecated.V1Beta1.Conditions) == 0 { + if capiMachine.Status.Deprecated != nil && + capiMachine.Status.Deprecated.V1Beta1 != nil && + capiMachine.Status.Deprecated.V1Beta1.FailureReason == nil && + capiMachine.Status.Deprecated.V1Beta1.FailureMessage == nil && + len(capiMachine.Status.Deprecated.V1Beta1.Conditions) == 0 { capiMachine.Status.Deprecated = nil }
240-249: Add nil checks before accessing nested Deprecated fields.Similar to lines 140-144, this code accesses
capiMachineSet.Status.Deprecated.V1Beta1fields without nil checks, risking a panic.- capiMachineSet.Status.Deprecated.V1Beta1.Conditions = nil - // Set Deprecated to nil if the values are zero - if capiMachineSet.Status.Deprecated.V1Beta1.FullyLabeledReplicas == 0 && - capiMachineSet.Status.Deprecated.V1Beta1.ReadyReplicas == 0 && - capiMachineSet.Status.Deprecated.V1Beta1.AvailableReplicas == 0 && - capiMachineSet.Status.Deprecated.V1Beta1.FailureReason == nil && - capiMachineSet.Status.Deprecated.V1Beta1.FailureMessage == nil && - len(capiMachineSet.Status.Deprecated.V1Beta1.Conditions) == 0 { - capiMachineSet.Status.Deprecated = nil - } + if capiMachineSet.Status.Deprecated != nil && + capiMachineSet.Status.Deprecated.V1Beta1 != nil { + capiMachineSet.Status.Deprecated.V1Beta1.Conditions = nil + // Set Deprecated to nil if the values are zero + if capiMachineSet.Status.Deprecated.V1Beta1.FullyLabeledReplicas == 0 && + capiMachineSet.Status.Deprecated.V1Beta1.ReadyReplicas == 0 && + capiMachineSet.Status.Deprecated.V1Beta1.AvailableReplicas == 0 && + capiMachineSet.Status.Deprecated.V1Beta1.FailureReason == nil && + capiMachineSet.Status.Deprecated.V1Beta1.FailureMessage == nil { + capiMachineSet.Status.Deprecated = nil + } + }pkg/controllers/infracluster/powervs.go (1)
32-33: Incomplete v1beta2 migration - mixed API version usage.The file imports both
clusterv1beta1(v1beta1) andclusterv1(v1beta2), but only usesclusterv1beta1at line 107 forAPIEndpoint. SinceAPIEndpointhas the same structure in v1beta2, complete the migration by updating line 107 to useclusterv1.APIEndpointand remove the unusedclusterv1beta1import.- ibmpowervsv1 "sigs.k8s.io/cluster-api-provider-ibmcloud/api/v1beta2" - clusterv1beta1 "sigs.k8s.io/cluster-api/api/core/v1beta1" - clusterv1 "sigs.k8s.io/cluster-api/api/core/v1beta2" + ibmpowervsv1 "sigs.k8s.io/cluster-api-provider-ibmcloud/api/v1beta2" + clusterv1 "sigs.k8s.io/cluster-api/api/core/v1beta2"And at line 107:
- ControlPlaneEndpoint: clusterv1beta1.APIEndpoint{ + ControlPlaneEndpoint: clusterv1.APIEndpoint{e2e/framework/machine.go (1)
88-88: Copy-paste error in doc comment.The doc comment says "GetMachine" but the function is
GetMachineWithError. This issue was already flagged in a previous review.pkg/controllers/machinesync/machine_sync_controller.go (1)
268-273: Critical: Timestamp gate prevents InfraMachine creation in intended scenario.The timestamp check on line 271 (
!mapiMachine.CreationTimestamp.After(capiMachine.CreationTimestamp.Time)) blocks the PR's stated objective. When a user creates a CAPI Machine first, then creates a MAPI Machine withauthoritativeAPI: ClusterAPI, this condition will be false (MAPI created after CAPI), preventing InfraMachine creation. This matches the QA failure report where no AWSMachine was created.Apply this diff to enable InfraMachine creation based solely on existence and deletion state:
- if capiMachine.DeletionTimestamp.IsZero() && mapiMachine.DeletionTimestamp.IsZero() && - !capiInfraMachineExists && !mapiMachine.CreationTimestamp.After(capiMachine.CreationTimestamp.Time) { + if capiMachine.DeletionTimestamp.IsZero() && mapiMachine.DeletionTimestamp.IsZero() && + !capiInfraMachineExists { return r.reconcileMAPIMachinetoCAPIMachine(ctx, mapiMachine, capiMachine) }Note: This issue was previously identified in past review comments.
🧹 Nitpick comments (5)
pkg/conversion/mapi2capi/machineset_test.go (1)
255-255: Consider using consistent pointer comparison pattern.Line 255 dereferences
capiStatus.Replicasbefore comparing, while lines 123, 209, and 282 compare the pointer directly usingEqual(ptr.To(int32(...))). For consistency with the rest of the test, consider:- Expect(ptr.Deref(capiStatus.Replicas, 0)).To(Equal(int32(3))) + Expect(capiStatus.Replicas).To(Equal(ptr.To(int32(3))))pkg/conversion/test/fuzz/fuzz.go (1)
749-760: Consider simplifying NodeRef normalization logic.The two consecutive
if m.NodeRef != nilblocks could be combined for clarity:- // The only valid node reference is of kind Node and APIVersion v1. - if m.NodeRef != nil { - m.NodeRef = &corev1.ObjectReference{ - Kind: "Node", - Name: m.NodeRef.Name, - APIVersion: "v1", - } - } - // Otherwise set it to nil. - if m.NodeRef != nil && m.NodeRef.Name == "" { - m.NodeRef = nil - } + // The only valid node reference is of kind Node and APIVersion v1. + if m.NodeRef != nil && m.NodeRef.Name != "" { + m.NodeRef = &corev1.ObjectReference{ + Kind: "Node", + Name: m.NodeRef.Name, + APIVersion: "v1", + } + } else { + m.NodeRef = nil + }pkg/controllers/corecluster/corecluster_controller.go (2)
162-162: Consider refactoring the function signature to reduce parameter count.The function signature is correct but could be simplified. Consider grouping related parameters (APIGroup, Kind) into a struct or using the existing mapping function's return values more directly.
Example refactor:
type InfraClusterReference struct { APIGroup string Kind string Version string } func (r *CoreClusterController) generateCoreClusterObject(_ context.Context, clusterObjectKey client.ObjectKey, infraRef InfraClusterReference) (*clusterv1.Cluster, error) {This would make the signature more maintainable if additional infrastructure reference fields are needed in the future.
225-239: LGTM: Platform mapping correctly returns APIGroup.The function properly maps each platform to its infrastructure cluster kind, version, and API group. The explicit return of
capiInfraClusterAPIGroupin each case is correct and maintains clarity.Optional: The function name
mapOCPPlatformToInfraClusterKindAndVersionAndGroupis quite long. Consider a shorter alternative likegetInfraClusterReferenceormapPlatformToInfraClusterRef, especially if you refactor to return a struct (see comment on line 162).pkg/controllers/machinesync/machine_sync_controller_test.go (1)
831-852: Context name vs. setup: “owned by a machineset” branch doesn’t set an ownerRefInside
Context("when the CAPI infra machine resource does not exist")→Context("when the MAPI machine is owned by a machineset"), the MachineAPI‑authoritative branch builds the MAPI machine withownerReferencesToMapiMachineSet, but the ClusterAPI‑authoritative branch later does:mapiMachine = mapiMachineBuilder.WithName("test-machine").Build() ... // no WithOwnerReferences(ownerReferencesToMapiMachineSet) hereSo in the ClusterAPI‑authoritative tests, the MAPI machine is not actually owned by a MachineSet, despite the enclosing context name. That can be confusing when reasoning about which ownership paths are covered.
If the intention is to validate behavior specifically when a MachineSet owns the MAPI machine, consider also applying
ownerReferencesToMapiMachineSetin this branch; otherwise, you might want to tweak the context description to clarify that this sub‑scenario is “without MAPI MachineSet ownership”.Also applies to: 931-942
📜 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 ignored due to path filters (62)
e2e/go.sumis excluded by!**/*.sumgo.sumis excluded by!**/*.sumgo.workis excluded by!**/*.workgo.work.sumis excluded by!**/*.sumvendor/github.com/openshift/cluster-api-actuator-pkg/testutils/resourcebuilder/cluster-api/core/v1beta1/cluster.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/cluster-api-actuator-pkg/testutils/resourcebuilder/cluster-api/core/v1beta1/machine.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/cluster-api-actuator-pkg/testutils/resourcebuilder/cluster-api/core/v1beta1/machineset.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/cluster-api-actuator-pkg/testutils/resourcebuilder/cluster-api/core/v1beta2/cluster.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/cluster-api-actuator-pkg/testutils/resourcebuilder/cluster-api/core/v1beta2/machine.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/cluster-api-actuator-pkg/testutils/resourcebuilder/cluster-api/core/v1beta2/machineset.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/cluster-api-actuator-pkg/testutils/resourcebuilder/cluster-api/infrastructure/v1beta1/openstackcluster.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/cluster-api-actuator-pkg/testutils/resourcebuilder/cluster-api/infrastructure/v1beta1/openstackmachine.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/cluster-api-actuator-pkg/testutils/resourcebuilder/cluster-api/infrastructure/v1beta2/awscluster.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/cluster-api-actuator-pkg/testutils/resourcebuilder/cluster-api/infrastructure/v1beta2/awsmachine.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/cluster-api-actuator-pkg/testutils/resourcebuilder/cluster-api/infrastructure/v1beta2/powervscluster.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/cluster-api-actuator-pkg/testutils/resourcebuilder/cluster-api/infrastructure/v1beta2/powervsmachine.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/cluster-api-actuator-pkg/testutils/tools.gois excluded by!**/vendor/**,!vendor/**vendor/modules.txtis excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/controllers/external/doc.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/controllers/external/tracker.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/controllers/external/types.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/controllers/external/util.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/internal/contract/bootstrap.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/internal/contract/bootstrap_config_template.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/internal/contract/controlplane.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/internal/contract/controlplane_template.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/internal/contract/doc.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/internal/contract/infrastructure_cluster.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/internal/contract/infrastructure_cluster_template.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/internal/contract/infrastructure_machine.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/internal/contract/infrastructure_machine_template.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/internal/contract/infrastructure_machinepool_template.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/internal/contract/metadata.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/internal/contract/references.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/internal/contract/types.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/internal/contract/version.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/aggregate.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/deprecated/v1beta1/doc.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/deprecated/v1beta1/getter.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/deprecated/v1beta1/matcher.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/deprecated/v1beta1/matchers.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/deprecated/v1beta1/merge.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/deprecated/v1beta1/merge_strategies.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/deprecated/v1beta1/patch.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/deprecated/v1beta1/setter.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/deprecated/v1beta1/unstructured.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/doc.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/getter.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/matcher.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/merge_strategies.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/mirror.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/options.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/patch.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/setter.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/sort.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/conditions/summary.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/contract/contract.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/contract/doc.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/labels/helpers.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/predicates/cluster_predicates.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/predicates/generic_predicates.gois excluded by!**/vendor/**,!vendor/**vendor/sigs.k8s.io/cluster-api/util/version/version.gois excluded by!**/vendor/**,!vendor/**
📒 Files selected for processing (87)
.golangci.yml(1 hunks)cmd/cluster-capi-operator/main.go(3 hunks)cmd/machine-api-migration/main.go(2 hunks)e2e/aws_test.go(2 hunks)e2e/azure_test.go(3 hunks)e2e/baremetal_test.go(3 hunks)e2e/e2e_common.go(3 hunks)e2e/framework/cluster.go(3 hunks)e2e/framework/machine.go(6 hunks)e2e/framework/machineset.go(13 hunks)e2e/framework/node.go(1 hunks)e2e/gcp_test.go(3 hunks)e2e/go.mod(1 hunks)e2e/machine_migration_capi_authoritative_test.go(9 hunks)e2e/machine_migration_helpers.go(7 hunks)e2e/machine_migration_mapi_authoritative_test.go(8 hunks)e2e/machineset_migration_capi_authoritative_test.go(8 hunks)e2e/machineset_migration_helpers.go(10 hunks)e2e/machineset_migration_mapi_authoritative_test.go(10 hunks)e2e/migration_common.go(2 hunks)e2e/openstack_test.go(3 hunks)e2e/powervs_test.go(3 hunks)e2e/vsphere_test.go(5 hunks)go.mod(1 hunks)manifests/0000_30_cluster-api_09_admission-policies.yaml(7 hunks)manifests/0000_30_cluster-api_10_webhooks.yaml(1 hunks)pkg/controllers/corecluster/corecluster_controller.go(11 hunks)pkg/controllers/corecluster/corecluster_controller_test.go(6 hunks)pkg/controllers/infracluster/aws.go(2 hunks)pkg/controllers/infracluster/azure.go(3 hunks)pkg/controllers/infracluster/gcp.go(2 hunks)pkg/controllers/infracluster/infracluster_controller.go(2 hunks)pkg/controllers/infracluster/infracluster_controller_test.go(9 hunks)pkg/controllers/infracluster/metal3.go(2 hunks)pkg/controllers/infracluster/powervs.go(2 hunks)pkg/controllers/infracluster/vsphere.go(2 hunks)pkg/controllers/kubeconfig/kubeconfig.go(2 hunks)pkg/controllers/machinemigration/machine_migration_controller.go(8 hunks)pkg/controllers/machinemigration/machine_migration_controller_test.go(12 hunks)pkg/controllers/machinesetmigration/machineset_migration_controller.go(6 hunks)pkg/controllers/machinesetmigration/machineset_migration_controller_test.go(11 hunks)pkg/controllers/machinesetsync/machineset_sync_controller.go(34 hunks)pkg/controllers/machinesetsync/machineset_sync_controller_test.go(15 hunks)pkg/controllers/machinesetsync/machineset_sync_controller_unit_test.go.bak(1 hunks)pkg/controllers/machinesetsync/machineset_vap_test.go(10 hunks)pkg/controllers/machinesync/aws_test.go(4 hunks)pkg/controllers/machinesync/machine_sync_controller.go(34 hunks)pkg/controllers/machinesync/machine_sync_controller_test.go(39 hunks)pkg/controllers/machinesync/machine_sync_controller_unit_test.go(1 hunks)pkg/controllers/machinesync/machine_sync_mapi2capi_infrastructure.go(3 hunks)pkg/conversion/capi2mapi/aws.go(5 hunks)pkg/conversion/capi2mapi/aws_fuzz_test.go(4 hunks)pkg/conversion/capi2mapi/aws_test.go(1 hunks)pkg/conversion/capi2mapi/common.go(4 hunks)pkg/conversion/capi2mapi/machine.go(8 hunks)pkg/conversion/capi2mapi/machine_test.go(4 hunks)pkg/conversion/capi2mapi/machineset.go(4 hunks)pkg/conversion/capi2mapi/machineset_test.go(3 hunks)pkg/conversion/capi2mapi/openstack.go(4 hunks)pkg/conversion/capi2mapi/openstack_fuzz_test.go(4 hunks)pkg/conversion/capi2mapi/openstack_test.go(1 hunks)pkg/conversion/capi2mapi/powervs.go(3 hunks)pkg/conversion/capi2mapi/powervs_fuzz_test.go(4 hunks)pkg/conversion/capi2mapi/powervs_test.go(2 hunks)pkg/conversion/capi2mapi/suite_test.go(2 hunks)pkg/conversion/mapi2capi/aws.go(9 hunks)pkg/conversion/mapi2capi/aws_fuzz_test.go(3 hunks)pkg/conversion/mapi2capi/interface.go(1 hunks)pkg/conversion/mapi2capi/machine.go(15 hunks)pkg/conversion/mapi2capi/machine_test.go(24 hunks)pkg/conversion/mapi2capi/machineset.go(8 hunks)pkg/conversion/mapi2capi/machineset_test.go(9 hunks)pkg/conversion/mapi2capi/openstack.go(8 hunks)pkg/conversion/mapi2capi/openstack_fuzz_test.go(3 hunks)pkg/conversion/mapi2capi/powervs.go(7 hunks)pkg/conversion/mapi2capi/powervs_fuzz_test.go(3 hunks)pkg/conversion/mapi2capi/util.go(6 hunks)pkg/conversion/test/fuzz/fuzz.go(19 hunks)pkg/conversion/test/matchers/capi_condition.go(3 hunks)pkg/conversion/util/util.go(1 hunks)pkg/test/crdbuilder.go(4 hunks)pkg/test/envtest.go(2 hunks)pkg/util/conditions.go(3 hunks)pkg/util/sync.go(8 hunks)pkg/util/sync_test.go(5 hunks)pkg/util/watch_filters.go(2 hunks)pkg/webhook/cluster.go(6 hunks)
🚧 Files skipped from review as they are similar to previous changes (29)
- pkg/controllers/infracluster/metal3.go
- pkg/controllers/infracluster/vsphere.go
- pkg/controllers/machinesync/machine_sync_controller_unit_test.go
- pkg/conversion/capi2mapi/openstack_test.go
- pkg/controllers/infracluster/infracluster_controller.go
- e2e/vsphere_test.go
- pkg/util/watch_filters.go
- pkg/conversion/mapi2capi/util.go
- pkg/controllers/machinesetsync/machineset_sync_controller_unit_test.go.bak
- pkg/controllers/machinesync/machine_sync_mapi2capi_infrastructure.go
- e2e/e2e_common.go
- pkg/conversion/mapi2capi/openstack_fuzz_test.go
- e2e/machineset_migration_capi_authoritative_test.go
- e2e/framework/node.go
- pkg/conversion/mapi2capi/powervs_fuzz_test.go
- cmd/machine-api-migration/main.go
- e2e/azure_test.go
- pkg/conversion/capi2mapi/openstack.go
- pkg/conversion/util/util.go
- .golangci.yml
- go.mod
- e2e/framework/machineset.go
- pkg/controllers/infracluster/azure.go
- pkg/conversion/mapi2capi/interface.go
- e2e/openstack_test.go
- pkg/conversion/capi2mapi/machineset_test.go
- manifests/0000_30_cluster-api_10_webhooks.yaml
- pkg/webhook/cluster.go
- pkg/conversion/test/matchers/capi_condition.go
🧰 Additional context used
🧬 Code graph analysis (26)
pkg/controllers/machinesetmigration/machineset_migration_controller.go (2)
pkg/conversion/mapi2capi/interface.go (1)
MachineSet(29-31)e2e/framework/framework.go (1)
CAPINamespace(14-14)
e2e/aws_test.go (1)
pkg/conversion/mapi2capi/interface.go (1)
MachineSet(29-31)
e2e/machine_migration_helpers.go (2)
pkg/conversion/mapi2capi/interface.go (1)
Machine(24-26)e2e/framework/machine.go (2)
GetMachineWithError(89-102)GetMachine(75-86)
pkg/conversion/mapi2capi/machineset_test.go (1)
pkg/conversion/test/matchers/capi_condition.go (1)
MatchCAPICondition(51-55)
e2e/powervs_test.go (1)
pkg/conversion/mapi2capi/interface.go (1)
MachineSet(29-31)
pkg/conversion/mapi2capi/machineset.go (1)
pkg/conversion/mapi2capi/interface.go (1)
MachineSet(29-31)
e2e/gcp_test.go (1)
pkg/conversion/mapi2capi/interface.go (1)
MachineSet(29-31)
pkg/conversion/mapi2capi/aws_fuzz_test.go (1)
pkg/conversion/mapi2capi/interface.go (2)
Machine(24-26)MachineSet(29-31)
e2e/machine_migration_mapi_authoritative_test.go (1)
pkg/conversion/mapi2capi/interface.go (1)
Machine(24-26)
pkg/controllers/machinemigration/machine_migration_controller.go (4)
pkg/conversion/mapi2capi/interface.go (1)
Machine(24-26)e2e/framework/framework.go (1)
CAPINamespace(14-14)pkg/util/conditions.go (1)
GetConditionStatus(88-99)pkg/util/annotations.go (1)
RemoveAnnotation(27-39)
e2e/framework/cluster.go (1)
e2e/framework/framework.go (1)
CAPINamespace(14-14)
e2e/framework/machine.go (2)
pkg/conversion/mapi2capi/interface.go (1)
Machine(24-26)e2e/framework/framework.go (2)
WaitLong(25-25)RetryMedium(18-18)
pkg/conversion/capi2mapi/openstack_fuzz_test.go (1)
pkg/conversion/test/fuzz/fuzz.go (2)
CAPIMachineFuzzerFuncs(475-546)CAPIMachineSetFuzzerFuncs(549-626)
pkg/controllers/machinesetsync/machineset_vap_test.go (1)
pkg/conversion/mapi2capi/interface.go (2)
MachineSet(29-31)Machine(24-26)
pkg/controllers/machinesync/aws_test.go (1)
pkg/conversion/mapi2capi/interface.go (1)
Machine(24-26)
pkg/controllers/machinesync/machine_sync_controller_test.go (3)
pkg/conversion/mapi2capi/interface.go (2)
Machine(24-26)MachineSet(29-31)e2e/migration_common.go (1)
SynchronizedCondition(10-10)pkg/controllers/common_consts.go (1)
SynchronizedCondition(41-41)
e2e/machineset_migration_mapi_authoritative_test.go (2)
pkg/conversion/mapi2capi/interface.go (1)
MachineSet(29-31)e2e/framework/framework.go (3)
WaitMedium(24-24)RetryShort(17-17)WaitShort(23-23)
pkg/conversion/mapi2capi/machine_test.go (1)
pkg/conversion/test/matchers/capi_condition.go (1)
MatchCAPICondition(51-55)
pkg/conversion/mapi2capi/aws.go (1)
pkg/conversion/mapi2capi/interface.go (2)
Machine(24-26)MachineSet(29-31)
pkg/controllers/machinesync/machine_sync_controller.go (5)
pkg/conversion/mapi2capi/interface.go (1)
Machine(24-26)pkg/controllers/common.go (1)
InitInfraMachineAndInfraClusterFromProvider(41-52)e2e/framework/framework.go (1)
CAPINamespace(14-14)pkg/util/finalizer.go (1)
RemoveFinalizer(60-85)pkg/util/conditions.go (2)
EnsureCAPIDeprecatedV1Beta1Conditions(246-255)EnsureCAPIConditions(258-267)
pkg/controllers/machinesetmigration/machineset_migration_controller_test.go (1)
pkg/conversion/mapi2capi/interface.go (2)
MachineSet(29-31)Machine(24-26)
pkg/conversion/mapi2capi/machine.go (1)
pkg/conversion/mapi2capi/interface.go (1)
Machine(24-26)
pkg/conversion/capi2mapi/aws.go (3)
pkg/conversion/capi2mapi/interface.go (2)
MachineAndInfrastructureMachine(21-23)MachineSetAndMachineTemplate(26-28)pkg/conversion/consts/consts.go (1)
MAPIMachineMetadataLabelZone(26-26)third_party/sigs.k8s.io/cluster-api/util/util.go (1)
IsControlPlaneMachine(25-28)
pkg/conversion/capi2mapi/aws_fuzz_test.go (1)
pkg/conversion/test/fuzz/fuzz.go (2)
CAPIMachineFuzzerFuncs(475-546)CAPIMachineSetFuzzerFuncs(549-626)
pkg/conversion/test/fuzz/fuzz.go (2)
pkg/conversion/mapi2capi/interface.go (2)
Machine(24-26)MachineSet(29-31)pkg/conversion/capi2mapi/interface.go (2)
MachineAndInfrastructureMachine(21-23)MachineSetAndMachineTemplate(26-28)
pkg/controllers/machinesetsync/machineset_sync_controller.go (3)
pkg/conversion/mapi2capi/interface.go (1)
MachineSet(29-31)pkg/util/conditions.go (2)
EnsureCAPIDeprecatedV1Beta1Conditions(246-255)EnsureCAPIConditions(258-267)pkg/util/finalizer.go (1)
RemoveFinalizer(60-85)
pkg/controllers/machinesetmigration/machineset_migration_controller_test.go
Show resolved
Hide resolved
| MinReadySeconds: ptr.Deref(capiMachineSet.Spec.Template.Spec.MinReadySeconds, 0), | ||
| DeletePolicy: string(capiMachineSet.Spec.Deletion.Order), |
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.
Potential nil pointer dereference when accessing Deletion.Order.
If capiMachineSet.Spec.Deletion is nil, accessing Deletion.Order will cause a panic. Consider adding a nil guard or using ptr.Deref pattern similar to the MinReadySeconds handling.
- MinReadySeconds: ptr.Deref(capiMachineSet.Spec.Template.Spec.MinReadySeconds, 0),
- DeletePolicy: string(capiMachineSet.Spec.Deletion.Order),
+ MinReadySeconds: ptr.Deref(capiMachineSet.Spec.Template.Spec.MinReadySeconds, 0),
+ DeletePolicy: getDeletionOrder(capiMachineSet.Spec.Deletion),
Add a helper function:
func getDeletionOrder(deletion *clusterv1.MachineSetDeletionSpec) string {
if deletion == nil {
return ""
}
return string(deletion.Order)
}
🤖 Prompt for AI Agents
In pkg/conversion/capi2mapi/machineset.go around lines 44 to 45, accessing
capiMachineSet.Spec.Deletion.Order can panic if Spec.Deletion is nil; update the
code to guard against nil by adding a helper that returns an empty string when
Deletion is nil (e.g., getDeletionOrder(deletion
*clusterv1.MachineSetDeletionSpec) string) and replace direct access with a call
to that helper so DeletePolicy :=
getDeletionOrder(capiMachineSet.Spec.Deletion).
| gcpv1 "sigs.k8s.io/cluster-api-provider-gcp/api/v1beta1" | ||
| openstackv1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1" | ||
| clusterv1beta1 "sigs.k8s.io/cluster-api/api/core/v1beta1" | ||
| clusterv1 "sigs.k8s.io/cluster-api/api/core/v1beta2" |
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.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# Check for remaining v1beta1 references to ensure migration consistency
echo "=== Checking for remaining v1beta1 imports ==="
rg -n 'cluster-api/api/core/v1beta1' --type=go
echo "=== Checking for clusterv1beta1 alias usage ==="
rg -n '\bclusterv1beta1\b' --type=go
echo "=== Overview of all v1beta imports in the repo ==="
rg -n 'cluster-api/api/core/v1beta' --type=go | head -20
Repository: openshift/cluster-capi-operator
Length of output: 6595
🌐 Web query:
Cluster API v1beta2 release notes breaking changes
💡 Result:
Key breaking changes introduced with the v1beta2 API (and in Cluster API v1.11 series where v1beta2 became storage) — concise summary:
- API/CRD contract changes: fields made required or renamed (e.g., KubeadmControlPlane.rolloutStrategy.type becomes required in v1beta2 causing conversion failures from v1beta1 if omitted). (github.com)
- Status model changes: switch to Kubernetes-aligned metav1.Conditions, removal of FailureReason/FailureMessage, and standardized/changed replica counters and status semantics. (cluster-api.sigs.k8s.io)
- Object reference changes: some fields removed/changed to be GitOps-friendly (API version not overwritten). (cluster-api.sigs.k8s.io)
- Provider/runtime SDK changes: Runtime SDK behavioral changes (e.g., chained upgrade observability and AfterClusterUpgrade hook made blocking) noted as breaking. (github.com)
- Tooling/dependency bumps and operational changes: controller-runtime/controller-tools version bumps and clusterctl behavior changes (e.g., blocking move when Cluster or ClusterClass is paused); CI and other infra changes flagged as breaking. (github.com)
If you want, I can:
- list every CRD/field changed in v1beta2 with example diffs, or
- fetch the full v1.11 (v1beta2) release notes and link each breaking-change PR.
Citations:
- 1: Breaking conversion issues from v1beta1 → v1beta2 in CAPI 1.11 for KubeadmControlPlaneTemplate kubernetes-sigs/cluster-api#12605
- 2: https://cluster-api.sigs.k8s.io/developer/providers/migrations/v1.10-to-v1.11?utm_source=openai
- 3: https://cluster-api.sigs.k8s.io/developer/providers/migrations/v1.10-to-v1.11?utm_source=openai
- 4: https://github.com/kubernetes-sigs/cluster-api/releases?utm_source=openai
- 5: https://github.com/kubernetes-sigs/cluster-api/releases?utm_source=openai
Incomplete cluster-api version migration creates version mismatch between test environment and infrastructure controllers.
The migration from v1beta1 to v1beta2 in pkg/test/envtest.go is mechanically correct, but the codebase migration is incomplete. Infrastructure controllers (pkg/controllers/infracluster/{aws,gcp,azure,openstack,powervs}.go) and other files remain on v1beta1, creating a version mismatch with the v1beta2 test environment. v1beta2 introduces breaking changes to status models (metav1.Conditions, removal of FailureReason/FailureMessage), which could cause compatibility issues. Before merging, complete the migration of all infrastructure controllers to v1beta2 to ensure consistency and avoid contributing to InfraMachine creation failures.
🤖 Prompt for AI Agents
In pkg/test/envtest.go around line 37, the test environment was migrated to
cluster-api v1beta2 but several infrastructure controllers still use v1beta1,
causing a version mismatch; update all infracluster controllers
(pkg/controllers/infracluster/{aws,gcp,azure,openstack,powervs}.go) and any
other files still importing sigs.k8s.io/cluster-api/api/core/v1beta1 to use
sigs.k8s.io/cluster-api/api/core/v1beta2, then adapt code to v1beta2 breaking
changes: replace Usage of FailureReason/FailureMessage with metav1.Conditions
for status, update status types and getters/setters, adjust any helper functions
and RBAC/CRD references accordingly, run go mod tidy to update deps and run
unit/integration tests to confirm InfraMachine creation and controller behaviors
are consistent with v1beta2.
e00163b to
8c6f770
Compare
|
/retest |
8c6f770 to
b30800f
Compare
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
📜 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)
pkg/controllers/machinesync/machine_sync_controller.gopkg/controllers/machinesync/machine_sync_controller_test.gopkg/controllers/machinesync/machine_sync_controller_unit_test.go
🧰 Additional context used
🧬 Code graph analysis (3)
pkg/controllers/machinesync/machine_sync_controller_test.go (2)
e2e/migration_common.go (1)
SynchronizedCondition(10-10)pkg/controllers/common_consts.go (1)
SynchronizedCondition(41-41)
pkg/controllers/machinesync/machine_sync_controller_unit_test.go (2)
pkg/controllers/machinesync/machine_sync_controller.go (1)
MachineSyncReconciler(136-145)pkg/conversion/mapi2capi/interface.go (1)
Machine(24-26)
pkg/controllers/machinesync/machine_sync_controller.go (2)
pkg/controllers/common.go (1)
InitInfraMachineAndInfraClusterFromProvider(41-52)e2e/framework/framework.go (1)
CAPINamespace(14-14)
🔇 Additional comments (6)
pkg/controllers/machinesync/machine_sync_controller.go (5)
254-258: LGTM: Infrastructure existence check.The existence check is well-placed before routing reconciliation paths. Error handling is appropriate and the comment clearly explains the intent.
997-1038: LGTM: Refactored infra resource fetching with proper delegation.The refactoring cleanly separates infraMachine retrieval into a dedicated helper while maintaining proper error handling. The terminal configuration error checks ensure user intervention is required for misconfigured resources.
1040-1058: LGTM: Clean helper for fetching infra machines.The helper properly handles the NotFound case by returning
nilfor the infraMachine while propagating other errors. This allows calling code to distinguish between "not found" (nil) and "error retrieving" scenarios.
1060-1076: LGTM: Existence check with sensible fallback.The helper properly handles the nil
capiMachinecase by falling back to the MAPI machine's name. This allows the existence check to work in scenarios where the CAPI machine hasn't been created yet.
266-271: The timestamp check is correctly designed and serves the authoritativeAPI contract.The condition at line 269 is a guard, not a blocker for all scenarios. The control flow has two distinct paths:
When CAPI Machine doesn't exist (
capiMachineNotFound == true): The timestamp check is bypassed entirely—MAPI can create CAPI infrastructure without restriction.When CAPI Machine exists (
!capiMachineNotFound): The timestamp check prevents MAPI (created after CAPI) from creating CAPI infrastructure. Instead, the code delegates toreconcileCAPIMachinetoMAPIMachine, which syncs from the authoritative CAPI Machine to MAPI.This design correctly enforces the
authoritativeAPI: ClusterAPIcontract: a MAPI Machine created after an existing CAPI Machine should not attempt to create infrastructure, since the CAPI Machine is the source of truth and should already have its infrastructure provisioned. The timestamp gate prevents duplicate or conflicting infrastructure creation when MAPI is created as a mirror of existing CAPI resources.The scenario described in the review comment—CAPI created first, then MAPI created later with
authoritativeAPI: ClusterAPI—is intentionally prevented from triggering InfraMachine creation through the MAPI path. This is the correct behavior.pkg/controllers/machinesync/machine_sync_controller_unit_test.go (1)
30-118: LGTM: Comprehensive unit tests for infra resource fetching.The test cases properly cover all scenarios:
- Nil machine input → no resources returned
- Missing cluster → error with appropriate message
- Missing infra machine → cluster returned, machine nil
- All present → both returned
The tests use appropriate fake clients and validate both success and error paths.
| It("should create the Cluster API InfraMachine", func() { | ||
| Eventually(k.Object(mapiMachine), timeout).Should( | ||
| HaveField("Status.Conditions", ContainElement( | ||
| SatisfyAll( | ||
| HaveField("Type", Equal(consts.SynchronizedCondition)), | ||
| HaveField("Status", Equal(corev1.ConditionFalse)), | ||
| HaveField("Reason", Equal("FailedToConvertCAPIMachineToMAPI")), | ||
| HaveField("Message", ContainSubstring("unexpected InfraMachine type, expected AWSMachine, got <nil>")), | ||
| HaveField("Status", Equal(corev1.ConditionTrue)), | ||
| HaveField("Reason", Equal("ResourceSynchronized")), | ||
| HaveField("Message", ContainSubstring("Successfully synchronized CAPI Machine to MAPI")), | ||
| ))), | ||
| ) | ||
|
|
||
| capiInfraMachine := awsv1resourcebuilder.AWSMachine().WithName(mapiMachine.Name).WithNamespace(capiNamespace.Name).Build() | ||
| Eventually(k.Get(capiInfraMachine), timeout).Should(Succeed()) | ||
| }) |
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.
Verify the synchronization message direction.
The test expects the message to contain "Successfully synchronized CAPI Machine to MAPI" (line 999), but the context is "when the MAPI machine has MachineAuthority set to Cluster API" with a missing InfraMachine. According to the controller code at line 270 in machine_sync_controller.go, this scenario calls reconcileMAPIMachinetoCAPIMachine, which should set the message to messageSuccessfullySynchronizedMAPItoCAPI (line 608: "Successfully synchronized MAPI Machine to CAPI").
The test assertion should expect "MAPI Machine to CAPI" not "CAPI Machine to MAPI".
🔎 Proposed fix
It("should create the Cluster API InfraMachine", func() {
Eventually(k.Object(mapiMachine), timeout).Should(
HaveField("Status.Conditions", ContainElement(
SatisfyAll(
HaveField("Type", Equal(consts.SynchronizedCondition)),
HaveField("Status", Equal(corev1.ConditionTrue)),
HaveField("Reason", Equal("ResourceSynchronized")),
- HaveField("Message", ContainSubstring("Successfully synchronized CAPI Machine to MAPI")),
+ HaveField("Message", Equal("Successfully synchronized MAPI Machine to CAPI")),
))),
)
capiInfraMachine := awsv1resourcebuilder.AWSMachine().WithName(mapiMachine.Name).WithNamespace(capiNamespace.Name).Build()
Eventually(k.Get(capiInfraMachine), timeout).Should(Succeed())
})
🤖 Prompt for AI Agents
In pkg/controllers/machinesync/machine_sync_controller_test.go around lines 992
to 1005, the test asserts the wrong synchronization message direction; update
the expected message substring from "Successfully synchronized CAPI Machine to
MAPI" to "Successfully synchronized MAPI Machine to CAPI" so the assertion
matches the controller path reconcileMAPIMachinetoCAPIMachine and the
messageSuccessfullySynchronizedMAPItoCAPI constant; leave the rest of the
assertion intact and run tests to verify.
|
/pipeline required |
|
Scheduling tests matching the |
|
@chrischdi: The following tests failed, say
Full PR test history. Your PR dashboard. DetailsInstructions 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. |
b30800f to
8f1feea
Compare
|
@chrischdi: This pull request references Jira Issue OCPBUGS-63411, which is invalid:
Comment DetailsIn 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. |
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
♻️ Duplicate comments (1)
pkg/controllers/machinesync/machine_sync_controller.go (1)
266-271: Timestamp gate blocks intended InfraMachine creation flow.The condition
!mapiMachine.CreationTimestamp.After(capiMachine.CreationTimestamp.Time)prevents InfraMachine creation when the MAPI Machine is created after the CAPI Machine. This matches the QA failure where creating a CAPI Machine first, then a MAPI Machine withauthoritativeAPI: ClusterAPI, results in no InfraMachine being created.Per the PR objective (scenario 1: "creating a MAPI Machine with CAPI authoritative should produce a CAPI Machine and an InfraMachine from the MAPI Machine"), consider removing the timestamp comparison:
Suggested fix
- // Create Cluster API Infrastructure Machine from MAPI if it doesn't exist and no deletion is in progress. - // the CAPI machine is not marked for deletion and the MAPI machine was created before the Cluster API machine. - if capiMachine.DeletionTimestamp.IsZero() && mapiMachine.DeletionTimestamp.IsZero() && - !capiInfraMachineExists && !mapiMachine.CreationTimestamp.After(capiMachine.CreationTimestamp.Time) { + // Create Cluster API Infrastructure Machine from MAPI if it doesn't exist and no deletion is in progress. + if capiMachine.DeletionTimestamp.IsZero() && mapiMachine.DeletionTimestamp.IsZero() && + !capiInfraMachineExists { return r.reconcileMAPIMachinetoCAPIMachine(ctx, mapiMachine, capiMachine) }
🧹 Nitpick comments (1)
pkg/controllers/machinesync/machine_sync_controller.go (1)
1040-1058: Consider avoiding duplicateInitInfraMachineAndInfraClusterFromProvidercalls.When
fetchCAPIInfraResourcescallsfetchCAPIInfraMachine(line 1032),InitInfraMachineAndInfraClusterFromProvideris invoked twice: once at line 1023 and again at line 1041. While not incorrect, passing the already-initializedinfraMachinetype or extracting the initialization could reduce redundancy.Optional refactor
func (r *MachineSyncReconciler) fetchCAPIInfraResources(ctx context.Context, capiMachine *clusterv1.Machine) (client.Object, client.Object, error) { if capiMachine == nil { return nil, nil, nil } - var infraCluster client.Object + infraMachine, infraCluster, err := controllers.InitInfraMachineAndInfraClusterFromProvider(r.Platform) + if err != nil { + return nil, nil, fmt.Errorf("unable to devise Cluster API infra resources: %w", err) + } infraClusterKey := client.ObjectKey{ Namespace: capiMachine.Namespace, Name: capiMachine.Spec.ClusterName, } infraMachineRef := capiMachine.Spec.InfrastructureRef // Validate that required references are not empty... if capiMachine.Spec.ClusterName == "" { return nil, nil, fmt.Errorf("machine %s/%s: %w", capiMachine.Namespace, capiMachine.Name, errInvalidInfraClusterReference) } if infraMachineRef.Name == "" { return nil, nil, fmt.Errorf("machine %s/%s: %w", capiMachine.Namespace, capiMachine.Name, errInvalidInfraMachineReference) } - _, infraCluster, err := controllers.InitInfraMachineAndInfraClusterFromProvider(r.Platform) - if err != nil { - return nil, nil, fmt.Errorf("unable to devise Cluster API infra resources: %w", err) - } if err := r.Get(ctx, infraClusterKey, infraCluster); err != nil { return nil, nil, fmt.Errorf("failed to get Cluster API infrastructure cluster: %w", err) } - infraMachine, err := r.fetchCAPIInfraMachine(ctx, infraMachineRef.Name, capiMachine.Namespace) - if err != nil { - return nil, nil, fmt.Errorf("failed to fetch Cluster API infrastructure machine: %w", err) + infraMachineKey := client.ObjectKey{ + Namespace: capiMachine.Namespace, + Name: infraMachineRef.Name, } + if err := r.Get(ctx, infraMachineKey, infraMachine); err != nil && !apierrors.IsNotFound(err) { + return nil, nil, fmt.Errorf("failed to get Cluster API infrastructure machine: %w", err) + } else if apierrors.IsNotFound(err) { + infraMachine = nil + } + return infraCluster, infraMachine, nil }
📜 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)
pkg/controllers/machinesync/machine_sync_controller.gopkg/controllers/machinesync/machine_sync_controller_test.gopkg/controllers/machinesync/machine_sync_controller_unit_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
- pkg/controllers/machinesync/machine_sync_controller_test.go
- pkg/controllers/machinesync/machine_sync_controller_unit_test.go
🧰 Additional context used
🧬 Code graph analysis (1)
pkg/controllers/machinesync/machine_sync_controller.go (2)
pkg/controllers/common.go (1)
InitInfraMachineAndInfraClusterFromProvider(41-52)e2e/framework/framework.go (1)
CAPINamespace(14-14)
🔇 Additional comments (2)
pkg/controllers/machinesync/machine_sync_controller.go (2)
254-258: LGTM on the existence check.The existence check is properly placed after confirming
mapiMachineis not nil, anddoesCAPIInfraMachineExistcorrectly handles nilcapiMachineby falling back tomapiMachine.Name.
1002-1037: Clean refactoring of infrastructure resource fetching.The separation of
fetchCAPIInfraMachinefromfetchCAPIInfraResourcesimproves modularity. The return order (infraCluster, infraMachine) is consistent with call sites at lines 305 and 440.
✏️ Tip: You can disable this entire section by setting review_details to false in your review settings.
| // doesCAPIInfraMachineExist checks if the Cluster API Infrastructure Machine exists. It uses the infrastructureRef of the Cluster API Machine with fallback to the name of the MAPI Machine. | ||
| func (r *MachineSyncReconciler) doesCAPIInfraMachineExist(ctx context.Context, capiMachine *clusterv1.Machine, mapiMachine *mapiv1beta1.Machine) (bool, error) { | ||
| namespace := r.CAPINamespace | ||
| name := mapiMachine.Name | ||
|
|
||
| if capiMachine != nil { | ||
| name = capiMachine.Spec.InfrastructureRef.Name | ||
| namespace = capiMachine.Namespace | ||
| } | ||
|
|
||
| infraMachine, err := r.fetchCAPIInfraMachine(ctx, name, namespace) | ||
| if err != nil { | ||
| return false, fmt.Errorf("checking existence: %w", err) | ||
| } | ||
|
|
||
| return infraMachine != nil, nil | ||
| } |
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.
Consider validating InfrastructureRef.Name when capiMachine is not nil.
When capiMachine is not nil but capiMachine.Spec.InfrastructureRef.Name is empty, the method will search for an infra machine with an empty name, which could return misleading results. Consider adding validation or falling back to mapiMachine.Name:
Suggested fix
func (r *MachineSyncReconciler) doesCAPIInfraMachineExist(ctx context.Context, capiMachine *clusterv1.Machine, mapiMachine *mapiv1beta1.Machine) (bool, error) {
namespace := r.CAPINamespace
name := mapiMachine.Name
- if capiMachine != nil {
+ if capiMachine != nil && capiMachine.Spec.InfrastructureRef.Name != "" {
name = capiMachine.Spec.InfrastructureRef.Name
namespace = capiMachine.Namespace
}
infraMachine, err := r.fetchCAPIInfraMachine(ctx, name, namespace)
if err != nil {
return false, fmt.Errorf("checking existence: %w", err)
}
return infraMachine != nil, nil
}
Summary by CodeRabbit
Bug Fixes
Tests
✏️ Tip: You can customize this high-level summary in your review settings.