diff --git a/cloud/interfaces.go b/cloud/interfaces.go index 27abdcb42..0c81f7668 100644 --- a/cloud/interfaces.go +++ b/cloud/interfaces.go @@ -86,6 +86,7 @@ type MachineGetter interface { Project() string Role() string IsControlPlane() bool + IsMachineProvisioned() bool ControlPlaneGroupName() string GetInstanceID() *string GetProviderID() string diff --git a/cloud/scope/machine.go b/cloud/scope/machine.go index 1683d16d0..b56374f69 100644 --- a/cloud/scope/machine.go +++ b/cloud/scope/machine.go @@ -140,6 +140,17 @@ func (m *MachineScope) IsControlPlane() bool { return IsControlPlaneMachine(m.Machine) } +// IsMachineProvisioned returns true if the machine has been provisioned. +func (m *MachineScope) IsMachineProvisioned() bool { + // return m.Machine.Status.GetTypedPhase() == clusterv1.MachinePhaseProvisioned + for _, condition := range m.Machine.Status.Conditions { + if condition.Type == clusterv1.MachineNodeHealthyCondition && condition.Reason == clusterv1.WaitingForNodeRefReason { + return true + } + } + return false +} + // Role returns the machine role from the labels. func (m *MachineScope) Role() string { if IsControlPlaneMachine(m.Machine) { diff --git a/cloud/services/compute/instances/reconcile.go b/cloud/services/compute/instances/reconcile.go index 76277d072..62a1e907b 100644 --- a/cloud/services/compute/instances/reconcile.go +++ b/cloud/services/compute/instances/reconcile.go @@ -89,8 +89,13 @@ func (s *Service) Reconcile(ctx context.Context) error { s.scope.SetInstanceStatus(infrav1.InstanceStatus(instance.Status)) if s.scope.IsControlPlane() { - if err := s.registerControlPlaneInstance(ctx, instance); err != nil { - return err + if s.scope.IsMachineProvisioned() { + log.V(2).Info("[DEBUG] Registering control plane instance in the instancegroup", "name", instance.Name) + if err := s.registerControlPlaneInstance(ctx, instance); err != nil { + return err + } + } else { + log.V(2).Info("[DEBUG] Skipping registering control plane instance in the instancegroup because machine is not yet provisioned", "name", instance.Name) } } diff --git a/controllers/gcpmachine_controller.go b/controllers/gcpmachine_controller.go index 87c4f582c..01254a852 100644 --- a/controllers/gcpmachine_controller.go +++ b/controllers/gcpmachine_controller.go @@ -33,11 +33,14 @@ import ( "sigs.k8s.io/cluster-api/util/predicates" "sigs.k8s.io/cluster-api/util/record" ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/builder" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/controller" "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" + "sigs.k8s.io/controller-runtime/pkg/event" "sigs.k8s.io/controller-runtime/pkg/handler" "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/predicate" "sigs.k8s.io/controller-runtime/pkg/source" ) @@ -63,6 +66,33 @@ func (r *GCPMachineReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Ma Watches( &clusterv1.Machine{}, handler.EnqueueRequestsFromMapFunc(util.MachineToInfrastructureMapFunc(infrav1.GroupVersion.WithKind("GCPMachine"))), + builder.WithPredicates(predicate.Funcs{ + UpdateFunc: func(e event.UpdateEvent) bool { + oldMachine := e.ObjectOld.(*clusterv1.Machine) + newMachine := e.ObjectNew.(*clusterv1.Machine) + + // Reconcile if the spec changes. + if newMachine.GetGeneration() != oldMachine.GetGeneration() { + return true + } + + // Reconcile if the machine just transitioned to the Provisioned phase. + if newMachine.Status.GetTypedPhase() == clusterv1.MachinePhaseProvisioned && oldMachine.Status.GetTypedPhase() != clusterv1.MachinePhaseProvisioned { + return true + } + + for _, condition := range newMachine.Status.Conditions { + if condition.Type == clusterv1.MachineNodeHealthyCondition { + // TODO: Reconcile if the MachineNodeHealthyCondition condition changed. + if condition.Type == clusterv1.MachineNodeHealthyCondition && condition.Reason == clusterv1.WaitingForNodeRefReason { + return true + } + } + } + + return false + }, + }), ). Watches( &infrav1.GCPCluster{}, @@ -224,7 +254,8 @@ func (r *GCPMachineReconciler) reconcile(ctx context.Context, machineScope *scop return ctrl.Result{}, err } - if err := instances.New(machineScope).Reconcile(ctx); err != nil { + instancesSvc := instances.New(machineScope) + if err := instancesSvc.Reconcile(ctx); err != nil { log.Error(err, "Error reconciling instance resources") record.Warnf(machineScope.GCPMachine, "GCPMachineReconcile", "Reconcile error - %v", err) return ctrl.Result{}, err