sigs.k8s.io/cluster-api-provider-azure@v1.14.3/api/v1beta1/azuremanagedmachinepooltemplate_webhook_test.go (about)

     1  /*
     2  Copyright 2023 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package v1beta1
    18  
    19  import (
    20  	"context"
    21  	"testing"
    22  
    23  	. "github.com/onsi/gomega"
    24  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    25  	"k8s.io/utils/ptr"
    26  	azureutil "sigs.k8s.io/cluster-api-provider-azure/util/azure"
    27  )
    28  
    29  func TestManagedMachinePoolTemplateDefaultingWebhook(t *testing.T) {
    30  	g := NewWithT(t)
    31  
    32  	t.Logf("Testing ammpt defaulting webhook with no baseline")
    33  	ammpt := getAzureManagedMachinePoolTemplate()
    34  	mmptw := &azureManagedMachinePoolTemplateWebhook{}
    35  	err := mmptw.Default(context.Background(), ammpt)
    36  	g.Expect(err).NotTo(HaveOccurred())
    37  	g.Expect(ammpt.Labels).To(Equal(map[string]string{
    38  		LabelAgentPoolMode: "System",
    39  	}))
    40  	g.Expect(ammpt.Spec.Template.Spec.Name).To(Equal(ptr.To("fooName")))
    41  	g.Expect(ammpt.Spec.Template.Spec.OSType).To(Equal(ptr.To("Linux")))
    42  
    43  	t.Logf("Testing ammpt defaulting webhook with baseline")
    44  	ammpt = getAzureManagedMachinePoolTemplate(func(ammpt *AzureManagedMachinePoolTemplate) {
    45  		ammpt.Spec.Template.Spec.Mode = "User"
    46  		ammpt.Spec.Template.Spec.Name = ptr.To("barName")
    47  		ammpt.Spec.Template.Spec.OSType = ptr.To("Windows")
    48  	})
    49  	err = mmptw.Default(context.Background(), ammpt)
    50  	g.Expect(err).NotTo(HaveOccurred())
    51  	g.Expect(ammpt.Labels).To(Equal(map[string]string{
    52  		LabelAgentPoolMode: "User",
    53  	}))
    54  	g.Expect(ammpt.Spec.Template.Spec.Name).To(Equal(ptr.To("barName")))
    55  	g.Expect(ammpt.Spec.Template.Spec.OSType).To(Equal(ptr.To("Windows")))
    56  }
    57  
    58  func TestManagedMachinePoolTemplateUpdateWebhook(t *testing.T) {
    59  	tests := []struct {
    60  		name                   string
    61  		oldMachinePoolTemplate *AzureManagedMachinePoolTemplate
    62  		machinePoolTemplate    *AzureManagedMachinePoolTemplate
    63  		wantErr                bool
    64  	}{
    65  		{
    66  			name:                   "azuremanagedmachinepooltemplate no changes - valid spec",
    67  			oldMachinePoolTemplate: getAzureManagedMachinePoolTemplate(),
    68  			machinePoolTemplate:    getAzureManagedMachinePoolTemplate(),
    69  			wantErr:                false,
    70  		},
    71  		{
    72  			name:                   "azuremanagedmachinepooltemplate name is immutable",
    73  			oldMachinePoolTemplate: getAzureManagedMachinePoolTemplate(),
    74  			machinePoolTemplate: getAzureManagedMachinePoolTemplate(func(ammpt *AzureManagedMachinePoolTemplate) {
    75  				ammpt.Spec.Template.Spec.Name = ptr.To("barName")
    76  			}),
    77  			wantErr: true,
    78  		},
    79  		{
    80  			name:                   "azuremanagedmachinepooltemplate invalid nodeLabel",
    81  			oldMachinePoolTemplate: getAzureManagedMachinePoolTemplate(),
    82  			machinePoolTemplate: getAzureManagedMachinePoolTemplate(func(ammpt *AzureManagedMachinePoolTemplate) {
    83  				ammpt.Spec.Template.Spec.NodeLabels = map[string]string{
    84  					azureutil.AzureSystemNodeLabelPrefix: "foo",
    85  				}
    86  			}),
    87  			wantErr: true,
    88  		},
    89  		{
    90  			name: "azuremanagedmachinepooltemplate osType is immutable",
    91  			oldMachinePoolTemplate: getAzureManagedMachinePoolTemplate(func(ammpt *AzureManagedMachinePoolTemplate) {
    92  				ammpt.Spec.Template.Spec.OSType = ptr.To("Windows")
    93  			}),
    94  			machinePoolTemplate: getAzureManagedMachinePoolTemplate(func(ammpt *AzureManagedMachinePoolTemplate) {
    95  				ammpt.Spec.Template.Spec.OSType = ptr.To("Linux")
    96  			}),
    97  			wantErr: true,
    98  		},
    99  		{
   100  			name: "azuremanagedmachinepooltemplate SKU is immutable",
   101  			oldMachinePoolTemplate: getAzureManagedMachinePoolTemplate(func(ammpt *AzureManagedMachinePoolTemplate) {
   102  				ammpt.Spec.Template.Spec.SKU = "Standard_D2s_v3"
   103  			}),
   104  			machinePoolTemplate: getAzureManagedMachinePoolTemplate(func(ammpt *AzureManagedMachinePoolTemplate) {
   105  				ammpt.Spec.Template.Spec.SKU = "Standard_D4s_v3"
   106  			}),
   107  			wantErr: true,
   108  		},
   109  		{
   110  			name: "azuremanagedmachinepooltemplate OSDiskSizeGB is immutable",
   111  			oldMachinePoolTemplate: getAzureManagedMachinePoolTemplate(func(ammpt *AzureManagedMachinePoolTemplate) {
   112  				ammpt.Spec.Template.Spec.OSDiskSizeGB = ptr.To(128)
   113  			}),
   114  			machinePoolTemplate: getAzureManagedMachinePoolTemplate(func(ammpt *AzureManagedMachinePoolTemplate) {
   115  				ammpt.Spec.Template.Spec.OSDiskSizeGB = ptr.To(256)
   116  			}),
   117  			wantErr: true,
   118  		},
   119  		{
   120  			name: "azuremanagedmachinepooltemplate SubnetName is immutable",
   121  			oldMachinePoolTemplate: getAzureManagedMachinePoolTemplate(func(ammpt *AzureManagedMachinePoolTemplate) {
   122  				ammpt.Spec.Template.Spec.SubnetName = ptr.To("fooSubnet")
   123  			}),
   124  			machinePoolTemplate: getAzureManagedMachinePoolTemplate(func(ammpt *AzureManagedMachinePoolTemplate) {
   125  				ammpt.Spec.Template.Spec.SubnetName = ptr.To("barSubnet")
   126  			}),
   127  			wantErr: true,
   128  		},
   129  		{
   130  			name: "azuremanagedmachinepooltemplate enableFIPS is immutable",
   131  			oldMachinePoolTemplate: getAzureManagedMachinePoolTemplate(func(ammpt *AzureManagedMachinePoolTemplate) {
   132  				ammpt.Spec.Template.Spec.EnableFIPS = ptr.To(true)
   133  			}),
   134  			machinePoolTemplate: getAzureManagedMachinePoolTemplate(func(ammpt *AzureManagedMachinePoolTemplate) {
   135  				ammpt.Spec.Template.Spec.EnableFIPS = ptr.To(false)
   136  			}),
   137  			wantErr: true,
   138  		},
   139  		{
   140  			name: "azuremanagedmachinepooltemplate MaxPods is immutable",
   141  			oldMachinePoolTemplate: getAzureManagedMachinePoolTemplate(func(ammpt *AzureManagedMachinePoolTemplate) {
   142  				ammpt.Spec.Template.Spec.MaxPods = ptr.To(128)
   143  			}),
   144  			machinePoolTemplate: getAzureManagedMachinePoolTemplate(func(ammpt *AzureManagedMachinePoolTemplate) {
   145  				ammpt.Spec.Template.Spec.MaxPods = ptr.To(256)
   146  			}),
   147  			wantErr: true,
   148  		},
   149  		{
   150  			name: "azuremanagedmachinepooltemplate OSDiskType is immutable",
   151  			oldMachinePoolTemplate: getAzureManagedMachinePoolTemplate(func(ammpt *AzureManagedMachinePoolTemplate) {
   152  				ammpt.Spec.Template.Spec.OsDiskType = ptr.To("Standard_LRS")
   153  			}),
   154  			machinePoolTemplate: getAzureManagedMachinePoolTemplate(func(ammpt *AzureManagedMachinePoolTemplate) {
   155  				ammpt.Spec.Template.Spec.OsDiskType = ptr.To("Premium_LRS")
   156  			}),
   157  			wantErr: true,
   158  		},
   159  		{
   160  			name: "azuremanagedmachinepooltemplate scaleSetPriority is immutable",
   161  			oldMachinePoolTemplate: getAzureManagedMachinePoolTemplate(func(ammpt *AzureManagedMachinePoolTemplate) {
   162  				ammpt.Spec.Template.Spec.ScaleSetPriority = ptr.To("Regular")
   163  			}),
   164  			machinePoolTemplate: getAzureManagedMachinePoolTemplate(func(ammpt *AzureManagedMachinePoolTemplate) {
   165  				ammpt.Spec.Template.Spec.ScaleSetPriority = ptr.To("Spot")
   166  			}),
   167  			wantErr: true,
   168  		},
   169  		{
   170  			name: "azuremanagedmachinepooltemplate enableUltraSSD is immutable",
   171  			oldMachinePoolTemplate: getAzureManagedMachinePoolTemplate(func(ammpt *AzureManagedMachinePoolTemplate) {
   172  				ammpt.Spec.Template.Spec.EnableUltraSSD = ptr.To(true)
   173  			}),
   174  			machinePoolTemplate: getAzureManagedMachinePoolTemplate(func(ammpt *AzureManagedMachinePoolTemplate) {
   175  				ammpt.Spec.Template.Spec.EnableUltraSSD = ptr.To(false)
   176  			}),
   177  			wantErr: true,
   178  		},
   179  		{
   180  			name: "azuremanagedmachinepooltemplate enableNodePublicIP is immutable",
   181  			oldMachinePoolTemplate: getAzureManagedMachinePoolTemplate(func(ammpt *AzureManagedMachinePoolTemplate) {
   182  				ammpt.Spec.Template.Spec.EnableNodePublicIP = ptr.To(true)
   183  			}),
   184  			machinePoolTemplate: getAzureManagedMachinePoolTemplate(func(ammpt *AzureManagedMachinePoolTemplate) {
   185  				ammpt.Spec.Template.Spec.EnableNodePublicIP = ptr.To(false)
   186  			}),
   187  			wantErr: true,
   188  		},
   189  		{
   190  			name: "azuremanagedmachinepooltemplate nodePublicIPPrefixID is immutable",
   191  			oldMachinePoolTemplate: getAzureManagedMachinePoolTemplate(func(ammpt *AzureManagedMachinePoolTemplate) {
   192  				ammpt.Spec.Template.Spec.NodePublicIPPrefixID = ptr.To("fooPublicIPPrefixID")
   193  			}),
   194  			machinePoolTemplate: getAzureManagedMachinePoolTemplate(func(ammpt *AzureManagedMachinePoolTemplate) {
   195  				ammpt.Spec.Template.Spec.NodePublicIPPrefixID = ptr.To("barPublicIPPrefixID")
   196  			}),
   197  			wantErr: true,
   198  		},
   199  		{
   200  			name: "azuremanagedmachinepooltemplate kubeletConfig is immutable",
   201  			oldMachinePoolTemplate: getAzureManagedMachinePoolTemplate(func(ammpt *AzureManagedMachinePoolTemplate) {
   202  				ammpt.Spec.Template.Spec.KubeletConfig = &KubeletConfig{}
   203  			}),
   204  			machinePoolTemplate: getAzureManagedMachinePoolTemplate(func(ammpt *AzureManagedMachinePoolTemplate) {
   205  				ammpt.Spec.Template.Spec.KubeletConfig = &KubeletConfig{
   206  					FailSwapOn: ptr.To(true),
   207  				}
   208  			}),
   209  			wantErr: true,
   210  		},
   211  		{
   212  			name: "azuremanagedmachinepooltemplate kubeletDiskType is immutable",
   213  			oldMachinePoolTemplate: getAzureManagedMachinePoolTemplate(func(ammpt *AzureManagedMachinePoolTemplate) {
   214  				ammpt.Spec.Template.Spec.KubeletDiskType = ptr.To(KubeletDiskTypeOS)
   215  			}),
   216  			machinePoolTemplate: getAzureManagedMachinePoolTemplate(func(ammpt *AzureManagedMachinePoolTemplate) {
   217  				ammpt.Spec.Template.Spec.KubeletDiskType = ptr.To(KubeletDiskTypeTemporary)
   218  			}),
   219  			wantErr: true,
   220  		},
   221  		{
   222  			name: "azuremanagedmachinepooltemplate linuxOSConfig is immutable",
   223  			oldMachinePoolTemplate: getAzureManagedMachinePoolTemplate(func(ammpt *AzureManagedMachinePoolTemplate) {
   224  				ammpt.Spec.Template.Spec.LinuxOSConfig = &LinuxOSConfig{}
   225  			}),
   226  			machinePoolTemplate: getAzureManagedMachinePoolTemplate(func(ammpt *AzureManagedMachinePoolTemplate) {
   227  				ammpt.Spec.Template.Spec.LinuxOSConfig = &LinuxOSConfig{
   228  					SwapFileSizeMB: ptr.To(128),
   229  				}
   230  			}),
   231  			wantErr: true,
   232  		},
   233  	}
   234  	for _, tc := range tests {
   235  		t.Run(tc.name, func(t *testing.T) {
   236  			g := NewWithT(t)
   237  			mpw := &azureManagedMachinePoolTemplateWebhook{}
   238  			_, err := mpw.ValidateUpdate(context.Background(), tc.oldMachinePoolTemplate, tc.machinePoolTemplate)
   239  			if tc.wantErr {
   240  				g.Expect(err).To(HaveOccurred())
   241  			} else {
   242  				g.Expect(err).NotTo(HaveOccurred())
   243  			}
   244  		})
   245  	}
   246  }
   247  
   248  func getAzureManagedMachinePoolTemplate(changes ...func(*AzureManagedMachinePoolTemplate)) *AzureManagedMachinePoolTemplate {
   249  	input := &AzureManagedMachinePoolTemplate{
   250  		ObjectMeta: metav1.ObjectMeta{
   251  			Name: "fooName",
   252  		},
   253  		Spec: AzureManagedMachinePoolTemplateSpec{
   254  			Template: AzureManagedMachinePoolTemplateResource{
   255  				Spec: AzureManagedMachinePoolTemplateResourceSpec{
   256  					AzureManagedMachinePoolClassSpec: AzureManagedMachinePoolClassSpec{
   257  						Mode: "System",
   258  					},
   259  				},
   260  			},
   261  		},
   262  	}
   263  
   264  	for _, change := range changes {
   265  		change(input)
   266  	}
   267  
   268  	return input
   269  }