sigs.k8s.io/cluster-api-provider-azure@v1.14.3/test/e2e/aks_byo_node.go (about) 1 //go:build e2e 2 // +build e2e 3 4 /* 5 Copyright 2023 The Kubernetes Authors. 6 7 Licensed under the Apache License, Version 2.0 (the "License"); 8 you may not use this file except in compliance with the License. 9 You may obtain a copy of the License at 10 11 http://www.apache.org/licenses/LICENSE-2.0 12 13 Unless required by applicable law or agreed to in writing, software 14 distributed under the License is distributed on an "AS IS" BASIS, 15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 See the License for the specific language governing permissions and 17 limitations under the License. 18 */ 19 20 package e2e 21 22 import ( 23 "context" 24 "os" 25 26 . "github.com/onsi/ginkgo/v2" 27 . "github.com/onsi/gomega" 28 corev1 "k8s.io/api/core/v1" 29 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 30 "k8s.io/utils/ptr" 31 infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1" 32 infrav1exp "sigs.k8s.io/cluster-api-provider-azure/exp/api/v1beta1" 33 clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" 34 bootstrapv1 "sigs.k8s.io/cluster-api/bootstrap/kubeadm/api/v1beta1" 35 expv1 "sigs.k8s.io/cluster-api/exp/api/v1beta1" 36 "sigs.k8s.io/cluster-api/util/conditions" 37 "sigs.k8s.io/controller-runtime/pkg/client" 38 ) 39 40 type AKSBYONodeSpecInput struct { 41 Cluster *clusterv1.Cluster 42 KubernetesVersion string 43 WaitIntervals []interface{} 44 ExpectedWorkerNodes int32 45 } 46 47 func AKSBYONodeSpec(ctx context.Context, inputGetter func() AKSBYONodeSpecInput) { 48 input := inputGetter() 49 50 mgmtClient := bootstrapClusterProxy.GetClient() 51 Expect(mgmtClient).NotTo(BeNil()) 52 53 infraControlPlane := &infrav1.AzureManagedControlPlane{} 54 err := mgmtClient.Get(ctx, client.ObjectKey{Namespace: input.Cluster.Spec.ControlPlaneRef.Namespace, Name: input.Cluster.Spec.ControlPlaneRef.Name}, infraControlPlane) 55 Expect(err).NotTo(HaveOccurred()) 56 57 By("Creating a self-managed machine pool with 2 nodes") 58 infraMachinePool := &infrav1exp.AzureMachinePool{ 59 ObjectMeta: metav1.ObjectMeta{ 60 Name: "byo-pool", 61 Namespace: input.Cluster.Namespace, 62 }, 63 Spec: infrav1exp.AzureMachinePoolSpec{ 64 Location: infraControlPlane.Spec.Location, 65 Template: infrav1exp.AzureMachinePoolMachineTemplate{ 66 VMSize: os.Getenv("AZURE_NODE_MACHINE_TYPE"), 67 }, 68 }, 69 } 70 err = mgmtClient.Create(ctx, infraMachinePool) 71 Expect(err).NotTo(HaveOccurred()) 72 73 kubeadmConfig := &bootstrapv1.KubeadmConfig{ 74 ObjectMeta: metav1.ObjectMeta{ 75 Namespace: infraMachinePool.Namespace, 76 Name: infraMachinePool.Name, 77 }, 78 Spec: bootstrapv1.KubeadmConfigSpec{ 79 Files: []bootstrapv1.File{ 80 { 81 ContentFrom: &bootstrapv1.FileSource{ 82 Secret: bootstrapv1.SecretFileSource{ 83 Name: infraMachinePool.Name + "-azure-json", 84 Key: "worker-node-azure.json", 85 }, 86 }, 87 Path: "/etc/kubernetes/azure.json", 88 Permissions: "0644", 89 Owner: "root:root", 90 }, 91 { 92 ContentFrom: &bootstrapv1.FileSource{ 93 Secret: bootstrapv1.SecretFileSource{ 94 Name: input.Cluster.Name + "-kubeconfig", 95 Key: "value", 96 }, 97 }, 98 Path: "/etc/kubernetes/admin.conf", 99 Permissions: "0644", 100 Owner: "root:root", 101 }, 102 }, 103 JoinConfiguration: &bootstrapv1.JoinConfiguration{ 104 Discovery: bootstrapv1.Discovery{ 105 File: &bootstrapv1.FileDiscovery{ 106 KubeConfigPath: "/etc/kubernetes/admin.conf", 107 }, 108 }, 109 NodeRegistration: bootstrapv1.NodeRegistrationOptions{ 110 Name: "{{ ds.meta_data[\"local_hostname\"] }}", 111 KubeletExtraArgs: map[string]string{ 112 "cloud-provider": "external", 113 }, 114 }, 115 }, 116 PreKubeadmCommands: []string{"kubeadm init phase upload-config all"}, 117 }, 118 } 119 err = mgmtClient.Create(ctx, kubeadmConfig) 120 Expect(err).NotTo(HaveOccurred()) 121 122 machinePool := &expv1.MachinePool{ 123 ObjectMeta: metav1.ObjectMeta{ 124 Namespace: infraMachinePool.Namespace, 125 Name: infraMachinePool.Name, 126 }, 127 Spec: expv1.MachinePoolSpec{ 128 ClusterName: input.Cluster.Name, 129 Replicas: ptr.To[int32](2), 130 Template: clusterv1.MachineTemplateSpec{ 131 Spec: clusterv1.MachineSpec{ 132 Bootstrap: clusterv1.Bootstrap{ 133 ConfigRef: &corev1.ObjectReference{ 134 APIVersion: bootstrapv1.GroupVersion.String(), 135 Kind: "KubeadmConfig", 136 Name: kubeadmConfig.Name, 137 }, 138 }, 139 ClusterName: input.Cluster.Name, 140 InfrastructureRef: corev1.ObjectReference{ 141 APIVersion: infrav1.GroupVersion.String(), 142 Kind: "AzureMachinePool", 143 Name: infraMachinePool.Name, 144 }, 145 Version: ptr.To(input.KubernetesVersion), 146 }, 147 }, 148 }, 149 } 150 err = mgmtClient.Create(ctx, machinePool) 151 Expect(err).NotTo(HaveOccurred()) 152 153 By("creating a Kubernetes client to the workload cluster") 154 workloadClusterProxy := bootstrapClusterProxy.GetWorkloadCluster(ctx, input.Cluster.Spec.ControlPlaneRef.Namespace, input.Cluster.Spec.ControlPlaneRef.Name) 155 Expect(workloadClusterProxy).NotTo(BeNil()) 156 clientset := workloadClusterProxy.GetClientSet() 157 Expect(clientset).NotTo(BeNil()) 158 159 By("Verifying the bootstrap succeeded") 160 Eventually(func(g Gomega) { 161 pool := &infrav1exp.AzureMachinePool{} 162 err := mgmtClient.Get(ctx, client.ObjectKeyFromObject(infraMachinePool), pool) 163 g.Expect(err).NotTo(HaveOccurred()) 164 g.Expect(conditions.IsTrue(pool, infrav1.BootstrapSucceededCondition)).To(BeTrue()) 165 }, input.WaitIntervals...).Should(Succeed()) 166 167 By("Adding the expected AKS labels to the nodes") 168 // TODO: move this to the MachinePool object once MachinePools support label propagation 169 Eventually(func(g Gomega) { 170 nodeList, err := clientset.CoreV1().Nodes().List(ctx, metav1.ListOptions{}) 171 g.Expect(err).NotTo(HaveOccurred()) 172 g.Expect(int32(len(nodeList.Items))).To(Equal(input.ExpectedWorkerNodes + 2)) 173 for i, node := range nodeList.Items { 174 if _, ok := node.Labels["kubernetes.azure.com/cluster"]; !ok { 175 node.Labels["kubernetes.azure.com/cluster"] = infraControlPlane.Spec.NodeResourceGroupName 176 _, err := clientset.CoreV1().Nodes().Update(ctx, &nodeList.Items[i], metav1.UpdateOptions{}) 177 g.Expect(err).NotTo(HaveOccurred()) 178 } 179 } 180 }, input.WaitIntervals...).Should(Succeed()) 181 182 By("Verifying the MachinePool becomes ready") 183 Eventually(func(g Gomega) { 184 pool := &expv1.MachinePool{} 185 err := mgmtClient.Get(ctx, client.ObjectKeyFromObject(machinePool), pool) 186 g.Expect(err).NotTo(HaveOccurred()) 187 g.Expect(conditions.IsTrue(pool, clusterv1.ReadyCondition)).To(BeTrue()) 188 }, input.WaitIntervals...).Should(Succeed()) 189 }