Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🐛 Fix unit test coverage in KubeadmConfig #7678

Merged
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,17 @@ func TestKubeadmConfigReconciler_MachineToBootstrapMapFuncReturn(t *testing.T) {
// Reconcile returns early if the kubeadm config is ready because it should never re-generate bootstrap data.
func TestKubeadmConfigReconciler_Reconcile_ReturnEarlyIfKubeadmConfigIsReady(t *testing.T) {
g := NewWithT(t)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The intention here was to ensure that the tests were actually testing conditions resulting from reconcile, rather than just the controller runtime result. Overall package test coverage goes from 68.8 -> 71.1 with these changes.

cluster := builder.Cluster(metav1.NamespaceDefault, "cluster1").Build()
cluster.Status.InfrastructureReady = true
machine := builder.Machine(metav1.NamespaceDefault, "m1").WithClusterName("cluster1").Build()
config := newKubeadmConfig(metav1.NamespaceDefault, "cfg")
addKubeadmConfigToMachine(config, machine)

config.Status.Ready = true

objects := []client.Object{
cluster,
machine,
config,
}
myclient := fake.NewClientBuilder().WithObjects(objects...).Build()
Expand All @@ -117,7 +123,7 @@ func TestKubeadmConfigReconciler_Reconcile_ReturnEarlyIfKubeadmConfigIsReady(t *
g.Expect(result.RequeueAfter).To(Equal(time.Duration(0)))
}

// Reconcile returns early if the kubeadm config is ready because it should never re-generate bootstrap data.
// Reconcile should update owner references on bootstrap secrets on creation and update.
func TestKubeadmConfigReconciler_TestSecretOwnerReferenceReconciliation(t *testing.T) {
g := NewWithT(t)

Expand Down Expand Up @@ -249,14 +255,20 @@ func TestKubeadmConfigReconciler_Reconcile_ReturnNilIfReferencedMachineIsNotFoun
// If the machine has bootstrap data secret reference, there is no need to generate more bootstrap data.
func TestKubeadmConfigReconciler_Reconcile_ReturnEarlyIfMachineHasDataSecretName(t *testing.T) {
g := NewWithT(t)
cluster := builder.Cluster(metav1.NamespaceDefault, "cluster1").Build()
cluster.Status.InfrastructureReady = true

machine := builder.Machine(metav1.NamespaceDefault, "machine").
WithVersion("v1.19.1").
WithClusterName("cluster1").
WithBootstrapTemplate(bootstrapbuilder.KubeadmConfig(metav1.NamespaceDefault, "cfg").Unstructured()).
Build()
machine.Spec.Bootstrap.DataSecretName = pointer.String("something")

config := newKubeadmConfig(metav1.NamespaceDefault, "cfg")
addKubeadmConfigToMachine(config, machine)
objects := []client.Object{
cluster,
machine,
config,
}
Expand All @@ -273,9 +285,12 @@ func TestKubeadmConfigReconciler_Reconcile_ReturnEarlyIfMachineHasDataSecretName
},
}
result, err := k.Reconcile(ctx, request)
actual := &bootstrapv1.KubeadmConfig{}
g.Expect(myclient.Get(ctx, client.ObjectKey{Namespace: config.Namespace, Name: config.Name}, actual)).To(Succeed())
g.Expect(err).NotTo(HaveOccurred())
g.Expect(result.Requeue).To(BeFalse())
g.Expect(result.RequeueAfter).To(Equal(time.Duration(0)))
assertHasTrueCondition(g, myclient, request, bootstrapv1.DataSecretAvailableCondition)
}

func TestKubeadmConfigReconciler_ReturnEarlyIfClusterInfraNotReady(t *testing.T) {
Expand Down Expand Up @@ -328,35 +343,7 @@ func TestKubeadmConfigReconciler_Reconcile_ReturnEarlyIfMachineHasNoCluster(t *t
WithBootstrapTemplate(bootstrapbuilder.KubeadmConfig(metav1.NamespaceDefault, "cfg").Unstructured()).
Build()
config := newKubeadmConfig(metav1.NamespaceDefault, "cfg")

objects := []client.Object{
machine,
config,
}
myclient := fake.NewClientBuilder().WithObjects(objects...).Build()

k := &KubeadmConfigReconciler{
Client: myclient,
}

request := ctrl.Request{
NamespacedName: client.ObjectKey{
Namespace: metav1.NamespaceDefault,
Name: "cfg",
},
}
_, err := k.Reconcile(ctx, request)
g.Expect(err).NotTo(HaveOccurred())
}

// This does not expect an error, hoping the machine gets updated with a cluster.
func TestKubeadmConfigReconciler_Reconcile_ReturnNilIfMachineDoesNotHaveAssociatedCluster(t *testing.T) {
killianmuldoon marked this conversation as resolved.
Show resolved Hide resolved
g := NewWithT(t)
machine := builder.Machine(metav1.NamespaceDefault, "machine").
WithVersion("v1.19.1").
WithBootstrapTemplate(bootstrapbuilder.KubeadmConfig(metav1.NamespaceDefault, "cfg").Unstructured()).
Build()
config := newKubeadmConfig(metav1.NamespaceDefault, "cfg")
addKubeadmConfigToMachine(config, machine)

objects := []client.Object{
machine,
Expand Down Expand Up @@ -390,6 +377,7 @@ func TestKubeadmConfigReconciler_Reconcile_ReturnNilIfAssociatedClusterIsNotFoun
Build()
config := newKubeadmConfig(metav1.NamespaceDefault, "cfg")

addKubeadmConfigToMachine(config, machine)
objects := []client.Object{
// intentionally omitting cluster
machine,
Expand Down Expand Up @@ -430,7 +418,7 @@ func TestKubeadmConfigReconciler_Reconcile_RequeueJoiningNodesIfControlPlaneNotI
objects []client.Object
}{
{
name: "requeue worker when control plane is not yet initialiezd",
name: "requeue worker when control plane is not yet initialized",
request: ctrl.Request{
NamespacedName: client.ObjectKey{
Namespace: workerJoinConfig.Namespace,
Expand Down Expand Up @@ -482,11 +470,19 @@ func TestKubeadmConfigReconciler_Reconcile_RequeueJoiningNodesIfControlPlaneNotI
func TestKubeadmConfigReconciler_Reconcile_GenerateCloudConfigData(t *testing.T) {
g := NewWithT(t)

configName := "control-plane-init-cfg"
cluster := builder.Cluster(metav1.NamespaceDefault, "cluster").Build()
cluster.Spec.ControlPlaneEndpoint = clusterv1.APIEndpoint{Host: "validhost", Port: 6443}
cluster.Status.InfrastructureReady = true
conditions.MarkTrue(cluster, clusterv1.ControlPlaneInitializedCondition)

controlPlaneInitMachine := newControlPlaneMachine(cluster, "control-plane-init-machine")
controlPlaneInitConfig := newControlPlaneInitKubeadmConfig(controlPlaneInitMachine.Namespace, "control-plane-init-cfg")
controlPlaneInitConfig := newControlPlaneInitKubeadmConfig(controlPlaneInitMachine.Namespace, configName)
controlPlaneInitConfig.Spec.JoinConfiguration = &bootstrapv1.JoinConfiguration{}
controlPlaneInitConfig.Spec.JoinConfiguration.Discovery.BootstrapToken = &bootstrapv1.BootstrapTokenDiscovery{
CACertHashes: []string{"...."},
}

addKubeadmConfigToMachine(controlPlaneInitConfig, controlPlaneInitMachine)

objects := []client.Object{
Expand All @@ -499,8 +495,9 @@ func TestKubeadmConfigReconciler_Reconcile_GenerateCloudConfigData(t *testing.T)
myclient := fake.NewClientBuilder().WithObjects(objects...).Build()

k := &KubeadmConfigReconciler{
Client: myclient,
KubeadmInitLock: &myInitLocker{},
Client: myclient,
KubeadmInitLock: &myInitLocker{},
remoteClientGetter: fakeremote.NewClusterClient,
}

request := ctrl.Request{
Expand All @@ -509,6 +506,9 @@ func TestKubeadmConfigReconciler_Reconcile_GenerateCloudConfigData(t *testing.T)
Name: "control-plane-init-cfg",
},
}
s := &corev1.Secret{}
g.Expect(myclient.Get(ctx, client.ObjectKey{Namespace: metav1.NamespaceDefault, Name: configName}, s)).ToNot(Succeed())

result, err := k.Reconcile(ctx, request)
g.Expect(err).NotTo(HaveOccurred())
g.Expect(result.Requeue).To(BeFalse())
Expand All @@ -522,6 +522,9 @@ func TestKubeadmConfigReconciler_Reconcile_GenerateCloudConfigData(t *testing.T)
assertHasTrueCondition(g, myclient, request, bootstrapv1.CertificatesAvailableCondition)
assertHasTrueCondition(g, myclient, request, bootstrapv1.DataSecretAvailableCondition)

// Expect the Secret to exist, and for it to contain some data under the "value" key.
g.Expect(myclient.Get(ctx, client.ObjectKey{Namespace: metav1.NamespaceDefault, Name: configName}, s)).To(Succeed())
g.Expect(len(s.Data["value"])).To(BeNumerically(">", 0))
// Ensure that we don't fail trying to refresh any bootstrap tokens
_, err = k.Reconcile(ctx, request)
g.Expect(err).NotTo(HaveOccurred())
Expand Down Expand Up @@ -561,11 +564,15 @@ func TestKubeadmConfigReconciler_Reconcile_ErrorIfJoiningControlPlaneHasInvalidC
request := ctrl.Request{
NamespacedName: client.ObjectKey{
Namespace: metav1.NamespaceDefault,
Name: "control-plane-join-cfg",
Name: controlPlaneJoinConfig.Name,
},
}
_, err := k.Reconcile(ctx, request)
g.Expect(err).NotTo(HaveOccurred())
actualConfig := &bootstrapv1.KubeadmConfig{}
g.Expect(myclient.Get(ctx, client.ObjectKey{Namespace: controlPlaneJoinConfig.Namespace, Name: controlPlaneJoinConfig.Name}, actualConfig)).To(Succeed())
assertHasTrueCondition(g, myclient, request, bootstrapv1.DataSecretAvailableCondition)
assertHasTrueCondition(g, myclient, request, bootstrapv1.CertificatesAvailableCondition)
}

// If there is no APIEndpoint but everything is ready then requeue in hopes of a new APIEndpoint showing up eventually.
Expand Down Expand Up @@ -607,9 +614,16 @@ func TestKubeadmConfigReconciler_Reconcile_RequeueIfControlPlaneIsMissingAPIEndp
g.Expect(err).NotTo(HaveOccurred())
g.Expect(result.Requeue).To(BeFalse())
g.Expect(result.RequeueAfter).To(Equal(10 * time.Second))

actualConfig := &bootstrapv1.KubeadmConfig{}
g.Expect(myclient.Get(ctx, client.ObjectKey{Namespace: workerJoinConfig.Namespace, Name: workerJoinConfig.Name}, actualConfig)).To(Succeed())

// At this point the DataSecretAvailableCondition should not be set. CertificatesAvailableCondition should be true.
g.Expect(conditions.Get(actualConfig, bootstrapv1.DataSecretAvailableCondition)).To(BeNil())
assertHasTrueCondition(g, myclient, request, bootstrapv1.CertificatesAvailableCondition)
}

func TestReconcileIfJoinNodesAndControlPlaneIsReady(t *testing.T) {
func TestReconcileIfJoinCertificatesAvailableConditioninNodesAndControlPlaneIsReady(t *testing.T) {
cluster := builder.Cluster(metav1.NamespaceDefault, "cluster").Build()
cluster.Status.InfrastructureReady = true
conditions.MarkTrue(cluster, clusterv1.ControlPlaneInitializedCondition)
Expand Down Expand Up @@ -1848,6 +1862,17 @@ func TestKubeadmConfigReconciler_Reconcile_ExactlyOneControlPlaneMachineInitiali
g.Expect(err).NotTo(HaveOccurred())
g.Expect(result.Requeue).To(BeFalse())
g.Expect(result.RequeueAfter).To(Equal(30 * time.Second))
confList := &bootstrapv1.KubeadmConfigList{}
g.Expect(myclient.List(ctx, confList)).To(Succeed())
for _, c := range confList.Items {
// Ensure the DataSecretName is only set for controlPlaneInitConfigFirst.
if c.Name == controlPlaneInitConfigFirst.Name {
g.Expect(*c.Status.DataSecretName).To(Not(BeEmpty()))
}
if c.Name == controlPlaneInitConfigSecond.Name {
g.Expect(c.Status.DataSecretName).To(BeNil())
}
}
}

// Patch should be applied if there is an error in reconcile.
Expand Down Expand Up @@ -2252,6 +2277,10 @@ func addKubeadmConfigToMachine(config *bootstrapv1.KubeadmConfig, machine *clust
},
}

if machine.Spec.Bootstrap.ConfigRef == nil {
machine.Spec.Bootstrap.ConfigRef = &corev1.ObjectReference{}
}

machine.Spec.Bootstrap.ConfigRef.Name = config.Name
machine.Spec.Bootstrap.ConfigRef.Namespace = config.Namespace
}
Expand Down