From 32002624de8de8c7beacee8190010f50e0b3e31d Mon Sep 17 00:00:00 2001 From: fabriziopandini Date: Tue, 7 Jul 2020 11:08:49 +0200 Subject: [PATCH] cleanup MatchesKubeadmBootstrapConfig and add unit tests --- controlplane/kubeadm/controllers/helpers.go | 2 +- .../machinefilters/machine_filters.go | 186 ++-- .../internal/machinefilters/util_test.go | 825 ++++++++++++++++++ 3 files changed, 940 insertions(+), 73 deletions(-) create mode 100644 controlplane/kubeadm/internal/machinefilters/util_test.go diff --git a/controlplane/kubeadm/controllers/helpers.go b/controlplane/kubeadm/controllers/helpers.go index 919225bd8277..d9b9f74fb342 100644 --- a/controlplane/kubeadm/controllers/helpers.go +++ b/controlplane/kubeadm/controllers/helpers.go @@ -267,6 +267,6 @@ func (r *KubeadmControlPlaneReconciler) machinesNeedingRollout(ctx context.Conte // Machines that are scheduled for rollout (KCP.Spec.UpgradeAfter set, the UpgradeAfter deadline is expired, and the machine was created before the deadline). machinefilters.ShouldRolloutAfter(c.KCP.Spec.UpgradeAfter), // Machines that do not match with KCP config. - machinefilters.Not(machinefilters.MatchesKCPConfiguration(ctx, r.Client, *c.KCP, *c.Cluster)), + machinefilters.Not(machinefilters.MatchesKCPConfiguration(ctx, r.Client, c.KCP)), ) } diff --git a/controlplane/kubeadm/internal/machinefilters/machine_filters.go b/controlplane/kubeadm/internal/machinefilters/machine_filters.go index 20555672d3b0..0a611883bf96 100644 --- a/controlplane/kubeadm/internal/machinefilters/machine_filters.go +++ b/controlplane/kubeadm/internal/machinefilters/machine_filters.go @@ -211,16 +211,16 @@ func ControlPlaneSelectorForCluster(clusterName string) labels.Selector { // MatchesKCPConfiguration returns a filter to find all machines that matches with KCP config and do not require any rollout. // Kubernetes version, infrastructure template, and KubeadmConfig field need to be equivalent. -func MatchesKCPConfiguration(ctx context.Context, c client.Client, kcp controlplanev1.KubeadmControlPlane, cluster clusterv1.Cluster) func(machine *clusterv1.Machine) bool { +func MatchesKCPConfiguration(ctx context.Context, c client.Client, kcp *controlplanev1.KubeadmControlPlane) func(machine *clusterv1.Machine) bool { return And( MatchesKubernetesVersion(kcp.Spec.Version), - MatchesKubeadmBootstrapConfig(ctx, c, kcp, cluster), + MatchesKubeadmBootstrapConfig(ctx, c, kcp), MatchesTemplateClonedFrom(ctx, c, kcp), ) } // MatchesTemplateClonedFrom returns a filter to find all machines that match a given KCP infra template. -func MatchesTemplateClonedFrom(ctx context.Context, c client.Client, kcp controlplanev1.KubeadmControlPlane) Func { +func MatchesTemplateClonedFrom(ctx context.Context, c client.Client, kcp *controlplanev1.KubeadmControlPlane) Func { return func(machine *clusterv1.Machine) bool { if machine == nil { return false @@ -263,91 +263,133 @@ func MatchesKubernetesVersion(kubernetesVersion string) Func { } // MatchesKubeadmBootstrapConfig checks if machine's KubeadmConfigSpec is equivalent with KCP's KubeadmConfigSpec. -func MatchesKubeadmBootstrapConfig(ctx context.Context, c client.Client, kcp controlplanev1.KubeadmControlPlane, cluster clusterv1.Cluster) Func { +func MatchesKubeadmBootstrapConfig(ctx context.Context, c client.Client, kcp *controlplanev1.KubeadmControlPlane) Func { return func(machine *clusterv1.Machine) bool { if machine == nil { return false } - bootstrapRef := machine.Spec.Bootstrap.ConfigRef - if bootstrapRef == nil { - // Missing bootstrap reference should not be considered as unmatching. - // This is a safety precaution to avoid selecting machines that are broken, which in the future should be remediated separately. - return true - } - bootstrapObj := &bootstrapv1.KubeadmConfig{} - if err := c.Get(ctx, client.ObjectKey{Name: bootstrapRef.Name, Namespace: machine.Namespace}, bootstrapObj); err != nil { - // Return true here because failing to get KubeadmConfig should not be considered as unmatching. - // This is a safety precaution to avoid rolling out machines if the client or the api-server is misbehaving. - return true + // Check if KCP and machine ClusterConfiguration matches, if not return + if match := matchClusterConfiguration(kcp, machine); !match { + return false } - kcpConfigSpecLocal := kcp.Spec.KubeadmConfigSpec.DeepCopy() + // Check if KCP and machine InitConfiguration or JoinConfiguration matches + // NOTE: only one between init configuration and join configuration is set on a machine, depending + // on the fact that the machine was the initial control plane node or a joining control plane node. + return matchInitOrJoinConfiguration(ctx, c, kcp, machine) + } +} - // Machine's init configuration is nil when machine is the control plane is already initialized. - if bootstrapObj.Spec.InitConfiguration == nil { - kcpConfigSpecLocal.InitConfiguration = nil +// matchClusterConfiguration verifies if KCP and machine ClusterConfiguration matches. +// NOTE: Machines that have KubeadmClusterConfigurationAnnotation will have to match with KCP ClusterConfiguration. +// If the annotation is not present (machine is either old or adopted), we won't roll out on any possible changes +// made in KCP's ClusterConfiguration given that we don't have enough information to make a decision. +// Users should use KCP.Spec.UpgradeAfter field to force a rollout in this case. +func matchClusterConfiguration(kcp *controlplanev1.KubeadmControlPlane, machine *clusterv1.Machine) bool { + machineClusterConfigStr, ok := machine.GetAnnotations()[controlplanev1.KubeadmClusterConfigurationAnnotation] + if ok { + machineClusterConfig := &kubeadmv1.ClusterConfiguration{} + // ClusterConfiguration annotation is not correct, only solution is to rollout. + if err := json.Unmarshal([]byte(machineClusterConfigStr), machineClusterConfig); err != nil { + return false } + return reflect.DeepEqual(machineClusterConfig, kcp.Spec.KubeadmConfigSpec.ClusterConfiguration) + } - // Machine's join configuration is nil when a machine is the first machine in the control plane. - if bootstrapObj.Spec.JoinConfiguration == nil { - kcpConfigSpecLocal.JoinConfiguration = nil - } else if kcpConfigSpecLocal.JoinConfiguration == nil { - // If KCP join configuration is not present, set machine join configuration to nil (nothing can trigger rollout here). - bootstrapObj.Spec.JoinConfiguration = nil - } + // We don't have enough information to make a decision; don't' trigger a roll out. + return true +} - // Clear up the TypeMeta information from the comparison. Today, the kubeadm types are embedded in CABPK and KCP types don't carry this information. - if bootstrapObj.Spec.InitConfiguration != nil && kcpConfigSpecLocal.InitConfiguration != nil { - bootstrapObj.Spec.InitConfiguration.TypeMeta = kcpConfigSpecLocal.InitConfiguration.TypeMeta - } - if bootstrapObj.Spec.JoinConfiguration != nil && kcpConfigSpecLocal.JoinConfiguration != nil { - bootstrapObj.Spec.JoinConfiguration.TypeMeta = kcpConfigSpecLocal.JoinConfiguration.TypeMeta - } +// matchInitOrJoinConfiguration verifies if KCP and machine InitConfiguration or JoinConfiguration matches. +// NOTE: By extension this method takes care of detecting changes in other fields of the KubeadmConfig configuration (e.g. Files, Mounts etc.) +func matchInitOrJoinConfiguration(ctx context.Context, c client.Client, kcp *controlplanev1.KubeadmControlPlane, machine *clusterv1.Machine) bool { + bootstrapRef := machine.Spec.Bootstrap.ConfigRef + if bootstrapRef == nil { + // Missing bootstrap reference should not be considered as unmatching. + // This is a safety precaution to avoid selecting machines that are broken, which in the future should be remediated separately. + return true + } - // Machines that have KubeadmClusterConfigurationAnnotation will have to match with KCP ClusterConfiguration. - // If the annotation is not present (machine is either old or adopted), we won't roll out on any possible changes - // made in KCP's ClusterConfiguration given that we don't have enough information to make a decision. - // Users should use KCP.Spec.UpgradeAfter field to force a rollout in this case. - machineClusterConfigStr, ok := machine.GetAnnotations()[controlplanev1.KubeadmClusterConfigurationAnnotation] - if ok { - machineClusterConfig := &kubeadmv1.ClusterConfiguration{} - // ClusterConfiguration annotation is not correct, only solution is to rollout. - if err := json.Unmarshal([]byte(machineClusterConfigStr), machineClusterConfig); err != nil { - return false - } - if !reflect.DeepEqual(machineClusterConfig, kcp.Spec.KubeadmConfigSpec.ClusterConfiguration) { - return false - } - } + machineConfig := &bootstrapv1.KubeadmConfig{} + if err := c.Get(ctx, client.ObjectKey{Name: bootstrapRef.Name, Namespace: machine.Namespace}, machineConfig); err != nil { + // Return true here because failing to get KubeadmConfig should not be considered as unmatching. + // This is a safety precaution to avoid rolling out machines if the client or the api-server is misbehaving. + return true + } - // KCP ClusterConfiguration will only be compared with a machine's ClusterConfiguration annotation. - // To skip ClusterConfiguration merge during SemanticMerge(), set both Machine's and KCP's ClusterConfigurations to nil here. - kcpConfigSpecLocal.ClusterConfiguration = nil - bootstrapObj.Spec.ClusterConfiguration = nil + // takes the KubeadmConfigSpec from KCP and applies the transformations required + // to allow a comparison with the KubeadmConfig referenced from the machine. + kcpConfig := getAdjustedKcpConfig(kcp, machineConfig) - // Machine's JoinConfiguration Discovery is set to an empty object by KubeadmConfig controller if KCP is Discovery is nil, also - // adopted machines may have an unrelated discovery setting so ignore discovery completely when comparing JoinConfigurations. - emptyDiscovery := kubeadmv1.Discovery{} - if kcpConfigSpecLocal.JoinConfiguration != nil { - kcpConfigSpecLocal.JoinConfiguration.Discovery = emptyDiscovery - } - if bootstrapObj.Spec.JoinConfiguration != nil { - bootstrapObj.Spec.JoinConfiguration.Discovery = emptyDiscovery - } + // cleanups all the fields that are not relevant for the comparison. + cleanupConfigFields(kcpConfig, machineConfig) - // Machine's JoinConfiguration ControlPlane is set to an empty object by KubeadmConfig controller if KCP is ControlPlane is nil. - // Set Machine's ControlPlane to nil to avoid - if kcpConfigSpecLocal.JoinConfiguration != nil && kcpConfigSpecLocal.JoinConfiguration.ControlPlane == nil { - bootstrapObj.Spec.JoinConfiguration.ControlPlane = nil - } + return reflect.DeepEqual(&machineConfig.Spec, kcpConfig) +} - // If KCP's join NodeRegistration is empty, set machine's node registration to empty as no changes should trigger rollout. - emptyNodeRegistration := kubeadmv1.NodeRegistrationOptions{} - if kcpConfigSpecLocal.JoinConfiguration != nil && reflect.DeepEqual(kcpConfigSpecLocal.JoinConfiguration.NodeRegistration, emptyNodeRegistration) { - bootstrapObj.Spec.JoinConfiguration.NodeRegistration = emptyNodeRegistration - } +// getAdjustedKcpConfig takes the KubeadmConfigSpec from KCP and applies the transformations required +// to allow a comparison with the KubeadmConfig referenced from the machine. +// NOTE: The KCP controller applies a set of transformations when creating a KubeadmConfig referenced from the machine, +// mostly depending on the fact that the machine was the initial control plane node or a joining control plane node. +// In this function we don't have such information, so we are making the KubeadmConfigSpec similar to the KubeadmConfig. +func getAdjustedKcpConfig(kcp *controlplanev1.KubeadmControlPlane, machineConfig *bootstrapv1.KubeadmConfig) *bootstrapv1.KubeadmConfigSpec { + kcpConfig := kcp.Spec.KubeadmConfigSpec.DeepCopy() + + // Machine's join configuration is nil when it is the first machine in the control plane. + if machineConfig.Spec.JoinConfiguration == nil { + kcpConfig.JoinConfiguration = nil + } + + // Machine's init configuration is nil when the control plane is already initialized. + if machineConfig.Spec.InitConfiguration == nil { + kcpConfig.InitConfiguration = nil + } + + return kcpConfig +} - return reflect.DeepEqual(bootstrapObj.Spec, *kcpConfigSpecLocal) +// cleanupConfigFields cleanups all the fields that are not relevant for the comparison. +func cleanupConfigFields(kcpConfig *bootstrapv1.KubeadmConfigSpec, machineConfig *bootstrapv1.KubeadmConfig) { + // KCP ClusterConfiguration will only be compared with a machine's ClusterConfiguration annotation, so + // we are cleaning up from the reflect.DeepEqual comparison. + kcpConfig.ClusterConfiguration = nil + machineConfig.Spec.ClusterConfiguration = nil + + // If KCP JoinConfiguration is not present, set machine JoinConfiguration to nil (nothing can trigger rollout here). + // NOTE: this is required because CABPK applies an empty joinConfiguration in case no one is provided. + if kcpConfig.JoinConfiguration == nil { + machineConfig.Spec.JoinConfiguration = nil + } + + // Cleanup JoinConfiguration.Discovery from kcpConfig and machineConfig, because those info are relevant only for + // the join process and not for comparing the configuration of the machine. + emptyDiscovery := kubeadmv1.Discovery{} + if kcpConfig.JoinConfiguration != nil { + kcpConfig.JoinConfiguration.Discovery = emptyDiscovery + } + if machineConfig.Spec.JoinConfiguration != nil { + machineConfig.Spec.JoinConfiguration.Discovery = emptyDiscovery + } + + // If KCP JoinConfiguration.ControlPlane is not present, set machine join configuration to nil (nothing can trigger rollout here). + // NOTE: this is required because CABPK applies an empty joinConfiguration.ControlPlane in case no one is provided. + if kcpConfig.JoinConfiguration != nil && kcpConfig.JoinConfiguration.ControlPlane == nil { + machineConfig.Spec.JoinConfiguration.ControlPlane = nil + } + + // If KCP's join NodeRegistration is empty, set machine's node registration to empty as no changes should trigger rollout. + emptyNodeRegistration := kubeadmv1.NodeRegistrationOptions{} + if kcpConfig.JoinConfiguration != nil && reflect.DeepEqual(kcpConfig.JoinConfiguration.NodeRegistration, emptyNodeRegistration) { + machineConfig.Spec.JoinConfiguration.NodeRegistration = emptyNodeRegistration + } + + // Clear up the TypeMeta information from the comparison. + // NOTE: KCP types don't carry this information. + if machineConfig.Spec.InitConfiguration != nil && kcpConfig.InitConfiguration != nil { + machineConfig.Spec.InitConfiguration.TypeMeta = kcpConfig.InitConfiguration.TypeMeta + } + if machineConfig.Spec.JoinConfiguration != nil && kcpConfig.JoinConfiguration != nil { + machineConfig.Spec.JoinConfiguration.TypeMeta = kcpConfig.JoinConfiguration.TypeMeta } } diff --git a/controlplane/kubeadm/internal/machinefilters/util_test.go b/controlplane/kubeadm/internal/machinefilters/util_test.go new file mode 100644 index 000000000000..21a5775a785f --- /dev/null +++ b/controlplane/kubeadm/internal/machinefilters/util_test.go @@ -0,0 +1,825 @@ +/* +Copyright 2020 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package machinefilters + +import ( + "context" + "testing" + + "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/runtime" + clusterv1 "sigs.k8s.io/cluster-api/api/v1alpha3" + bootstrapv1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1alpha3" + kubeadmv1beta1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/types/v1beta1" + controlplanev1 "sigs.k8s.io/cluster-api/controlplane/kubeadm/api/v1alpha3" + "sigs.k8s.io/controller-runtime/pkg/client/fake" +) + +func TestMatchClusterConfiguration(t *testing.T) { + t.Run("machine without the ClusterConfiguration annotation should match (not enough information to make a decision)", func(t *testing.T) { + g := gomega.NewWithT(t) + kcp := &controlplanev1.KubeadmControlPlane{} + m := &clusterv1.Machine{} + g.Expect(matchClusterConfiguration(kcp, m)).To(gomega.BeTrue()) + }) + t.Run("machine without an invalid ClusterConfiguration annotation should not match (only solution is to rollout)", func(t *testing.T) { + g := gomega.NewWithT(t) + kcp := &controlplanev1.KubeadmControlPlane{} + m := &clusterv1.Machine{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + controlplanev1.KubeadmClusterConfigurationAnnotation: "$|^^_", + }, + }, + } + g.Expect(matchClusterConfiguration(kcp, m)).To(gomega.BeFalse()) + }) + t.Run("Return true if cluster configuration matches", func(t *testing.T) { + g := gomega.NewWithT(t) + kcp := &controlplanev1.KubeadmControlPlane{ + Spec: controlplanev1.KubeadmControlPlaneSpec{ + KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ + ClusterConfiguration: &kubeadmv1beta1.ClusterConfiguration{ + ClusterName: "foo", + }, + }, + }, + } + m := &clusterv1.Machine{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + controlplanev1.KubeadmClusterConfigurationAnnotation: "{\n \"clusterName\": \"foo\"\n}", + }, + }, + } + g.Expect(matchClusterConfiguration(kcp, m)).To(gomega.BeTrue()) + }) + t.Run("Return false if cluster configuration does not match", func(t *testing.T) { + g := gomega.NewWithT(t) + kcp := &controlplanev1.KubeadmControlPlane{ + Spec: controlplanev1.KubeadmControlPlaneSpec{ + KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ + ClusterConfiguration: &kubeadmv1beta1.ClusterConfiguration{ + ClusterName: "foo", + }, + }, + }, + } + m := &clusterv1.Machine{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + controlplanev1.KubeadmClusterConfigurationAnnotation: "{\n \"clusterName\": \"bar\"\n}", + }, + }, + } + g.Expect(matchClusterConfiguration(kcp, m)).To(gomega.BeFalse()) + }) +} + +func TestGetAdjustedKcpConfig(t *testing.T) { + t.Run("if the machine is the first control plane, kcp config should get InitConfiguration", func(t *testing.T) { + g := gomega.NewWithT(t) + kcp := &controlplanev1.KubeadmControlPlane{ + Spec: controlplanev1.KubeadmControlPlaneSpec{ + KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ + InitConfiguration: &kubeadmv1beta1.InitConfiguration{}, + JoinConfiguration: &kubeadmv1beta1.JoinConfiguration{}, + }, + }, + } + machineConfig := &bootstrapv1.KubeadmConfig{ + Spec: bootstrapv1.KubeadmConfigSpec{ + InitConfiguration: &kubeadmv1beta1.InitConfiguration{}, // first control-plane + }, + } + kcpConfig := getAdjustedKcpConfig(kcp, machineConfig) + g.Expect(kcpConfig.InitConfiguration).ToNot(gomega.BeNil()) + g.Expect(kcpConfig.JoinConfiguration).To(gomega.BeNil()) + }) + t.Run("if the machine is a joining control plane, kcp config should get JoinConfiguration", func(t *testing.T) { + g := gomega.NewWithT(t) + kcp := &controlplanev1.KubeadmControlPlane{ + Spec: controlplanev1.KubeadmControlPlaneSpec{ + KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ + InitConfiguration: &kubeadmv1beta1.InitConfiguration{}, + JoinConfiguration: &kubeadmv1beta1.JoinConfiguration{}, + }, + }, + } + machineConfig := &bootstrapv1.KubeadmConfig{ + Spec: bootstrapv1.KubeadmConfigSpec{ + JoinConfiguration: &kubeadmv1beta1.JoinConfiguration{}, // joining control-plane + }, + } + kcpConfig := getAdjustedKcpConfig(kcp, machineConfig) + g.Expect(kcpConfig.InitConfiguration).To(gomega.BeNil()) + g.Expect(kcpConfig.JoinConfiguration).ToNot(gomega.BeNil()) + }) +} + +func TestCleanupConfigFields(t *testing.T) { + t.Run("ClusterConfiguration gets removed from KcpConfig and MachineConfig", func(t *testing.T) { + g := gomega.NewWithT(t) + kcpConfig := &bootstrapv1.KubeadmConfigSpec{ + ClusterConfiguration: &kubeadmv1beta1.ClusterConfiguration{}, + } + machineConfig := &bootstrapv1.KubeadmConfig{ + Spec: bootstrapv1.KubeadmConfigSpec{ + ClusterConfiguration: &kubeadmv1beta1.ClusterConfiguration{}, + }, + } + cleanupConfigFields(kcpConfig, machineConfig) + g.Expect(kcpConfig.ClusterConfiguration).To(gomega.BeNil()) + g.Expect(machineConfig.Spec.ClusterConfiguration).To(gomega.BeNil()) + }) + t.Run("JoinConfiguration gets removed from MachineConfig if it was not derived by KCPConfig", func(t *testing.T) { + g := gomega.NewWithT(t) + kcpConfig := &bootstrapv1.KubeadmConfigSpec{ + JoinConfiguration: nil, // KCP not providing a JoinConfiguration + } + machineConfig := &bootstrapv1.KubeadmConfig{ + Spec: bootstrapv1.KubeadmConfigSpec{ + JoinConfiguration: &kubeadmv1beta1.JoinConfiguration{}, // Machine gets a default JoinConfiguration from CABPK + }, + } + cleanupConfigFields(kcpConfig, machineConfig) + g.Expect(kcpConfig.JoinConfiguration).To(gomega.BeNil()) + g.Expect(machineConfig.Spec.JoinConfiguration).To(gomega.BeNil()) + }) + t.Run("JoinConfiguration.Discovery gets removed because it is not relevant for compare", func(t *testing.T) { + g := gomega.NewWithT(t) + kcpConfig := &bootstrapv1.KubeadmConfigSpec{ + JoinConfiguration: &kubeadmv1beta1.JoinConfiguration{ + Discovery: kubeadmv1beta1.Discovery{TLSBootstrapToken: "aaa"}, + }, + } + machineConfig := &bootstrapv1.KubeadmConfig{ + Spec: bootstrapv1.KubeadmConfigSpec{ + JoinConfiguration: &kubeadmv1beta1.JoinConfiguration{ + Discovery: kubeadmv1beta1.Discovery{TLSBootstrapToken: "aaa"}, + }, + }, + } + cleanupConfigFields(kcpConfig, machineConfig) + g.Expect(kcpConfig.JoinConfiguration.Discovery).To(gomega.Equal(kubeadmv1beta1.Discovery{})) + g.Expect(machineConfig.Spec.JoinConfiguration.Discovery).To(gomega.Equal(kubeadmv1beta1.Discovery{})) + }) + t.Run("JoinConfiguration.ControlPlane gets removed from MachineConfig if it was not derived by KCPConfig", func(t *testing.T) { + g := gomega.NewWithT(t) + kcpConfig := &bootstrapv1.KubeadmConfigSpec{ + JoinConfiguration: &kubeadmv1beta1.JoinConfiguration{ + ControlPlane: nil, // Control plane configuration missing in KCP + }, + } + machineConfig := &bootstrapv1.KubeadmConfig{ + Spec: bootstrapv1.KubeadmConfigSpec{ + JoinConfiguration: &kubeadmv1beta1.JoinConfiguration{ + ControlPlane: &kubeadmv1beta1.JoinControlPlane{}, // Machine gets a default JoinConfiguration.ControlPlane from CABPK + }, + }, + } + cleanupConfigFields(kcpConfig, machineConfig) + g.Expect(kcpConfig.JoinConfiguration).ToNot(gomega.BeNil()) + g.Expect(machineConfig.Spec.JoinConfiguration.ControlPlane).To(gomega.BeNil()) + }) + t.Run("JoinConfiguration.NodeRegistrationOptions gets removed from MachineConfig if it was not derived by KCPConfig", func(t *testing.T) { + g := gomega.NewWithT(t) + kcpConfig := &bootstrapv1.KubeadmConfigSpec{ + JoinConfiguration: &kubeadmv1beta1.JoinConfiguration{ + NodeRegistration: kubeadmv1beta1.NodeRegistrationOptions{}, // NodeRegistrationOptions configuration missing in KCP + }, + } + machineConfig := &bootstrapv1.KubeadmConfig{ + Spec: bootstrapv1.KubeadmConfigSpec{ + JoinConfiguration: &kubeadmv1beta1.JoinConfiguration{ + NodeRegistration: kubeadmv1beta1.NodeRegistrationOptions{Name: "test"}, // Machine gets a some JoinConfiguration.NodeRegistrationOptions + }, + }, + } + cleanupConfigFields(kcpConfig, machineConfig) + g.Expect(kcpConfig.JoinConfiguration).ToNot(gomega.BeNil()) + g.Expect(machineConfig.Spec.JoinConfiguration.NodeRegistration).To(gomega.Equal(kubeadmv1beta1.NodeRegistrationOptions{})) + }) + t.Run("InitConfiguration.TypeMeta gets removed from MachineConfig", func(t *testing.T) { + g := gomega.NewWithT(t) + kcpConfig := &bootstrapv1.KubeadmConfigSpec{ + InitConfiguration: &kubeadmv1beta1.InitConfiguration{}, + } + machineConfig := &bootstrapv1.KubeadmConfig{ + Spec: bootstrapv1.KubeadmConfigSpec{ + InitConfiguration: &kubeadmv1beta1.InitConfiguration{ + TypeMeta: metav1.TypeMeta{ + Kind: "JoinConfiguration", + APIVersion: kubeadmv1beta1.GroupVersion.String(), + }, + }, + }, + } + cleanupConfigFields(kcpConfig, machineConfig) + g.Expect(kcpConfig.InitConfiguration).ToNot(gomega.BeNil()) + g.Expect(machineConfig.Spec.InitConfiguration.TypeMeta).To(gomega.Equal(metav1.TypeMeta{})) + }) + t.Run("JoinConfiguration.TypeMeta gets removed from MachineConfig", func(t *testing.T) { + g := gomega.NewWithT(t) + kcpConfig := &bootstrapv1.KubeadmConfigSpec{ + JoinConfiguration: &kubeadmv1beta1.JoinConfiguration{}, + } + machineConfig := &bootstrapv1.KubeadmConfig{ + Spec: bootstrapv1.KubeadmConfigSpec{ + JoinConfiguration: &kubeadmv1beta1.JoinConfiguration{ + TypeMeta: metav1.TypeMeta{ + Kind: "JoinConfiguration", + APIVersion: kubeadmv1beta1.GroupVersion.String(), + }, + }, + }, + } + cleanupConfigFields(kcpConfig, machineConfig) + g.Expect(kcpConfig.JoinConfiguration).ToNot(gomega.BeNil()) + g.Expect(machineConfig.Spec.JoinConfiguration.TypeMeta).To(gomega.Equal(metav1.TypeMeta{})) + }) +} + +func TestMatchInitOrJoinConfiguration(t *testing.T) { + scheme := runtime.NewScheme() + _ = bootstrapv1.AddToScheme(scheme) + t.Run("returns true if the machine does not have bootstrap config", func(t *testing.T) { + g := gomega.NewWithT(t) + kcp := &controlplanev1.KubeadmControlPlane{} + m := &clusterv1.Machine{} + g.Expect(matchInitOrJoinConfiguration(context.TODO(), nil, kcp, m)).To(gomega.BeTrue()) + }) + t.Run("returns true if the there are problems reading the bootstrap config", func(t *testing.T) { + g := gomega.NewWithT(t) + kcp := &controlplanev1.KubeadmControlPlane{} + m := &clusterv1.Machine{ + Spec: clusterv1.MachineSpec{ + Bootstrap: clusterv1.Bootstrap{ + ConfigRef: &corev1.ObjectReference{}, + }, + }, + } + client := fake.NewFakeClientWithScheme(scheme) + g.Expect(matchInitOrJoinConfiguration(context.TODO(), client, kcp, m)).To(gomega.BeTrue()) + }) + t.Run("returns true if InitConfiguration is equal", func(t *testing.T) { + g := gomega.NewWithT(t) + kcp := &controlplanev1.KubeadmControlPlane{ + Spec: controlplanev1.KubeadmControlPlaneSpec{ + KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ + ClusterConfiguration: &kubeadmv1beta1.ClusterConfiguration{}, + InitConfiguration: &kubeadmv1beta1.InitConfiguration{}, + JoinConfiguration: &kubeadmv1beta1.JoinConfiguration{}, + }, + }, + } + m := &clusterv1.Machine{ + TypeMeta: metav1.TypeMeta{ + Kind: "KubeadmConfig", + APIVersion: clusterv1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "test", + }, + Spec: clusterv1.MachineSpec{ + Bootstrap: clusterv1.Bootstrap{ + ConfigRef: &corev1.ObjectReference{ + Kind: "KubeadmConfig", + Namespace: "default", + Name: "test", + APIVersion: bootstrapv1.GroupVersion.String(), + }, + }, + }, + } + machineConfig := &bootstrapv1.KubeadmConfig{ + TypeMeta: metav1.TypeMeta{ + Kind: "KubeadmConfig", + APIVersion: bootstrapv1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "test", + }, + Spec: bootstrapv1.KubeadmConfigSpec{ + InitConfiguration: &kubeadmv1beta1.InitConfiguration{}, + }, + } + client := fake.NewFakeClientWithScheme(scheme, machineConfig) + g.Expect(matchInitOrJoinConfiguration(context.TODO(), client, kcp, m)).To(gomega.BeTrue()) + }) + t.Run("returns false if InitConfiguration is NOT equal", func(t *testing.T) { + g := gomega.NewWithT(t) + kcp := &controlplanev1.KubeadmControlPlane{ + Spec: controlplanev1.KubeadmControlPlaneSpec{ + KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ + ClusterConfiguration: &kubeadmv1beta1.ClusterConfiguration{}, + InitConfiguration: &kubeadmv1beta1.InitConfiguration{ + NodeRegistration: kubeadmv1beta1.NodeRegistrationOptions{ + Name: "A new name", // This is a change + }, + }, + JoinConfiguration: &kubeadmv1beta1.JoinConfiguration{}, + }, + }, + } + m := &clusterv1.Machine{ + TypeMeta: metav1.TypeMeta{ + Kind: "KubeadmConfig", + APIVersion: clusterv1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "test", + }, + Spec: clusterv1.MachineSpec{ + Bootstrap: clusterv1.Bootstrap{ + ConfigRef: &corev1.ObjectReference{ + Kind: "KubeadmConfig", + Namespace: "default", + Name: "test", + APIVersion: bootstrapv1.GroupVersion.String(), + }, + }, + }, + } + machineConfig := &bootstrapv1.KubeadmConfig{ + TypeMeta: metav1.TypeMeta{ + Kind: "KubeadmConfig", + APIVersion: bootstrapv1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "test", + }, + Spec: bootstrapv1.KubeadmConfigSpec{ + InitConfiguration: &kubeadmv1beta1.InitConfiguration{}, + }, + } + client := fake.NewFakeClientWithScheme(scheme, machineConfig) + g.Expect(matchInitOrJoinConfiguration(context.TODO(), client, kcp, m)).To(gomega.BeFalse()) + }) + t.Run("returns true if JoinConfiguration is equal", func(t *testing.T) { + g := gomega.NewWithT(t) + kcp := &controlplanev1.KubeadmControlPlane{ + Spec: controlplanev1.KubeadmControlPlaneSpec{ + KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ + ClusterConfiguration: &kubeadmv1beta1.ClusterConfiguration{}, + InitConfiguration: &kubeadmv1beta1.InitConfiguration{}, + JoinConfiguration: &kubeadmv1beta1.JoinConfiguration{}, + }, + }, + } + m := &clusterv1.Machine{ + TypeMeta: metav1.TypeMeta{ + Kind: "KubeadmConfig", + APIVersion: clusterv1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "test", + }, + Spec: clusterv1.MachineSpec{ + Bootstrap: clusterv1.Bootstrap{ + ConfigRef: &corev1.ObjectReference{ + Kind: "KubeadmConfig", + Namespace: "default", + Name: "test", + APIVersion: bootstrapv1.GroupVersion.String(), + }, + }, + }, + } + machineConfig := &bootstrapv1.KubeadmConfig{ + TypeMeta: metav1.TypeMeta{ + Kind: "KubeadmConfig", + APIVersion: bootstrapv1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "test", + }, + Spec: bootstrapv1.KubeadmConfigSpec{ + JoinConfiguration: &kubeadmv1beta1.JoinConfiguration{}, + }, + } + client := fake.NewFakeClientWithScheme(scheme, machineConfig) + g.Expect(matchInitOrJoinConfiguration(context.TODO(), client, kcp, m)).To(gomega.BeTrue()) + }) + t.Run("returns false if JoinConfiguration is NOT equal", func(t *testing.T) { + g := gomega.NewWithT(t) + kcp := &controlplanev1.KubeadmControlPlane{ + Spec: controlplanev1.KubeadmControlPlaneSpec{ + KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ + ClusterConfiguration: &kubeadmv1beta1.ClusterConfiguration{}, + InitConfiguration: &kubeadmv1beta1.InitConfiguration{}, + JoinConfiguration: &kubeadmv1beta1.JoinConfiguration{ + NodeRegistration: kubeadmv1beta1.NodeRegistrationOptions{ + Name: "A new name", // This is a change + }, + }, + }, + }, + } + m := &clusterv1.Machine{ + TypeMeta: metav1.TypeMeta{ + Kind: "KubeadmConfig", + APIVersion: clusterv1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "test", + }, + Spec: clusterv1.MachineSpec{ + Bootstrap: clusterv1.Bootstrap{ + ConfigRef: &corev1.ObjectReference{ + Kind: "KubeadmConfig", + Namespace: "default", + Name: "test", + APIVersion: bootstrapv1.GroupVersion.String(), + }, + }, + }, + } + machineConfig := &bootstrapv1.KubeadmConfig{ + TypeMeta: metav1.TypeMeta{ + Kind: "KubeadmConfig", + APIVersion: bootstrapv1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "test", + }, + Spec: bootstrapv1.KubeadmConfigSpec{ + JoinConfiguration: &kubeadmv1beta1.JoinConfiguration{}, + }, + } + client := fake.NewFakeClientWithScheme(scheme, machineConfig) + g.Expect(matchInitOrJoinConfiguration(context.TODO(), client, kcp, m)).To(gomega.BeFalse()) + }) + t.Run("returns false if some other configurations are not equal", func(t *testing.T) { + g := gomega.NewWithT(t) + kcp := &controlplanev1.KubeadmControlPlane{ + Spec: controlplanev1.KubeadmControlPlaneSpec{ + KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ + ClusterConfiguration: &kubeadmv1beta1.ClusterConfiguration{}, + InitConfiguration: &kubeadmv1beta1.InitConfiguration{}, + JoinConfiguration: &kubeadmv1beta1.JoinConfiguration{}, + Files: []bootstrapv1.File{}, // This is a change + }, + }, + } + m := &clusterv1.Machine{ + TypeMeta: metav1.TypeMeta{ + Kind: "KubeadmConfig", + APIVersion: clusterv1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "test", + }, + Spec: clusterv1.MachineSpec{ + Bootstrap: clusterv1.Bootstrap{ + ConfigRef: &corev1.ObjectReference{ + Kind: "KubeadmConfig", + Namespace: "default", + Name: "test", + APIVersion: bootstrapv1.GroupVersion.String(), + }, + }, + }, + } + machineConfig := &bootstrapv1.KubeadmConfig{ + TypeMeta: metav1.TypeMeta{ + Kind: "KubeadmConfig", + APIVersion: bootstrapv1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "test", + }, + Spec: bootstrapv1.KubeadmConfigSpec{ + InitConfiguration: &kubeadmv1beta1.InitConfiguration{}, + }, + } + client := fake.NewFakeClientWithScheme(scheme, machineConfig) + g.Expect(matchInitOrJoinConfiguration(context.TODO(), client, kcp, m)).To(gomega.BeFalse()) + }) +} + +func TestMatchesKubeadmBootstrapConfig(t *testing.T) { + scheme := runtime.NewScheme() + _ = bootstrapv1.AddToScheme(scheme) + t.Run("returns true if ClusterConfiguration is equal", func(t *testing.T) { + g := gomega.NewWithT(t) + kcp := &controlplanev1.KubeadmControlPlane{ + Spec: controlplanev1.KubeadmControlPlaneSpec{ + KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ + ClusterConfiguration: &kubeadmv1beta1.ClusterConfiguration{ + ClusterName: "foo", + }, + }, + }, + } + m := &clusterv1.Machine{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + controlplanev1.KubeadmClusterConfigurationAnnotation: "{\n \"clusterName\": \"foo\"\n}", + }, + }, + } + machineConfig := &bootstrapv1.KubeadmConfig{} + client := fake.NewFakeClientWithScheme(scheme, machineConfig) + f := MatchesKubeadmBootstrapConfig(context.TODO(), client, kcp) + g.Expect(f(m)).To(gomega.BeTrue()) + }) + t.Run("returns false if ClusterConfiguration is NOT equal", func(t *testing.T) { + g := gomega.NewWithT(t) + kcp := &controlplanev1.KubeadmControlPlane{ + Spec: controlplanev1.KubeadmControlPlaneSpec{ + KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ + ClusterConfiguration: &kubeadmv1beta1.ClusterConfiguration{ + ClusterName: "foo", + }, + }, + }, + } + m := &clusterv1.Machine{ + ObjectMeta: metav1.ObjectMeta{ + Annotations: map[string]string{ + controlplanev1.KubeadmClusterConfigurationAnnotation: "{\n \"clusterName\": \"bar\"\n}", + }, + }, + } + machineConfig := &bootstrapv1.KubeadmConfig{} + client := fake.NewFakeClientWithScheme(scheme, machineConfig) + f := MatchesKubeadmBootstrapConfig(context.TODO(), client, kcp) + g.Expect(f(m)).To(gomega.BeFalse()) + }) + t.Run("returns true if InitConfiguration is equal", func(t *testing.T) { + g := gomega.NewWithT(t) + kcp := &controlplanev1.KubeadmControlPlane{ + Spec: controlplanev1.KubeadmControlPlaneSpec{ + KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ + ClusterConfiguration: &kubeadmv1beta1.ClusterConfiguration{}, + InitConfiguration: &kubeadmv1beta1.InitConfiguration{}, + JoinConfiguration: &kubeadmv1beta1.JoinConfiguration{}, + }, + }, + } + m := &clusterv1.Machine{ + TypeMeta: metav1.TypeMeta{ + Kind: "KubeadmConfig", + APIVersion: clusterv1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "test", + }, + Spec: clusterv1.MachineSpec{ + Bootstrap: clusterv1.Bootstrap{ + ConfigRef: &corev1.ObjectReference{ + Kind: "KubeadmConfig", + Namespace: "default", + Name: "test", + APIVersion: bootstrapv1.GroupVersion.String(), + }, + }, + }, + } + machineConfig := &bootstrapv1.KubeadmConfig{ + TypeMeta: metav1.TypeMeta{ + Kind: "KubeadmConfig", + APIVersion: bootstrapv1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "test", + }, + Spec: bootstrapv1.KubeadmConfigSpec{ + InitConfiguration: &kubeadmv1beta1.InitConfiguration{}, + }, + } + client := fake.NewFakeClientWithScheme(scheme, machineConfig) + f := MatchesKubeadmBootstrapConfig(context.TODO(), client, kcp) + g.Expect(f(m)).To(gomega.BeTrue()) + }) + t.Run("returns false if InitConfiguration is NOT equal", func(t *testing.T) { + g := gomega.NewWithT(t) + kcp := &controlplanev1.KubeadmControlPlane{ + Spec: controlplanev1.KubeadmControlPlaneSpec{ + KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ + ClusterConfiguration: &kubeadmv1beta1.ClusterConfiguration{}, + InitConfiguration: &kubeadmv1beta1.InitConfiguration{ + NodeRegistration: kubeadmv1beta1.NodeRegistrationOptions{ + Name: "foo", // This is a change + }, + }, + JoinConfiguration: &kubeadmv1beta1.JoinConfiguration{}, + }, + }, + } + m := &clusterv1.Machine{ + TypeMeta: metav1.TypeMeta{ + Kind: "KubeadmConfig", + APIVersion: clusterv1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "test", + }, + Spec: clusterv1.MachineSpec{ + Bootstrap: clusterv1.Bootstrap{ + ConfigRef: &corev1.ObjectReference{ + Kind: "KubeadmConfig", + Namespace: "default", + Name: "test", + APIVersion: bootstrapv1.GroupVersion.String(), + }, + }, + }, + } + machineConfig := &bootstrapv1.KubeadmConfig{ + TypeMeta: metav1.TypeMeta{ + Kind: "KubeadmConfig", + APIVersion: bootstrapv1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "test", + }, + Spec: bootstrapv1.KubeadmConfigSpec{ + InitConfiguration: &kubeadmv1beta1.InitConfiguration{}, + }, + } + client := fake.NewFakeClientWithScheme(scheme, machineConfig) + f := MatchesKubeadmBootstrapConfig(context.TODO(), client, kcp) + g.Expect(f(m)).To(gomega.BeFalse()) + }) + t.Run("returns true if JoinConfiguration is equal", func(t *testing.T) { + g := gomega.NewWithT(t) + kcp := &controlplanev1.KubeadmControlPlane{ + Spec: controlplanev1.KubeadmControlPlaneSpec{ + KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ + ClusterConfiguration: &kubeadmv1beta1.ClusterConfiguration{}, + InitConfiguration: &kubeadmv1beta1.InitConfiguration{}, + JoinConfiguration: &kubeadmv1beta1.JoinConfiguration{}, + }, + }, + } + m := &clusterv1.Machine{ + TypeMeta: metav1.TypeMeta{ + Kind: "KubeadmConfig", + APIVersion: clusterv1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "test", + }, + Spec: clusterv1.MachineSpec{ + Bootstrap: clusterv1.Bootstrap{ + ConfigRef: &corev1.ObjectReference{ + Kind: "KubeadmConfig", + Namespace: "default", + Name: "test", + APIVersion: bootstrapv1.GroupVersion.String(), + }, + }, + }, + } + machineConfig := &bootstrapv1.KubeadmConfig{ + TypeMeta: metav1.TypeMeta{ + Kind: "KubeadmConfig", + APIVersion: bootstrapv1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "test", + }, + Spec: bootstrapv1.KubeadmConfigSpec{ + JoinConfiguration: &kubeadmv1beta1.JoinConfiguration{}, + }, + } + client := fake.NewFakeClientWithScheme(scheme, machineConfig) + f := MatchesKubeadmBootstrapConfig(context.TODO(), client, kcp) + g.Expect(f(m)).To(gomega.BeTrue()) + }) + t.Run("returns false if JoinConfiguration is NOT equal", func(t *testing.T) { + g := gomega.NewWithT(t) + kcp := &controlplanev1.KubeadmControlPlane{ + Spec: controlplanev1.KubeadmControlPlaneSpec{ + KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ + ClusterConfiguration: &kubeadmv1beta1.ClusterConfiguration{}, + InitConfiguration: &kubeadmv1beta1.InitConfiguration{}, + JoinConfiguration: &kubeadmv1beta1.JoinConfiguration{ + NodeRegistration: kubeadmv1beta1.NodeRegistrationOptions{ + Name: "foo", // This is a change + }, + }, + }, + }, + } + m := &clusterv1.Machine{ + TypeMeta: metav1.TypeMeta{ + Kind: "KubeadmConfig", + APIVersion: clusterv1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "test", + }, + Spec: clusterv1.MachineSpec{ + Bootstrap: clusterv1.Bootstrap{ + ConfigRef: &corev1.ObjectReference{ + Kind: "KubeadmConfig", + Namespace: "default", + Name: "test", + APIVersion: bootstrapv1.GroupVersion.String(), + }, + }, + }, + } + machineConfig := &bootstrapv1.KubeadmConfig{ + TypeMeta: metav1.TypeMeta{ + Kind: "KubeadmConfig", + APIVersion: bootstrapv1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "test", + }, + Spec: bootstrapv1.KubeadmConfigSpec{ + JoinConfiguration: &kubeadmv1beta1.JoinConfiguration{}, + }, + } + client := fake.NewFakeClientWithScheme(scheme, machineConfig) + f := MatchesKubeadmBootstrapConfig(context.TODO(), client, kcp) + g.Expect(f(m)).To(gomega.BeFalse()) + }) + t.Run("returns false if some other configurations are not equal", func(t *testing.T) { + g := gomega.NewWithT(t) + kcp := &controlplanev1.KubeadmControlPlane{ + Spec: controlplanev1.KubeadmControlPlaneSpec{ + KubeadmConfigSpec: bootstrapv1.KubeadmConfigSpec{ + ClusterConfiguration: &kubeadmv1beta1.ClusterConfiguration{}, + InitConfiguration: &kubeadmv1beta1.InitConfiguration{}, + JoinConfiguration: &kubeadmv1beta1.JoinConfiguration{}, + Files: []bootstrapv1.File{}, // This is a change + }, + }, + } + m := &clusterv1.Machine{ + TypeMeta: metav1.TypeMeta{ + Kind: "KubeadmConfig", + APIVersion: clusterv1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "test", + }, + Spec: clusterv1.MachineSpec{ + Bootstrap: clusterv1.Bootstrap{ + ConfigRef: &corev1.ObjectReference{ + Kind: "KubeadmConfig", + Namespace: "default", + Name: "test", + APIVersion: bootstrapv1.GroupVersion.String(), + }, + }, + }, + } + machineConfig := &bootstrapv1.KubeadmConfig{ + TypeMeta: metav1.TypeMeta{ + Kind: "KubeadmConfig", + APIVersion: bootstrapv1.GroupVersion.String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Namespace: "default", + Name: "test", + }, + Spec: bootstrapv1.KubeadmConfigSpec{ + InitConfiguration: &kubeadmv1beta1.InitConfiguration{}, + }, + } + client := fake.NewFakeClientWithScheme(scheme, machineConfig) + f := MatchesKubeadmBootstrapConfig(context.TODO(), client, kcp) + g.Expect(f(m)).To(gomega.BeFalse()) + }) +}