Skip to content

Commit 37dc14b

Browse files
authored
🌱 KCP: Add current/desired objects to NotUpToDateResult & refactor object creation (#12817)
* KCP: Add current/desired objects to NotUpToDateResult Signed-off-by: Stefan Büringer [email protected] * Fix review findings * Fix review findings --------- Signed-off-by: Stefan Büringer [email protected]
1 parent b0e330b commit 37dc14b

File tree

18 files changed

+2176
-1351
lines changed

18 files changed

+2176
-1351
lines changed

‎api/bootstrap/kubeadm/v1beta2/kubeadm_types.go‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,11 @@ type APIEndpoint struct {
347347
BindPort int32 `json:"bindPort,omitempty"`
348348
}
349349

350+
// IsDefined returns true if the APIEndpoint is defined.
351+
func (r *APIEndpoint) IsDefined() bool {
352+
return r.AdvertiseAddress != "" || r.BindPort != 0
353+
}
354+
350355
// NodeRegistrationOptions holds fields that relate to registering a new control-plane or node to the cluster, either via "kubeadm init" or "kubeadm join".
351356
// Note: The NodeRegistrationOptions struct has to be kept in sync with the structs in MarshalJSON.
352357
// +kubebuilder:validation:MinProperties=1

‎controlplane/kubeadm/internal/cluster_labels.go‎

Lines changed: 0 additions & 41 deletions
This file was deleted.

‎controlplane/kubeadm/internal/control_plane.go‎

Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,12 @@ type ControlPlane struct {
5050
Machines collections.Machines
5151
machinesPatchHelpers map[string]*patch.Helper
5252

53-
machinesNotUptoDate collections.Machines
53+
// MachinesNotUpToDate is the source of truth for Machines that are not up-to-date.
54+
// It should be used to check if a Machine is up-to-date (not machinesNotUpToDateResults).
55+
MachinesNotUpToDate collections.Machines
56+
// machinesNotUpToDateResults is used to store the result of the UpToDate call for all Machines
57+
// (even for Machines that are up-to-date).
58+
// MachinesNotUpToDate should always be used instead to check if a Machine is up-to-date.
5459
machinesNotUpToDateResults map[string]NotUpToDateResult
5560

5661
// reconciliationTime is the time of the current reconciliation, and should be used for all "now" calculations
@@ -119,22 +124,24 @@ func NewControlPlane(ctx context.Context, managementCluster ManagementCluster, c
119124
machinesNotUptoDate := make(collections.Machines, len(ownedMachines))
120125
machinesNotUpToDateResults := map[string]NotUpToDateResult{}
121126
for _, m := range ownedMachines {
122-
upToDate, notUpToDateResult, err := UpToDate(m, kcp, &reconciliationTime, infraMachines, kubeadmConfigs)
127+
upToDate, notUpToDateResult, err := UpToDate(ctx, client, cluster, m, kcp, &reconciliationTime, infraMachines, kubeadmConfigs)
123128
if err != nil {
124129
return nil, err
125130
}
126131
if !upToDate {
127132
machinesNotUptoDate.Insert(m)
128-
machinesNotUpToDateResults[m.Name] = *notUpToDateResult
129133
}
134+
// Set this even if machine is UpToDate. This is needed to complete triggering in-place updates
135+
// MachinesNotUpToDate should always be used instead to check if a Machine is up-to-date.
136+
machinesNotUpToDateResults[m.Name] = *notUpToDateResult
130137
}
131138

132139
return &ControlPlane{
133140
KCP: kcp,
134141
Cluster: cluster,
135142
Machines: ownedMachines,
136143
machinesPatchHelpers: patchHelpers,
137-
machinesNotUptoDate: machinesNotUptoDate,
144+
MachinesNotUpToDate: machinesNotUptoDate,
138145
machinesNotUpToDateResults: machinesNotUpToDateResults,
139146
KubeadmConfigs: kubeadmConfigs,
140147
InfraResources: infraMachines,
@@ -216,25 +223,6 @@ func getGetFailureDomainIDs(failureDomains []clusterv1.FailureDomain) []string {
216223
return ids
217224
}
218225

219-
// InitialControlPlaneConfig returns a new KubeadmConfigSpec that is to be used for an initializing control plane.
220-
func (c *ControlPlane) InitialControlPlaneConfig() *bootstrapv1.KubeadmConfigSpec {
221-
bootstrapSpec := c.KCP.Spec.KubeadmConfigSpec.DeepCopy()
222-
// Note: When building a KubeadmConfig for the first CP machine empty out the unnecessary JoinConfiguration.
223-
bootstrapSpec.JoinConfiguration = bootstrapv1.JoinConfiguration{}
224-
return bootstrapSpec
225-
}
226-
227-
// JoinControlPlaneConfig returns a new KubeadmConfigSpec that is to be used for joining control planes.
228-
func (c *ControlPlane) JoinControlPlaneConfig() *bootstrapv1.KubeadmConfigSpec {
229-
bootstrapSpec := c.KCP.Spec.KubeadmConfigSpec.DeepCopy()
230-
// Note: When building a KubeadmConfig for a joining CP machine empty out the unnecessary InitConfiguration.
231-
bootstrapSpec.InitConfiguration = bootstrapv1.InitConfiguration{}
232-
// NOTE: For the joining we are preserving the ClusterConfiguration in order to determine if the
233-
// cluster is using an external etcd in the kubeadm bootstrap provider (even if this is not required by kubeadm Join).
234-
// TODO: Determine if this copy of cluster configuration can be used for rollouts (thus allowing to remove the annotation at machine level)
235-
return bootstrapSpec
236-
}
237-
238226
// HasDeletingMachine returns true if any machine in the control plane is in the process of being deleted.
239227
func (c *ControlPlane) HasDeletingMachine() bool {
240228
return len(c.Machines.Filter(collections.HasDeletionTimestamp)) > 0
@@ -254,19 +242,19 @@ func (c *ControlPlane) GetKubeadmConfig(machineName string) (*bootstrapv1.Kubead
254242
// MachinesNeedingRollout return a list of machines that need to be rolled out.
255243
func (c *ControlPlane) MachinesNeedingRollout() (collections.Machines, map[string]NotUpToDateResult) {
256244
// Note: Machines already deleted are dropped because they will be replaced by new machines after deletion completes.
257-
return c.machinesNotUptoDate.Filter(collections.Not(collections.HasDeletionTimestamp)), c.machinesNotUpToDateResults
245+
return c.MachinesNotUpToDate.Filter(collections.Not(collections.HasDeletionTimestamp)), c.machinesNotUpToDateResults
258246
}
259247

260248
// NotUpToDateMachines return a list of machines that are not up to date with the control
261249
// plane's configuration.
262250
func (c *ControlPlane) NotUpToDateMachines() (collections.Machines, map[string]NotUpToDateResult) {
263-
return c.machinesNotUptoDate, c.machinesNotUpToDateResults
251+
return c.MachinesNotUpToDate, c.machinesNotUpToDateResults
264252
}
265253

266254
// UpToDateMachines returns the machines that are up to date with the control
267255
// plane's configuration.
268256
func (c *ControlPlane) UpToDateMachines() collections.Machines {
269-
return c.Machines.Difference(c.machinesNotUptoDate)
257+
return c.Machines.Difference(c.MachinesNotUpToDate)
270258
}
271259

272260
// getInfraMachines fetches the InfraMachine for each machine in the collection and returns a map of machine.Name -> InfraMachine.

‎controlplane/kubeadm/internal/control_plane_test.go‎

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,13 +124,15 @@ func TestControlPlane(t *testing.T) {
124124

125125
machinesNotUptoDate, machinesNotUpToDateResults := controlPlane.NotUpToDateMachines()
126126
g.Expect(machinesNotUptoDate.Names()).To(ConsistOf("m2", "m3"))
127-
g.Expect(machinesNotUpToDateResults).To(HaveLen(2))
127+
// machinesNotUpToDateResults contains results for all Machines (including up-to-date Machines).
128+
g.Expect(machinesNotUpToDateResults).To(HaveLen(5))
128129
g.Expect(machinesNotUpToDateResults["m2"].ConditionMessages).To(Equal([]string{"Version v1.29.0, v1.31.0 required"}))
129130
g.Expect(machinesNotUpToDateResults["m3"].ConditionMessages).To(Equal([]string{"Version v1.29.3, v1.31.0 required"}))
130131

131132
machinesNeedingRollout, machinesNotUpToDateResults := controlPlane.MachinesNeedingRollout()
132133
g.Expect(machinesNeedingRollout.Names()).To(ConsistOf("m2"))
133-
g.Expect(machinesNotUpToDateResults).To(HaveLen(2))
134+
// machinesNotUpToDateResults contains results for all Machines (including up-to-date Machines).
135+
g.Expect(machinesNotUpToDateResults).To(HaveLen(5))
134136
g.Expect(machinesNotUpToDateResults["m2"].LogMessages).To(Equal([]string{"Machine version \"v1.29.0\" is not equal to KCP version \"v1.31.0\""}))
135137
g.Expect(machinesNotUpToDateResults["m3"].LogMessages).To(Equal([]string{"Machine version \"v1.29.3\" is not equal to KCP version \"v1.31.0\""}))
136138

@@ -339,7 +341,7 @@ func TestStatusToLogKeyAndValues(t *testing.T) {
339341
c := &ControlPlane{
340342
KCP: &controlplanev1.KubeadmControlPlane{},
341343
Machines: collections.FromMachines(healthyMachine, machineWithoutNode, machineJustDeleted, machineNotUpToDate, machineMarkedForRemediation),
342-
machinesNotUptoDate: collections.FromMachines(machineNotUpToDate),
344+
MachinesNotUpToDate: collections.FromMachines(machineNotUpToDate),
343345
EtcdMembers: []*etcd.Member{{Name: "m1"}, {Name: "m2"}, {Name: "m3"}},
344346
}
345347

‎controlplane/kubeadm/internal/controllers/controller.go‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -802,7 +802,11 @@ func (r *KubeadmControlPlaneReconciler) syncMachines(ctx context.Context, contro
802802
if err != nil {
803803
return errors.Wrapf(err, "failed to update Machine: %s", klog.KObj(m))
804804
}
805+
// Note: Ensure ControlPlane has the latest version of the Machine.
805806
controlPlane.Machines[machineName] = updatedMachine
807+
if _, ok := controlPlane.MachinesNotUpToDate[machineName]; ok {
808+
controlPlane.MachinesNotUpToDate[machineName] = updatedMachine
809+
}
806810
// Since the machine is updated, re-create the patch helper so that any subsequent
807811
// Patch calls use the correct base machine object to calculate the diffs.
808812
// Example: reconcileControlPlaneAndMachinesConditions patches the machine objects in a subsequent call

‎controlplane/kubeadm/internal/controllers/controller_test.go‎

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ import (
5252
"sigs.k8s.io/cluster-api/controllers/clustercache"
5353
"sigs.k8s.io/cluster-api/controllers/external"
5454
"sigs.k8s.io/cluster-api/controlplane/kubeadm/internal"
55+
"sigs.k8s.io/cluster-api/controlplane/kubeadm/internal/desiredstate"
5556
controlplanev1webhooks "sigs.k8s.io/cluster-api/controlplane/kubeadm/internal/webhooks"
5657
"sigs.k8s.io/cluster-api/feature"
5758
"sigs.k8s.io/cluster-api/internal/contract"
@@ -520,7 +521,7 @@ func TestKubeadmControlPlaneReconciler_adoption(t *testing.T) {
520521
ObjectMeta: metav1.ObjectMeta{
521522
Namespace: cluster.Namespace,
522523
Name: name,
523-
Labels: internal.ControlPlaneMachineLabelsForCluster(kcp, cluster.Name),
524+
Labels: desiredstate.ControlPlaneMachineLabels(kcp, cluster.Name),
524525
},
525526
Spec: clusterv1.MachineSpec{
526527
Bootstrap: clusterv1.Bootstrap{
@@ -588,7 +589,7 @@ func TestKubeadmControlPlaneReconciler_adoption(t *testing.T) {
588589
ObjectMeta: metav1.ObjectMeta{
589590
Namespace: cluster.Namespace,
590591
Name: name,
591-
Labels: internal.ControlPlaneMachineLabelsForCluster(kcp, cluster.Name),
592+
Labels: desiredstate.ControlPlaneMachineLabels(kcp, cluster.Name),
592593
},
593594
Spec: clusterv1.MachineSpec{
594595
Bootstrap: clusterv1.Bootstrap{
@@ -703,7 +704,7 @@ func TestKubeadmControlPlaneReconciler_adoption(t *testing.T) {
703704
ObjectMeta: metav1.ObjectMeta{
704705
Namespace: cluster.Namespace,
705706
Name: name,
706-
Labels: internal.ControlPlaneMachineLabelsForCluster(kcp, cluster.Name),
707+
Labels: desiredstate.ControlPlaneMachineLabels(kcp, cluster.Name),
707708
},
708709
Spec: clusterv1.MachineSpec{
709710
Bootstrap: clusterv1.Bootstrap{
@@ -761,7 +762,7 @@ func TestKubeadmControlPlaneReconciler_adoption(t *testing.T) {
761762
ObjectMeta: metav1.ObjectMeta{
762763
Namespace: cluster.Namespace,
763764
Name: "test0",
764-
Labels: internal.ControlPlaneMachineLabelsForCluster(kcp, cluster.Name),
765+
Labels: desiredstate.ControlPlaneMachineLabels(kcp, cluster.Name),
765766
},
766767
Spec: clusterv1.MachineSpec{
767768
Bootstrap: clusterv1.Bootstrap{
@@ -1841,7 +1842,7 @@ func TestKubeadmControlPlaneReconciler_syncMachines(t *testing.T) {
18411842
NodeVolumeDetachTimeoutSeconds: duration5s,
18421843
NodeDeletionTimeoutSeconds: duration5s,
18431844
},
1844-
ReadinessGates: mandatoryMachineReadinessGates,
1845+
ReadinessGates: desiredstate.MandatoryMachineReadinessGates,
18451846
},
18461847
}
18471848
g.Expect(env.PatchAndWait(ctx, deletingMachine, client.FieldOwner(kcpManagerName))).To(Succeed())
@@ -3921,17 +3922,17 @@ func TestObjectsPendingDelete(t *testing.T) {
39213922

39223923
// test utils.
39233924

3924-
func newFakeClient(initObjs ...client.Object) client.Client {
3925+
func newFakeClient(initObjs ...client.Object) client.WithWatch {
39253926
return &fakeClient{
39263927
startTime: time.Now(),
3927-
Client: fake.NewClientBuilder().WithObjects(initObjs...).WithStatusSubresource(&controlplanev1.KubeadmControlPlane{}).Build(),
3928+
WithWatch: fake.NewClientBuilder().WithObjects(initObjs...).WithStatusSubresource(&controlplanev1.KubeadmControlPlane{}).Build(),
39283929
}
39293930
}
39303931

39313932
type fakeClient struct {
39323933
startTime time.Time
39333934
mux sync.Mutex
3934-
client.Client
3935+
client.WithWatch
39353936
}
39363937

39373938
type fakeClientI interface {
@@ -3947,7 +3948,7 @@ func (c *fakeClient) Create(ctx context.Context, obj client.Object, opts ...clie
39473948
f.SetCreationTimestamp(metav1.NewTime(c.startTime))
39483949
c.mux.Unlock()
39493950
}
3950-
return c.Client.Create(ctx, obj, opts...)
3951+
return c.WithWatch.Create(ctx, obj, opts...)
39513952
}
39523953

39533954
func createClusterWithControlPlane(namespace string) (*clusterv1.Cluster, *controlplanev1.KubeadmControlPlane, *unstructured.Unstructured) {
@@ -4038,7 +4039,7 @@ func createMachineNodePair(name string, cluster *clusterv1.Cluster, kcp *control
40384039
ObjectMeta: metav1.ObjectMeta{
40394040
Namespace: cluster.Namespace,
40404041
Name: name,
4041-
Labels: internal.ControlPlaneMachineLabelsForCluster(kcp, cluster.Name),
4042+
Labels: desiredstate.ControlPlaneMachineLabels(kcp, cluster.Name),
40424043
Annotations: map[string]string{},
40434044
OwnerReferences: []metav1.OwnerReference{
40444045
*metav1.NewControllerRef(kcp, controlplanev1.GroupVersion.WithKind("KubeadmControlPlane")),

0 commit comments

Comments
 (0)