OCPCLOUD-2998: implement synchronizedAPI#376
Conversation
|
Skipping CI for Draft Pull Request. |
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
WalkthroughThis PR refactors Machine API ↔ Cluster API migration orchestration by introducing a shared ChangesMachine API Migration Refactor with SynchronizedAPI Tracking
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Suggested labels
Suggested reviewers
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
57b06ba to
6bcba96
Compare
|
@RadekManak: This pull request references OCPCLOUD-2998 which is a valid jira issue. Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.21.0" version, but no target version was set. 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. |
6bcba96 to
4af6d4e
Compare
|
@RadekManak: This pull request references OCPCLOUD-2998 which is a valid jira issue. Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.21.0" version, but no target version was set. 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. |
4af6d4e to
f00ae34
Compare
f00ae34 to
7488790
Compare
|
@RadekManak: This pull request references OCPCLOUD-2998 which is a valid jira issue. Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.21.0" version, but no target version was set. 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. |
|
@RadekManak: This pull request references OCPCLOUD-2998 which is a valid jira issue. Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.21.0" version, but no target version was set. 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.
Actionable comments posted: 0
🧹 Nitpick comments (3)
e2e/machine_migration_mapi_authoritative_test.go (1)
207-287: Excellent rollback test coverage!The new "Machine Migration Rollback Tests" comprehensively test the cancellation workflow:
- Initial state verification
- Rollback from Migrating state back to MachineAPI
- Successful migration after a previous rollback
- Cleanup verification
One structural note: This
Describeblock is nested inside the "Machine Migration Round Trip Tests"Describe(line 136). While Ginkgo supports this, it may be cleaner to place this as a siblingDescribeblock rather than a child, for better test organization. However, this is a minor style preference and doesn't affect test execution.Consider moving this
Describeblock to be a sibling of "Machine Migration Round Trip Tests" rather than nested inside it:- var _ = Describe("Machine Migration Round Trip Tests", Ordered, func() { - // ... existing round trip tests ... - - var _ = Describe("Machine Migration Rollback Tests", Ordered, func() { + var _ = Describe("Machine Migration Round Trip Tests", Ordered, func() { + // ... existing round trip tests ... + }) + + var _ = Describe("Machine Migration Rollback Tests", Ordered, func() {pkg/controllers/synccommon/migratestatus.go (1)
129-142: Consider handling unknown authority values explicitly.The function correctly maps
MachineAPIandClusterAPIto their synchronized counterparts and returns empty string forMigrating. However, the default case silently returns empty string for any unknown values.Consider whether logging a warning for unknown values would aid debugging, or if the empty string fallback is intentional for forward compatibility.
case mapiv1beta1.MachineAuthorityMigrating: return "" default: + // Unknown authority values return empty string. + // This provides forward compatibility if new authority values are added. return "" }pkg/controllers/machinemigration/machine_migration_controller.go (1)
230-277: Consider extracting shared initialization logic to reduce duplication.The
handleMigrationStatusInitializationfunction is identical to the one inMachineSetMigrationReconciler. While the duplication is understandable given the different resource types and apply configurations, consider whether a shared helper could be created insynccommonpackage using generics, similar to the existingApplyMigrationStatuspattern.This is a minor refactor suggestion for future maintainability - not blocking.
📜 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 (83)
e2e/go.sumis excluded by!**/*.sumgo.sumis excluded by!**/*.sumvendor/github.com/openshift/api/config/v1/register.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/config/v1/types_infrastructure.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/config/v1/types_insights.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/config/v1/types_node.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/config/v1/types_scheduling.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_00_cluster-version-operator_01_clusterversions-Default.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_images-Default.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_images-DevPreviewNoUpgrade.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_images-TechPreviewNoUpgrade.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_images.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-CustomNoUpgrade.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-DevPreviewNoUpgrade.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_infrastructures-TechPreviewNoUpgrade.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_insightsdatagathers-CustomNoUpgrade.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_insightsdatagathers-DevPreviewNoUpgrade.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_insightsdatagathers-TechPreviewNoUpgrade.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_schedulers-Hypershift.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_schedulers-SelfManagedHA-CustomNoUpgrade.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_schedulers-SelfManagedHA-Default.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_schedulers-SelfManagedHA-DevPreviewNoUpgrade.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/config/v1/zz_generated.crd-manifests/0000_10_config-operator_01_schedulers-SelfManagedHA-TechPreviewNoUpgrade.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/config/v1/zz_generated.deepcopy.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/config/v1/zz_generated.featuregated-crd-manifests.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/config/v1/zz_generated.swagger_doc_generated.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/config/v1alpha1/types_cluster_monitoring.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/config/v1alpha1/zz_generated.featuregated-crd-manifests.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/console/v1/types.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/console/v1/zz_generated.swagger_doc_generated.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/features.mdis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/features/features.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/machine/v1beta1/types_awsprovider.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/machine/v1beta1/types_machine.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/machine/v1beta1/types_machineset.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/machine/v1beta1/zz_generated.crd-manifests/0000_10_machine-api_01_machines-CustomNoUpgrade.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/machine/v1beta1/zz_generated.crd-manifests/0000_10_machine-api_01_machines-DevPreviewNoUpgrade.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/machine/v1beta1/zz_generated.crd-manifests/0000_10_machine-api_01_machines-TechPreviewNoUpgrade.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/machine/v1beta1/zz_generated.crd-manifests/0000_10_machine-api_01_machinesets-CustomNoUpgrade.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/machine/v1beta1/zz_generated.crd-manifests/0000_10_machine-api_01_machinesets-DevPreviewNoUpgrade.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/machine/v1beta1/zz_generated.crd-manifests/0000_10_machine-api_01_machinesets-TechPreviewNoUpgrade.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/machine/v1beta1/zz_generated.deepcopy.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/machine/v1beta1/zz_generated.swagger_doc_generated.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/openapi/generated_openapi/zz_generated.openapi.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/operator/v1/types_ingress.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/operator/v1/zz_generated.crd-manifests/0000_50_ingress_00_ingresscontrollers.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/operator/v1/zz_generated.deepcopy.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/operator/v1/zz_generated.swagger_doc_generated.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/awsplatformstatus.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/azureplatformstatus.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/baremetalplatformstatus.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/custom.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/gatherconfig.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/gathererconfig.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/gatherers.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/gcpplatformstatus.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/gcpserviceendpoint.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/insightsdatagather.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/insightsdatagatherspec.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/nutanixplatformstatus.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/openstackplatformstatus.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/ovirtplatformstatus.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/persistentvolumeclaimreference.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/persistentvolumeconfig.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/storage.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/config/applyconfigurations/config/v1/vsphereplatformstatus.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/config/applyconfigurations/internal/internal.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/config/clientset/versioned/typed/config/v1/config_client.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/config/clientset/versioned/typed/config/v1/generated_expansion.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/config/clientset/versioned/typed/config/v1/insightsdatagather.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/config/informers/externalversions/config/v1/insightsdatagather.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/config/informers/externalversions/config/v1/interface.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/config/informers/externalversions/generic.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/config/listers/config/v1/expansion_generated.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/config/listers/config/v1/insightsdatagather.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/machine/applyconfigurations/machine/v1beta1/machinesetstatus.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/machine/applyconfigurations/machine/v1beta1/machinestatus.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/operator/applyconfigurations/internal/internal.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/operator/applyconfigurations/operator/v1/ingresscontrollerspec.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/operator/applyconfigurations/operator/v1/ingresscontrollertuningoptions.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/cluster-api-actuator-pkg/testutils/resourcebuilder/machine/v1beta1/machine.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/cluster-api-actuator-pkg/testutils/resourcebuilder/machine/v1beta1/machineset.gois excluded by!**/vendor/**,!vendor/**vendor/modules.txtis excluded by!**/vendor/**,!vendor/**
📒 Files selected for processing (19)
e2e/go.mod(1 hunks)e2e/machine_migration_capi_authoritative_test.go(3 hunks)e2e/machine_migration_helpers.go(2 hunks)e2e/machine_migration_mapi_authoritative_test.go(4 hunks)e2e/machineset_migration_capi_authoritative_test.go(2 hunks)e2e/machineset_migration_helpers.go(1 hunks)e2e/machineset_migration_mapi_authoritative_test.go(3 hunks)go.mod(2 hunks)pkg/controllers/machinemigration/machine_migration_controller.go(4 hunks)pkg/controllers/machinemigration/machine_migration_controller_test.go(16 hunks)pkg/controllers/machinesetmigration/machineset_migration_controller.go(4 hunks)pkg/controllers/machinesetmigration/machineset_migration_controller_test.go(16 hunks)pkg/controllers/machinesetsync/machineset_sync_controller.go(1 hunks)pkg/controllers/machinesync/machine_sync_controller.go(1 hunks)pkg/controllers/synccommon/applyconfiguration.go(1 hunks)pkg/controllers/synccommon/migratestatus.go(2 hunks)pkg/controllers/synccommon/migratestatus_test.go(1 hunks)pkg/controllers/synccommon/suite_test.go(1 hunks)pkg/conversion/test/fuzz/fuzz.go(2 hunks)
🧰 Additional context used
🧬 Code graph analysis (7)
pkg/controllers/synccommon/migratestatus_test.go (1)
pkg/controllers/synccommon/migratestatus.go (1)
IsMigrationCancellationRequested(121-127)
pkg/controllers/machinesetmigration/machineset_migration_controller_test.go (2)
e2e/migration_common.go (1)
SynchronizedCondition(10-10)pkg/controllers/common_consts.go (1)
SynchronizedCondition(41-41)
e2e/machine_migration_mapi_authoritative_test.go (3)
pkg/conversion/mapi2capi/interface.go (1)
Machine(24-26)e2e/framework/machine.go (2)
GetMachine(75-86)DeleteMachines(89-119)e2e/framework/framework.go (1)
CAPINamespace(14-14)
pkg/controllers/machinemigration/machine_migration_controller.go (1)
pkg/controllers/synccommon/migratestatus.go (4)
IsMigrationCancellationRequested(121-127)AuthoritativeAPIToSynchronizedAPI(131-142)ApplyMigrationStatus(63-79)ApplyMigrationStatusAndResetSyncStatus(42-60)
e2e/machine_migration_helpers.go (1)
e2e/framework/framework.go (2)
WaitMedium(24-24)RetryMedium(18-18)
pkg/controllers/machinesetmigration/machineset_migration_controller.go (2)
pkg/controllers/synccommon/migratestatus.go (4)
IsMigrationCancellationRequested(121-127)ApplyMigrationStatus(63-79)AuthoritativeAPIToSynchronizedAPI(131-142)ApplyMigrationStatusAndResetSyncStatus(42-60)pkg/conversion/mapi2capi/interface.go (1)
MachineSet(29-31)
e2e/machineset_migration_helpers.go (2)
pkg/conversion/mapi2capi/interface.go (1)
MachineSet(29-31)e2e/framework/framework.go (2)
WaitMedium(24-24)RetryMedium(18-18)
🔇 Additional comments (58)
pkg/conversion/test/fuzz/fuzz.go (2)
736-736: LGTM! Correct handling of MAPI-only field in roundtrip testing.The change properly clears the
SynchronizedAPIfield during fuzzing to ensure roundtrip conversion tests pass, since this field has no CAPI equivalent and would be lost during MAPI→CAPI→MAPI conversion. The implementation follows the established pattern for other MAPI-only fields likeAuthoritativeAPIandSynchronizedGeneration.
783-783: LGTM! Consistent handling across MachineSet fuzzing.The change correctly clears the
SynchronizedAPIfield for MachineSet status, mirroring the implementation for Machine status (line 736). This ensures consistent behavior across both resource types during roundtrip conversion testing.e2e/go.mod (1)
19-19: LGTM! Dependency version aligned with root module.The openshift/api version is correctly aligned with the root go.mod (line 26), ensuring consistency across the e2e test module and main module.
pkg/controllers/synccommon/applyconfiguration.go (1)
44-44: LGTM! Interface extension follows established pattern.The new
WithSynchronizedAPImethod follows the same design pattern as the existing interface methods (WithConditions,WithSynchronizedGeneration,WithAuthoritativeAPI), maintaining consistency in the fluent API design.pkg/controllers/machinesync/machine_sync_controller.go (1)
1547-1547: LGTM! Proper status field preservation.The SynchronizedAPI field is correctly preserved from the existing machine status, following the same pattern as AuthoritativeAPI (line 1545) and SynchronizedGeneration (line 1546). This ensures the synchronization state is maintained during status updates.
pkg/controllers/synccommon/migratestatus_test.go (1)
26-74: LGTM! Comprehensive test coverage for migration cancellation logic.The test table covers all the key scenarios for detecting migration cancellation:
- Both directions of cancellation (ClusterAPI → MachineAPI and vice versa)
- In-progress migrations that should NOT trigger cancellation
- Pre-migration states that should NOT trigger cancellation
The test structure follows Ginkgo best practices with descriptive entry names and clear expectations.
pkg/controllers/synccommon/suite_test.go (1)
26-29: LGTM! Standard test suite setup.The test suite follows the standard Ginkgo/Gomega pattern for test registration, correctly setting up the fail handler and naming the suite "SyncCommon Suite".
e2e/machineset_migration_helpers.go (1)
221-228: LGTM! Helper function follows established patterns.The new
verifyMachineSetSynchronizedAPIhelper is well-designed:
- Mirrors the structure of
verifyMachineSetAuthoritative(lines 95-101)- Uses appropriate timeouts (WaitMedium, RetryMedium) consistent with similar assertions in the file
- Provides clear assertion messages for test failures
e2e/machineset_migration_capi_authoritative_test.go (2)
169-169: LGTM! Appropriate synchronization verification after authority switch.The addition of
verifyMachineSetSynchronizedAPIcorrectly validates that after switching the MachineSet authority to MachineAPI (line 165), the synchronization status reflectsMachineAPISynchronized. This aligns with the PR's objective of tracking the last successfully synchronized API.
208-208: LGTM! Complete test coverage for bidirectional migration.The verification at line 208 properly validates the synchronization state after switching back to ClusterAPI authority (line 204), ensuring
ClusterAPISynchronizedis set. Together with the verification at line 169, this provides complete coverage for both migration directions.go.mod (1)
5-11: Ensure temporary replace directives are tracked for removal.The TODO comment and temporary replace directives in go.mod (lines 5-11) reference changes that should be reverted when companion PRs are merged. Verify that removal of these replacements is tracked via linked GitHub issues, PR dependencies, or a dedicated tracking mechanism beyond the inline TODO comment, to ensure they don't persist longer than necessary. Consider updating the TODO with specific issue numbers or PR links if not already linked.
e2e/machine_migration_helpers.go (2)
163-171: LGTM! Well-structured helper function.The
verifyMachineMigratinghelper correctly usesSatisfyAllto verify both the Migrating state and the expected SynchronizedAPI value in a single assertion, following the established patterns in this file.
337-345: LGTM! Consistent implementation.The
verifyMachineSynchronizedAPIhelper follows the same pattern asverifyMachineAuthoritativeand other verification helpers in the file, usingEventuallywithkomega.Objectand appropriate timeouts.e2e/machine_migration_capi_authoritative_test.go (3)
201-201: LGTM! Appropriate verification placement.Adding
verifyMachineSynchronizedAPIafterverifyMachineSynchronizedGenerationprovides complete coverage of the synchronization state, ensuring both generation and API are correctly tracked.
213-213: LGTM!Correctly verifies
MachineAPISynchronizedafter switching authority to MachineAPI.
225-225: LGTM!Correctly verifies
ClusterAPISynchronizedafter switching back to ClusterAPI.pkg/controllers/machinesetsync/machineset_sync_controller.go (1)
1101-1104: LGTM! Correct status field preservation.Preserving
SynchronizedAPIalongsideSynchronizedGenerationandAuthoritativeAPIensures consistency during CAPI-to-MAPI synchronization, with these fields being managed separately viaapplySynchronizedConditionWithPatch.e2e/machineset_migration_mapi_authoritative_test.go (3)
169-170: LGTM! Comprehensive verification added.Adding both
verifyMachineSetAuthoritativeandverifyMachineSetSynchronizedAPIensures complete state verification after the authority switch.
209-210: LGTM!Correctly verifies MachineAPI authority and
MachineAPISynchronizedafter switching back.
338-339: LGTM!Consistent verification pattern for the update context after switching to ClusterAPI.
pkg/controllers/machinemigration/machine_migration_controller_test.go (5)
20-20: LGTM! Good addition for debugging.Adding
cmppackage enables clearer diff output in test failure messages, improving debugging experience.
220-226: Good improvement to test assertions.Using
cmp.Diffin the failure message provides detailed comparison output when the test fails, making it easier to identify unexpected changes to the machine object.
777-903: Comprehensive migration cancellation test coverage.The three cancellation contexts cover the essential scenarios:
- Cancelling back to MachineAPI
- Cancelling back to ClusterAPI
- Cancelling back to ClusterAPI with paused CAPI resources (verifying unpause behavior)
The tests correctly simulate stuck migration states and verify proper status transitions.
905-937: Good edge case coverage for status initialization.This test verifies the
handleMigrationStatusInitializationlogic whereSynchronizedAPIis empty butAuthoritativeAPIis set, ensuring backward compatibility and proper bootstrapping.
939-977: Important test for SynchronizedAPI preservation.This test verifies that when transitioning from a stable state (ClusterAPI) to Migrating, the
SynchronizedAPIis preserved to enable rollback detection. This is critical for the cancellation mechanism to work correctly.e2e/machine_migration_mapi_authoritative_test.go (3)
166-166: LGTM!Correctly verifies
MachineAPISynchronizedafter initial synchronization.
178-178: LGTM!Correctly verifies
ClusterAPISynchronizedafter switching to ClusterAPI.
190-190: LGTM!Correctly verifies
MachineAPISynchronizedafter switching back to MachineAPI.pkg/controllers/machinesetmigration/machineset_migration_controller_test.go (17)
200-211: LGTM - Test setup properly initializes SynchronizedAPI.The test correctly sets both
AuthoritativeAPIandSynchronizedAPItoMachineAPIin the status, matching the expected synchronized state for this scenario.
247-249: LGTM - SynchronizedAPI initialization added to migration request test.Correctly sets
SynchronizedAPItoMachineAPISynchronizedwhen starting a migration from MachineAPI to ClusterAPI.
288-290: LGTM - Proper SynchronizedAPI tracking during MachineAPI→ClusterAPI migration.Test correctly maintains
MachineAPISynchronizedas the synchronized state while inMigratingstatus.
323-330: LGTM - ClusterAPI→MachineAPI migration uses correct synchronized state.Test properly uses
WithSynchronizedAPIStatus(mapiv1beta1.ClusterAPISynchronized)and sets it on the status, reflecting that ClusterAPI was the last synchronized source.
374-391: LGTM - Synchronized state properly tracked during pausing phase.Test correctly sets
SynchronizedAPItoMachineAPISynchronizedwhen testing the pausing flow during MachineAPI→ClusterAPI migration.
430-438: LGTM - ClusterAPI→MachineAPI pause flow correctly sets synchronized state.Test properly uses
ClusterAPISynchronizedas the synchronized state when migrating from ClusterAPI to MachineAPI.
496-506: LGTM - Synchronized state properly set for generation mismatch test.Test correctly uses
MachineAPISynchronizedwhen testing the scenario wheresynchronizedGenerationdoesn't match.
537-547: LGTM - ClusterAPI generation mismatch test properly configured.Test correctly sets
ClusterAPISynchronizedfor the ClusterAPI→MachineAPI generation mismatch scenario.
579-597: LGTM - Complete migration prerequisites test properly configured.Test correctly sets
MachineAPISynchronizedfor the MachineAPI→ClusterAPI completion scenario with all prerequisites satisfied.
630-634: Verify assertion uses correct SynchronizedAPI value after migration completion.The test asserts
SynchronizedAPIequalsClusterAPISynchronizedafter migration completes from MachineAPI to ClusterAPI. This is correct since the new authority (ClusterAPI) should also be the new synchronized state.
660-678: LGTM - ClusterAPI→MachineAPI completion test properly configured.Test correctly sets
ClusterAPISynchronizedas the starting synchronized state for migration from ClusterAPI to MachineAPI.
702-707: LGTM - Correct assertion for ClusterAPI→MachineAPI migration completion.Test properly asserts
MachineAPISynchronizedas the final synchronized state after completing migration to MachineAPI.
711-742: LGTM - Migration cancellation back to MachineAPI test is well-structured.The test correctly simulates a stuck migration (status
Migrating, synchronized toMachineAPI) and verifies that whenspec.AuthoritativeAPImatches the synchronized state, the controller detects cancellation and transitions back.
745-776: LGTM - Migration cancellation back to ClusterAPI test is comprehensive.Test properly verifies rollback to ClusterAPI when
spec.AuthoritativeAPIequalsClusterAPIandSynchronizedAPIisClusterAPISynchronized.
778-820: LGTM - Migration cancellation with paused CAPI resource is well-tested.Test verifies that when cancelling back to ClusterAPI, the paused CAPI resource gets unpaused. This is important for ensuring the rollback target becomes operational.
823-853: LGTM - Empty SynchronizedAPI initialization test covers important edge case.Test verifies that when
AuthoritativeAPIis set butSynchronizedAPIis empty, the reconciler initializesSynchronizedAPIfromAuthoritativeAPI. This handles upgrade scenarios from older versions.
855-891: LGTM - Transition to Migrating preserves SynchronizedAPI correctly.Test verifies that when transitioning from a stable state (ClusterAPI) to
Migrating, theSynchronizedAPIis preserved asClusterAPISynchronized. This is essential for enabling future cancellation/rollback.pkg/controllers/synccommon/migratestatus.go (4)
33-60: LGTM - ApplyMigrationStatusAndResetSyncStatus correctly extended to include SynchronizedAPI.The function now atomically sets both
AuthoritativeAPIandSynchronizedAPIwhile resetting sync status. The call tostatusAC.WithSynchronizedAPI(synchronizedAPI)at line 57 ensures the synchronized state is properly included in the patch.
62-79: LGTM - ApplyMigrationStatus correctly extended to include SynchronizedAPI.The function now properly sets both
AuthoritativeAPIandSynchronizedAPIin a single patch operation, ensuring atomicity of the status update.
100-108: LGTM - Comments clarify field ownership management.The updated comments correctly explain the field ownership semantics and the validation rule requiring
synchronizedGenerationreset when changingauthoritativeAPI.
116-127: LGTM - IsMigrationCancellationRequested correctly detects rollback intent.The function properly detects when a user wants to cancel a migration by checking:
- Status is
Migrating- Spec's AuthoritativeAPI (converted to SynchronizedAPI) matches the current SynchronizedAPI
This correctly identifies when
spec.authoritativeAPIhas been reverted to the last synchronized state.pkg/controllers/machinesetmigration/machineset_migration_controller.go (5)
130-158: LGTM - Migration status initialization and cancellation handling are well-implemented.The code correctly:
- Delegates to
handleMigrationStatusInitializationfor empty status fields- Detects migration cancellation using
IsMigrationCancellationRequested- Ensures the rollback target is unpaused before applying the status patch
- Provides clear logging for cancellation scenarios
178-182: LGTM - Transition to Migrating correctly captures the source as SynchronizedAPI.Before entering the
Migratingstate, the currentAuthoritativeAPIis converted toSynchronizedAPIand both are patched atomically. This ensures the source of truth is preserved for potential rollback.
215-222: LGTM - Migration completion correctly updates both AuthoritativeAPI and SynchronizedAPI.The new synchronized state is derived from the target authority, and both fields are updated atomically while resetting the sync status. The enhanced logging provides useful debugging information.
228-275: Consider potential edge case in SynchronizedAPI inference logic.The
handleMigrationStatusInitializationfunction handles three scenarios well. However, in the third case (lines 251-271), whenSynchronizedAPIis empty butAuthoritativeAPIis set:The logic assumes we're in a forward migration and infers the source from the opposite of spec. This could be incorrect if the controller restarts mid-cancellation. However, given this is a transitional state for upgrades from older versions, the assumption is reasonable.
Consider adding a comment explaining this assumption:
if mapiMachineSet.Status.SynchronizedAPI == "" { // We are in a migration (Status.AuthoritativeAPI is Migrating) but we don't have SynchronizedAPI. // Assuming this is a standard forward migration (not a cancellation), the Spec tells us the Target. // Therefore, the Source (SynchronizedAPI) must be the opposite of the Spec. + // Note: This heuristic is for upgrade compatibility from older versions without SynchronizedAPI. + // In edge cases (e.g., controller restart mid-cancellation), this may not be perfectly accurate, + // but the worst case is a failed cancellation that requires re-initiating migration. targetAPI := mapiMachineSet.Spec.AuthoritativeAPI
423-431: LGTM - Wrapper functions improve code readability.The
applyMigrationStatusWithPatchandapplyMigrationStatusAndResetSyncStatusWithPatchwrappers encapsulate the generic function calls, making the reconciler code cleaner and more maintainable.pkg/controllers/machinemigration/machine_migration_controller.go (4)
130-157: LGTM - Migration status initialization and cancellation handling consistent with MachineSet controller.The implementation correctly mirrors the MachineSet controller logic:
- Delegates to
handleMigrationStatusInitialization- Detects cancellation with
IsMigrationCancellationRequested- Unpauses rollback target before patching
- Provides clear logging
177-181: LGTM - Transition to Migrating correctly captures synchronizedAPI.Identical pattern to MachineSet controller - captures current authority as synchronized state before transitioning to
Migrating.
217-224: LGTM - Migration completion correctly updates status fields.The implementation properly derives
newSynchronizedAPIfrom the target authority and updates both fields atomically with enhanced logging.
462-470: LGTM - Wrapper functions properly encapsulate status patching.The wrapper functions correctly use
MachineStatusApplyConfigurationtype parameter and call the sharedsynccommonfunctions.
7488790 to
1466b09
Compare
|
@RadekManak: This pull request references OCPCLOUD-2998 which is a valid jira issue. Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set. 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.
Actionable comments posted: 2
🤖 Fix all issues with AI agents
In @e2e/machine_migration_mapi_authoritative_test.go:
- Around line 208-215: There’s a duplicated/overlapping test block: the outer
Context("Machine Migration Rollback Tests", Ordered, func() { with vars
machineRollbackName, newMapiMachine, newCapiMachine is immediately followed by a
Describe("Machine Migration Rollback Tests", Ordered, func() { and a repeated
set of the same variable declarations; remove the structural duplication by
keeping only one block (either the Context or the Describe) and the single set
of declarations (machineRollbackName, newMapiMachine, newCapiMachine), or if
both are intended, properly close the Context before starting the Describe;
ensure only one declaration of those variables remains to fix the
compilation/runtime error.
In @pkg/controllers/machinemigration/machine_migration_controller_test.go:
- Around line 852-863: Replace the incorrect clusterv1beta1.PausedAnnotation
usages with clusterv1.PausedAnnotation in the machine_migration_controller_test
to match the v1beta2 CAPI Machine type; find occurrences of
clusterv1beta1.PausedAnnotation (used when building capiMachine and capaMachine
via capiMachineBuilder/capaMachineBuilder) and swap them to
clusterv1.PausedAnnotation so the test annotations match the controller and
other tests that use clusterv1.PausedAnnotation.
🧹 Nitpick comments (2)
pkg/controllers/synccommon/migratestatus_test.go (1)
26-74: Solid unit test coverage forIsMigrationCancellationRequested.The test table covers the key scenarios:
- ✓ Cancellation requests (spec reverted to match synchronized state while migrating)
- ✓ Normal migrations in progress (spec differs from synchronized state)
- ✓ Migration requests not yet acknowledged
Consider adding edge case entries for empty
SynchronizedAPIor whenspec.AuthoritativeAPIisMigrating(though schema validation prevents this).pkg/controllers/machinesetmigration/machineset_migration_controller.go (1)
149-153: Inconsistent method usage for status patching.Line 151 directly calls
synccommon.ApplyMigrationStatus[...]instead of using the wrapper methodr.applyMigrationStatusWithPatch. Other status patches in this file (e.g., lines 181, 236, 245, 266) use the wrapper methods.For consistency and maintainability, consider using the wrapper:
♻️ Suggested refactor
- if err := synccommon.ApplyMigrationStatus[*machinev1applyconfigs.MachineSetStatusApplyConfiguration](ctx, r.Client, controllerName, machinev1applyconfigs.MachineSet, mapiMachineSet, mapiMachineSet.Spec.AuthoritativeAPI, mapiMachineSet.Status.SynchronizedAPI); err != nil { + if err := r.applyMigrationStatusWithPatch(ctx, mapiMachineSet, mapiMachineSet.Spec.AuthoritativeAPI, mapiMachineSet.Status.SynchronizedAPI); err != 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 ignored due to path filters (17)
go.workis excluded by!**/*.workgo.work.sumis excluded by!**/*.sumvendor/github.com/openshift/api/machine/v1beta1/types_machine.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/machine/v1beta1/types_machineset.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/machine/v1beta1/zz_generated.crd-manifests/0000_10_machine-api_01_machines-CustomNoUpgrade.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/machine/v1beta1/zz_generated.crd-manifests/0000_10_machine-api_01_machines-DevPreviewNoUpgrade.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/machine/v1beta1/zz_generated.crd-manifests/0000_10_machine-api_01_machines-TechPreviewNoUpgrade.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/machine/v1beta1/zz_generated.crd-manifests/0000_10_machine-api_01_machinesets-CustomNoUpgrade.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/machine/v1beta1/zz_generated.crd-manifests/0000_10_machine-api_01_machinesets-DevPreviewNoUpgrade.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/machine/v1beta1/zz_generated.crd-manifests/0000_10_machine-api_01_machinesets-TechPreviewNoUpgrade.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/machine/v1beta1/zz_generated.swagger_doc_generated.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/openapi/generated_openapi/zz_generated.openapi.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/machine/applyconfigurations/machine/v1beta1/machinesetstatus.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/machine/applyconfigurations/machine/v1beta1/machinestatus.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/cluster-api-actuator-pkg/testutils/resourcebuilder/machine/v1beta1/machine.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/cluster-api-actuator-pkg/testutils/resourcebuilder/machine/v1beta1/machineset.gois excluded by!**/vendor/**,!vendor/**vendor/modules.txtis excluded by!**/vendor/**,!vendor/**
📒 Files selected for processing (17)
e2e/machine_migration_capi_authoritative_test.goe2e/machine_migration_helpers.goe2e/machine_migration_mapi_authoritative_test.goe2e/machineset_migration_capi_authoritative_test.goe2e/machineset_migration_helpers.goe2e/machineset_migration_mapi_authoritative_test.gopkg/controllers/machinemigration/machine_migration_controller.gopkg/controllers/machinemigration/machine_migration_controller_test.gopkg/controllers/machinesetmigration/machineset_migration_controller.gopkg/controllers/machinesetmigration/machineset_migration_controller_test.gopkg/controllers/machinesetsync/machineset_sync_controller.gopkg/controllers/machinesync/machine_sync_controller.gopkg/controllers/synccommon/applyconfiguration.gopkg/controllers/synccommon/migratestatus.gopkg/controllers/synccommon/migratestatus_test.gopkg/controllers/synccommon/suite_test.gopkg/conversion/test/fuzz/fuzz.go
🚧 Files skipped from review as they are similar to previous changes (5)
- pkg/conversion/test/fuzz/fuzz.go
- e2e/machine_migration_capi_authoritative_test.go
- e2e/machine_migration_helpers.go
- pkg/controllers/machinesetsync/machineset_sync_controller.go
- pkg/controllers/machinesync/machine_sync_controller.go
🧰 Additional context used
🧬 Code graph analysis (6)
pkg/controllers/synccommon/migratestatus.go (2)
pkg/controllers/common_consts.go (1)
ReasonAuthoritativeAPIChanged(48-48)pkg/util/ssa.go (1)
ApplyConfigPatch(42-46)
pkg/controllers/synccommon/migratestatus_test.go (1)
pkg/controllers/synccommon/migratestatus.go (1)
IsMigrationCancellationRequested(121-127)
e2e/machineset_migration_helpers.go (2)
pkg/conversion/mapi2capi/interface.go (1)
MachineSet(29-31)e2e/framework/framework.go (2)
WaitMedium(24-24)RetryMedium(18-18)
pkg/controllers/machinesetmigration/machineset_migration_controller.go (2)
pkg/controllers/synccommon/migratestatus.go (4)
IsMigrationCancellationRequested(121-127)ApplyMigrationStatus(63-79)AuthoritativeAPIToSynchronizedAPI(131-142)ApplyMigrationStatusAndResetSyncStatus(42-60)pkg/conversion/mapi2capi/interface.go (1)
MachineSet(29-31)
pkg/controllers/machinesetmigration/machineset_migration_controller_test.go (2)
e2e/migration_common.go (1)
SynchronizedCondition(10-10)pkg/controllers/common_consts.go (1)
SynchronizedCondition(41-41)
e2e/machine_migration_mapi_authoritative_test.go (2)
e2e/framework/machine.go (2)
GetMachine(75-86)DeleteMachines(105-135)e2e/framework/framework.go (1)
CAPINamespace(14-14)
🔇 Additional comments (22)
pkg/controllers/synccommon/suite_test.go (1)
1-29: LGTM!Standard Ginkgo test suite scaffolding that enables the new
IsMigrationCancellationRequestedtests inmigratestatus_test.go.pkg/controllers/synccommon/applyconfiguration.go (1)
40-45: LGTM!The interface extension follows the existing pattern and enables the migration status helpers to set
SynchronizedAPIalongsideAuthoritativeAPIduring status patches.pkg/controllers/machinemigration/machine_migration_controller_test.go (2)
772-897: Comprehensive migration cancellation test coverage added.The new test contexts thoroughly cover:
- Cancellation back to MachineAPI from stuck migration
- Cancellation back to ClusterAPI from stuck migration
- Cancellation with paused CAPI resources (verifying unpause behavior)
The assertions correctly verify both
AuthoritativeAPIandSynchronizedAPIstatus fields after cancellation.
899-999: Status initialization edge cases well covered.The tests properly cover:
- Empty
SynchronizedAPIwith setAuthoritativeAPI(lines 899-931)- Empty
AuthoritativeAPIwith setSynchronizedAPI(lines 933-959)- Stable-to-Migrating transition preserving
SynchronizedAPI(lines 961-999)This aligns with the initialization logic in
handleMigrationStatusInitialization.pkg/controllers/synccommon/migratestatus.go (3)
116-127: Clean cancellation detection logic.The
IsMigrationCancellationRequestedfunction correctly identifies the cancellation scenario: whenstatus.AuthoritativeAPIisMigratingandspec.AuthoritativeAPImatches thestatus.SynchronizedAPI(via the conversion helper). This enables administrators to abort stuck migrations by reverting spec to the last known good state.
129-142: Mapping function handles all authority values correctly.The
AuthoritativeAPIToSynchronizedAPIhelper appropriately:
- Maps
MachineAPI→MachineAPISynchronized- Maps
ClusterAPI→ClusterAPISynchronized- Returns empty string for
Migratingand unknown values (safe default)
42-60: Updated status patching functions correctly propagateSynchronizedAPI.The renamed
ApplyMigrationStatusAndResetSyncStatusfunction now:
- Accepts the
synchronizedAPIparameter- Calls
WithSynchronizedAPIon the status apply configuration before patchingThis ensures atomic updates of both
AuthoritativeAPIandSynchronizedAPIduring migration state transitions.pkg/controllers/machinemigration/machine_migration_controller.go (4)
138-159: Migration cancellation flow is well-structured.The cancellation logic:
- Detects cancellation via
IsMigrationCancellationRequested- Ensures the rollback target is unpaused
- Applies status patch to transition back to synchronized state
- Logs success with both field values
This provides a clean escape hatch for stuck migrations.
464-472: Clean wrapper methods for status patching.The new
applyMigrationStatusWithPatchandapplyMigrationStatusAndResetSyncStatusWithPatchmethods properly encapsulate the generic function calls with controller-specific types, improving readability throughout the reconciler.
243-253: Implicit coupling based on string value assumptions.Line 248 casts
SynchronizedAPItoMachineAuthority:mapiv1beta1.MachineAuthority(mapiMachine.Status.SynchronizedAPI)This relies on
MachineAPISynchronizedandMachineAuthorityMachineAPIhaving identical underlying string values (and similarly for the ClusterAPI variants). While the forward conversion functionAuthoritativeAPIToSynchronizedAPIdocuments this mapping explicitly, the reverse conversion at line 248 uses a direct type cast without validation or a helper function. This creates implicit coupling to external API package constants that could silently break if their values diverge.Consider adding a reverse conversion helper (e.g.,
SynchronizedAPIToMachineAuthority) to make this dependency explicit and maintainable.
255-275: This concern is not valid—the scenario described cannot occur.The code handles an initialization edge case where
SynchronizedAPIis empty. However, wheneverstatus.AuthoritativeAPItransitions toMigrating, the controller explicitly setsSynchronizedAPIat the same time (line 186-189). All test cases confirm this invariant: whenstatus.AuthoritativeAPIisMigrating,status.SynchronizedAPIis always populated, never empty.Therefore, the third code block (which handles empty
SynchronizedAPI) cannot execute whenstatus.AuthoritativeAPIis alreadyMigrating. The inference logic is only used for recovery from inconsistent states and correctly reflects the actual last synchronized state.pkg/controllers/machinesetmigration/machineset_migration_controller.go (2)
229-276:handleMigrationStatusInitializationmirrors Machine controller logic.The initialization logic is identical to the Machine controller implementation, correctly handling:
- Both fields empty → initialize from spec
- Only
AuthoritativeAPIempty → derive fromSynchronizedAPI- Only
SynchronizedAPIempty → infer from migration directionThis duplication is acceptable given the different receiver types, though a shared implementation via generics could be considered in the future.
137-159: Migration cancellation flow correctly implemented for MachineSet.The cancellation handling follows the same pattern as the Machine controller, ensuring consistent behavior across both resource types.
e2e/machineset_migration_capi_authoritative_test.go (1)
169-169: LGTM! Synchronization state verification is correctly integrated.The additions of
verifyMachineSetSynchronizedAPIcalls after authority transitions properly validate that the synchronization tracking field reflects the expected state following MachineAPI ↔ ClusterAPI switches.Also applies to: 208-208
e2e/machineset_migration_helpers.go (1)
221-228: LGTM! Well-implemented verification helper.The new
verifyMachineSetSynchronizedAPIfunction follows the established pattern used by other verification helpers in this file, with appropriate Eventually assertions and descriptive logging.e2e/machineset_migration_mapi_authoritative_test.go (1)
169-170: LGTM! Consistent synchronization state verification.The additions properly verify both authoritative status and synchronization state after authority switches, ensuring comprehensive validation of migration state transitions.
Also applies to: 208-209, 339-340
e2e/machine_migration_mapi_authoritative_test.go (2)
166-166: LGTM! Synchronization state verification enhances round-trip test coverage.The additions of
verifyMachineSynchronizedAPIcalls throughout the round-trip test correctly validate that the synchronization state is tracked across MAPI → CAPI → MAPI transitions.Also applies to: 178-178, 190-190
217-291: Excellent rollback test coverage.The rollback test scenario comprehensively validates the migration cancellation workflow:
- Initiates migration from MAPI to ClusterAPI
- Cancels during Migrating state
- Verifies rollback to MachineAPI with preserved synchronization state
- Completes a subsequent successful migration to ClusterAPI
This provides valuable coverage for the administrator workflow described in the PR objectives.
pkg/controllers/machinesetmigration/machineset_migration_controller_test.go (4)
199-209: LGTM! Consistent SynchronizedAPI field integration across all test scenarios.The updates consistently set and verify
Status.SynchronizedAPIalongsideStatus.AuthoritativeAPIthroughout the test suite, ensuring proper tracking of the synchronized state in all migration scenarios.Also applies to: 246-246, 287-287, 322-329, 373-388, 429-436, 493-501, 534-542, 576-592, 627-627, 655-671, 697-697
704-814: Excellent migration cancellation test coverage.The new test contexts comprehensively validate migration cancellation scenarios:
- Cancellation back to MachineAPI from Migrating state
- Cancellation back to ClusterAPI from Migrating state
- Proper unpausing of target resources when cancelling
These tests ensure the cancellation detection logic (mentioned in PR objectives as
IsMigrationCancellationRequested()) works correctly in both directions.
816-874: Comprehensive status initialization test coverage.The initialization tests properly validate bootstrap logic for edge cases:
AuthoritativeAPIset butSynchronizedAPIemptySynchronizedAPIset butAuthoritativeAPIemptyThis coverage ensures the
handleMigrationStatusInitialization()function (referenced in PR description) handles partial state correctly.
876-912: Good coverage for SynchronizedAPI preservation during state transitions.The test validates that when transitioning from a stable state (ClusterAPI) to Migrating, the
SynchronizedAPIfield correctly preserves the source API, which is essential for the cancellation detection workflow.
1466b09 to
f081583
Compare
|
@RadekManak: This pull request references OCPCLOUD-2998 which is a valid jira issue. Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set. 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.
Actionable comments posted: 0
🧹 Nitpick comments (2)
pkg/controllers/machinemigration/machine_migration_controller_test.go (1)
899-959: LGTM: Good coverage of status initialization scenarios.These tests handle important bootstrap cases where status fields are partially populated:
- Lines 899-931: Initialize
SynchronizedAPIwhen onlyAuthoritativeAPIis set- Lines 933-959: Derive
AuthoritativeAPIwhen onlySynchronizedAPIis setBoth scenarios correctly verify the controller fills in the missing field with the appropriate value.
💡 Optional: Consider verifying requeue behavior
The test descriptions mention "requeue" (line 922) but don't verify
result.Requeue. While this appears to be a consistent pattern in the file (e.g., line 183), explicitly asserting the requeue behavior could make the tests more precise:It("should initialize SynchronizedAPI from AuthoritativeAPI and requeue", func() { - _, err := reconciler.Reconcile(ctx, req) + result, err := reconciler.Reconcile(ctx, req) Expect(err).NotTo(HaveOccurred()) + Expect(result.Requeue).To(BeTrue(), "expected requeue after initialization") Eventually(k.Object(mapiMachine)).Should(SatisfyAll(However, if the existing pattern is intentional (e.g., the requeue is implicit or tested via
Eventually), this can be safely ignored.pkg/controllers/machinesetmigration/machineset_migration_controller_test.go (1)
816-874: Test coverage is good but could be extended.The tests verify initialization when one field is empty and can be derived from the other. However, consider adding test coverage for the more complex inference scenario in
handleMigrationStatusInitializationwhere:
spec.AuthoritativeAPI != status.AuthoritativeAPI(migration requested)status.AuthoritativeAPIis set butstatus.SynchronizedAPIis empty- The controller must infer the source API from the target
This would exercise the inference logic at lines 255-267 that I flagged in the controller review.
📝 Suggested additional test
Context("when migration is in progress but SynchronizedAPI is empty (inference scenario)", func() { BeforeEach(func() { By("Setting the MAPI machine set spec AuthoritativeAPI to ClusterAPI (migration target)") mapiMachineSet = mapiMachineSetBuilder. WithAuthoritativeAPI(mapiv1beta1.MachineAuthorityClusterAPI). Build() Eventually(k8sClient.Create(ctx, mapiMachineSet)).Should(Succeed()) By("Creating mirror CAPI machine set") capiMachineSet = capiMachineSetBuilder.Build() Eventually(k8sClient.Create(ctx, capiMachineSet)).Should(Succeed()) By("Setting AuthoritativeAPI to MachineAPI (source) but leaving SynchronizedAPI empty") Eventually(k.UpdateStatus(mapiMachineSet, func() { mapiMachineSet.Status.AuthoritativeAPI = mapiv1beta1.MachineAuthorityMachineAPI // SynchronizedAPI intentionally left empty - should be inferred as opposite of target })).Should(Succeed()) req = reconcile.Request{NamespacedName: client.ObjectKeyFromObject(mapiMachineSet)} }) It("should infer SynchronizedAPI as the opposite of the migration target", func() { _, err := reconciler.Reconcile(ctx, req) Expect(err).NotTo(HaveOccurred()) Eventually(k.Object(mapiMachineSet)).Should(SatisfyAll( HaveField("Status.AuthoritativeAPI", Equal(mapiv1beta1.MachineAuthorityMachineAPI)), HaveField("Status.SynchronizedAPI", Equal(mapiv1beta1.MachineAPISynchronized)), )) }) })
📜 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 (17)
go.workis excluded by!**/*.workgo.work.sumis excluded by!**/*.sumvendor/github.com/openshift/api/machine/v1beta1/types_machine.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/machine/v1beta1/types_machineset.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/machine/v1beta1/zz_generated.crd-manifests/0000_10_machine-api_01_machines-CustomNoUpgrade.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/machine/v1beta1/zz_generated.crd-manifests/0000_10_machine-api_01_machines-DevPreviewNoUpgrade.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/machine/v1beta1/zz_generated.crd-manifests/0000_10_machine-api_01_machines-TechPreviewNoUpgrade.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/machine/v1beta1/zz_generated.crd-manifests/0000_10_machine-api_01_machinesets-CustomNoUpgrade.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/machine/v1beta1/zz_generated.crd-manifests/0000_10_machine-api_01_machinesets-DevPreviewNoUpgrade.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/machine/v1beta1/zz_generated.crd-manifests/0000_10_machine-api_01_machinesets-TechPreviewNoUpgrade.crd.yamlis excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/machine/v1beta1/zz_generated.swagger_doc_generated.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/api/openapi/generated_openapi/zz_generated.openapi.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/machine/applyconfigurations/machine/v1beta1/machinesetstatus.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/client-go/machine/applyconfigurations/machine/v1beta1/machinestatus.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/cluster-api-actuator-pkg/testutils/resourcebuilder/machine/v1beta1/machine.gois excluded by!**/vendor/**,!vendor/**vendor/github.com/openshift/cluster-api-actuator-pkg/testutils/resourcebuilder/machine/v1beta1/machineset.gois excluded by!**/vendor/**,!vendor/**vendor/modules.txtis excluded by!**/vendor/**,!vendor/**
📒 Files selected for processing (17)
e2e/machine_migration_capi_authoritative_test.goe2e/machine_migration_helpers.goe2e/machine_migration_mapi_authoritative_test.goe2e/machineset_migration_capi_authoritative_test.goe2e/machineset_migration_helpers.goe2e/machineset_migration_mapi_authoritative_test.gopkg/controllers/machinemigration/machine_migration_controller.gopkg/controllers/machinemigration/machine_migration_controller_test.gopkg/controllers/machinesetmigration/machineset_migration_controller.gopkg/controllers/machinesetmigration/machineset_migration_controller_test.gopkg/controllers/machinesetsync/machineset_sync_controller.gopkg/controllers/machinesync/machine_sync_controller.gopkg/controllers/synccommon/applyconfiguration.gopkg/controllers/synccommon/migratestatus.gopkg/controllers/synccommon/migratestatus_test.gopkg/controllers/synccommon/suite_test.gopkg/conversion/test/fuzz/fuzz.go
🚧 Files skipped from review as they are similar to previous changes (5)
- e2e/machine_migration_capi_authoritative_test.go
- e2e/machineset_migration_mapi_authoritative_test.go
- pkg/controllers/synccommon/suite_test.go
- pkg/controllers/machinesetsync/machineset_sync_controller.go
- pkg/controllers/synccommon/applyconfiguration.go
🧰 Additional context used
🧬 Code graph analysis (6)
e2e/machine_migration_helpers.go (1)
e2e/framework/framework.go (2)
WaitMedium(24-24)RetryMedium(18-18)
pkg/controllers/machinesetmigration/machineset_migration_controller_test.go (2)
e2e/migration_common.go (1)
SynchronizedCondition(10-10)pkg/controllers/common_consts.go (1)
SynchronizedCondition(41-41)
pkg/controllers/machinemigration/machine_migration_controller.go (1)
pkg/controllers/synccommon/migratestatus.go (4)
IsMigrationCancellationRequested(121-127)AuthoritativeAPIToSynchronizedAPI(131-142)ApplyMigrationStatus(63-79)ApplyMigrationStatusAndResetSyncStatus(42-60)
pkg/controllers/machinesetmigration/machineset_migration_controller.go (2)
pkg/controllers/synccommon/migratestatus.go (4)
IsMigrationCancellationRequested(121-127)ApplyMigrationStatus(63-79)AuthoritativeAPIToSynchronizedAPI(131-142)ApplyMigrationStatusAndResetSyncStatus(42-60)pkg/conversion/mapi2capi/interface.go (1)
MachineSet(29-31)
pkg/controllers/synccommon/migratestatus_test.go (1)
pkg/controllers/synccommon/migratestatus.go (1)
IsMigrationCancellationRequested(121-127)
e2e/machineset_migration_helpers.go (2)
pkg/conversion/mapi2capi/interface.go (1)
MachineSet(29-31)e2e/framework/framework.go (2)
WaitMedium(24-24)RetryMedium(18-18)
🔇 Additional comments (29)
pkg/controllers/machinesync/machine_sync_controller.go (1)
1515-1515: LGTM! SynchronizedAPI field properly preserved during synchronization.The added line correctly preserves the
SynchronizedAPIstatus field from the existing MAPI machine to the converted MAPI machine, following the same pattern as other preserved fields (AuthoritativeAPI,SynchronizedGeneration,LastOperation,ProviderStatus). This ensures the synchronization state is maintained during CAPI→MAPI machine status updates.pkg/controllers/machinemigration/machine_migration_controller_test.go (4)
20-20: LGTM: Helpful debugging aid.The
go-cmpimport is used at line 225 to provide detailed diff output when the resource-version assertion fails, which aids in debugging test failures.
201-770: LGTM: Comprehensive updates to existing migration tests.All existing migration scenarios have been systematically updated to handle the new
SynchronizedAPIstatus field:
- Test setup properly initializes
SynchronizedAPIalongsideAuthoritativeAPIusing the builder pattern- Assertions verify both fields in migration completion scenarios (lines 678, 765)
- The defensive use of
cmp.Diffat line 225 provides helpful debugging context when assertions fail- The pattern is consistent across all migration directions (MachineAPI ↔ ClusterAPI)
772-897: LGTM: Excellent coverage of migration cancellation scenarios.The new cancellation tests thoroughly exercise the rollback functionality:
- Lines 772-806: Cancel migration back to MachineAPI
- Lines 808-841: Cancel migration back to ClusterAPI
- Lines 843-896: Cancel to ClusterAPI with proper unpause of CAPI resources
Each scenario correctly:
- Simulates a stuck migration state (
status.AuthoritativeAPI: Migrating)- Sets
status.SynchronizedAPIto reflect the last good API- Reverts
spec.AuthoritativeAPIto trigger cancellation detection- Verifies the controller transitions back to the synchronized state
- Explicitly confirms no requeue is needed (lines 799, 834, 877)
The paused-resource scenario (lines 843-896) is particularly valuable, ensuring that CAPI resources are properly unpaused when rolling back.
961-999: LGTM: Important invariant verification for migration transitions.This test verifies a critical behavior: when transitioning from a stable state (ClusterAPI) to
Migrating, theSynchronizedAPIfield correctly preserves the last synchronized API rather than followingAuthoritativeAPItoMigrating.This preservation is essential for the cancellation detection logic, which relies on comparing
spec.AuthoritativeAPIwithstatus.SynchronizedAPIto detect rollback requests.pkg/conversion/test/fuzz/fuzz.go (1)
764-764: LGTM! Consistent handling of MAPI-only field in fuzz tests.The SynchronizedAPI field is correctly cleared during fuzzing since it has no CAPI equivalent, consistent with how other MAPI-only fields like AuthoritativeAPI are handled.
Also applies to: 811-811
e2e/machine_migration_helpers.go (2)
172-180: LGTM! Well-structured helper for migration state verification.The function correctly validates both the Migrating state and the expected SynchronizedAPI value in a single assertion, with clear error messaging.
347-354: LGTM! Clean and focused helper function.The function provides a reusable way to verify SynchronizedAPI status with proper timeout handling and descriptive messaging.
pkg/controllers/machinesetmigration/machineset_migration_controller.go (5)
138-159: LGTM! Migration cancellation logic is sound.The code correctly detects cancellation requests and ensures the rollback target is unpaused before transitioning. The call to
ensureUnpauseRequestedOnNewAuthoritativeResourcehandles cases where the migration was cancelled early, before all pausing completed.
179-183: LGTM! Correct synchronization state capture.The code properly captures the current authoritative API as the synchronized state before transitioning to Migrating, creating the necessary breadcrumb for potential rollback.
216-223: LGTM! Proper migration completion.The code correctly updates both
authoritativeAPIandsynchronizedAPIatomically to reflect the new stable state after successful migration, with appropriate sync status reset.
424-432: LGTM! Clean patch helper wrappers.The helper functions provide a clean interface for atomic status updates, properly delegating to the shared migration status utilities.
255-267: The proposed validation is ineffective and doesn't address the actual risk in the inference logic.The if/else structure (lines 258-262) guarantees that
synchronizedAPIwill always be set to one of two valid enum values (ClusterAPISynchronizedorMachineAPISynchronized), making the proposed validation redundant—it will never catch an error.The actual concern should be the input validation, not the output. If
spec.AuthoritativeAPI(targetAPI) isMachineAuthorityMigratingor some other unexpected value, the code silently defaults toMachineAPISynchronized, which may be incorrect. The inference logic only works safely when targetAPI is guaranteed to be eitherMachineAuthorityMachineAPIorMachineAuthorityClusterAPI.Consider validating that
targetAPImatches one of the two expected values before the inference:if targetAPI != mapiv1beta1.MachineAuthorityMachineAPI && targetAPI != mapiv1beta1.MachineAuthorityClusterAPI { return &ctrl.Result{}, fmt.Errorf("cannot infer synchronizedAPI from unexpected targetAPI: %s", targetAPI) }pkg/controllers/machinemigration/machine_migration_controller.go (2)
138-159: LGTM! Consistent migration controller implementation.The migration cancellation detection, synchronizedAPI capture, completion logic, and helper functions correctly mirror the MachineSet controller implementation with appropriate handling for Machine resources.
Also applies to: 179-183, 219-226, 464-472
255-267: Remove the proposed validation—it's redundant and adds no safety.The inference logic is intentional and correct. In a binary system with only two possible authority states (MachineAPI or ClusterAPI), knowing the target authority reveals the source. The if-else statement deterministically assigns one of the two valid
SynchronizedAPIconstants, so a runtime validation on the result can never fail. The function already guarantees valid values through its type constraints and logic.If there are concerns about the inference pattern itself (whether inverting target to infer source is always correct during migrations), that would require domain-specific review, but the proposed code does not address such concerns.
pkg/controllers/machinesetmigration/machineset_migration_controller_test.go (2)
704-814: LGTM! Comprehensive migration cancellation test coverage.The test contexts thoroughly exercise cancellation scenarios including:
- Cancellation back to both MachineAPI and ClusterAPI
- Verification that paused resources are properly unpaused during cancellation
- Proper state transitions during rollback
876-912: LGTM! Good coverage of Migrating state transition.The test verifies that when transitioning to Migrating state, the controller correctly preserves the
SynchronizedAPIas a snapshot of the source state, which is essential for potential migration cancellation.e2e/machineset_migration_capi_authoritative_test.go (2)
164-170: LGTM! Good addition of synchronization state verification.The
verifyMachineSetSynchronizedAPIcall appropriately verifies that the status reflectsMachineAPISynchronizedafter the authority switch to MachineAPI. This aligns well with the existing verification pattern for paused conditions and synchronized conditions.
203-209: LGTM! Consistent synchronization verification after authority switch.The verification correctly asserts that the MachineSet's
status.synchronizedAPIis set toClusterAPISynchronizedafter switching authority back to ClusterAPI, maintaining consistency with the earlier verification at Line 169.pkg/controllers/synccommon/migratestatus_test.go (1)
26-74: LGTM! Comprehensive test coverage for migration cancellation detection.The table-driven tests thoroughly cover all critical scenarios:
- Both directions of migration cancellation (MAPI→CAPI and CAPI→MAPI)
- In-progress migrations that should not be cancelled
- Pre-migration states
The test logic correctly validates the cancellation detection algorithm where cancellation is identified when
status.authoritativeAPIisMigratingand thespec.authoritativeAPImatchesstatus.synchronizedAPI.e2e/machineset_migration_helpers.go (2)
221-228: LGTM! Well-structured verification helper.The
verifyMachineSetSynchronizedAPIfunction follows the established pattern from other verification helpers likeverifyMachineSetAuthoritative(Lines 94-101), using appropriate timeouts (WaitMedium/RetryMedium) and clear assertion messages.
230-246: LGTM! Clean refactor using WithTransform pattern.The introduction of
getAWSProviderSpecFromMachineSetas an extraction helper and its use viaWithTransforminverifyMAPIMachineSetProviderSpec(Line 234) is an idiomatic Gomega pattern that improves testability and readability by separating extraction logic from assertion logic.e2e/machine_migration_mapi_authoritative_test.go (3)
27-27: LGTM! Non-functional test structure improvement.The change from
DescribetoContextblocks better organizes the test hierarchy and aligns with Ginkgo best practices for distinguishing between test suites (Describe) and test scenarios (Context).Also applies to: 65-65, 136-136
162-193: LGTM! Comprehensive synchronization state verification throughout the round trip.The additions of
verifyMachineSynchronizedAPIat Lines 166, 178, and 190 ensure that thestatus.synchronizedAPIfield correctly reflects the current synchronized state at each stage of the MAPI→CAPI→MAPI round trip. This provides valuable coverage for the synchronization tracking feature.
209-288: LGTM! Excellent test coverage for migration rollback scenario.This new test suite validates a critical user workflow described in the PR objectives: canceling a stuck migration by reverting
spec.authoritativeAPIto the last successfully synchronized state. The test comprehensively verifies:
- Entry into the
Migratingstate with propersynchronizedAPItracking (Line 245)- Cancellation detection and rollback when spec is reverted (Lines 247-262)
- Successful completion of a subsequent full migration after rollback (Lines 264-275)
- Proper cleanup of all resources (Lines 277-286)
The test flow matches the administrator workflow described in the PR objectives and provides strong validation of the cancellation mechanism.
pkg/controllers/synccommon/migratestatus.go (4)
42-60: LGTM! Clean extension to support atomic synchronizedAPI updates.The addition of the
synchronizedAPIparameter and the call toWithSynchronizedAPI(Line 57) enables atomic updates of bothauthoritativeAPIandsynchronizedAPIfields during migration state transitions, which is essential for consistent state management.
63-79: LGTM! Consistent pattern for synchronizedAPI propagation.The function signature extension and
WithSynchronizedAPIcall (Line 76) mirror the pattern inApplyMigrationStatusAndResetSyncStatus, maintaining consistency across migration status update paths.
116-127: LGTM! Correct cancellation detection logic.The
IsMigrationCancellationRequestedfunction correctly identifies when an administrator has revertedspec.authoritativeAPIto the last successfully synchronized state whilestatus.authoritativeAPIis stillMigrating. This implements the cancellation workflow described in the PR objectives.The logic is validated by the comprehensive test coverage in
migratestatus_test.go.
129-142: LGTM! Straightforward and correct authority-to-synchronization mapping.The
AuthoritativeAPIToSynchronizedAPIfunction provides a clean mapping fromMachineAuthoritytoSynchronizedAPIvalues. The explicit handling ofMachineAuthorityMigratingreturning an empty string (Line 138) is appropriate since "Migrating" is a transient state that doesn't represent a synchronized API.
|
/test unit |
1b3828b to
6b018ab
Compare
6b018ab to
41e98f1
Compare
|
/hold cancel |
6cca7ab to
fd27ec0
Compare
|
/retest |
5a3eb57 to
42d1ce4
Compare
|
@RadekManak: This pull request references OCPCLOUD-2998 which is a valid jira issue. Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "5.0.0" version, but no target version was set. 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. |
|
@coderabbitai full review |
✅ Actions performedFull review triggered. |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (3)
e2e/machineset_migration_disruptive_test.go (1)
119-244: 🏗️ Heavy liftSplit the combined paused/unpaused rollback flow into separate scenario specs.
e2e/machineset_migration_disruptive_test.gohas a singleIt(should reuse one outage to verify paused-target and unpaused-target rollback behavior) that validates both paused-target and unpaused-target rollback behaviors in one end-to-end sequence, with no nestedContext()/When()blocks. Split into separateIts (or aDescribeTablewith entries) so each behavior has isolated setup and assertions for clearer failure attribution.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@e2e/machineset_migration_disruptive_test.go` around lines 119 - 244, Split the big It("should reuse one outage...") into two separate specs: one It for the paused-target flow and one It for the unpaused-target flow (or a DescribeTable with two entries). Move the paused-target specific setup/assertions that use createZeroReplicaMachineSetMigrationDisruptiveFixture, verifyMAPIMachineSetSynchronizedState, verifyCAPIMachineSetPausedState, switchMachineSetAuthoritativeAPI, verifyMachineSetAuthoritative, verifyMachineSetPausedCondition into the paused-target spec; move the unpaused-target setup/assertions that use createZeroReplicaMachineSetMigrationDisruptiveFixture, switchMachineSetAuthoritativeAPI, verifyMAPIMachineSetSynchronizedState, verifyMachineSetPausedCondition, verifyCAPIMachineSetPausedState, consistentlyVerifyMachineSetRollbackPinnedAtClusterAPI and the recovery sequence that calls readAndValidateMachineSetMigrationDisruptionBaseline, setMachineSetMigrationCAPIOperatorOverride, scaleDeploymentAndWaitForAvailableReplicas, scaleDeployment, waitForDeploymentAvailableReplicas, waitForClusterAPIOperatorHealthy, and final verifyMAPIMachineSetSynchronizedState/verifyCAPIMachineSetPausedState into the unpaused-target spec; ensure shared utilities (disruptionState handling and setMachineSetMigrationCAPIOperatorOverride) are factored into BeforeEach/AfterEach or helper functions to avoid duplication and preserve teardown behavior.pkg/controllers/synccommon/syncstatus_integration_test.go (1)
45-292: ⚡ Quick winAdd
AfterEachcleanup to avoid cross-spec resource buildup.This suite creates namespaces and objects per spec but never tears them down, which can increase flake risk and slow envtest over time.
As per coding guidelines, use
testutils.CleanupResources()in AfterEach for standard resource cleanup.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@pkg/controllers/synccommon/syncstatus_integration_test.go` around lines 45 - 292, Add an AfterEach that calls testutils.CleanupResources(ctx, k8sClient) to tear down created namespaces and objects after each spec; place one AfterEach inside each Describe that has a BeforeEach creating resources (the Describe blocks that contain BeforeEach which creates namespace/machineSet and namespace/machine), referencing the existing ctx and k8sClient variables and ensuring it runs after each test to avoid resource buildup.pkg/controllers/synccommon/migratestatus_test.go (1)
33-156: ⚡ Quick winAdd standard
AfterEachcleanup for created resources.These specs create namespaces and API objects but don’t clean them up, which can leak state across specs in a shared envtest run.
As per coding guidelines, use
testutils.CleanupResources()in AfterEach for standard resource cleanup.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@pkg/controllers/synccommon/migratestatus_test.go` around lines 33 - 156, Add a standard AfterEach cleanup to the test suite so resources created by the Describe("Migration status helpers") specs are removed: inside the top-level var _ = Describe("Migration status helpers", ...) block add an AfterEach that calls testutils.CleanupResources(ctx, k8sClient) (or appropriate cleanup helper signature) to delete created namespaces and API objects; ensure the test file imports the testutils package and that ctx and k8sClient are the same variables used by the tests so ApplySyncStatus, ApplyMigrationStatus, and ApplyMigrationStatusAndResetSyncStatus specs are cleaned up between runs.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@e2e/machineset_migration_disruptive_test.go`:
- Around line 67-75: Add an early skip in the existing BeforeAll to detect
MicroShift and skip the test: update the BeforeAll block (which already checks
platform and capiframework.IsFeatureGateEnabled) to also call the MicroShift
detection helper (e.g., utils.IsMicroShift(), framework.IsMicroShift(), or check
platform == configv1.MicroShiftPlatformType) and invoke Skip(...) if true so
tests using Machine API migration and ClusterVersion overrides are not run on
MicroShift.
In `@e2e/machineset_migration_helpers.go`:
- Around line 766-784: The test currently only requires AvailableReplicas > 0
which allows degraded deployments to pass; change the availability assertion to
require full availability by comparing deployment.Status.AvailableReplicas to
the desired replica count (derived from ptr.Deref(deployment.Spec.Replicas,
int32(1))) so that
Expect(deployment.Status.AvailableReplicas).To(Equal(desiredReplicas),
"Deployment/%s/%s must have all desired replicas available before the outage",
namespace, name). Keep the existing desiredReplicas nonzero check and the
ObservedGeneration equality assertion.
In `@pkg/controllers/machinesetmigration/machineset_migration_controller.go`:
- Around line 212-227: The helper ensureCAPIUnpaused currently treats a
MachineSet with a stale PausedCondition=True as still paused even if it lacks
the CAPI finalizer; update ensureCAPIUnpaused to short-circuit and return (true,
nil) when the MachineSet does not contain clusterv1.MachineSetFinalizer (i.e.,
treat it as already unpaused), preserving the existing flow that first tries
RemovePausedAnnotation and then checks the PausedCondition; reference the
function ensureCAPIUnpaused and the clusterv1.MachineSetFinalizer symbol when
applying this change.
In `@pkg/controllers/machinesync/machine_sync_controller.go`:
- Around line 1516-1522: The call in applySynchronizedConditionWithPatch always
computes and writes SynchronizedAPI via
synccommon.AuthoritativeAPIToSynchronizedAPI, which can overwrite the “last
successful sync” on non-success paths; change
applySynchronizedConditionWithPatch to only compute and pass the synchronized
API when a successful sync generation is present (i.e., generation != nil / a
successful write), otherwise pass nil to synccommon.ApplySyncStatus so
SynchronizedAPI is not updated on ConditionFalse/Unknown paths; update the call
site in applySynchronizedConditionWithPatch (and any local variable you add)
accordingly.
In `@pkg/controllers/migrationcommon/pause.go`:
- Around line 67-68: RemovePausedAnnotation uses client.MergeFrom(before) which
doesn't include optimistic locking, so replace the patch call to use
client.MergeFromWithOptions(before, client.MergeFromWithOptimisticLock{}) to
detect stale-write conflicts like the add path; update the call in
RemovePausedAnnotation where k8sClient.Patch(ctx, obj, client.MergeFrom(before))
is used to instead pass MergeFromWithOptions with
client.MergeFromWithOptimisticLock{}, and add any necessary import adjustments
for the client option symbol.
---
Nitpick comments:
In `@e2e/machineset_migration_disruptive_test.go`:
- Around line 119-244: Split the big It("should reuse one outage...") into two
separate specs: one It for the paused-target flow and one It for the
unpaused-target flow (or a DescribeTable with two entries). Move the
paused-target specific setup/assertions that use
createZeroReplicaMachineSetMigrationDisruptiveFixture,
verifyMAPIMachineSetSynchronizedState, verifyCAPIMachineSetPausedState,
switchMachineSetAuthoritativeAPI, verifyMachineSetAuthoritative,
verifyMachineSetPausedCondition into the paused-target spec; move the
unpaused-target setup/assertions that use
createZeroReplicaMachineSetMigrationDisruptiveFixture,
switchMachineSetAuthoritativeAPI, verifyMAPIMachineSetSynchronizedState,
verifyMachineSetPausedCondition, verifyCAPIMachineSetPausedState,
consistentlyVerifyMachineSetRollbackPinnedAtClusterAPI and the recovery sequence
that calls readAndValidateMachineSetMigrationDisruptionBaseline,
setMachineSetMigrationCAPIOperatorOverride,
scaleDeploymentAndWaitForAvailableReplicas, scaleDeployment,
waitForDeploymentAvailableReplicas, waitForClusterAPIOperatorHealthy, and final
verifyMAPIMachineSetSynchronizedState/verifyCAPIMachineSetPausedState into the
unpaused-target spec; ensure shared utilities (disruptionState handling and
setMachineSetMigrationCAPIOperatorOverride) are factored into
BeforeEach/AfterEach or helper functions to avoid duplication and preserve
teardown behavior.
In `@pkg/controllers/synccommon/migratestatus_test.go`:
- Around line 33-156: Add a standard AfterEach cleanup to the test suite so
resources created by the Describe("Migration status helpers") specs are removed:
inside the top-level var _ = Describe("Migration status helpers", ...) block add
an AfterEach that calls testutils.CleanupResources(ctx, k8sClient) (or
appropriate cleanup helper signature) to delete created namespaces and API
objects; ensure the test file imports the testutils package and that ctx and
k8sClient are the same variables used by the tests so ApplySyncStatus,
ApplyMigrationStatus, and ApplyMigrationStatusAndResetSyncStatus specs are
cleaned up between runs.
In `@pkg/controllers/synccommon/syncstatus_integration_test.go`:
- Around line 45-292: Add an AfterEach that calls
testutils.CleanupResources(ctx, k8sClient) to tear down created namespaces and
objects after each spec; place one AfterEach inside each Describe that has a
BeforeEach creating resources (the Describe blocks that contain BeforeEach which
creates namespace/machineSet and namespace/machine), referencing the existing
ctx and k8sClient variables and ensuring it runs after each test to avoid
resource buildup.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository YAML (base), Central YAML (inherited)
Review profile: CHILL
Plan: Enterprise
Run ID: ac3337bf-5164-496a-8eb7-bccfe3e992bb
📒 Files selected for processing (32)
cmd/machine-api-migration/main.goe2e/go.mode2e/machine_migration_capi_authoritative_test.goe2e/machine_migration_helpers.goe2e/machine_migration_mapi_authoritative_test.goe2e/machineset_migration_capi_authoritative_test.goe2e/machineset_migration_disruptive_test.goe2e/machineset_migration_helpers.goe2e/machineset_migration_mapi_authoritative_test.gopkg/controllers/machinemigration/machine_migration_controller.gopkg/controllers/machinemigration/machine_migration_controller_test.gopkg/controllers/machinesetmigration/machineset_migration_controller.gopkg/controllers/machinesetmigration/machineset_migration_controller_test.gopkg/controllers/machinesetsync/machineset_sync_controller.gopkg/controllers/machinesetsync/machineset_sync_controller_test.gopkg/controllers/machinesetsync/machineset_sync_controller_unit_test.gopkg/controllers/machinesync/machine_sync_controller.gopkg/controllers/machinesync/machine_sync_controller_test.gopkg/controllers/migrationcommon/controller.gopkg/controllers/migrationcommon/controller_test.gopkg/controllers/migrationcommon/controllertest/helpers.gopkg/controllers/migrationcommon/pause.gopkg/controllers/migrationcommon/pause_test.gopkg/controllers/migrationcommon/suite_test.gopkg/controllers/synccommon/applyconfiguration.gopkg/controllers/synccommon/migratestatus.gopkg/controllers/synccommon/migratestatus_test.gopkg/controllers/synccommon/suite_test.gopkg/controllers/synccommon/syncstatus.gopkg/controllers/synccommon/syncstatus_integration_test.gopkg/controllers/synccommon/syncstatus_test.gopkg/conversion/test/fuzz/fuzz.go
💤 Files with no reviewable changes (1)
- cmd/machine-api-migration/main.go
1c9c77c to
7d010c8
Compare
|
/lgtm |
|
Scheduling tests matching the |
|
/retest-required |
1 similar comment
|
/retest-required |
| func verifyMachineSynchronizedAPI(mapiMachine *mapiv1beta1.Machine, expectedSynchronizedAPI mapiv1beta1.SynchronizedAPI) { | ||
| By(fmt.Sprintf("Verifying MAPI Machine SynchronizedAPI is %s", expectedSynchronizedAPI)) |
There was a problem hiding this comment.
| func verifyMachineSynchronizedAPI(mapiMachine *mapiv1beta1.Machine, expectedSynchronizedAPI mapiv1beta1.SynchronizedAPI) { | |
| By(fmt.Sprintf("Verifying MAPI Machine SynchronizedAPI is %s", expectedSynchronizedAPI)) | |
| func verifyMachineSynchronizedAPI(mapiMachine *mapiv1beta1.Machine, expectedSynchronizedAPI mapiv1beta1.SynchronizedAPI) { | |
| GinkgoHelper() | |
| By(fmt.Sprintf("Verifying MAPI Machine SynchronizedAPI is %s", expectedSynchronizedAPI)) |
| func verifyMachineSetSynchronizedAPI(mapiMachineSet *mapiv1beta1.MachineSet, expectedSynchronizedAPI mapiv1beta1.SynchronizedAPI) { | ||
| By(fmt.Sprintf("Verifying MAPI MachineSet SynchronizedAPI is %s", expectedSynchronizedAPI)) |
There was a problem hiding this comment.
| func verifyMachineSetSynchronizedAPI(mapiMachineSet *mapiv1beta1.MachineSet, expectedSynchronizedAPI mapiv1beta1.SynchronizedAPI) { | |
| By(fmt.Sprintf("Verifying MAPI MachineSet SynchronizedAPI is %s", expectedSynchronizedAPI)) | |
| func verifyMachineSetSynchronizedAPI(mapiMachineSet *mapiv1beta1.MachineSet, expectedSynchronizedAPI mapiv1beta1.SynchronizedAPI) { | |
| GinkgoHelper() | |
| By(fmt.Sprintf("Verifying MAPI MachineSet SynchronizedAPI is %s", expectedSynchronizedAPI)) |
| // On success, currentAuthority is guaranteed to be either MachineAPI or ClusterAPI. | ||
| // Missing or invalid SynchronizedAPI values are returned as errors instead of | ||
| // surfacing as a Migrating or otherwise unsupported current authority. | ||
| func MigrationDirection(statusAuthority mapiv1beta1.MachineAuthority, synchronizedAPI mapiv1beta1.SynchronizedAPI, specAuthority mapiv1beta1.MachineAuthority) (mapiv1beta1.MachineAuthority, mapiv1beta1.MachineAuthority, bool, error) { |
There was a problem hiding this comment.
nit for making it more readable for callers:
| func MigrationDirection(statusAuthority mapiv1beta1.MachineAuthority, synchronizedAPI mapiv1beta1.SynchronizedAPI, specAuthority mapiv1beta1.MachineAuthority) (mapiv1beta1.MachineAuthority, mapiv1beta1.MachineAuthority, bool, error) { | |
| func MigrationDirection(statusAuthority mapiv1beta1.MachineAuthority, synchronizedAPI mapiv1beta1.SynchronizedAPI, specAuthority mapiv1beta1.MachineAuthority) (currentAuthority, desiredAuthority mapiv1beta1.MachineAuthority, isMigrating bool, err error) { |
Advance status.AuthoritativeAPI toward spec.AuthoritativeAPI only when status.SynchronizedAPI and status.SynchronizedGeneration show the object is synchronized against the stable source state. Keep the transition through Migrating explicit, and reset synchronized status after the final status.AuthoritativeAPI change so sync can re-establish state from the new authoritative API. Align machine and MachineSet migration behavior around the same state machine by moving the shared transition logic into migrationcommon. Add shared unit and integration coverage for the new migration flow, and outage e2e coverage showing MachineSet migration can still advance with Cluster API controllers down and that rollback remains possible while the target stays paused.
7d010c8 to
508169b
Compare
|
New changes are detected. LGTM label has been removed. |
|
@RadekManak: 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. |
Summary
status.AuthoritativeAPItowardspec.AuthoritativeAPIonstatus.SynchronizedAPIandstatus.SynchronizedGeneration, so authority only advances from a stable synchronized source state.Migratingexplicit and reset synchronized status after the finalstatus.AuthoritativeAPIhandoff so sync can re-establish state from the new authoritative API.pkg/controllers/migrationcommon.Why
Before this PR, the migration controllers inferred the stable source of truth from
spec.AuthoritativeAPIandstatus.SynchronizedGenerationalone.That breaks down when a migration request changes mid-transition. Once
status.AuthoritativeAPIisMigrating,status.SynchronizedGenerationdoes not say whether it reflects Machine API or Cluster API state, so the controller can no longer safely tell which side is stable enough to advance towardspec.AuthoritativeAPI.In practice, that can block or mis-handle reversals of in-progress migration requests, especially when the target Cluster API side is unavailable. This PR makes the migration state explicit by tracking
status.SynchronizedAPI, gating authority changes on the actual synchronized source state, and resetting sync status after the final handoff.Implements OCPCLOUD-2998.
Reviewer Guide
This PR is large, but the behavior change is concentrated in a few places. It will likely be easier to review by area rather than as one continuous diff.
Start with
pkg/controllers/synccommon/syncstatus.goandpkg/controllers/synccommon/migratestatus.go.These define the status contract used by migration:
status.SynchronizedAPI,status.SynchronizedGeneration, and how synchronized status is reset after authority changes.Then read
pkg/controllers/migrationcommon/controller.go.This is the shared migration state machine that moves
status.AuthoritativeAPItowardspec.AuthoritativeAPI, including the explicitMigratingtransition.Then review the thin controller adapters:
pkg/controllers/machinemigration/...pkg/controllers/machinesetmigration/...These mostly wire Machines and MachineSets into the shared logic.
Review the remaining diff with that model in mind.
Most of the PR size after that is test restructuring and expanded coverage around the shared state machine and outage scenarios.
Test Plan
migrationcommonandsynccommonSummary by CodeRabbit
Release Notes
New Features
Tests