sigs.k8s.io/cluster-api-provider-azure@v1.17.0/test/e2e/aks_marketplace.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 "fmt" 25 26 "github.com/Azure/azure-sdk-for-go/sdk/azidentity" 27 "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/containerservice/armcontainerservice/v4" 28 "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/kubernetesconfiguration/armkubernetesconfiguration" 29 . "github.com/onsi/ginkgo/v2" 30 . "github.com/onsi/gomega" 31 corev1 "k8s.io/api/core/v1" 32 "k8s.io/apimachinery/pkg/types" 33 "k8s.io/utils/ptr" 34 infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1" 35 clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" 36 "sigs.k8s.io/cluster-api/util/conditions" 37 "sigs.k8s.io/controller-runtime/pkg/client" 38 ) 39 40 type AKSMarketplaceExtensionSpecInput struct { 41 Cluster *clusterv1.Cluster 42 WaitIntervals []interface{} 43 } 44 45 const ( 46 extensionName = "AKS-marketplace-extension" // Test that upper case name is allowed 47 officialExtensionName = "official-aks-extension" 48 ) 49 50 func AKSMarketplaceExtensionSpec(ctx context.Context, inputGetter func() AKSMarketplaceExtensionSpecInput) { 51 input := inputGetter() 52 53 cred, err := azidentity.NewDefaultAzureCredential(nil) 54 Expect(err).NotTo(HaveOccurred()) 55 56 mgmtClient := bootstrapClusterProxy.GetClient() 57 Expect(mgmtClient).NotTo(BeNil()) 58 59 amcp := &infrav1.AzureManagedControlPlane{} 60 err = mgmtClient.Get(ctx, types.NamespacedName{ 61 Namespace: input.Cluster.Spec.ControlPlaneRef.Namespace, 62 Name: input.Cluster.Spec.ControlPlaneRef.Name, 63 }, amcp) 64 Expect(err).NotTo(HaveOccurred()) 65 66 agentpoolsClient, err := armcontainerservice.NewAgentPoolsClient(amcp.Spec.SubscriptionID, cred, nil) 67 Expect(err).NotTo(HaveOccurred()) 68 69 extensionClient, err := armkubernetesconfiguration.NewExtensionsClient(amcp.Spec.SubscriptionID, cred, nil) 70 Expect(err).NotTo(HaveOccurred()) 71 72 By("Deleting all node taints for windows machine pool") 73 var ammp = &infrav1.AzureManagedMachinePool{} 74 Expect(mgmtClient.Get(ctx, types.NamespacedName{ 75 Namespace: input.Cluster.Namespace, 76 Name: input.Cluster.Name + "-pool2", 77 }, ammp)).To(Succeed()) 78 initialTaints := ammp.Spec.Taints 79 var expectedTaints []infrav1.Taint 80 expectedTaints = nil 81 checkTaints := func(g Gomega) { 82 var expectedTaintStrs []*string 83 if expectedTaints != nil { 84 expectedTaintStrs = make([]*string, 0, len(expectedTaints)) 85 for _, taint := range expectedTaints { 86 expectedTaintStrs = append(expectedTaintStrs, ptr.To(fmt.Sprintf("%s=%s:%s", taint.Key, taint.Value, taint.Effect))) 87 } 88 } 89 90 resp, err := agentpoolsClient.Get(ctx, amcp.Spec.ResourceGroupName, amcp.Name, *ammp.Spec.Name, nil) 91 g.Expect(err).NotTo(HaveOccurred()) 92 g.Expect(resp.Properties.ProvisioningState).To(Equal(ptr.To("Succeeded"))) 93 actualTaintStrs := resp.AgentPool.Properties.NodeTaints 94 if expectedTaintStrs == nil { 95 g.Expect(actualTaintStrs).To(BeNil()) 96 } else { 97 g.Expect(actualTaintStrs).To(Equal(expectedTaintStrs)) 98 } 99 } 100 Eventually(func(g Gomega) { 101 g.Expect(mgmtClient.Get(ctx, client.ObjectKeyFromObject(ammp), ammp)).To(Succeed()) 102 ammp.Spec.Taints = expectedTaints 103 g.Expect(mgmtClient.Update(ctx, ammp)).To(Succeed()) 104 }, inputGetter().WaitIntervals...).Should(Succeed()) 105 Eventually(checkTaints, input.WaitIntervals...).Should(Succeed()) 106 107 By("Adding a taint to the Windows node pool") 108 expectedTaints = []infrav1.Taint{ 109 { 110 Effect: infrav1.TaintEffect(corev1.TaintEffectNoSchedule), 111 Key: "capz-e2e-1", 112 Value: "test1", 113 }, 114 } 115 Eventually(func(g Gomega) { 116 g.Expect(mgmtClient.Get(ctx, client.ObjectKeyFromObject(ammp), ammp)).To(Succeed()) 117 ammp.Spec.Taints = expectedTaints 118 g.Expect(mgmtClient.Update(ctx, ammp)).To(Succeed()) 119 Eventually(checkTaints, input.WaitIntervals...).Should(Succeed()) 120 }, input.WaitIntervals...).Should(Succeed()) 121 122 By("Updating taints for Windows machine pool") 123 expectedTaints = expectedTaints[:1] 124 Eventually(func(g Gomega) { 125 g.Expect(mgmtClient.Get(ctx, client.ObjectKeyFromObject(ammp), ammp)).To(Succeed()) 126 ammp.Spec.Taints = expectedTaints 127 g.Expect(mgmtClient.Update(ctx, ammp)).To(Succeed()) 128 }, input.WaitIntervals...).Should(Succeed()) 129 Eventually(checkTaints, input.WaitIntervals...).Should(Succeed()) 130 131 By("Adding an official AKS Extension & AKS Marketplace Extension to the AzureManagedControlPlane") 132 var infraControlPlane = &infrav1.AzureManagedControlPlane{} 133 Eventually(func(g Gomega) { 134 err = mgmtClient.Get(ctx, client.ObjectKey{ 135 Namespace: input.Cluster.Spec.ControlPlaneRef.Namespace, 136 Name: input.Cluster.Spec.ControlPlaneRef.Name, 137 }, infraControlPlane) 138 g.Expect(err).NotTo(HaveOccurred()) 139 infraControlPlane.Spec.Extensions = []infrav1.AKSExtension{ 140 { 141 Name: extensionName, 142 ExtensionType: ptr.To("TraefikLabs.TraefikProxy"), 143 Plan: &infrav1.ExtensionPlan{ 144 Name: "traefik-proxy", 145 Product: "traefik-proxy", 146 Publisher: "containous", 147 }, 148 }, 149 { 150 Name: officialExtensionName, 151 ExtensionType: ptr.To("microsoft.flux"), 152 }, 153 } 154 g.Expect(mgmtClient.Update(ctx, infraControlPlane)).To(Succeed()) 155 }, input.WaitIntervals...).Should(Succeed()) 156 157 By("Ensuring the AKS Marketplace Extension status is ready on the AzureManagedControlPlane") 158 Eventually(func(g Gomega) { 159 err = mgmtClient.Get(ctx, client.ObjectKey{Namespace: input.Cluster.Spec.ControlPlaneRef.Namespace, Name: input.Cluster.Spec.ControlPlaneRef.Name}, infraControlPlane) 160 g.Expect(err).NotTo(HaveOccurred()) 161 g.Expect(conditions.IsTrue(infraControlPlane, infrav1.AKSExtensionsReadyCondition)).To(BeTrue()) 162 }, input.WaitIntervals...).Should(Succeed()) 163 164 By("Ensuring the AKS Marketplace Extension is added to the AzureManagedControlPlane") 165 ensureAKSExtensionAdded(ctx, input, extensionName, "TraefikLabs.TraefikProxy", extensionClient, amcp) 166 ensureAKSExtensionAdded(ctx, input, officialExtensionName, "microsoft.flux", extensionClient, amcp) 167 168 By("Restoring initial taints for Windows machine pool") 169 expectedTaints = initialTaints 170 Eventually(func(g Gomega) { 171 g.Expect(mgmtClient.Get(ctx, client.ObjectKeyFromObject(ammp), ammp)).To(Succeed()) 172 ammp.Spec.Taints = expectedTaints 173 g.Expect(mgmtClient.Update(ctx, ammp)).To(Succeed()) 174 }, input.WaitIntervals...).Should(Succeed()) 175 Eventually(checkTaints, input.WaitIntervals...).Should(Succeed()) 176 } 177 178 func ensureAKSExtensionAdded(ctx context.Context, input AKSMarketplaceExtensionSpecInput, extensionName, extensionType string, extensionClient *armkubernetesconfiguration.ExtensionsClient, amcp *infrav1.AzureManagedControlPlane) { 179 Eventually(func(g Gomega) { 180 resp, err := extensionClient.Get(ctx, amcp.Spec.ResourceGroupName, "Microsoft.ContainerService", "managedClusters", input.Cluster.Name, extensionName, nil) 181 g.Expect(err).NotTo(HaveOccurred()) 182 g.Expect(resp.Properties.ProvisioningState).To(Equal(ptr.To(armkubernetesconfiguration.ProvisioningStateSucceeded))) 183 extension := resp.Extension 184 g.Expect(extension.Properties).NotTo(BeNil()) 185 g.Expect(extension.Name).To(Equal(ptr.To(extensionName))) 186 g.Expect(extension.Properties.AutoUpgradeMinorVersion).To(Equal(ptr.To(true))) 187 g.Expect(extension.Properties.ExtensionType).To(Equal(ptr.To(extensionType))) 188 }, input.WaitIntervals...).Should(Succeed()) 189 }