sigs.k8s.io/cluster-api-provider-azure@v1.14.3/test/e2e/aks_public_ip_prefix.go (about)

     1  //go:build e2e
     2  // +build e2e
     3  
     4  /*
     5  Copyright 2022 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/Azure/azure-sdk-for-go/sdk/azidentity"
    27  	"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v4"
    28  	. "github.com/onsi/ginkgo/v2"
    29  	. "github.com/onsi/gomega"
    30  	corev1 "k8s.io/api/core/v1"
    31  	apierrors "k8s.io/apimachinery/pkg/api/errors"
    32  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    33  	"k8s.io/utils/ptr"
    34  	infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1"
    35  	"sigs.k8s.io/cluster-api-provider-azure/azure"
    36  	clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1"
    37  	expv1 "sigs.k8s.io/cluster-api/exp/api/v1beta1"
    38  	"sigs.k8s.io/cluster-api/util/conditions"
    39  	"sigs.k8s.io/controller-runtime/pkg/client"
    40  )
    41  
    42  type AKSPublicIPPrefixSpecInput struct {
    43  	Cluster           *clusterv1.Cluster
    44  	KubernetesVersion string
    45  	WaitIntervals     []interface{}
    46  }
    47  
    48  func AKSPublicIPPrefixSpec(ctx context.Context, inputGetter func() AKSPublicIPPrefixSpecInput) {
    49  	input := inputGetter()
    50  
    51  	subscriptionID := getSubscriptionID(Default)
    52  
    53  	cred, err := azidentity.NewDefaultAzureCredential(nil)
    54  	Expect(err).NotTo(HaveOccurred())
    55  
    56  	mgmtClient := bootstrapClusterProxy.GetClient()
    57  	Expect(mgmtClient).NotTo(BeNil())
    58  
    59  	infraControlPlane := &infrav1.AzureManagedControlPlane{}
    60  	err = mgmtClient.Get(ctx, client.ObjectKey{Namespace: input.Cluster.Spec.ControlPlaneRef.Namespace, Name: input.Cluster.Spec.ControlPlaneRef.Name}, infraControlPlane)
    61  	Expect(err).NotTo(HaveOccurred())
    62  
    63  	resourceGroupName := infraControlPlane.Spec.ResourceGroupName
    64  
    65  	publicIPPrefixClient, err := armnetwork.NewPublicIPPrefixesClient(subscriptionID, cred, nil)
    66  	Expect(err).NotTo(HaveOccurred())
    67  
    68  	By("Creating public IP prefix with 2 addresses")
    69  	poller, err := publicIPPrefixClient.BeginCreateOrUpdate(ctx, resourceGroupName, input.Cluster.Name, armnetwork.PublicIPPrefix{
    70  		Location: ptr.To(infraControlPlane.Spec.Location),
    71  		SKU: &armnetwork.PublicIPPrefixSKU{
    72  			Name: ptr.To(armnetwork.PublicIPPrefixSKUNameStandard),
    73  		},
    74  		Properties: &armnetwork.PublicIPPrefixPropertiesFormat{
    75  			PrefixLength: ptr.To[int32](31), // In bits. This provides 2 addresses.
    76  		},
    77  	}, nil)
    78  	Expect(err).NotTo(HaveOccurred())
    79  	var publicIPPrefix armnetwork.PublicIPPrefix
    80  	Eventually(func(g Gomega) {
    81  		resp, err := poller.PollUntilDone(ctx, nil)
    82  		Expect(err).NotTo(HaveOccurred())
    83  		publicIPPrefix = resp.PublicIPPrefix
    84  	}, input.WaitIntervals...).Should(Succeed(), "failed to create public IP prefix")
    85  
    86  	By("Creating node pool with 3 nodes")
    87  	infraMachinePool := &infrav1.AzureManagedMachinePool{
    88  		ObjectMeta: metav1.ObjectMeta{
    89  			Name:      "pool3",
    90  			Namespace: input.Cluster.Namespace,
    91  		},
    92  		Spec: infrav1.AzureManagedMachinePoolSpec{
    93  			AzureManagedMachinePoolClassSpec: infrav1.AzureManagedMachinePoolClassSpec{
    94  				Mode:                 "User",
    95  				SKU:                  os.Getenv("AZURE_NODE_MACHINE_TYPE"),
    96  				EnableNodePublicIP:   ptr.To(true),
    97  				NodePublicIPPrefixID: ptr.To(azure.PublicIPPrefixID(subscriptionID, resourceGroupName, *publicIPPrefix.Name)),
    98  			},
    99  		},
   100  	}
   101  	err = mgmtClient.Create(ctx, infraMachinePool)
   102  	Expect(err).NotTo(HaveOccurred())
   103  
   104  	machinePool := &expv1.MachinePool{
   105  		ObjectMeta: metav1.ObjectMeta{
   106  			Namespace: infraMachinePool.Namespace,
   107  			Name:      infraMachinePool.Name,
   108  		},
   109  		Spec: expv1.MachinePoolSpec{
   110  			ClusterName: input.Cluster.Name,
   111  			Replicas:    ptr.To[int32](3),
   112  			Template: clusterv1.MachineTemplateSpec{
   113  				Spec: clusterv1.MachineSpec{
   114  					Bootstrap: clusterv1.Bootstrap{
   115  						DataSecretName: ptr.To(""),
   116  					},
   117  					ClusterName: input.Cluster.Name,
   118  					InfrastructureRef: corev1.ObjectReference{
   119  						APIVersion: infrav1.GroupVersion.String(),
   120  						Kind:       "AzureManagedMachinePool",
   121  						Name:       infraMachinePool.Name,
   122  					},
   123  					Version: ptr.To(input.KubernetesVersion),
   124  				},
   125  			},
   126  		},
   127  	}
   128  	err = mgmtClient.Create(ctx, machinePool)
   129  	Expect(err).NotTo(HaveOccurred())
   130  
   131  	defer func() {
   132  		By("Deleting the node pool")
   133  		err := mgmtClient.Delete(ctx, machinePool)
   134  		Expect(err).NotTo(HaveOccurred())
   135  
   136  		Eventually(func(g Gomega) {
   137  			err := mgmtClient.Get(ctx, client.ObjectKeyFromObject(machinePool), &expv1.MachinePool{})
   138  			g.Expect(apierrors.IsNotFound(err)).To(BeTrue())
   139  		}, input.WaitIntervals...).Should(Succeed(), "Deleted MachinePool %s/%s still exists", machinePool.Namespace, machinePool.Name)
   140  
   141  		Eventually(func(g Gomega) {
   142  			err := mgmtClient.Get(ctx, client.ObjectKeyFromObject(infraMachinePool), &infrav1.AzureManagedMachinePool{})
   143  			g.Expect(apierrors.IsNotFound(err)).To(BeTrue())
   144  		}, input.WaitIntervals...).Should(Succeed(), "Deleted AzureManagedMachinePool %s/%s still exists", infraMachinePool.Namespace, infraMachinePool.Name)
   145  	}()
   146  
   147  	By("Verifying the AzureManagedMachinePool converges to a failed ready status")
   148  	Eventually(func(g Gomega) {
   149  		infraMachinePool := &infrav1.AzureManagedMachinePool{}
   150  		err := mgmtClient.Get(ctx, client.ObjectKeyFromObject(machinePool), infraMachinePool)
   151  		g.Expect(err).NotTo(HaveOccurred())
   152  		cond := conditions.Get(infraMachinePool, infrav1.AgentPoolsReadyCondition)
   153  		g.Expect(cond).NotTo(BeNil())
   154  		g.Expect(cond.Status).To(Equal(corev1.ConditionFalse))
   155  		g.Expect(cond.Reason).To(Equal(infrav1.FailedReason))
   156  		g.Expect(cond.Message).To(ContainSubstring("PublicIpPrefixOutOfIpAddressesForVMScaleSet"))
   157  	}, input.WaitIntervals...).Should(Succeed())
   158  
   159  	By("Scaling the MachinePool to 2 nodes")
   160  	Eventually(func(g Gomega) {
   161  		err = mgmtClient.Get(ctx, client.ObjectKeyFromObject(machinePool), machinePool)
   162  		g.Expect(err).NotTo(HaveOccurred())
   163  		machinePool.Spec.Replicas = ptr.To[int32](2)
   164  		err = mgmtClient.Update(ctx, machinePool)
   165  		g.Expect(err).NotTo(HaveOccurred())
   166  	}, input.WaitIntervals...).Should(Succeed())
   167  
   168  	By("Verifying the AzureManagedMachinePool becomes ready")
   169  	Eventually(func(g Gomega) {
   170  		infraMachinePool := &infrav1.AzureManagedMachinePool{}
   171  		err := mgmtClient.Get(ctx, client.ObjectKeyFromObject(machinePool), infraMachinePool)
   172  		g.Expect(err).NotTo(HaveOccurred())
   173  		g.Expect(conditions.IsTrue(infraMachinePool, infrav1.AgentPoolsReadyCondition)).To(BeTrue())
   174  	}, input.WaitIntervals...).Should(Succeed())
   175  }