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

Commit 6d6589b

Browse files
initialize config objects if missing
1 parent 46acfbd commit 6d6589b

File tree

2 files changed

+166
-137
lines changed

2 files changed

+166
-137
lines changed

controllers/kubeadmconfig_controller.go

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,8 +176,8 @@ func (r *KubeadmConfigReconciler) Reconcile(req ctrl.Request) (_ ctrl.Result, re
176176
return ctrl.Result{RequeueAfter: 30 * time.Second}, nil
177177
}
178178

179-
// if the machine has not ClusterConfiguration and InitConfiguration, requeue
180-
if config.Spec.InitConfiguration == nil && config.Spec.ClusterConfiguration == nil {
179+
// if the machine is configured has a secondary control-plane, requeue
180+
if config.Spec.JoinConfiguration != nil {
181181
log.Info("Control plane is not ready, requeing joining control planes until ready.")
182182
return ctrl.Result{RequeueAfter: 30 * time.Second}, nil
183183
}
@@ -260,13 +260,21 @@ func (r *KubeadmConfigReconciler) Reconcile(req ctrl.Request) (_ ctrl.Result, re
260260
}
261261

262262
// Every other case it's a join scenario
263-
// Nb. in this case ClusterConfiguration and JoinConfiguration should not be defined by users, but in case of misconfigurations, CABPK simply ignore them
263+
264+
//In case of join, ClusterConfiguration and InitConfiguration should not be defined by users
265+
if config.Spec.ClusterConfiguration != nil || config.Spec.InitConfiguration != nil {
266+
return ctrl.Result{}, errors.New("Control plane already exists for the cluster, KubeadmConfig objects with ClusterConfiguration or InitConfiguration can not be processed at this stage")
267+
}
264268

265269
// Unlock any locks that might have been set during init process
266270
r.KubeadmInitLock.Unlock(ctx, cluster)
267271

272+
// if the JoinConfiguration is missing, create a default one
268273
if config.Spec.JoinConfiguration == nil {
269-
return ctrl.Result{}, errors.New("Control plane already exists for the cluster, only KubeadmConfig objects with JoinConfiguration are allowed")
274+
config.Spec.JoinConfiguration = &kubeadmv1beta1.JoinConfiguration{}
275+
if util.IsControlPlaneMachine(machine) {
276+
config.Spec.JoinConfiguration.ControlPlane = &kubeadmv1beta1.JoinControlPlane{}
277+
}
270278
}
271279

272280
// Get certificates to improve security of discovery

controllers/kubeadmconfig_controller_test.go

Lines changed: 154 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -285,75 +285,93 @@ func TestKubeadmConfigReconciler_Reconcile_GenerateCloudConfigData(t *testing.T)
285285
cluster.Status.InfrastructureReady = true
286286

287287
controlPlaneMachine := newControlPlaneMachine(cluster)
288-
controlPlaneInitConfig := newControlPlaneInitKubeadmConfig(controlPlaneMachine, "control-plane-init-cfg")
289288

290-
objects := []runtime.Object{
291-
cluster,
292-
controlPlaneMachine,
293-
controlPlaneInitConfig,
289+
var useCases = []struct {
290+
name string
291+
controlPlaneInitConfig *bootstrapv1.KubeadmConfig
292+
}{
293+
{
294+
name: "machine with a fully compiled kubeadm config object",
295+
controlPlaneInitConfig: newControlPlaneInitKubeadmConfig(controlPlaneMachine, "control-plane-init-cfg"),
296+
},
297+
{
298+
name: "machine with an empty kubeadm config object",
299+
controlPlaneInitConfig: newKubeadmConfig(controlPlaneMachine, "control-plane-init-cfg"),
300+
},
294301
}
295-
objects = append(objects, createSecrets(t, cluster)...)
296302

297-
myclient := fake.NewFakeClientWithScheme(setupScheme(), objects...)
303+
for _, rt := range useCases {
304+
rt := rt // pin!
305+
t.Run(rt.name, func(t *testing.T) {
298306

299-
k := &KubeadmConfigReconciler{
300-
Log: log.Log,
301-
Client: myclient,
302-
KubeadmInitLock: &myInitLocker{},
303-
}
307+
objects := []runtime.Object{
308+
cluster,
309+
controlPlaneMachine,
310+
rt.controlPlaneInitConfig,
311+
}
312+
objects = append(objects, createSecrets(t, cluster)...)
304313

305-
request := ctrl.Request{
306-
NamespacedName: types.NamespacedName{
307-
Namespace: "default",
308-
Name: "control-plane-init-cfg",
309-
},
310-
}
311-
result, err := k.Reconcile(request)
312-
if err != nil {
313-
t.Fatalf("Failed to reconcile:\n %+v", err)
314-
}
315-
if result.Requeue != false {
316-
t.Fatal("did not expected to requeue")
317-
}
318-
if result.RequeueAfter != time.Duration(0) {
319-
t.Fatal("did not expected to requeue after")
320-
}
314+
myclient := fake.NewFakeClientWithScheme(setupScheme(), objects...)
321315

322-
cfg, err := getKubeadmConfig(myclient, "control-plane-init-cfg")
323-
if err != nil {
324-
t.Fatalf("Failed to reconcile:\n %+v", err)
325-
}
326-
if cfg.Status.Ready != true {
327-
t.Fatal("Expected status ready")
328-
}
329-
if cfg.Status.BootstrapData == nil {
330-
t.Fatal("Expected status ready")
331-
}
316+
k := &KubeadmConfigReconciler{
317+
Log: log.Log,
318+
Client: myclient,
319+
KubeadmInitLock: &myInitLocker{},
320+
}
332321

333-
c, err := k.getClusterCertificates(cluster)
334-
if err != nil {
335-
t.Fatalf("Failed to locate certs secret:\n %+v", err)
336-
}
337-
if err := c.Validate(); err != nil {
338-
t.Fatalf("Failed to validate certs: %+v", err)
322+
request := ctrl.Request{
323+
NamespacedName: types.NamespacedName{
324+
Namespace: "default",
325+
Name: "control-plane-init-cfg",
326+
},
327+
}
328+
result, err := k.Reconcile(request)
329+
if err != nil {
330+
t.Fatalf("Failed to reconcile:\n %+v", err)
331+
}
332+
if result.Requeue != false {
333+
t.Fatal("did not expected to requeue")
334+
}
335+
if result.RequeueAfter != time.Duration(0) {
336+
t.Fatal("did not expected to requeue after")
337+
}
338+
339+
cfg, err := getKubeadmConfig(myclient, "control-plane-init-cfg")
340+
if err != nil {
341+
t.Fatalf("Failed to reconcile:\n %+v", err)
342+
}
343+
if cfg.Status.Ready != true {
344+
t.Fatal("Expected status ready")
345+
}
346+
if cfg.Status.BootstrapData == nil {
347+
t.Fatal("Expected status ready")
348+
}
349+
350+
c, err := k.getClusterCertificates(cluster)
351+
if err != nil {
352+
t.Fatalf("Failed to locate certs secret:\n %+v", err)
353+
}
354+
if err := c.Validate(); err != nil {
355+
t.Fatalf("Failed to validate certs: %+v", err)
356+
}
357+
})
339358
}
340359
}
341360

342-
// Return an error if a worker has no JoinConfiguration defined
343-
// TODO: This logic should not error in this case. A JoinConfiguration should be autogenerated
344-
func TestKubeadmConfigReconciler_Reconcile_ErrorIfAWorkerHasNoJoinConfigurationAndTheControlPlaneIsInitialized(t *testing.T) {
361+
// Tests for cluster with infrastructure ready, control pane ready
362+
363+
func TestFailIfClusterOrInitConfigurationAndControlPlaneIsReady(t *testing.T) {
345364
cluster := newCluster("cluster")
346365
cluster.Status.InfrastructureReady = true
347366
cluster.Status.ControlPlaneInitialized = true
348367

349-
workerMachine := newWorkerMachine(cluster)
350-
workerJoinConfig := newWorkerJoinKubeadmConfig(workerMachine)
351-
workerJoinConfig.Spec.JoinConfiguration = nil // Makes workerJoinConfig invalid
368+
controlPaneMachine := newControlPlaneMachine(cluster)
369+
controlPaneJoinConfig := newControlPlaneInitKubeadmConfig(controlPaneMachine, "control-plane-init-cfg")
352370

353371
objects := []runtime.Object{
354372
cluster,
355-
workerMachine,
356-
workerJoinConfig,
373+
controlPaneMachine,
374+
controlPaneJoinConfig,
357375
}
358376
myclient := fake.NewFakeClientWithScheme(setupScheme(), objects...)
359377

@@ -366,7 +384,7 @@ func TestKubeadmConfigReconciler_Reconcile_ErrorIfAWorkerHasNoJoinConfigurationA
366384
request := ctrl.Request{
367385
NamespacedName: types.NamespacedName{
368386
Namespace: "default",
369-
Name: "worker-join-cfg",
387+
Name: "control-plane-init-cfg",
370388
},
371389
}
372390
_, err := k.Reconcile(request)
@@ -458,96 +476,99 @@ func TestReconcileIfJoinNodesAndControlPlaneIsReady(t *testing.T) {
458476
cluster.Status.ControlPlaneInitialized = true
459477
cluster.Status.APIEndpoints = []clusterv1.APIEndpoint{{Host: "100.105.150.1", Port: 6443}}
460478

461-
workerMachine := newWorkerMachine(cluster)
462-
workerJoinConfig := newWorkerJoinKubeadmConfig(workerMachine)
463-
464-
controlPlaneMachine := newControlPlaneMachine(cluster)
465-
controlPlaneJoinConfig := newControlPlaneJoinKubeadmConfig(controlPlaneMachine, "control-plane-join-cfg")
466-
467-
objects := []runtime.Object{
468-
cluster,
469-
workerMachine,
470-
workerJoinConfig,
471-
controlPlaneMachine,
472-
controlPlaneJoinConfig,
473-
}
474-
objects = append(objects, createSecrets(t, cluster)...)
475-
myclient := fake.NewFakeClientWithScheme(setupScheme(), objects...)
476-
k := &KubeadmConfigReconciler{
477-
Log: log.Log,
478-
Client: myclient,
479-
SecretsClientFactory: newFakeSecretFactory(),
480-
KubeadmInitLock: &myInitLocker{},
481-
}
482-
483-
request := ctrl.Request{
484-
NamespacedName: types.NamespacedName{
485-
Namespace: "default",
486-
Name: "worker-join-cfg",
479+
var useCases = []struct {
480+
name string
481+
machine *clusterv1.Machine
482+
configName string
483+
configBuilder func(*clusterv1.Machine, string) *bootstrapv1.KubeadmConfig
484+
}{
485+
{
486+
name: "Join a worker node with a fully compiled kubeadm config object",
487+
machine: newWorkerMachine(cluster),
488+
configName: "worker-join-cfg",
489+
configBuilder: func(machine *clusterv1.Machine, name string) *bootstrapv1.KubeadmConfig {
490+
return newWorkerJoinKubeadmConfig(machine)
491+
},
492+
},
493+
{
494+
name: "Join a worker node with an empty kubeadm config object",
495+
machine: newWorkerMachine(cluster),
496+
configName: "worker-join-cfg",
497+
configBuilder: newKubeadmConfig,
498+
},
499+
{
500+
name: "Join a control plane node with a fully compiled kubeadm config object",
501+
machine: newControlPlaneMachine(cluster),
502+
configName: "control-plane-join-cfg",
503+
configBuilder: newControlPlaneJoinKubeadmConfig,
504+
},
505+
{
506+
name: "Join a control plane node with an empty kubeadm config object",
507+
machine: newControlPlaneMachine(cluster),
508+
configName: "control-plane-join-cfg",
509+
configBuilder: newKubeadmConfig,
487510
},
488-
}
489-
result, err := k.Reconcile(request)
490-
if err != nil {
491-
t.Fatal(fmt.Sprintf("Failed to reconcile:\n %+v", err))
492-
}
493-
if result.Requeue == true {
494-
t.Fatal("did not expected to requeue")
495-
}
496-
if result.RequeueAfter != time.Duration(0) {
497-
t.Fatal("did not expected to requeue after")
498-
}
499-
500-
cfg, err := getKubeadmConfig(myclient, "worker-join-cfg")
501-
if err != nil {
502-
t.Fatal(fmt.Sprintf("Failed to reconcile:\n %+v", err))
503511
}
504512

505-
if cfg.Status.Ready != true {
506-
t.Fatal("Expected status ready")
507-
}
513+
for _, rt := range useCases {
514+
rt := rt // pin!
515+
t.Run(rt.name, func(t *testing.T) {
516+
config := rt.configBuilder(rt.machine, rt.configName)
508517

509-
if cfg.Status.BootstrapData == nil {
510-
t.Fatal("Expected status ready")
511-
}
518+
objects := []runtime.Object{
519+
cluster,
520+
rt.machine,
521+
config,
522+
}
523+
objects = append(objects, createSecrets(t, cluster)...)
524+
myclient := fake.NewFakeClientWithScheme(setupScheme(), objects...)
525+
k := &KubeadmConfigReconciler{
526+
Log: log.Log,
527+
Client: myclient,
528+
SecretsClientFactory: newFakeSecretFactory(),
529+
KubeadmInitLock: &myInitLocker{},
530+
}
512531

513-
request = ctrl.Request{
514-
NamespacedName: types.NamespacedName{
515-
Namespace: "default",
516-
Name: "control-plane-join-cfg",
517-
},
518-
}
519-
result, err = k.Reconcile(request)
520-
if err != nil {
521-
t.Fatal(fmt.Sprintf("Failed to reconcile:\n %+v", err))
522-
}
523-
if result.Requeue == true {
524-
t.Fatal("did not expected to requeue")
525-
}
526-
if result.RequeueAfter != time.Duration(0) {
527-
t.Fatal("did not expected to requeue after")
528-
}
532+
request := ctrl.Request{
533+
NamespacedName: types.NamespacedName{
534+
Namespace: config.GetNamespace(),
535+
Name: rt.configName,
536+
},
537+
}
538+
result, err := k.Reconcile(request)
539+
if err != nil {
540+
t.Fatal(fmt.Sprintf("Failed to reconcile:\n %+v", err))
541+
}
542+
if result.Requeue == true {
543+
t.Fatal("did not expected to requeue")
544+
}
545+
if result.RequeueAfter != time.Duration(0) {
546+
t.Fatal("did not expected to requeue after")
547+
}
529548

530-
cfg, err = getKubeadmConfig(myclient, "control-plane-join-cfg")
531-
if err != nil {
532-
t.Fatal(fmt.Sprintf("Failed to reconcile:\n %+v", err))
533-
}
549+
cfg, err := getKubeadmConfig(myclient, rt.configName)
550+
if err != nil {
551+
t.Fatal(fmt.Sprintf("Failed to reconcile:\n %+v", err))
552+
}
534553

535-
if cfg.Status.Ready != true {
536-
t.Fatal("Expected status ready")
537-
}
554+
if cfg.Status.Ready != true {
555+
t.Fatal("Expected status ready")
556+
}
538557

539-
if cfg.Status.BootstrapData == nil {
540-
t.Fatal("Expected status ready")
541-
}
558+
if cfg.Status.BootstrapData == nil {
559+
t.Fatal("Expected status ready")
560+
}
542561

543-
myremoteclient, _ := k.SecretsClientFactory.NewSecretsClient(nil, nil)
544-
l, err := myremoteclient.List(metav1.ListOptions{})
545-
if err != nil {
546-
t.Fatal(fmt.Sprintf("Failed to reconcile:\n %+v", err))
547-
}
562+
myremoteclient, _ := k.SecretsClientFactory.NewSecretsClient(nil, nil)
563+
l, err := myremoteclient.List(metav1.ListOptions{})
564+
if err != nil {
565+
t.Fatal(fmt.Sprintf("Failed to get secrets after reconcyle:\n %+v", err))
566+
}
548567

549-
if len(l.Items) != 2 {
550-
t.Fatal(fmt.Sprintf("Failed to reconcile:\n %+v", err))
568+
if len(l.Items) != 1 {
569+
t.Fatal(fmt.Sprintf("Failed to bootstrap token secrets:\n %+v", err))
570+
}
571+
})
551572
}
552573
}
553574

0 commit comments

Comments
 (0)