From a53b2c5efd9e981332ec7ca369fe3a5578ee7ea5 Mon Sep 17 00:00:00 2001 From: Yuvaraj Kakaraparthi Date: Wed, 24 May 2023 00:17:45 -0700 Subject: [PATCH] refactor --- .../topology/cluster/desired_state.go | 83 ++++++++----------- .../topology/cluster/desired_state_test.go | 66 ++++++++------- .../topology/cluster/reconcile_state.go | 22 ++--- .../topology/cluster/scope/upgradetracker.go | 5 ++ 4 files changed, 79 insertions(+), 97 deletions(-) diff --git a/internal/controllers/topology/cluster/desired_state.go b/internal/controllers/topology/cluster/desired_state.go index 62eefde67261..a11e2d3018b8 100644 --- a/internal/controllers/topology/cluster/desired_state.go +++ b/internal/controllers/topology/cluster/desired_state.go @@ -89,7 +89,7 @@ func (r *Reconciler) computeDesiredState(ctx context.Context, s *scope.Scope) (* // If required, compute the desired state of the MachineDeployments from the list of MachineDeploymentTopologies // defined in the cluster. if s.Blueprint.HasMachineDeployments() { - desiredState.MachineDeployments, err = r.computeMachineDeployments(ctx, s, desiredState.ControlPlane) + desiredState.MachineDeployments, err = r.computeMachineDeployments(ctx, s) if err != nil { return nil, errors.Wrapf(err, "failed to compute MachineDeployments") } @@ -461,6 +461,7 @@ func (r *Reconciler) computeControlPlaneVersion(ctx context.Context, s *scope.Sc // Control plane and machine deployments are stable. All the required hook are called. // Ready to pick up the topology version. s.UpgradeTracker.ControlPlane.PendingUpgrade = false + s.UpgradeTracker.ControlPlane.IsStartingUpgrade = true return desiredVersion, nil } @@ -524,7 +525,7 @@ func calculateRefDesiredAPIVersion(currentRef *corev1.ObjectReference, desiredRe } // computeMachineDeployments computes the desired state of the list of MachineDeployments. -func (r *Reconciler) computeMachineDeployments(ctx context.Context, s *scope.Scope, desiredControlPlaneState *scope.ControlPlaneState) (scope.MachineDeploymentsStateMap, error) { +func (r *Reconciler) computeMachineDeployments(ctx context.Context, s *scope.Scope) (scope.MachineDeploymentsStateMap, error) { // Mark all the MachineDeployments that are currently upgrading. // This captured information is used for: // - Building the TopologyReconciled condition. @@ -542,7 +543,7 @@ func (r *Reconciler) computeMachineDeployments(ctx context.Context, s *scope.Sco machineDeploymentsStateMap := make(scope.MachineDeploymentsStateMap) for _, mdTopology := range s.Blueprint.Topology.Workers.MachineDeployments { - desiredMachineDeployment, err := computeMachineDeployment(ctx, s, desiredControlPlaneState, mdTopology) + desiredMachineDeployment, err := computeMachineDeployment(ctx, s, mdTopology) if err != nil { return nil, errors.Wrapf(err, "failed to compute MachineDepoyment for topology %q", mdTopology.Name) } @@ -554,7 +555,7 @@ func (r *Reconciler) computeMachineDeployments(ctx context.Context, s *scope.Sco // computeMachineDeployment computes the desired state for a MachineDeploymentTopology. // The generated machineDeployment object is calculated using the values from the machineDeploymentTopology and // the machineDeployment class. -func computeMachineDeployment(_ context.Context, s *scope.Scope, desiredControlPlaneState *scope.ControlPlaneState, machineDeploymentTopology clusterv1.MachineDeploymentTopology) (*scope.MachineDeploymentState, error) { +func computeMachineDeployment(_ context.Context, s *scope.Scope, machineDeploymentTopology clusterv1.MachineDeploymentTopology) (*scope.MachineDeploymentState, error) { desiredMachineDeployment := &scope.MachineDeploymentState{} // Gets the blueprint for the MachineDeployment class. @@ -701,10 +702,7 @@ func computeMachineDeployment(_ context.Context, s *scope.Scope, desiredControlP desiredMachineDeploymentObj.SetName(currentMachineDeployment.Object.Name) } - version, err := computeMachineDeploymentVersion(s, desiredMachineDeploymentObj.Name, machineDeploymentTopology, desiredControlPlaneState, currentMachineDeployment) - if err != nil { - return nil, errors.Wrapf(err, "failed to compute version for %s", machineDeploymentTopology.Name) - } + version := computeMachineDeploymentVersion(s, desiredMachineDeploymentObj.Name, machineDeploymentTopology, currentMachineDeployment) desiredMachineDeploymentObj.Spec.Template.Spec.Version = pointer.String(version) // Apply annotations @@ -760,16 +758,23 @@ func computeMachineDeployment(_ context.Context, s *scope.Scope, desiredControlP // computeMachineDeploymentVersion calculates the version of the desired machine deployment. // The version is calculated using the state of the current machine deployments, // the current control plane and the version defined in the topology. -// Nb: No MachineDeployment upgrades will be triggered while any MachineDeployment is in the middle -// of an upgrade. Even if the number of MachineDeployments that are being upgraded is less -// than the number of allowed concurrent upgrades. -func computeMachineDeploymentVersion(s *scope.Scope, desiredMDName string, machineDeploymentTopology clusterv1.MachineDeploymentTopology, desiredControlPlaneState *scope.ControlPlaneState, currentMDState *scope.MachineDeploymentState) (string, error) { +func computeMachineDeploymentVersion(s *scope.Scope, desiredMDName string, machineDeploymentTopology clusterv1.MachineDeploymentTopology, currentMDState *scope.MachineDeploymentState) string { desiredVersion := s.Blueprint.Topology.Version - // If creating a new machine deployment, we can pick up the desired version - // Note: We are not blocking the creation of new machine deployments when - // the control plane or any of the machine deployments are upgrading/scaling. + // If creating a new machine deployment mark it as pending if the control plane is not + // yet stable. Creating a new MD while the control plane is upgrading is unsafe. if currentMDState == nil || currentMDState.Object == nil { - return desiredVersion, nil + if s.UpgradeTracker.ControlPlane.IsStartingUpgrade || + s.UpgradeTracker.ControlPlane.IsUpgrading || + s.UpgradeTracker.ControlPlane.IsScaling || + s.UpgradeTracker.ControlPlane.IsProvisioning { + // TODO(ykakarap): Here we are marking as pending upgrade so that the reconciliation of this MD does not + // occur and therefore not create the new MD. Find a better name. + // TODO(ykakarap): Reusing MarkPendingUpgrade is a problem because then MD creations will be counted + // against upgrade concurrency which should not be the case, at least according to the current concurrency + // definitions. + s.UpgradeTracker.MachineDeployments.MarkPendingUpgrade(desiredMDName) + } + return desiredVersion } // Get the current version of the machine deployment. @@ -778,19 +783,20 @@ func computeMachineDeploymentVersion(s *scope.Scope, desiredMDName string, machi // Return early if the currentVersion is already equal to the desiredVersion // no further checks required. if currentVersion == desiredVersion { - return currentVersion, nil + return currentVersion } // Return early if the upgrade for the MachineDeployment is deferred. if isMachineDeploymentDeferred(s.Blueprint.Topology, machineDeploymentTopology) { s.UpgradeTracker.MachineDeployments.MarkDeferredUpgrade(desiredMDName) - return currentVersion, nil + s.UpgradeTracker.MachineDeployments.MarkPendingUpgrade(desiredMDName) + return currentVersion } // Return early if we are not allowed to upgrade the machine deployment. if !s.UpgradeTracker.MachineDeployments.AllowUpgrade() { s.UpgradeTracker.MachineDeployments.MarkPendingUpgrade(desiredMDName) - return currentVersion, nil + return currentVersion } // If the control plane is being created (current control plane is nil), do not perform @@ -800,21 +806,15 @@ func computeMachineDeploymentVersion(s *scope.Scope, desiredMDName string, machi // but we are implementing this check for extra safety. if s.Current.ControlPlane == nil || s.Current.ControlPlane.Object == nil { s.UpgradeTracker.MachineDeployments.MarkPendingUpgrade(desiredMDName) - // TODO(ykakarap): Hold out creating new MD. - return currentVersion, nil + return currentVersion } // If the current control plane is upgrading, then do not pick up the desiredVersion yet. // Return the current version of the machine deployment. We will pick up the new version after the control // plane is stable. - cpUpgrading, err := contract.ControlPlane().IsUpgrading(s.Current.ControlPlane.Object) - if err != nil { - return "", errors.Wrap(err, "failed to check if control plane is upgrading") - } - if cpUpgrading { + if s.UpgradeTracker.ControlPlane.IsUpgrading { s.UpgradeTracker.MachineDeployments.MarkPendingUpgrade(desiredMDName) - // TODO(ykakarap): Hold out creating new MD. - return currentVersion, nil + return currentVersion } // If control plane supports replicas, check if the control plane is in the middle of a scale operation. @@ -822,47 +822,32 @@ func computeMachineDeploymentVersion(s *scope.Scope, desiredMDName string, machi // Return the current version of the machine deployment. We will pick up the new version after the control // plane is stable. if s.Blueprint.Topology.ControlPlane.Replicas != nil { - cpScaling, err := contract.ControlPlane().IsScaling(s.Current.ControlPlane.Object) - if err != nil { - return "", errors.Wrap(err, "failed to check if the control plane is scaling") - } - if cpScaling { + if s.UpgradeTracker.ControlPlane.IsScaling { s.UpgradeTracker.MachineDeployments.MarkPendingUpgrade(desiredMDName) - // TODO(ykakarap): Hold out creating new MD. - return currentVersion, nil + return currentVersion } } // Check if we are about to upgrade the control plane. In that case, do not upgrade the machine deployment yet. // Wait for the new upgrade operation on the control plane to finish before picking up the new version for the // machine deployment. - currentCPVersion, err := contract.ControlPlane().Version().Get(s.Current.ControlPlane.Object) - if err != nil { - return "", errors.Wrap(err, "failed to get version of current control plane") - } - desiredCPVersion, err := contract.ControlPlane().Version().Get(desiredControlPlaneState.Object) - if err != nil { - return "", errors.Wrap(err, "failed to get version of desired control plane") - } - if *currentCPVersion != *desiredCPVersion { + if s.UpgradeTracker.ControlPlane.IsStartingUpgrade { // The versions of the current and desired control planes do no match, // implies we are about to upgrade the control plane. s.UpgradeTracker.MachineDeployments.MarkPendingUpgrade(desiredMDName) - // TODO(ykakarap): Hold out creating new MD. - return currentVersion, nil + return currentVersion } // If the ControlPlane is pending picking up an upgrade then do not pick up the new version yet. if s.UpgradeTracker.ControlPlane.PendingUpgrade { s.UpgradeTracker.MachineDeployments.MarkPendingUpgrade(desiredMDName) - // TODO(ykakarap): Hold out creating new MD. - return currentVersion, nil + return currentVersion } // Control plane and machine deployments are stable. // Ready to pick up the topology version. s.UpgradeTracker.MachineDeployments.MarkUpgradingAndRollingOut(desiredMDName) - return desiredVersion, nil + return desiredVersion } // isMachineDeploymentDeferred returns true if the upgrade for the mdTopology is deferred. diff --git a/internal/controllers/topology/cluster/desired_state_test.go b/internal/controllers/topology/cluster/desired_state_test.go index ebfed2619eaf..6922fd2e5019 100644 --- a/internal/controllers/topology/cluster/desired_state_test.go +++ b/internal/controllers/topology/cluster/desired_state_test.go @@ -27,7 +27,6 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/util/intstr" - "k8s.io/apimachinery/pkg/util/sets" utilfeature "k8s.io/component-base/featuregate/testing" "k8s.io/utils/pointer" "sigs.k8s.io/controller-runtime/pkg/client/fake" @@ -1461,7 +1460,7 @@ func TestComputeMachineDeployment(t *testing.T) { scope := scope.New(cluster) scope.Blueprint = blueprint - actual, err := computeMachineDeployment(ctx, scope, nil, mdTopology) + actual, err := computeMachineDeployment(ctx, scope, mdTopology) g.Expect(err).ToNot(HaveOccurred()) g.Expect(actual.BootstrapTemplate.GetLabels()).To(HaveKeyWithValue(clusterv1.ClusterTopologyMachineDeploymentNameLabel, "big-pool-of-machines")) @@ -1530,7 +1529,7 @@ func TestComputeMachineDeployment(t *testing.T) { // missing FailureDomain, NodeDrainTimeout, NodeVolumeDetachTimeout, NodeDeletionTimeout, MinReadySeconds, Strategy } - actual, err := computeMachineDeployment(ctx, scope, nil, mdTopology) + actual, err := computeMachineDeployment(ctx, scope, mdTopology) g.Expect(err).ToNot(HaveOccurred()) // checking only values from CC defaults @@ -1574,7 +1573,7 @@ func TestComputeMachineDeployment(t *testing.T) { }, } - actual, err := computeMachineDeployment(ctx, s, nil, mdTopology) + actual, err := computeMachineDeployment(ctx, s, mdTopology) g.Expect(err).ToNot(HaveOccurred()) actualMd := actual.Object @@ -1622,7 +1621,7 @@ func TestComputeMachineDeployment(t *testing.T) { Name: "big-pool-of-machines", } - _, err := computeMachineDeployment(ctx, scope, nil, mdTopology) + _, err := computeMachineDeployment(ctx, scope, mdTopology) g.Expect(err).To(HaveOccurred()) }) @@ -1728,9 +1727,6 @@ func TestComputeMachineDeployment(t *testing.T) { Object: controlPlaneStable123, } s.UpgradeTracker.MachineDeployments.MarkRollingOut(s.Current.MachineDeployments.RollingOut()...) - desiredControlPlaneState := &scope.ControlPlaneState{ - Object: controlPlaneStable123, - } mdTopology := clusterv1.MachineDeploymentTopology{ Class: "linux-worker", @@ -1738,7 +1734,7 @@ func TestComputeMachineDeployment(t *testing.T) { Replicas: pointer.Int32(2), } s.UpgradeTracker.MachineDeployments.MarkUpgradingAndRollingOut(tt.upgradingMachineDeployments...) - obj, err := computeMachineDeployment(ctx, s, desiredControlPlaneState, mdTopology) + obj, err := computeMachineDeployment(ctx, s, mdTopology) g.Expect(err).NotTo(HaveOccurred()) g.Expect(*obj.Object.Spec.Template.Spec.Version).To(Equal(tt.expectedVersion)) }) @@ -1754,7 +1750,7 @@ func TestComputeMachineDeployment(t *testing.T) { Name: "big-pool-of-machines", } - actual, err := computeMachineDeployment(ctx, scope, nil, mdTopology) + actual, err := computeMachineDeployment(ctx, scope, mdTopology) g.Expect(err).To(BeNil()) // Check that the ClusterName and selector are set properly for the MachineHealthCheck. g.Expect(actual.MachineHealthCheck.Spec.ClusterName).To(Equal(cluster.Name)) @@ -1825,6 +1821,9 @@ func TestComputeMachineDeploymentVersion(t *testing.T) { }). Build() + mdName := "md-1" + currentMachineDeploymentState := &scope.MachineDeploymentState{Object: builder.MachineDeployment("test1", mdName).WithVersion("v1.2.2").Build()} + tests := []struct { name string machineDeploymentTopology clusterv1.MachineDeploymentTopology @@ -1833,6 +1832,10 @@ func TestComputeMachineDeploymentVersion(t *testing.T) { upgradeConcurrency int currentControlPlane *unstructured.Unstructured desiredControlPlane *unstructured.Unstructured + controlPlaneStartingUpgrade bool + controlPlaneUpgrading bool + controlPlaneScaling bool + controlPlaneProvisioning bool topologyVersion string expectedVersion string }{ @@ -1851,7 +1854,7 @@ func TestComputeMachineDeploymentVersion(t *testing.T) { }, }, }, - currentMachineDeploymentState: &scope.MachineDeploymentState{Object: builder.MachineDeployment("test1", "md-current").WithVersion("v1.2.2").Build()}, + currentMachineDeploymentState: currentMachineDeploymentState, upgradingMachineDeployments: []string{}, currentControlPlane: controlPlaneStable123, desiredControlPlane: controlPlaneDesired, @@ -1861,34 +1864,37 @@ func TestComputeMachineDeploymentVersion(t *testing.T) { { // Control plane is considered upgrading if the control plane's spec.version and status.version is not equal. name: "should return machine deployment's spec.template.spec.version if control plane is upgrading", - currentMachineDeploymentState: &scope.MachineDeploymentState{Object: builder.MachineDeployment("test1", "md-current").WithVersion("v1.2.2").Build()}, + currentMachineDeploymentState: currentMachineDeploymentState, upgradingMachineDeployments: []string{}, currentControlPlane: controlPlaneUpgrading, + controlPlaneUpgrading: true, topologyVersion: "v1.2.3", expectedVersion: "v1.2.2", }, { // Control plane is considered ready to upgrade if spec.version of current and desired control planes are not equal. - name: "should return machine deployment's spec.template.spec.version if control plane is ready to upgrade", - currentMachineDeploymentState: &scope.MachineDeploymentState{Object: builder.MachineDeployment("test1", "md-current").WithVersion("v1.2.2").Build()}, + name: "should return machine deployment's spec.template.spec.version if control plane is starting upgrade", + currentMachineDeploymentState: currentMachineDeploymentState, upgradingMachineDeployments: []string{}, currentControlPlane: controlPlaneStable122, desiredControlPlane: controlPlaneDesired, + controlPlaneStartingUpgrade: true, topologyVersion: "v1.2.3", expectedVersion: "v1.2.2", }, { // Control plane is considered scaling if its spec.replicas is not equal to any of status.replicas, status.readyReplicas or status.updatedReplicas. name: "should return machine deployment's spec.template.spec.version if control plane is scaling", - currentMachineDeploymentState: &scope.MachineDeploymentState{Object: builder.MachineDeployment("test1", "md-current").WithVersion("v1.2.2").Build()}, + currentMachineDeploymentState: currentMachineDeploymentState, upgradingMachineDeployments: []string{}, currentControlPlane: controlPlaneScaling, + controlPlaneScaling: true, topologyVersion: "v1.2.3", expectedVersion: "v1.2.2", }, { name: "should return cluster.spec.topology.version if the control plane is not upgrading, not scaling, not ready to upgrade and none of the machine deployments are rolling out", - currentMachineDeploymentState: &scope.MachineDeploymentState{Object: builder.MachineDeployment("test1", "md-current").WithVersion("v1.2.2").Build()}, + currentMachineDeploymentState: currentMachineDeploymentState, upgradingMachineDeployments: []string{}, currentControlPlane: controlPlaneStable123, desiredControlPlane: controlPlaneDesired, @@ -1897,7 +1903,7 @@ func TestComputeMachineDeploymentVersion(t *testing.T) { }, { name: "should return cluster.spec.topology.version if control plane is stable, other machine deployments are rolling out, concurrency limit not reached", - currentMachineDeploymentState: &scope.MachineDeploymentState{Object: builder.MachineDeployment("test1", "md-current").WithVersion("v1.2.2").Build()}, + currentMachineDeploymentState: currentMachineDeploymentState, upgradingMachineDeployments: []string{"upgrading-md1"}, upgradeConcurrency: 2, currentControlPlane: controlPlaneStable123, @@ -1907,7 +1913,7 @@ func TestComputeMachineDeploymentVersion(t *testing.T) { }, { name: "should return machine deployment's spec.template.spec.version if control plane is stable, other machine deployments are rolling out, concurrency limit reached", - currentMachineDeploymentState: &scope.MachineDeploymentState{Object: builder.MachineDeployment("test1", "md-current").WithVersion("v1.2.2").Build()}, + currentMachineDeploymentState: currentMachineDeploymentState, upgradingMachineDeployments: []string{"upgrading-md1", "upgrading-md2"}, upgradeConcurrency: 2, currentControlPlane: controlPlaneStable123, @@ -1934,24 +1940,20 @@ func TestComputeMachineDeploymentVersion(t *testing.T) { }, UpgradeTracker: scope.NewUpgradeTracker(scope.MaxMDUpgradeConcurrency(tt.upgradeConcurrency)), } - desiredControlPlaneState := &scope.ControlPlaneState{Object: tt.desiredControlPlane} + s.UpgradeTracker.ControlPlane.IsStartingUpgrade = tt.controlPlaneStartingUpgrade + s.UpgradeTracker.ControlPlane.IsUpgrading = tt.controlPlaneUpgrading + s.UpgradeTracker.ControlPlane.IsScaling = tt.controlPlaneScaling + s.UpgradeTracker.ControlPlane.IsProvisioning = tt.controlPlaneProvisioning s.UpgradeTracker.MachineDeployments.MarkUpgradingAndRollingOut(tt.upgradingMachineDeployments...) - version, err := computeMachineDeploymentVersion(s, tt.machineDeploymentTopology, desiredControlPlaneState, tt.currentMachineDeploymentState) - g.Expect(err).NotTo(HaveOccurred()) + version := computeMachineDeploymentVersion(s, mdName, tt.machineDeploymentTopology, tt.currentMachineDeploymentState) g.Expect(version).To(Equal(tt.expectedVersion)) // Verify that if the upgrade is pending it is captured in the upgrade tracker. - if tt.currentMachineDeploymentState != nil { - mdName := tt.currentMachineDeploymentState.Object.Name - deferredUpgrade := sets.New[string](s.UpgradeTracker.MachineDeployments.DeferredUpgradeNames()...).Has(mdName) - if !deferredUpgrade { - pendingUpgrade := tt.expectedVersion != tt.topologyVersion - if pendingUpgrade { - g.Expect(s.UpgradeTracker.MachineDeployments.PendingUpgradeNames()).To(ContainElement(mdName), "MachineDeployment should be marked as pending upgrade") - } else { - g.Expect(s.UpgradeTracker.MachineDeployments.PendingUpgradeNames()).NotTo(ContainElement(mdName), "MachineDeployment should not be marked as pending upgrade") - } - } + pendingUpgrade := tt.expectedVersion != tt.topologyVersion + if pendingUpgrade { + g.Expect(s.UpgradeTracker.MachineDeployments.PendingUpgradeNames()).To(ContainElement(mdName), "MachineDeployment should be marked as pending upgrade") + } else { + g.Expect(s.UpgradeTracker.MachineDeployments.PendingUpgradeNames()).NotTo(ContainElement(mdName), "MachineDeployment should not be marked as pending upgrade") } }) } diff --git a/internal/controllers/topology/cluster/reconcile_state.go b/internal/controllers/topology/cluster/reconcile_state.go index 74daf8f73bd2..a9b04705b98e 100644 --- a/internal/controllers/topology/cluster/reconcile_state.go +++ b/internal/controllers/topology/cluster/reconcile_state.go @@ -462,17 +462,7 @@ func (r *Reconciler) reconcileMachineDeployments(ctx context.Context, s *scope.S // Create MachineDeployments. for _, mdTopologyName := range diff.toCreate { md := s.Desired.MachineDeployments[mdTopologyName] - if s.UpgradeTracker.ControlPlane.PendingUpgrade || s.UpgradeTracker.ControlPlane.IsUpgrading { - // If the control plane is pending an upgrade then do not create a new MachineDeployment. - // We cannot create the new MD with the new Kubernetes version as the ControlPlane is still at the old version and - // creating a new MD would not be safe. - // We cannot create the new MD with the old Kubernetes version as there could be topology changes that could - // be incompatible and therefore not safe to create. - // Therefore, create the new MD after the ControlPlane has picked up the new version. - // TODO(ykakarap): Question: What about when ControlPlane is upgrading? - If the user wants more safety they should opt-into MS preflight checks. - continue - } - if err := r.createMachineDeployment(ctx, s.Current.Cluster, md); err != nil { + if err := r.createMachineDeployment(ctx, s, s.Current.Cluster, md); err != nil { return err } } @@ -481,9 +471,6 @@ func (r *Reconciler) reconcileMachineDeployments(ctx context.Context, s *scope.S for _, mdTopologyName := range diff.toUpdate { currentMD := s.Current.MachineDeployments[mdTopologyName] desiredMD := s.Desired.MachineDeployments[mdTopologyName] - if s.UpgradeTracker.MachineDeployments.HoldReconcile(currentMD.Object.Name) { - continue - } if err := r.updateMachineDeployment(ctx, s, mdTopologyName, currentMD, desiredMD); err != nil { return err } @@ -500,9 +487,12 @@ func (r *Reconciler) reconcileMachineDeployments(ctx context.Context, s *scope.S } // createMachineDeployment creates a MachineDeployment and the corresponding Templates. -func (r *Reconciler) createMachineDeployment(ctx context.Context, cluster *clusterv1.Cluster, md *scope.MachineDeploymentState) error { - log := tlog.LoggerFrom(ctx).WithMachineDeployment(md.Object) +func (r *Reconciler) createMachineDeployment(ctx context.Context, s *scope.Scope, cluster *clusterv1.Cluster, md *scope.MachineDeploymentState) error { + if s.UpgradeTracker.MachineDeployments.HoldReconcile(md.Object.Name) { + return nil + } + log := tlog.LoggerFrom(ctx).WithMachineDeployment(md.Object) infraCtx, _ := log.WithObject(md.InfrastructureMachineTemplate).Into(ctx) if err := r.reconcileReferencedTemplate(infraCtx, reconcileReferencedTemplateInput{ cluster: cluster, diff --git a/internal/controllers/topology/cluster/scope/upgradetracker.go b/internal/controllers/topology/cluster/scope/upgradetracker.go index 247a3915986d..55d10a796b48 100644 --- a/internal/controllers/topology/cluster/scope/upgradetracker.go +++ b/internal/controllers/topology/cluster/scope/upgradetracker.go @@ -36,6 +36,11 @@ type ControlPlaneUpgradeTracker struct { // Note: Refer to control plane contract for definition of upgrading. IsUpgrading bool + // IsStartingUpgrade is true if the control plane is just picking up the new version + // and is starting the upgrade process. This happens when the control plane picks the new + // version in the current reconcile loop. + IsStartingUpgrade bool + // IsScaling is true if the control plane is in the middle of a scale operation. // Note: Refer to control plane contract for definition of scaling. IsScaling bool