Skip to content

Commit 27988ea

Browse files
committed
Update tests and condition messaging
1 parent 0b40256 commit 27988ea

File tree

8 files changed

+148
-20
lines changed

8 files changed

+148
-20
lines changed

api/bootstrap/kubeadm/v1beta1/kubeadmconfig_types.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -221,9 +221,6 @@ func (c *KubeadmConfigSpec) validateFiles(pathPrefix *field.Path) field.ErrorLis
221221
),
222222
)
223223
}
224-
// n.b.: if we ever add types besides Secret as a ContentFrom
225-
// Source, we must add webhook validation here for one of the
226-
// sources being non-nil.
227224
if file.ContentFormat != "" && file.ContentFormat != FileContentFormatGoTemplate {
228225
allErrs = append(
229226
allErrs,
@@ -234,6 +231,9 @@ func (c *KubeadmConfigSpec) validateFiles(pathPrefix *field.Path) field.ErrorLis
234231
),
235232
)
236233
}
234+
// n.b.: if we ever add types besides Secret as a ContentFrom
235+
// Source, we must add webhook validation here for one of the
236+
// sources being non-nil.
237237
if file.ContentFrom != nil {
238238
if file.ContentFrom.Secret.Name == "" {
239239
allErrs = append(

api/bootstrap/kubeadm/v1beta1/v1beta2_condition_consts.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,8 +68,11 @@ const (
6868
// could be resolved from the Cluster's control plane reference when applicable.
6969
KubeadmConfigControlPlaneKubernetesVersionAvailableV1Beta2Condition = "ControlPlaneKubernetesVersionAvailable"
7070

71-
// KubeadmConfigControlPlaneKubernetesVersionAvailableV1Beta2Reason surfaces when join version resolution succeeded.
72-
KubeadmConfigControlPlaneKubernetesVersionAvailableV1Beta2Reason = clusterv1beta1.AvailableV1Beta2Reason
71+
// KubeadmConfigControlPlaneKubernetesVersionFromControlPlaneV1Beta2Reason surfaces when join version was read from the control plane.
72+
KubeadmConfigControlPlaneKubernetesVersionFromControlPlaneV1Beta2Reason = "ControlPlaneKubernetesVersionFromControlPlane"
73+
74+
// KubeadmConfigControlPlaneKubernetesVersionFromMachineV1Beta2Reason surfaces when join version uses the Machine.
75+
KubeadmConfigControlPlaneKubernetesVersionFromMachineV1Beta2Reason = "ControlPlaneKubernetesVersionFromMachine"
7376

7477
// KubeadmConfigControlPlaneKubernetesVersionResolutionFailedV1Beta2Reason surfaces when resolution failed.
7578
KubeadmConfigControlPlaneKubernetesVersionResolutionFailedV1Beta2Reason = "ControlPlaneKubernetesVersionResolutionFailed"

api/bootstrap/kubeadm/v1beta2/kubeadm_types.go

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,15 +73,21 @@ const (
7373
)
7474

7575
// KubeadmConfig's ControlPlaneKubernetesVersionAvailable condition and corresponding reasons.
76-
// This condition is set when reconciling worker join bootstrap data: it reflects whether the controller
77-
// could resolve the Kubernetes version from the Cluster's control plane reference (when present).
76+
// This condition is set when reconciling worker join bootstrap data: it reflects how the controller chose
77+
// the Kubernetes version for join (from the control plane reference when possible, otherwise from the Machine).
7878
const (
79-
// KubeadmConfigControlPlaneKubernetesVersionAvailableCondition is true when the control plane Kubernetes
80-
// version for join could be resolved or is not required (no controlPlaneRef or control plane has no spec.version).
79+
// KubeadmConfigControlPlaneKubernetesVersionAvailableCondition is true when the Kubernetes version for worker
80+
// join was chosen successfully (from the control plane or from the Machine).
8181
KubeadmConfigControlPlaneKubernetesVersionAvailableCondition = "ControlPlaneKubernetesVersionAvailable"
8282

83-
// KubeadmConfigControlPlaneKubernetesVersionAvailableReason surfaces when join version resolution succeeded.
84-
KubeadmConfigControlPlaneKubernetesVersionAvailableReason = clusterv1.AvailableReason
83+
// KubeadmConfigControlPlaneKubernetesVersionFromControlPlaneReason surfaces when the Kubernetes version for
84+
// worker join was read from the referenced control plane's spec.version.
85+
KubeadmConfigControlPlaneKubernetesVersionFromControlPlaneReason = "FromControlPlane"
86+
87+
// KubeadmConfigControlPlaneKubernetesVersionFromMachineReason surfaces when the Kubernetes version for worker
88+
// join uses the Machine's spec.version because the Cluster has no controlPlaneRef or the referenced control
89+
// plane does not expose a version.
90+
KubeadmConfigControlPlaneKubernetesVersionFromMachineReason = "FromMachine"
8591

8692
// KubeadmConfigControlPlaneKubernetesVersionResolutionFailedReason surfaces when the controller could not
8793
// read the control plane object or its Kubernetes version while a controlPlaneRef is set.

api/bootstrap/kubeadm/v1beta2/kubeadmconfig_types.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -218,9 +218,6 @@ func (c *KubeadmConfigSpec) validateFiles(pathPrefix *field.Path) field.ErrorLis
218218
),
219219
)
220220
}
221-
// n.b.: if we ever add types besides Secret as a ContentFrom
222-
// Source, we must add webhook validation here for one of the
223-
// sources being non-nil.
224221
if file.ContentFormat != "" && file.ContentFormat != FileContentFormatGoTemplate {
225222
allErrs = append(
226223
allErrs,
@@ -231,6 +228,9 @@ func (c *KubeadmConfigSpec) validateFiles(pathPrefix *field.Path) field.ErrorLis
231228
),
232229
)
233230
}
231+
// n.b.: if we ever add types besides Secret as a ContentFrom
232+
// Source, we must add webhook validation here for one of the
233+
// sources being non-nil.
234234
if file.ContentFrom.IsDefined() {
235235
if file.ContentFrom.Secret.Name == "" {
236236
allErrs = append(

api/bootstrap/kubeadm/v1beta2/v1beta1_condition_consts.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,14 @@ const (
4747
// ControlPlaneKubernetesVersionResolutionFailedV1Beta1Reason (Severity=Warning) documents a failure to read
4848
// the control plane object or its Kubernetes version while resolving join bootstrap data.
4949
ControlPlaneKubernetesVersionResolutionFailedV1Beta1Reason = "ControlPlaneKubernetesVersionResolutionFailed"
50+
51+
// ControlPlaneKubernetesVersionFromControlPlaneV1Beta1Reason documents that the Kubernetes version for worker
52+
// join was read from the Cluster's control plane reference.
53+
ControlPlaneKubernetesVersionFromControlPlaneV1Beta1Reason = "ControlPlaneKubernetesVersionFromControlPlane"
54+
55+
// ControlPlaneKubernetesVersionFromMachineV1Beta1Reason documents that the Kubernetes version for worker join
56+
// uses the Machine's spec.version because the control plane reference is unset or does not expose a version.
57+
ControlPlaneKubernetesVersionFromMachineV1Beta1Reason = "ControlPlaneKubernetesVersionFromMachine"
5058
)
5159

5260
const (

bootstrap/kubeadm/internal/bootstrapfiles/template_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,4 +59,14 @@ func TestRenderTemplates(t *testing.T) {
5959
_, err := RenderTemplates(in, data)
6060
g.Expect(err).To(HaveOccurred())
6161
})
62+
63+
t.Run("template execution errors on missing field", func(t *testing.T) {
64+
g := NewWithT(t)
65+
in := []bootstrapv1.File{
66+
{Path: "/d", ContentFormat: bootstrapv1.FileContentFormatGoTemplate, Content: "{{ .NonExistentField }}"},
67+
}
68+
_, err := RenderTemplates(in, data)
69+
g.Expect(err).To(HaveOccurred())
70+
g.Expect(err.Error()).To(ContainSubstring(`failed to execute go-template for file "/d"`))
71+
})
6272
}

bootstrap/kubeadm/internal/controllers/kubeadmconfig_controller.go

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -721,14 +721,29 @@ func (r *KubeadmConfigReconciler) joinWorker(ctx context.Context, scope *Scope)
721721
})
722722
return ctrl.Result{}, err
723723
}
724+
var cpVersionReasonV1Beta1, cpVersionReason string
725+
var cpVersionMsg string
724726
if kubernetesVersion == "" {
725727
kubernetesVersion = scope.ConfigOwner.KubernetesVersion()
726-
}
727-
v1beta1conditions.MarkTrue(scope.Config, bootstrapv1.ControlPlaneKubernetesVersionAvailableV1Beta1Condition)
728+
cpVersionReasonV1Beta1 = bootstrapv1.ControlPlaneKubernetesVersionFromMachineV1Beta1Reason
729+
cpVersionReason = bootstrapv1.KubeadmConfigControlPlaneKubernetesVersionFromMachineReason
730+
cpVersionMsg = "Kubernetes version for join uses the Machine's spec.version because the control plane reference is unset or does not expose a version."
731+
} else {
732+
cpVersionReasonV1Beta1 = bootstrapv1.ControlPlaneKubernetesVersionFromControlPlaneV1Beta1Reason
733+
cpVersionReason = bootstrapv1.KubeadmConfigControlPlaneKubernetesVersionFromControlPlaneReason
734+
cpVersionMsg = "Kubernetes version for join was read from the Cluster's control plane reference."
735+
}
736+
v1beta1conditions.Set(scope.Config, &clusterv1.Condition{
737+
Type: bootstrapv1.ControlPlaneKubernetesVersionAvailableV1Beta1Condition,
738+
Status: corev1.ConditionTrue,
739+
Reason: cpVersionReasonV1Beta1,
740+
Message: cpVersionMsg,
741+
})
728742
conditions.Set(scope.Config, metav1.Condition{
729-
Type: bootstrapv1.KubeadmConfigControlPlaneKubernetesVersionAvailableCondition,
730-
Status: metav1.ConditionTrue,
731-
Reason: bootstrapv1.KubeadmConfigControlPlaneKubernetesVersionAvailableReason,
743+
Type: bootstrapv1.KubeadmConfigControlPlaneKubernetesVersionAvailableCondition,
744+
Status: metav1.ConditionTrue,
745+
Reason: cpVersionReason,
746+
Message: cpVersionMsg,
732747
})
733748
parsedVersion, err := semver.ParseTolerant(kubernetesVersion)
734749
if err != nil {

bootstrap/kubeadm/internal/controllers/kubeadmconfig_controller_test.go

Lines changed: 87 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@ import (
2525

2626
ignition "github.com/flatcar/ignition/config/v2_3"
2727
. "github.com/onsi/gomega"
28+
apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
2829
corev1 "k8s.io/api/core/v1"
2930
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
31+
"k8s.io/apimachinery/pkg/runtime"
3032
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
3133
"k8s.io/apimachinery/pkg/types"
3234
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
@@ -2787,8 +2789,23 @@ func TestKubeadmConfigReconciler_Reconcile_v1beta2_conditions(t *testing.T) {
27872789
condition := conditions.Get(newConfig, conditionType)
27882790
g.Expect(condition).ToNot(BeNil(), "condition %s is missing", conditionType)
27892791
g.Expect(condition.Status).To(Equal(metav1.ConditionTrue))
2790-
g.Expect(condition.Message).To(BeEmpty())
2792+
if conditionType == bootstrapv1.KubeadmConfigControlPlaneKubernetesVersionAvailableCondition {
2793+
g.Expect(condition.Reason).To(Equal(bootstrapv1.KubeadmConfigControlPlaneKubernetesVersionFromMachineReason))
2794+
g.Expect(condition.Message).To(ContainSubstring("Machine"))
2795+
} else {
2796+
g.Expect(condition.Message).To(BeEmpty())
2797+
}
27912798
}
2799+
foundCPKubeVer := false
2800+
for _, c := range newConfig.GetV1Beta1Conditions() {
2801+
if c.Type == bootstrapv1.ControlPlaneKubernetesVersionAvailableV1Beta1Condition {
2802+
g.Expect(c.Status).To(Equal(corev1.ConditionTrue))
2803+
g.Expect(c.Reason).To(Equal(bootstrapv1.ControlPlaneKubernetesVersionFromMachineV1Beta1Reason))
2804+
foundCPKubeVer = true
2805+
break
2806+
}
2807+
}
2808+
g.Expect(foundCPKubeVer).To(BeTrue())
27922809
for _, conditionType := range []string{clusterv1.PausedCondition} {
27932810
condition := conditions.Get(newConfig, conditionType)
27942811
g.Expect(condition).ToNot(BeNil(), "condition %s is missing", conditionType)
@@ -2798,3 +2815,72 @@ func TestKubeadmConfigReconciler_Reconcile_v1beta2_conditions(t *testing.T) {
27982815
})
27992816
}
28002817
}
2818+
2819+
func TestKubeadmConfigReconciler_Reconcile_v1beta2_conditions_ControlPlaneKubernetesVersionFromControlPlaneRef(t *testing.T) {
2820+
g := NewWithT(t)
2821+
scheme := runtime.NewScheme()
2822+
g.Expect(apiextensionsv1.AddToScheme(scheme)).To(Succeed())
2823+
g.Expect(clusterv1.AddToScheme(scheme)).To(Succeed())
2824+
g.Expect(bootstrapv1.AddToScheme(scheme)).To(Succeed())
2825+
2826+
clusterName := "my-cluster-cp"
2827+
cluster := builder.Cluster(metav1.NamespaceDefault, clusterName).Build()
2828+
cluster.Status.Conditions = []metav1.Condition{{Type: clusterv1.ClusterControlPlaneInitializedCondition, Status: metav1.ConditionTrue}}
2829+
cluster.Status.Initialization.InfrastructureProvisioned = ptr.To(true)
2830+
cluster.Spec.ControlPlaneEndpoint = clusterv1.APIEndpoint{Host: "example.com", Port: 6443}
2831+
cluster.Spec.ControlPlaneRef = clusterv1.ContractVersionedObjectReference{
2832+
APIGroup: builder.ControlPlaneGroupVersion.Group,
2833+
Kind: builder.TestControlPlaneKind,
2834+
Name: "cp",
2835+
}
2836+
cp := builder.TestControlPlane(metav1.NamespaceDefault, "cp").WithVersion(testSkewK8sVersion).Build()
2837+
crd := builder.TestControlPlaneCRD.DeepCopy()
2838+
2839+
machine := builder.Machine(metav1.NamespaceDefault, "my-machine").
2840+
WithVersion(testK8sVersion).
2841+
WithClusterName(cluster.Name).
2842+
WithBootstrapTemplate(bootstrapbuilder.KubeadmConfig(metav1.NamespaceDefault, "").Unstructured()).
2843+
Build()
2844+
kubeadmConfig := newKubeadmConfig(metav1.NamespaceDefault, "kubeadmconfig")
2845+
kubeadmConfig.SetOwnerReferences([]metav1.OwnerReference{{
2846+
APIVersion: clusterv1.GroupVersion.String(),
2847+
Kind: "Machine",
2848+
Name: machine.Name,
2849+
}})
2850+
2851+
objects := []client.Object{cluster, machine, kubeadmConfig, cp, crd}
2852+
objects = append(objects, createSecrets(t, cluster, kubeadmConfig)...)
2853+
2854+
myclient := fake.NewClientBuilder().WithScheme(scheme).WithObjects(objects...).WithStatusSubresource(&bootstrapv1.KubeadmConfig{}).Build()
2855+
2856+
r := &KubeadmConfigReconciler{
2857+
Client: myclient,
2858+
SecretCachingClient: myclient,
2859+
ClusterCache: clustercache.NewFakeClusterCache(myclient, client.ObjectKey{Name: cluster.Name, Namespace: cluster.Namespace}),
2860+
KubeadmInitLock: &myInitLocker{},
2861+
}
2862+
2863+
key := client.ObjectKeyFromObject(kubeadmConfig)
2864+
_, err := r.Reconcile(ctx, ctrl.Request{NamespacedName: key})
2865+
g.Expect(err).ToNot(HaveOccurred())
2866+
2867+
newConfig := &bootstrapv1.KubeadmConfig{}
2868+
g.Expect(myclient.Get(ctx, key, newConfig)).To(Succeed())
2869+
2870+
c := conditions.Get(newConfig, bootstrapv1.KubeadmConfigControlPlaneKubernetesVersionAvailableCondition)
2871+
g.Expect(c).ToNot(BeNil())
2872+
g.Expect(c.Status).To(Equal(metav1.ConditionTrue))
2873+
g.Expect(c.Reason).To(Equal(bootstrapv1.KubeadmConfigControlPlaneKubernetesVersionFromControlPlaneReason))
2874+
g.Expect(c.Message).To(ContainSubstring("control plane reference"))
2875+
2876+
foundCPKubeVer := false
2877+
for _, cond := range newConfig.GetV1Beta1Conditions() {
2878+
if cond.Type == bootstrapv1.ControlPlaneKubernetesVersionAvailableV1Beta1Condition {
2879+
g.Expect(cond.Status).To(Equal(corev1.ConditionTrue))
2880+
g.Expect(cond.Reason).To(Equal(bootstrapv1.ControlPlaneKubernetesVersionFromControlPlaneV1Beta1Reason))
2881+
foundCPKubeVer = true
2882+
break
2883+
}
2884+
}
2885+
g.Expect(foundCPKubeVer).To(BeTrue())
2886+
}

0 commit comments

Comments
 (0)