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  }