From b63a4ab1208dfe3a500dede009337fb9c9da6050 Mon Sep 17 00:00:00 2001 From: Stefan Bueringer Date: Fri, 6 Sep 2024 16:39:33 +0200 Subject: [PATCH] KCP: remove code handling Kubernetes <= v1.21 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Stefan Büringer buringerst@vmware.com --- .../internal/controllers/controller.go | 7 +- .../internal/controllers/fakes_test.go | 6 +- .../internal/controllers/remediation.go | 11 -- .../kubeadm/internal/controllers/scale.go | 11 -- .../kubeadm/internal/workload_cluster.go | 84 +++-------- .../kubeadm/internal/workload_cluster_etcd.go | 11 +- .../internal/workload_cluster_etcd_test.go | 128 +---------------- .../kubeadm/internal/workload_cluster_test.go | 131 ------------------ 8 files changed, 33 insertions(+), 356 deletions(-) diff --git a/controlplane/kubeadm/internal/controllers/controller.go b/controlplane/kubeadm/internal/controllers/controller.go index bdcc4e3e36af..1a643cf55dd8 100644 --- a/controlplane/kubeadm/internal/controllers/controller.go +++ b/controlplane/kubeadm/internal/controllers/controller.go @@ -802,12 +802,7 @@ func (r *KubeadmControlPlaneReconciler) reconcileEtcdMembers(ctx context.Context return errors.Wrap(err, "cannot get remote client to workload cluster") } - parsedVersion, err := semver.ParseTolerant(controlPlane.KCP.Spec.Version) - if err != nil { - return errors.Wrapf(err, "failed to parse kubernetes version %q", controlPlane.KCP.Spec.Version) - } - - removedMembers, err := workloadCluster.ReconcileEtcdMembers(ctx, nodeNames, parsedVersion) + removedMembers, err := workloadCluster.ReconcileEtcdMembers(ctx, nodeNames) if err != nil { return errors.Wrap(err, "failed attempt to reconcile etcd members") } diff --git a/controlplane/kubeadm/internal/controllers/fakes_test.go b/controlplane/kubeadm/internal/controllers/fakes_test.go index 6bf8ff1cb826..ee27e7d688de 100644 --- a/controlplane/kubeadm/internal/controllers/fakes_test.go +++ b/controlplane/kubeadm/internal/controllers/fakes_test.go @@ -84,7 +84,7 @@ func (f *fakeWorkloadCluster) ForwardEtcdLeadership(_ context.Context, _ *cluste return nil } -func (f *fakeWorkloadCluster) ReconcileEtcdMembers(_ context.Context, _ []string, _ semver.Version) ([]string, error) { +func (f *fakeWorkloadCluster) ReconcileEtcdMembers(_ context.Context, _ []string) ([]string, error) { return nil, nil } @@ -129,10 +129,6 @@ func (f *fakeWorkloadCluster) RemoveEtcdMemberForMachine(_ context.Context, _ *c return nil } -func (f *fakeWorkloadCluster) RemoveMachineFromKubeadmConfigMap(_ context.Context, _ *clusterv1.Machine, _ semver.Version) error { - return nil -} - func (f *fakeWorkloadCluster) EtcdMembers(_ context.Context) ([]string, error) { return f.EtcdMembersResult, nil } diff --git a/controlplane/kubeadm/internal/controllers/remediation.go b/controlplane/kubeadm/internal/controllers/remediation.go index 7b648441803b..e3a15668c593 100644 --- a/controlplane/kubeadm/internal/controllers/remediation.go +++ b/controlplane/kubeadm/internal/controllers/remediation.go @@ -22,7 +22,6 @@ import ( "fmt" "time" - "github.com/blang/semver/v4" "github.com/go-logr/logr" "github.com/pkg/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -227,16 +226,6 @@ func (r *KubeadmControlPlaneReconciler) reconcileUnhealthyMachines(ctx context.C // NOTE: etcd member removal will be performed by the kcp-cleanup hook after machine completes drain & all volumes are detached. } - - parsedVersion, err := semver.ParseTolerant(controlPlane.KCP.Spec.Version) - if err != nil { - return ctrl.Result{}, errors.Wrapf(err, "failed to parse kubernetes version %q", controlPlane.KCP.Spec.Version) - } - - if err := workloadCluster.RemoveMachineFromKubeadmConfigMap(ctx, machineToBeRemediated, parsedVersion); err != nil { - log.Error(err, "Failed to remove machine from kubeadm ConfigMap") - return ctrl.Result{}, err - } } // Delete the machine diff --git a/controlplane/kubeadm/internal/controllers/scale.go b/controlplane/kubeadm/internal/controllers/scale.go index 304ba9855f87..e70a4124f3cf 100644 --- a/controlplane/kubeadm/internal/controllers/scale.go +++ b/controlplane/kubeadm/internal/controllers/scale.go @@ -20,7 +20,6 @@ import ( "context" "strings" - "github.com/blang/semver/v4" "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" @@ -139,16 +138,6 @@ func (r *KubeadmControlPlaneReconciler) scaleDownControlPlane( // NOTE: etcd member removal will be performed by the kcp-cleanup hook after machine completes drain & all volumes are detached. } - parsedVersion, err := semver.ParseTolerant(controlPlane.KCP.Spec.Version) - if err != nil { - return ctrl.Result{}, errors.Wrapf(err, "failed to parse kubernetes version %q", controlPlane.KCP.Spec.Version) - } - - if err := workloadCluster.RemoveMachineFromKubeadmConfigMap(ctx, machineToDelete, parsedVersion); err != nil { - logger.Error(err, "Failed to remove machine from kubeadm ConfigMap") - return ctrl.Result{}, err - } - logger = logger.WithValues("Machine", klog.KObj(machineToDelete)) if err := r.Client.Delete(ctx, machineToDelete); err != nil && !apierrors.IsNotFound(err) { logger.Error(err, "Failed to delete control plane machine") diff --git a/controlplane/kubeadm/internal/workload_cluster.go b/controlplane/kubeadm/internal/workload_cluster.go index 0d35ae2d5306..9bb758743a5b 100644 --- a/controlplane/kubeadm/internal/workload_cluster.go +++ b/controlplane/kubeadm/internal/workload_cluster.go @@ -52,7 +52,6 @@ import ( "sigs.k8s.io/cluster-api/util/certs" containerutil "sigs.k8s.io/cluster-api/util/container" "sigs.k8s.io/cluster-api/util/patch" - "sigs.k8s.io/cluster-api/util/version" ) const ( @@ -68,18 +67,6 @@ const ( ) var ( - // Starting from v1.22.0 kubeadm dropped the usage of the ClusterStatus entry from the kubeadm-config ConfigMap - // so we're not anymore required to remove API endpoints for control plane nodes after deletion. - // - // NOTE: The following assumes that kubeadm version equals to Kubernetes version. - minKubernetesVersionWithoutClusterStatus = semver.MustParse("1.22.0") - - // Starting from v1.21.0 kubeadm defaults to systemdCGroup driver, as well as images built with ImageBuilder, - // so it is necessary to mutate the kubelet-config-xx ConfigMap. - // - // NOTE: The following assumes that kubeadm version equals to Kubernetes version. - minVerKubeletSystemdDriver = semver.MustParse("1.21.0") - // Starting from v1.24.0 kubeadm uses "kubelet-config" a ConfigMap name for KubeletConfiguration, // Dropping the X-Y suffix. // @@ -124,15 +111,13 @@ type WorkloadCluster interface { UpdateKubeProxyImageInfo(ctx context.Context, kcp *controlplanev1.KubeadmControlPlane, version semver.Version) error UpdateCoreDNS(ctx context.Context, kcp *controlplanev1.KubeadmControlPlane, version semver.Version) error RemoveEtcdMemberForMachine(ctx context.Context, machine *clusterv1.Machine) error - RemoveMachineFromKubeadmConfigMap(ctx context.Context, machine *clusterv1.Machine, version semver.Version) error - RemoveNodeFromKubeadmConfigMap(ctx context.Context, nodeName string, version semver.Version) error ForwardEtcdLeadership(ctx context.Context, machine *clusterv1.Machine, leaderCandidate *clusterv1.Machine) error AllowBootstrapTokensToGetNodes(ctx context.Context) error AllowClusterAdminPermissions(ctx context.Context, version semver.Version) error UpdateClusterConfiguration(ctx context.Context, version semver.Version, mutators ...func(*bootstrapv1.ClusterConfiguration)) error // State recovery tasks. - ReconcileEtcdMembers(ctx context.Context, nodeNames []string, version semver.Version) ([]string, error) + ReconcileEtcdMembers(ctx context.Context, nodeNames []string) ([]string, error) } // Workload defines operations on workload clusters. @@ -277,33 +262,31 @@ func (w *Workload) UpdateKubeletConfigMap(ctx context.Context, version semver.Ve // NOTE: It is considered safe to update the kubelet-config-1.21 ConfigMap // because only new nodes using v1.21 images will pick up the change during // kubeadm join. - if version.GE(minVerKubeletSystemdDriver) { - data, ok := cm.Data[kubeletConfigKey] - if !ok { - return errors.Errorf("unable to find %q key in %s", kubeletConfigKey, cm.Name) - } - kubeletConfig, err := yamlToUnstructured([]byte(data)) - if err != nil { - return errors.Wrapf(err, "unable to decode kubelet ConfigMap's %q content to Unstructured object", kubeletConfigKey) - } - cgroupDriver, _, err := unstructured.NestedString(kubeletConfig.UnstructuredContent(), cgroupDriverKey) - if err != nil { - return errors.Wrapf(err, "unable to extract %q from Kubelet ConfigMap's %q", cgroupDriverKey, cm.Name) - } + data, ok := cm.Data[kubeletConfigKey] + if !ok { + return errors.Errorf("unable to find %q key in %s", kubeletConfigKey, cm.Name) + } + kubeletConfig, err := yamlToUnstructured([]byte(data)) + if err != nil { + return errors.Wrapf(err, "unable to decode kubelet ConfigMap's %q content to Unstructured object", kubeletConfigKey) + } + cgroupDriver, _, err := unstructured.NestedString(kubeletConfig.UnstructuredContent(), cgroupDriverKey) + if err != nil { + return errors.Wrapf(err, "unable to extract %q from Kubelet ConfigMap's %q", cgroupDriverKey, cm.Name) + } - // If the value is not already explicitly set by the user, change according to kubeadm/image builder new requirements. - if cgroupDriver == "" { - cgroupDriver = "systemd" + // If the value is not already explicitly set by the user, change according to kubeadm/image builder new requirements. + if cgroupDriver == "" { + cgroupDriver = "systemd" - if err := unstructured.SetNestedField(kubeletConfig.UnstructuredContent(), cgroupDriver, cgroupDriverKey); err != nil { - return errors.Wrapf(err, "unable to update %q on Kubelet ConfigMap's %q", cgroupDriverKey, cm.Name) - } - updated, err := yaml.Marshal(kubeletConfig) - if err != nil { - return errors.Wrapf(err, "unable to encode Kubelet ConfigMap's %q to YAML", cm.Name) - } - cm.Data[kubeletConfigKey] = string(updated) + if err := unstructured.SetNestedField(kubeletConfig.UnstructuredContent(), cgroupDriver, cgroupDriverKey); err != nil { + return errors.Wrapf(err, "unable to update %q on Kubelet ConfigMap's %q", cgroupDriverKey, cm.Name) } + updated, err := yaml.Marshal(kubeletConfig) + if err != nil { + return errors.Wrapf(err, "unable to encode Kubelet ConfigMap's %q to YAML", cm.Name) + } + cm.Data[kubeletConfigKey] = string(updated) } // Update the name to the new name @@ -338,27 +321,6 @@ func (w *Workload) UpdateSchedulerInKubeadmConfigMap(scheduler bootstrapv1.Contr } } -// RemoveMachineFromKubeadmConfigMap removes the entry for the machine from the kubeadm configmap. -func (w *Workload) RemoveMachineFromKubeadmConfigMap(ctx context.Context, machine *clusterv1.Machine, version semver.Version) error { - if machine == nil || machine.Status.NodeRef == nil { - // Nothing to do, no node for Machine - return nil - } - - return w.RemoveNodeFromKubeadmConfigMap(ctx, machine.Status.NodeRef.Name, version) -} - -// RemoveNodeFromKubeadmConfigMap removes the entry for the node from the kubeadm configmap. -func (w *Workload) RemoveNodeFromKubeadmConfigMap(ctx context.Context, name string, v semver.Version) error { - if version.Compare(v, minKubernetesVersionWithoutClusterStatus, version.WithoutPreReleases()) >= 0 { - return nil - } - - return w.updateClusterStatus(ctx, func(s *bootstrapv1.ClusterStatus) { - delete(s.APIEndpoints, name) - }, v) -} - // updateClusterStatus gets the ClusterStatus kubeadm-config ConfigMap, converts it to the // Cluster API representation, and then applies a mutation func; if changes are detected, the // data are converted back into the Kubeadm API version in use for the target Kubernetes version and the diff --git a/controlplane/kubeadm/internal/workload_cluster_etcd.go b/controlplane/kubeadm/internal/workload_cluster_etcd.go index 48c06bc3f567..38a41635b46f 100644 --- a/controlplane/kubeadm/internal/workload_cluster_etcd.go +++ b/controlplane/kubeadm/internal/workload_cluster_etcd.go @@ -19,7 +19,6 @@ package internal import ( "context" - "github.com/blang/semver/v4" "github.com/pkg/errors" kerrors "k8s.io/apimachinery/pkg/util/errors" @@ -36,11 +35,11 @@ type etcdClientFor interface { // ReconcileEtcdMembers iterates over all etcd members and finds members that do not have corresponding nodes. // If there are any such members, it deletes them from etcd and removes their nodes from the kubeadm configmap so that kubeadm does not run etcd health checks on them. -func (w *Workload) ReconcileEtcdMembers(ctx context.Context, nodeNames []string, version semver.Version) ([]string, error) { +func (w *Workload) ReconcileEtcdMembers(ctx context.Context, nodeNames []string) ([]string, error) { allRemovedMembers := []string{} allErrs := []error{} for _, nodeName := range nodeNames { - removedMembers, errs := w.reconcileEtcdMember(ctx, nodeNames, nodeName, version) + removedMembers, errs := w.reconcileEtcdMember(ctx, nodeNames, nodeName) allRemovedMembers = append(allRemovedMembers, removedMembers...) allErrs = append(allErrs, errs...) } @@ -48,7 +47,7 @@ func (w *Workload) ReconcileEtcdMembers(ctx context.Context, nodeNames []string, return allRemovedMembers, kerrors.NewAggregate(allErrs) } -func (w *Workload) reconcileEtcdMember(ctx context.Context, nodeNames []string, nodeName string, version semver.Version) ([]string, []error) { +func (w *Workload) reconcileEtcdMember(ctx context.Context, nodeNames []string, nodeName string) ([]string, []error) { // Create the etcd Client for the etcd Pod scheduled on the Node etcdClient, err := w.etcdClientGenerator.forFirstAvailableNode(ctx, []string{nodeName}) if err != nil { @@ -84,10 +83,6 @@ loopmembers: if err := w.removeMemberForNode(ctx, member.Name); err != nil { errs = append(errs, err) } - - if err := w.RemoveNodeFromKubeadmConfigMap(ctx, member.Name, version); err != nil { - errs = append(errs, err) - } } return removedMembers, errs } diff --git a/controlplane/kubeadm/internal/workload_cluster_etcd_test.go b/controlplane/kubeadm/internal/workload_cluster_etcd_test.go index 3c8f8736ae0d..df9ccf9d252b 100644 --- a/controlplane/kubeadm/internal/workload_cluster_etcd_test.go +++ b/controlplane/kubeadm/internal/workload_cluster_etcd_test.go @@ -606,7 +606,6 @@ func TestReconcileEtcdMembers(t *testing.T) { tests := []struct { name string - kubernetesVersion semver.Version objs []client.Object nodes []string etcdClientGenerator etcdClientFor @@ -616,46 +615,9 @@ func TestReconcileEtcdMembers(t *testing.T) { { // the node to be removed is ip-10-0-0-3.ec2.internal since the // other two have nodes - name: "successfully removes the etcd member without a node and removes the node from kubeadm config for Kubernetes version < 1.22.0", - kubernetesVersion: semver.MustParse("1.19.1"), // Kubernetes version < 1.22.0 has ClusterStatus - objs: []client.Object{node1.DeepCopy(), node2.DeepCopy(), kubeadmConfig.DeepCopy()}, - nodes: []string{node1.Name, node2.Name}, - etcdClientGenerator: &fakeEtcdClientGenerator{ - forNodesClient: &etcd.Client{ - EtcdClient: fakeEtcdClient, - }, - }, - expectErr: false, - assert: func(g *WithT, c client.Client) { - g.Expect(fakeEtcdClient.RemovedMember).To(Equal(uint64(3))) - - var actualConfig corev1.ConfigMap - g.Expect(c.Get( - ctx, - client.ObjectKey{Name: kubeadmConfigKey, Namespace: metav1.NamespaceSystem}, - &actualConfig, - )).To(Succeed()) - expectedOutput := utilyaml.Raw(` - apiEndpoints: - ip-10-0-0-1.ec2.internal: - advertiseAddress: 10.0.0.1 - bindPort: 6443 - ip-10-0-0-2.ec2.internal: - advertiseAddress: 10.0.0.2 - bindPort: 6443 - apiVersion: kubeadm.k8s.io/v1beta2 - kind: ClusterStatus - `) - g.Expect(actualConfig.Data[clusterStatusKey]).To(Equal(expectedOutput)) - }, - }, - { - // the node to be removed is ip-10-0-0-3.ec2.internal since the - // other two have nodes - name: "successfully removes the etcd member without a node for Kubernetes version >= 1.22.0", - kubernetesVersion: minKubernetesVersionWithoutClusterStatus, // Kubernetes version >= 1.22.0 does not have ClusterStatus - objs: []client.Object{node1.DeepCopy(), node2.DeepCopy(), kubeadmConfigWithoutClusterStatus.DeepCopy()}, - nodes: []string{node1.Name, node2.Name}, + name: "successfully removes the etcd member without a node", + objs: []client.Object{node1.DeepCopy(), node2.DeepCopy(), kubeadmConfigWithoutClusterStatus.DeepCopy()}, + nodes: []string{node1.Name, node2.Name}, etcdClientGenerator: &fakeEtcdClientGenerator{ forNodesClient: &etcd.Client{ EtcdClient: fakeEtcdClient, @@ -671,6 +633,7 @@ func TestReconcileEtcdMembers(t *testing.T) { client.ObjectKey{Name: kubeadmConfigKey, Namespace: metav1.NamespaceSystem}, &actualConfig, )).To(Succeed()) + // Kubernetes version >= 1.22.0 does not have ClusterStatus g.Expect(actualConfig.Data).ToNot(HaveKey(clusterStatusKey)) }, }, @@ -703,7 +666,7 @@ func TestReconcileEtcdMembers(t *testing.T) { etcdClientGenerator: tt.etcdClientGenerator, } ctx := context.TODO() - _, err := w.ReconcileEtcdMembers(ctx, tt.nodes, tt.kubernetesVersion) + _, err := w.ReconcileEtcdMembers(ctx, tt.nodes) if tt.expectErr { g.Expect(err).To(HaveOccurred()) return @@ -717,87 +680,6 @@ func TestReconcileEtcdMembers(t *testing.T) { } } -func TestRemoveNodeFromKubeadmConfigMap(t *testing.T) { - tests := []struct { - name string - apiEndpoint string - clusterStatusData string - wantClusterStatus string - }{ - { - name: "removes the api endpoint", - apiEndpoint: "ip-10-0-0-2.ec2.internal", - clusterStatusData: utilyaml.Raw(` - apiEndpoints: - ip-10-0-0-1.ec2.internal: - advertiseAddress: 10.0.0.1 - bindPort: 6443 - ip-10-0-0-2.ec2.internal: - advertiseAddress: 10.0.0.2 - bindPort: 6443 - apiVersion: kubeadm.k8s.io/v1beta2 - kind: ClusterStatus - `), - wantClusterStatus: utilyaml.Raw(` - apiEndpoints: - ip-10-0-0-1.ec2.internal: - advertiseAddress: 10.0.0.1 - bindPort: 6443 - apiVersion: kubeadm.k8s.io/v1beta2 - kind: ClusterStatus - `), - }, - { - name: "no op if the api endpoint does not exists", - apiEndpoint: "ip-10-0-0-2.ec2.internal", - clusterStatusData: utilyaml.Raw(` - apiEndpoints: - ip-10-0-0-1.ec2.internal: - advertiseAddress: 10.0.0.1 - bindPort: 6443 - apiVersion: kubeadm.k8s.io/v1beta2 - kind: ClusterStatus - `), - wantClusterStatus: utilyaml.Raw(` - apiEndpoints: - ip-10-0-0-1.ec2.internal: - advertiseAddress: 10.0.0.1 - bindPort: 6443 - apiVersion: kubeadm.k8s.io/v1beta2 - kind: ClusterStatus - `), - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - g := NewWithT(t) - fakeClient := fake.NewClientBuilder().WithObjects(&corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: kubeadmConfigKey, - Namespace: metav1.NamespaceSystem, - }, - Data: map[string]string{ - clusterStatusKey: tt.clusterStatusData, - }, - }).Build() - - w := &Workload{ - Client: fakeClient, - } - err := w.RemoveNodeFromKubeadmConfigMap(ctx, tt.apiEndpoint, semver.MustParse("1.19.1")) - g.Expect(err).ToNot(HaveOccurred()) - - var actualConfig corev1.ConfigMap - g.Expect(w.Client.Get( - ctx, - client.ObjectKey{Name: kubeadmConfigKey, Namespace: metav1.NamespaceSystem}, - &actualConfig, - )).To(Succeed()) - g.Expect(actualConfig.Data[clusterStatusKey]).Should(Equal(tt.wantClusterStatus), cmp.Diff(tt.wantClusterStatus, actualConfig.Data[clusterStatusKey])) - }) - } -} - type fakeEtcdClientGenerator struct { forNodesClient *etcd.Client forNodesClientFunc func([]string) (*etcd.Client, error) diff --git a/controlplane/kubeadm/internal/workload_cluster_test.go b/controlplane/kubeadm/internal/workload_cluster_test.go index 9861419d99b4..7ff30cbd0da6 100644 --- a/controlplane/kubeadm/internal/workload_cluster_test.go +++ b/controlplane/kubeadm/internal/workload_cluster_test.go @@ -32,7 +32,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client/fake" "sigs.k8s.io/yaml" - clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" bootstrapv1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1beta1" controlplanev1 "sigs.k8s.io/cluster-api/controlplane/kubeadm/api/v1beta1" "sigs.k8s.io/cluster-api/util/version" @@ -249,136 +248,6 @@ func TestUpdateKubeProxyImageInfo(t *testing.T) { } } -func TestRemoveMachineFromKubeadmConfigMap(t *testing.T) { - machine := &clusterv1.Machine{ - Status: clusterv1.MachineStatus{ - NodeRef: &corev1.ObjectReference{ - Name: "ip-10-0-0-1.ec2.internal", - }, - }, - } - kubeadmConfig := &corev1.ConfigMap{ - ObjectMeta: metav1.ObjectMeta{ - Name: kubeadmConfigKey, - Namespace: metav1.NamespaceSystem, - }, - Data: map[string]string{ - clusterStatusKey: utilyaml.Raw(` - apiEndpoints: - ip-10-0-0-1.ec2.internal: - advertiseAddress: 10.0.0.1 - bindPort: 6443 - ip-10-0-0-2.ec2.internal: - advertiseAddress: 10.0.0.2 - bindPort: 6443 - apiVersion: kubeadm.k8s.io/v1beta2 - kind: ClusterStatus - `), - }, - BinaryData: map[string][]byte{ - "": nil, - }, - } - kubeadmConfigWithoutClusterStatus := kubeadmConfig.DeepCopy() - delete(kubeadmConfigWithoutClusterStatus.Data, clusterStatusKey) - - tests := []struct { - name string - kubernetesVersion semver.Version - machine *clusterv1.Machine - objs []client.Object - expectErr bool - expectedEndpoints string - }{ - { - name: "does not panic if machine is nil", - expectErr: false, - }, - { - name: "does not panic if machine noderef is nil", - machine: &clusterv1.Machine{ - Status: clusterv1.MachineStatus{ - NodeRef: nil, - }, - }, - expectErr: false, - }, - { - name: "returns error if unable to find kubeadm-config", - machine: machine, - expectErr: true, - }, - { - name: "returns error if unable to find kubeadm-config for Kubernetes version < 1.22.0", - kubernetesVersion: semver.MustParse("1.19.1"), - machine: machine, - objs: []client.Object{kubeadmConfigWithoutClusterStatus}, - expectErr: true, - }, - { - name: "returns error if unable to remove api endpoint for Kubernetes version < 1.22.0", - kubernetesVersion: semver.MustParse("1.19.1"), // Kubernetes version < 1.22.0 has ClusterStatus - machine: machine, - objs: []client.Object{kubeadmConfigWithoutClusterStatus}, - expectErr: true, - }, - { - name: "removes the machine node ref from kubeadm config for Kubernetes version < 1.22.0", - kubernetesVersion: semver.MustParse("1.19.1"), // Kubernetes version < 1.22.0 has ClusterStatus - machine: machine, - objs: []client.Object{kubeadmConfig}, - expectErr: false, - expectedEndpoints: utilyaml.Raw(` - apiEndpoints: - ip-10-0-0-2.ec2.internal: - advertiseAddress: 10.0.0.2 - bindPort: 6443 - apiVersion: kubeadm.k8s.io/v1beta2 - kind: ClusterStatus - `), - }, - { - name: "no op for Kubernetes version 1.22.0 alpha", - kubernetesVersion: semver.MustParse("1.22.0-alpha.0.734+ba502ee555924a"), // Kubernetes version >= 1.22.0 should not manage ClusterStatus - machine: machine, - objs: []client.Object{kubeadmConfigWithoutClusterStatus}, - expectErr: false, - }, - { - name: "no op for Kubernetes version >= 1.22.0", - kubernetesVersion: minKubernetesVersionWithoutClusterStatus, // Kubernetes version >= 1.22.0 should not manage ClusterStatus - machine: machine, - objs: []client.Object{kubeadmConfigWithoutClusterStatus}, - expectErr: false, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - g := NewWithT(t) - fakeClient := fake.NewClientBuilder().WithObjects(tt.objs...).Build() - w := &Workload{ - Client: fakeClient, - } - err := w.RemoveMachineFromKubeadmConfigMap(ctx, tt.machine, tt.kubernetesVersion) - if tt.expectErr { - g.Expect(err).To(HaveOccurred()) - return - } - g.Expect(err).ToNot(HaveOccurred()) - if tt.expectedEndpoints != "" { - var actualConfig corev1.ConfigMap - g.Expect(w.Client.Get( - ctx, - client.ObjectKey{Name: kubeadmConfigKey, Namespace: metav1.NamespaceSystem}, - &actualConfig, - )).To(Succeed()) - g.Expect(actualConfig.Data[clusterStatusKey]).To(Equal(tt.expectedEndpoints), cmp.Diff(tt.expectedEndpoints, actualConfig.Data[clusterStatusKey])) - } - }) - } -} - func TestUpdateKubeletConfigMap(t *testing.T) { tests := []struct { name string