Skip to content
This repository was archived by the owner on Jul 30, 2021. It is now read-only.

Commit 2fae9f4

Browse files
committed
refactor: use switch/case for early returns only
Also adds a requeueAfter parameter, because I realized doing this work that we should get an immediate second crack at the config before it's consumed.
1 parent 794be6e commit 2fae9f4

File tree

2 files changed

+105
-107
lines changed

2 files changed

+105
-107
lines changed

controllers/kubeadmconfig_controller.go

Lines changed: 103 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -112,18 +112,6 @@ func (r *KubeadmConfigReconciler) Reconcile(req ctrl.Request) (_ ctrl.Result, re
112112
}
113113
log = log.WithValues("machine-name", machine.Name)
114114

115-
// bail super early if it's already ready
116-
if config.Status.Ready && machine.Status.InfrastructureReady {
117-
log.Info("ignoring config for an already ready machine")
118-
return ctrl.Result{}, nil
119-
}
120-
121-
// Ignore machines that already have bootstrap data we didn't generate
122-
if machine.Spec.Bootstrap.Data != nil && !config.Status.Ready {
123-
// TODO: mark the config as ready?
124-
return ctrl.Result{}, nil
125-
}
126-
127115
// Lookup the cluster the machine is associated with
128116
cluster, err := util.GetClusterFromMetadata(ctx, r.Client, machine.ObjectMeta)
129117
if err != nil {
@@ -140,21 +128,19 @@ func (r *KubeadmConfigReconciler) Reconcile(req ctrl.Request) (_ ctrl.Result, re
140128
return ctrl.Result{}, err
141129
}
142130

143-
// Initialize the patch helper
144-
patchHelper, err := patch.NewHelper(config, r)
145-
if err != nil {
146-
return ctrl.Result{}, err
147-
}
148-
// Attempt to Patch the KubeadmConfig object and status after each reconciliation if no error occurs.
149-
defer func() {
150-
if rerr == nil {
151-
if rerr = patchHelper.Patch(ctx, config); rerr != nil {
152-
log.Error(rerr, "failed to patch config")
153-
}
154-
}
155-
}()
156-
157131
switch {
132+
// Wait patiently for the infrastructure to be ready
133+
case !cluster.Status.InfrastructureReady:
134+
log.Info("Infrastructure is not ready, waiting until ready.")
135+
return ctrl.Result{}, nil
136+
// bail super early if it's already ready
137+
case config.Status.Ready && machine.Status.InfrastructureReady:
138+
log.Info("ignoring config for an already ready machine")
139+
return ctrl.Result{}, nil
140+
// Ignore machines that already have bootstrap data we didn't generate
141+
case machine.Spec.Bootstrap.Data != nil && !config.Status.Ready:
142+
// TODO: mark the config as ready?
143+
return ctrl.Result{}, nil
158144
// If we've already embedded a time-limited join token into a config, but are still waiting for the token to be used, refresh it
159145
case config.Status.Ready:
160146
token := config.Spec.JoinConfiguration.Discovery.BootstrapToken.Token
@@ -171,12 +157,27 @@ func (r *KubeadmConfigReconciler) Reconcile(req ctrl.Request) (_ ctrl.Result, re
171157
// It would be nice to re-create the bootstrap token if the error was "not found", but we have no way to update the Machine's bootstrap data
172158
return ctrl.Result{}, errors.Wrapf(err, "failed to refresh bootstrap token")
173159
}
174-
return ctrl.Result{}, nil
175-
// Wait patiently for the infrastructure to be ready
176-
case !cluster.Status.InfrastructureReady:
177-
log.Info("Infrastructure is not ready, waiting until ready.")
178-
return ctrl.Result{}, nil
179-
case !cluster.Status.ControlPlaneInitialized:
160+
// NB: this may not be sufficient to keep the token live if we don't see it before it expires, but when we generate a config we will set the status to "ready" which should generate an update event
161+
return ctrl.Result{
162+
RequeueAfter: DefaultTokenTTL / 2,
163+
}, nil
164+
}
165+
166+
// Initialize the patch helper
167+
patchHelper, err := patch.NewHelper(config, r)
168+
if err != nil {
169+
return ctrl.Result{}, err
170+
}
171+
// Attempt to Patch the KubeadmConfig object and status after each reconciliation if no error occurs.
172+
defer func() {
173+
if rerr == nil {
174+
if rerr = patchHelper.Patch(ctx, config); rerr != nil {
175+
log.Error(rerr, "failed to patch config")
176+
}
177+
}
178+
}()
179+
180+
if !cluster.Status.ControlPlaneInitialized {
180181
// if it's NOT a control plane machine, requeue
181182
if !util.IsControlPlaneMachine(machine) {
182183
log.Info(fmt.Sprintf("Machine is not a control plane. If it should be a control plane, add `%s: true` as a label to the Machine", clusterv1.MachineControlPlaneLabelName))
@@ -268,102 +269,102 @@ func (r *KubeadmConfigReconciler) Reconcile(req ctrl.Request) (_ ctrl.Result, re
268269
config.Status.Ready = true
269270

270271
return ctrl.Result{}, nil
271-
// Every other case it's a join scenario
272-
default:
273-
// Nb. in this case ClusterConfiguration and JoinConfiguration should not be defined by users, but in case of misconfigurations, CABPK simply ignore them
272+
}
274273

275-
// Unlock any locks that might have been set during init process
276-
r.KubeadmInitLock.Unlock(ctx, cluster)
274+
// Every other case it's a join scenario
275+
// Nb. in this case ClusterConfiguration and JoinConfiguration should not be defined by users, but in case of misconfigurations, CABPK simply ignore them
277276

278-
if config.Spec.JoinConfiguration == nil {
279-
return ctrl.Result{}, errors.New("Control plane already exists for the cluster, only KubeadmConfig objects with JoinConfiguration are allowed")
280-
}
277+
// Unlock any locks that might have been set during init process
278+
r.KubeadmInitLock.Unlock(ctx, cluster)
281279

282-
certificates := internalcluster.NewCertificates()
283-
if err := certificates.Lookup(ctx, r.Client, cluster); err != nil {
284-
log.Error(err, "unable to lookup cluster certificates")
285-
return ctrl.Result{}, err
286-
}
287-
if err := certificates.EnsureAllExist(); err != nil {
288-
return ctrl.Result{}, err
289-
}
280+
if config.Spec.JoinConfiguration == nil {
281+
return ctrl.Result{}, errors.New("Control plane already exists for the cluster, only KubeadmConfig objects with JoinConfiguration are allowed")
282+
}
290283

291-
hashes, err := certificates.GetByPurpose(secret.ClusterCA).Hashes()
292-
if err != nil {
293-
log.Error(err, "Unable to generate Cluster CA certificate hashes")
294-
return ctrl.Result{}, err
295-
}
296-
// TODO: move this into reconcile.Discovery so that defaults for the Discovery are all in the same place
297-
if config.Spec.JoinConfiguration.Discovery.BootstrapToken == nil {
298-
config.Spec.JoinConfiguration.Discovery.BootstrapToken = &kubeadmv1beta1.BootstrapTokenDiscovery{}
299-
}
300-
config.Spec.JoinConfiguration.Discovery.BootstrapToken.CACertHashes = hashes
284+
certificates := internalcluster.NewCertificates()
285+
if err := certificates.Lookup(ctx, r.Client, cluster); err != nil {
286+
log.Error(err, "unable to lookup cluster certificates")
287+
return ctrl.Result{}, err
288+
}
289+
if err := certificates.EnsureAllExist(); err != nil {
290+
return ctrl.Result{}, err
291+
}
301292

302-
// ensure that joinConfiguration.Discovery is properly set for joining node on the current cluster
303-
if err := r.reconcileDiscovery(cluster, config); err != nil {
304-
if requeueErr, ok := errors.Cause(err).(capierrors.HasRequeueAfterError); ok {
305-
log.Info(err.Error())
306-
return ctrl.Result{RequeueAfter: requeueErr.GetRequeueAfter()}, nil
307-
}
308-
return ctrl.Result{}, err
309-
}
293+
hashes, err := certificates.GetByPurpose(secret.ClusterCA).Hashes()
294+
if err != nil {
295+
log.Error(err, "Unable to generate Cluster CA certificate hashes")
296+
return ctrl.Result{}, err
297+
}
298+
// TODO: move this into reconcile.Discovery so that defaults for the Discovery are all in the same place
299+
if config.Spec.JoinConfiguration.Discovery.BootstrapToken == nil {
300+
config.Spec.JoinConfiguration.Discovery.BootstrapToken = &kubeadmv1beta1.BootstrapTokenDiscovery{}
301+
}
302+
config.Spec.JoinConfiguration.Discovery.BootstrapToken.CACertHashes = hashes
310303

311-
joindata, err := kubeadmv1beta1.ConfigurationToYAML(config.Spec.JoinConfiguration)
312-
if err != nil {
313-
log.Error(err, "failed to marshal join configuration")
314-
return ctrl.Result{}, err
304+
// ensure that joinConfiguration.Discovery is properly set for joining node on the current cluster
305+
if err := r.reconcileDiscovery(cluster, config); err != nil {
306+
if requeueErr, ok := errors.Cause(err).(capierrors.HasRequeueAfterError); ok {
307+
log.Info(err.Error())
308+
return ctrl.Result{RequeueAfter: requeueErr.GetRequeueAfter()}, nil
315309
}
310+
return ctrl.Result{}, err
311+
}
316312

317-
// it's a control plane join
318-
if util.IsControlPlaneMachine(machine) {
319-
if config.Spec.JoinConfiguration.ControlPlane == nil {
320-
return ctrl.Result{}, errors.New("Machine is a ControlPlane, but JoinConfiguration.ControlPlane is not set in the KubeadmConfig object")
321-
}
322-
323-
cloudJoinData, err := cloudinit.NewJoinControlPlane(&cloudinit.ControlPlaneJoinInput{
324-
JoinConfiguration: joindata,
325-
Certificates: certificates,
326-
BaseUserData: cloudinit.BaseUserData{
327-
AdditionalFiles: config.Spec.Files,
328-
NTP: config.Spec.NTP,
329-
PreKubeadmCommands: config.Spec.PreKubeadmCommands,
330-
PostKubeadmCommands: config.Spec.PostKubeadmCommands,
331-
Users: config.Spec.Users,
332-
},
333-
})
334-
if err != nil {
335-
log.Error(err, "failed to create a control plane join configuration")
336-
return ctrl.Result{}, err
337-
}
338-
339-
config.Status.BootstrapData = cloudJoinData
340-
config.Status.Ready = true
341-
return ctrl.Result{}, nil
342-
}
313+
joindata, err := kubeadmv1beta1.ConfigurationToYAML(config.Spec.JoinConfiguration)
314+
if err != nil {
315+
log.Error(err, "failed to marshal join configuration")
316+
return ctrl.Result{}, err
317+
}
343318

344-
// otherwise it is a node
345-
if config.Spec.JoinConfiguration.ControlPlane != nil {
346-
return ctrl.Result{}, errors.New("Machine is a Worker, but JoinConfiguration.ControlPlane is set in the KubeadmConfig object")
319+
// it's a control plane join
320+
if util.IsControlPlaneMachine(machine) {
321+
if config.Spec.JoinConfiguration.ControlPlane == nil {
322+
return ctrl.Result{}, errors.New("Machine is a ControlPlane, but JoinConfiguration.ControlPlane is not set in the KubeadmConfig object")
347323
}
348324

349-
cloudJoinData, err := cloudinit.NewNode(&cloudinit.NodeInput{
325+
cloudJoinData, err := cloudinit.NewJoinControlPlane(&cloudinit.ControlPlaneJoinInput{
326+
JoinConfiguration: joindata,
327+
Certificates: certificates,
350328
BaseUserData: cloudinit.BaseUserData{
351329
AdditionalFiles: config.Spec.Files,
352330
NTP: config.Spec.NTP,
353331
PreKubeadmCommands: config.Spec.PreKubeadmCommands,
354332
PostKubeadmCommands: config.Spec.PostKubeadmCommands,
355333
Users: config.Spec.Users,
356334
},
357-
JoinConfiguration: joindata,
358335
})
359336
if err != nil {
360-
log.Error(err, "failed to create a worker join configuration")
337+
log.Error(err, "failed to create a control plane join configuration")
361338
return ctrl.Result{}, err
362339
}
340+
363341
config.Status.BootstrapData = cloudJoinData
364342
config.Status.Ready = true
365343
return ctrl.Result{}, nil
366344
}
345+
346+
// otherwise it is a node
347+
if config.Spec.JoinConfiguration.ControlPlane != nil {
348+
return ctrl.Result{}, errors.New("Machine is a Worker, but JoinConfiguration.ControlPlane is set in the KubeadmConfig object")
349+
}
350+
351+
cloudJoinData, err := cloudinit.NewNode(&cloudinit.NodeInput{
352+
BaseUserData: cloudinit.BaseUserData{
353+
AdditionalFiles: config.Spec.Files,
354+
NTP: config.Spec.NTP,
355+
PreKubeadmCommands: config.Spec.PreKubeadmCommands,
356+
PostKubeadmCommands: config.Spec.PostKubeadmCommands,
357+
Users: config.Spec.Users,
358+
},
359+
JoinConfiguration: joindata,
360+
})
361+
if err != nil {
362+
log.Error(err, "failed to create a worker join configuration")
363+
return ctrl.Result{}, err
364+
}
365+
config.Status.BootstrapData = cloudJoinData
366+
config.Status.Ready = true
367+
return ctrl.Result{}, nil
367368
}
368369

369370
// ClusterToKubeadmConfigs is a handler.ToRequestsFunc to be used to enqeue

controllers/kubeadmconfig_controller_test.go

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -650,11 +650,8 @@ func TestReconcileIfJoinNodesAndControlPlaneIsReady(t *testing.T) {
650650
if err != nil {
651651
t.Fatalf("Failed to reconcile:\n %+v", err)
652652
}
653-
if result.Requeue == true {
654-
t.Fatal("did not expect to requeue")
655-
}
656-
if result.RequeueAfter != time.Duration(0) {
657-
t.Fatal("did not expect to requeue after")
653+
if result.RequeueAfter >= DefaultTokenTTL {
654+
t.Fatal("expected a requeue duration less than the token TTL")
658655
}
659656
}
660657

0 commit comments

Comments
 (0)