@@ -47,12 +47,9 @@ import (
4747 "k8s.io/client-go/tools/record"
4848 "k8s.io/utils/ptr"
4949 awsv1 "sigs.k8s.io/cluster-api-provider-aws/v2/api/v1beta2"
50- ibmpowervsv1 "sigs.k8s.io/cluster-api-provider-ibmcloud/api/v1beta2"
5150 openstackv1 "sigs.k8s.io/cluster-api-provider-openstack/api/v1beta1"
5251 clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
5352 "sigs.k8s.io/cluster-api/util/annotations"
54- "sigs.k8s.io/cluster-api/util/conditions"
55- conditionsv1beta2 "sigs.k8s.io/cluster-api/util/conditions/v1beta2"
5653 "sigs.k8s.io/cluster-api/util/labels/format"
5754 ctrl "sigs.k8s.io/controller-runtime"
5855 "sigs.k8s.io/controller-runtime/pkg/builder"
@@ -93,6 +90,9 @@ const (
9390)
9491
9592var (
93+ // errAssertingInfrasMachineClientObject is returned when we encounter an issue asserting a runtime.Object into a client.Object.
94+ errAssertingInfrasMachineClientObject = errors .New ("error asserting the Cluster API Infrastructure Machine to client.Object" )
95+
9696 // errAssertingCAPIAWSMachine is returned when we encounter an issue asserting a client.Object into an AWSMachine.
9797 errAssertingCAPIAWSMachine = errors .New ("error asserting the Cluster API AWSMachine object" )
9898
@@ -622,114 +622,6 @@ func (r *MachineSyncReconciler) convertCAPIToMAPIMachine(capiMachine *clusterv1.
622622 }
623623}
624624
625- // createOrUpdateCAPIInfraMachine creates a CAPI infra machine from a MAPI machine, or updates if it exists and it is out of date.
626- //
627- //nolint:funlen,unparam
628- func (r * MachineSyncReconciler ) createOrUpdateCAPIInfraMachine (ctx context.Context , mapiMachine * mapiv1beta1.Machine , infraMachine client.Object , newCAPIInfraMachine client.Object ) (ctrl.Result , bool , error ) {
629- logger := logf .FromContext (ctx )
630- // This variable tracks whether or not we are still progressing
631- // towards syncronizing the MAPI machine with the CAPI infra machine.
632- // It is then passed up the stack so the syncronized condition can be set accordingly.
633- syncronizationIsProgressing := false
634-
635- alreadyExists := false
636-
637- //nolint: nestif
638- if util .IsNilObject (infraMachine ) {
639- if err := r .Create (ctx , newCAPIInfraMachine ); err != nil && ! apierrors .IsAlreadyExists (err ) {
640- logger .Error (err , "Failed to create Cluster API infra machine" )
641- createErr := fmt .Errorf ("failed to create Cluster API infra machine: %w" , err )
642-
643- if condErr := r .applySynchronizedConditionWithPatch (ctx , mapiMachine , corev1 .ConditionFalse , reasonFailedToCreateCAPIInfraMachine , createErr .Error (), nil ); condErr != nil {
644- return ctrl.Result {}, syncronizationIsProgressing , utilerrors .NewAggregate ([]error {createErr , condErr })
645- }
646-
647- return ctrl.Result {}, syncronizationIsProgressing , createErr
648- } else if apierrors .IsAlreadyExists (err ) {
649- // this handles the case where the CAPI Machine is not present, so we can't resolve the
650- // infraMachine ref from it - but the InfraMachine exists. (e.g a user deletes the CAPI machine manually).
651- // This would lead to the call to fetchCAPIInfraResources returning nil for the infraMachine.
652- alreadyExists = true
653- } else {
654- logger .Info ("Successfully created Cluster API infra machine" )
655-
656- return ctrl.Result {}, syncronizationIsProgressing , nil
657- }
658- }
659-
660- if alreadyExists {
661- if err := r .Get (ctx , client .ObjectKeyFromObject (newCAPIInfraMachine ), infraMachine ); err != nil {
662- logger .Error (err , "Failed to get Cluster API infra machine" )
663- getErr := fmt .Errorf ("failed to get Cluster API infra machine: %w" , err )
664-
665- if condErr := r .applySynchronizedConditionWithPatch (ctx , mapiMachine , corev1 .ConditionFalse , reasonFailedToGetCAPIInfraResources , getErr .Error (), nil ); condErr != nil {
666- return ctrl.Result {}, syncronizationIsProgressing , utilerrors .NewAggregate ([]error {getErr , condErr })
667- }
668-
669- return ctrl.Result {}, syncronizationIsProgressing , getErr
670- }
671- }
672-
673- capiInfraMachinesDiff , err := compareCAPIInfraMachines (r .Platform , infraMachine , newCAPIInfraMachine )
674- if err != nil {
675- logger .Error (err , "Failed to check Cluster API infra machine diff" )
676- updateErr := fmt .Errorf ("failed to check Cluster API infra machine diff: %w" , err )
677-
678- if condErr := r .applySynchronizedConditionWithPatch (
679- ctx , mapiMachine , corev1 .ConditionFalse , reasonFailedToUpdateCAPIInfraMachine , updateErr .Error (), nil ); condErr != nil {
680- return ctrl.Result {}, syncronizationIsProgressing , utilerrors .NewAggregate ([]error {updateErr , condErr })
681- }
682-
683- return ctrl.Result {}, syncronizationIsProgressing , updateErr
684- }
685-
686- if len (capiInfraMachinesDiff ) == 0 {
687- logger .Info ("No changes detected in Cluster API infra machine" )
688- return ctrl.Result {}, syncronizationIsProgressing , nil
689- }
690-
691- logger .Info ("Deleting the corresponding Cluster API infra machine as it is out of date, it will be recreated" , "diff" , fmt .Sprintf ("%+v" , capiInfraMachinesDiff ))
692-
693- if err := r .Delete (ctx , infraMachine ); err != nil {
694- logger .Error (err , "Failed to delete Cluster API infra machine" )
695-
696- deleteErr := fmt .Errorf ("failed to delete Cluster API infra machine: %w" , err )
697-
698- if condErr := r .applySynchronizedConditionWithPatch (
699- ctx , mapiMachine , corev1 .ConditionFalse , reasonFailedToUpdateCAPIInfraMachine , deleteErr .Error (), nil ); condErr != nil {
700- return ctrl.Result {}, syncronizationIsProgressing , utilerrors .NewAggregate ([]error {deleteErr , condErr })
701- }
702-
703- return ctrl.Result {}, syncronizationIsProgressing , deleteErr
704- }
705-
706- // Remove finalizers from the deleting CAPI infraMachine, it is not authoritative.
707- infraMachine .SetFinalizers (nil )
708-
709- if err := r .Update (ctx , infraMachine ); err != nil {
710- logger .Error (err , "Failed to remove finalizer for deleting Cluster API infra machine" )
711-
712- deleteErr := fmt .Errorf ("failed to remove finalizer for deleting Cluster API infra machine: %w" , err )
713-
714- if condErr := r .applySynchronizedConditionWithPatch (
715- ctx , mapiMachine , corev1 .ConditionFalse , reasonFailedToUpdateCAPIInfraMachine , deleteErr .Error (), nil ); condErr != nil {
716- return ctrl.Result {}, syncronizationIsProgressing , utilerrors .NewAggregate ([]error {deleteErr , condErr })
717- }
718-
719- return ctrl.Result {}, syncronizationIsProgressing , deleteErr
720- }
721-
722- // The outdated outdated CAPI infra machine has been deleted.
723- // We will try and recreate an up-to-date one later.
724- logger .Info ("Successfully deleted outdated Cluster API infra machine" )
725-
726- // Set the syncronized as progressing to signal the caller
727- // we are still progressing and aren't fully synced yet.
728- syncronizationIsProgressing = true
729-
730- return ctrl.Result {}, syncronizationIsProgressing , nil
731- }
732-
733625// ensureCAPIMachine creates a new CAPI machine if one doesn't exist.
734626func (r * MachineSyncReconciler ) ensureCAPIMachine (ctx context.Context , sourceMAPIMachine * mapiv1beta1.Machine , existingCAPIMachine , convertedCAPIMachine * clusterv1.Machine ) (* clusterv1.Machine , error ) {
735627 // If there is an existing CAPI machine, no need to create one.
@@ -1410,79 +1302,6 @@ func compareMAPIMachines(a, b *mapiv1beta1.Machine) (map[string]any, error) {
14101302 return diff , nil
14111303}
14121304
1413- // compareCAPIInfraMachines compares CAPI infra machines a and b, and returns a list of differences, or none if there are none.
1414- //
1415- //nolint:funlen
1416- func compareCAPIInfraMachines (platform configv1.PlatformType , infraMachine1 , infraMachine2 client.Object ) (map [string ]any , error ) {
1417- switch platform {
1418- case configv1 .AWSPlatformType :
1419- typedInfraMachine1 , ok := infraMachine1 .(* awsv1.AWSMachine )
1420- if ! ok {
1421- return nil , errAssertingCAPIAWSMachine
1422- }
1423-
1424- typedinfraMachine2 , ok := infraMachine2 .(* awsv1.AWSMachine )
1425- if ! ok {
1426- return nil , errAssertingCAPIAWSMachine
1427- }
1428-
1429- diff := make (map [string ]any )
1430- if diffSpec := deep .Equal (typedInfraMachine1 .Spec , typedinfraMachine2 .Spec ); len (diffSpec ) > 0 {
1431- diff [".spec" ] = diffSpec
1432- }
1433-
1434- if diffMetadata := util .ObjectMetaEqual (typedInfraMachine1 .ObjectMeta , typedinfraMachine2 .ObjectMeta ); len (diffMetadata ) > 0 {
1435- diff [".metadata" ] = diffMetadata
1436- }
1437-
1438- return diff , nil
1439- case configv1 .OpenStackPlatformType :
1440- typedInfraMachine1 , ok := infraMachine1 .(* openstackv1.OpenStackMachine )
1441- if ! ok {
1442- return nil , errAssertingCAPIOpenStackMachine
1443- }
1444-
1445- typedinfraMachine2 , ok := infraMachine2 .(* openstackv1.OpenStackMachine )
1446- if ! ok {
1447- return nil , errAssertingCAPIOpenStackMachine
1448- }
1449-
1450- diff := make (map [string ]any )
1451- if diffSpec := deep .Equal (typedInfraMachine1 .Spec , typedinfraMachine2 .Spec ); len (diffSpec ) > 0 {
1452- diff [".spec" ] = diffSpec
1453- }
1454-
1455- if diffMetadata := util .ObjectMetaEqual (typedInfraMachine1 .ObjectMeta , typedinfraMachine2 .ObjectMeta ); len (diffMetadata ) > 0 {
1456- diff [".metadata" ] = diffMetadata
1457- }
1458-
1459- return diff , nil
1460- case configv1 .PowerVSPlatformType :
1461- typedInfraMachine1 , ok := infraMachine1 .(* ibmpowervsv1.IBMPowerVSMachine )
1462- if ! ok {
1463- return nil , errAssertingCAPIIBMPowerVSMachine
1464- }
1465-
1466- typedinfraMachine2 , ok := infraMachine2 .(* ibmpowervsv1.IBMPowerVSMachine )
1467- if ! ok {
1468- return nil , errAssertingCAPIIBMPowerVSMachine
1469- }
1470-
1471- diff := make (map [string ]any )
1472- if diffSpec := deep .Equal (typedInfraMachine1 .Spec , typedinfraMachine2 .Spec ); len (diffSpec ) > 0 {
1473- diff [".spec" ] = diffSpec
1474- }
1475-
1476- if diffMetadata := util .ObjectMetaEqual (typedInfraMachine1 .ObjectMeta , typedinfraMachine2 .ObjectMeta ); len (diffMetadata ) > 0 {
1477- diff [".metadata" ] = diffMetadata
1478- }
1479-
1480- return diff , nil
1481- default :
1482- return nil , fmt .Errorf ("%w: %s" , errPlatformNotSupported , platform )
1483- }
1484- }
1485-
14861305// ensureCAPIMachineStatusUpdated updates the CAPI machine status if changes are detected and conditions are met.
14871306func (r * MachineSyncReconciler ) ensureCAPIMachineStatusUpdated (ctx context.Context , mapiMachine * mapiv1beta1.Machine , existingCAPIMachine , convertedCAPIMachine , updatedOrCreatedCAPIMachine * clusterv1.Machine , capiMachinesDiff map [string ]any , specUpdated bool ) (bool , error ) {
14881307 logger := logf .FromContext (ctx )
@@ -1580,6 +1399,10 @@ func (r *MachineSyncReconciler) ensureMAPIMachineStatusUpdated(ctx context.Conte
15801399 // Set the changed MAPI machine status fields from the converted MAPI machine.
15811400 setChangedMAPIMachineStatusFields (existingMAPIMachine , convertedMAPIMachine )
15821401
1402+ if err := setChangedMAPIMachineProviderStatusFields (r .Platform , existingMAPIMachine , convertedMAPIMachine ); err != nil {
1403+ return false , fmt .Errorf ("failed to set provider status fields: %w" , err )
1404+ }
1405+
15831406 // Here we would've updated the observed generation to match the updated source API object generation.
15841407 // MAPI Machine does not have the observed generation field.
15851408
@@ -1638,26 +1461,10 @@ func (r *MachineSyncReconciler) ensureMAPIMachineSpecUpdated(ctx context.Context
16381461func setChangedCAPIMachineStatusFields (existingCAPIMachine , convertedCAPIMachine * clusterv1.Machine ) {
16391462 // convertedCAPIMachine holds the computed and desired status changes converted from the source MAPI machine, so apply them to the existing existingCAPIMachine.
16401463 // Merge the v1beta1 conditions.
1641- for i := range convertedCAPIMachine .Status .Conditions {
1642- conditions .Set (existingCAPIMachine , & convertedCAPIMachine .Status .Conditions [i ])
1643- }
1644-
1645- // Copy them back to the convertedCAPIMachine.
1646- convertedCAPIMachine .Status .Conditions = existingCAPIMachine .Status .Conditions
1464+ util .EnsureCAPIConditions (existingCAPIMachine , convertedCAPIMachine )
16471465
16481466 // Merge the v1beta2 conditions.
1649- if convertedCAPIMachine .Status .V1Beta2 != nil {
1650- if existingCAPIMachine .Status .V1Beta2 == nil {
1651- existingCAPIMachine .Status .V1Beta2 = & clusterv1.MachineV1Beta2Status {}
1652- }
1653-
1654- for i := range convertedCAPIMachine .Status .V1Beta2 .Conditions {
1655- conditionsv1beta2 .Set (existingCAPIMachine , convertedCAPIMachine .Status .V1Beta2 .Conditions [i ])
1656- }
1657-
1658- // Copy them back to the convertedCAPIMachine.
1659- convertedCAPIMachine .Status .V1Beta2 .Conditions = existingCAPIMachine .Status .V1Beta2 .Conditions
1660- }
1467+ util .EnsureCAPIV1Beta2Conditions (existingCAPIMachine , convertedCAPIMachine )
16611468
16621469 // Finally overwrite the entire existingCAPIMachine status with the convertedCAPIMachine status.
16631470 existingCAPIMachine .Status = convertedCAPIMachine .Status
@@ -1701,9 +1508,18 @@ func (r *MachineSyncReconciler) applySynchronizedConditionWithPatch(ctx context.
17011508
17021509// hasSpecOrMetadataOrProviderSpecChanges checks if there are spec, metadata, or provider spec changes in the diff.
17031510func hasSpecOrMetadataOrProviderSpecChanges (diff map [string ]any ) bool {
1704- _ , hasSpec := diff [".spec" ]
1705- _ , hasMetadata := diff [".metadata" ]
17061511 _ , hasProviderSpec := diff [".providerSpec" ]
1512+ return hasSpecChanges (diff ) || hasMetadataChanges (diff ) || hasProviderSpec
1513+ }
1514+
1515+ // hasSpecChanges checks if there are spec changes in the diff.
1516+ func hasSpecChanges (diff map [string ]any ) bool {
1517+ _ , hasSpec := diff [".spec" ]
1518+ return hasSpec
1519+ }
17071520
1708- return hasSpec || hasMetadata || hasProviderSpec
1521+ // hasSpecChanges checks if there are spec changes in the diff.
1522+ func hasMetadataChanges (diff map [string ]any ) bool {
1523+ _ , hasSpec := diff [".metadata" ]
1524+ return hasSpec
17091525}
0 commit comments