sigs.k8s.io/cluster-api-provider-azure@v1.14.3/exp/api/v1beta1/azuremachinepool_default_test.go (about) 1 /* 2 Copyright 2021 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 "fmt" 21 "testing" 22 23 "github.com/google/uuid" 24 . "github.com/onsi/gomega" 25 corev1 "k8s.io/api/core/v1" 26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 "k8s.io/apimachinery/pkg/runtime" 28 "k8s.io/utils/ptr" 29 infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1" 30 clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" 31 expv1 "sigs.k8s.io/cluster-api/exp/api/v1beta1" 32 "sigs.k8s.io/controller-runtime/pkg/client/fake" 33 ) 34 35 func TestAzureMachinePool_SetDefaultSSHPublicKey(t *testing.T) { 36 g := NewWithT(t) 37 38 type test struct { 39 amp *AzureMachinePool 40 } 41 42 existingPublicKey := "testpublickey" 43 publicKeyExistTest := test{amp: createMachinePoolWithSSHPublicKey(existingPublicKey)} 44 publicKeyNotExistTest := test{amp: createMachinePoolWithSSHPublicKey("")} 45 46 err := publicKeyExistTest.amp.SetDefaultSSHPublicKey() 47 g.Expect(err).NotTo(HaveOccurred()) 48 g.Expect(publicKeyExistTest.amp.Spec.Template.SSHPublicKey).To(Equal(existingPublicKey)) 49 50 err = publicKeyNotExistTest.amp.SetDefaultSSHPublicKey() 51 g.Expect(err).NotTo(HaveOccurred()) 52 g.Expect(publicKeyNotExistTest.amp.Spec.Template.SSHPublicKey).NotTo(BeEmpty()) 53 } 54 55 func TestAzureMachinePool_SetIdentityDefaults(t *testing.T) { 56 fakeSubscriptionID := uuid.New().String() 57 fakeClusterName := "testcluster" 58 fakeRoleDefinitionID := "testroledefinitionid" 59 fakeScope := fmt.Sprintf("/subscriptions/%s/resourceGroups/%s", fakeSubscriptionID, fakeClusterName) 60 existingRoleAssignmentName := "42862306-e485-4319-9bf0-35dbc6f6fe9c" 61 62 tests := []struct { 63 name string 64 machinePool *AzureMachinePool 65 wantErr bool 66 expectedRoleAssignmentName string 67 expectedSystemAssignedIdentityRole *infrav1.SystemAssignedIdentityRole 68 }{ 69 { 70 name: "bothRoleAssignmentNamesPopulated", 71 machinePool: &AzureMachinePool{Spec: AzureMachinePoolSpec{ 72 Identity: infrav1.VMIdentitySystemAssigned, 73 RoleAssignmentName: existingRoleAssignmentName, 74 SystemAssignedIdentityRole: &infrav1.SystemAssignedIdentityRole{ 75 Name: existingRoleAssignmentName, 76 }, 77 }}, 78 expectedRoleAssignmentName: existingRoleAssignmentName, 79 expectedSystemAssignedIdentityRole: &infrav1.SystemAssignedIdentityRole{ 80 Name: existingRoleAssignmentName, 81 }, 82 }, 83 { 84 name: "roleAssignmentExist", 85 machinePool: &AzureMachinePool{Spec: AzureMachinePoolSpec{ 86 Identity: infrav1.VMIdentitySystemAssigned, 87 SystemAssignedIdentityRole: &infrav1.SystemAssignedIdentityRole{ 88 Name: existingRoleAssignmentName, 89 }, 90 }}, 91 expectedSystemAssignedIdentityRole: &infrav1.SystemAssignedIdentityRole{ 92 Name: existingRoleAssignmentName, 93 DefinitionID: fmt.Sprintf("/subscriptions/%s/providers/Microsoft.Authorization/roleDefinitions/%s", fakeSubscriptionID, infrav1.ContributorRoleID), 94 Scope: fmt.Sprintf("/subscriptions/%s/", fakeSubscriptionID), 95 }, 96 }, 97 { 98 name: "notSystemAssigned", 99 machinePool: &AzureMachinePool{Spec: AzureMachinePoolSpec{ 100 Identity: infrav1.VMIdentityUserAssigned, 101 }}, 102 expectedSystemAssignedIdentityRole: nil, 103 }, 104 { 105 name: "systemAssignedIdentityRoleExist", 106 machinePool: &AzureMachinePool{Spec: AzureMachinePoolSpec{ 107 Identity: infrav1.VMIdentitySystemAssigned, 108 SystemAssignedIdentityRole: &infrav1.SystemAssignedIdentityRole{ 109 Name: existingRoleAssignmentName, 110 DefinitionID: fakeRoleDefinitionID, 111 Scope: fakeScope, 112 }, 113 }}, 114 expectedSystemAssignedIdentityRole: &infrav1.SystemAssignedIdentityRole{ 115 Name: existingRoleAssignmentName, 116 DefinitionID: fakeRoleDefinitionID, 117 Scope: fakeScope, 118 }, 119 }, 120 { 121 name: "deprecatedRoleAssignmentName", 122 machinePool: &AzureMachinePool{Spec: AzureMachinePoolSpec{ 123 Identity: infrav1.VMIdentitySystemAssigned, 124 RoleAssignmentName: existingRoleAssignmentName, 125 }}, 126 expectedSystemAssignedIdentityRole: &infrav1.SystemAssignedIdentityRole{ 127 Name: existingRoleAssignmentName, 128 DefinitionID: fmt.Sprintf("/subscriptions/%s/providers/Microsoft.Authorization/roleDefinitions/%s", fakeSubscriptionID, infrav1.ContributorRoleID), 129 Scope: fmt.Sprintf("/subscriptions/%s/", fakeSubscriptionID), 130 }, 131 }, 132 } 133 134 for _, tc := range tests { 135 t.Run(tc.name, func(t *testing.T) { 136 g := NewWithT(t) 137 138 scheme := runtime.NewScheme() 139 _ = AddToScheme(scheme) 140 _ = infrav1.AddToScheme(scheme) 141 _ = clusterv1.AddToScheme(scheme) 142 _ = expv1.AddToScheme(scheme) 143 144 machinePool := &expv1.MachinePool{ 145 ObjectMeta: metav1.ObjectMeta{ 146 Name: "pool1", 147 Namespace: "default", 148 Labels: map[string]string{ 149 clusterv1.ClusterNameLabel: "testcluster", 150 }, 151 }, 152 Spec: expv1.MachinePoolSpec{ 153 ClusterName: "testcluster", 154 }, 155 } 156 azureCluster := &infrav1.AzureCluster{ 157 ObjectMeta: metav1.ObjectMeta{ 158 Name: "testcluster", 159 Namespace: "default", 160 }, 161 Spec: infrav1.AzureClusterSpec{ 162 AzureClusterClassSpec: infrav1.AzureClusterClassSpec{ 163 SubscriptionID: fakeSubscriptionID, 164 }, 165 }, 166 } 167 cluster := &clusterv1.Cluster{ 168 ObjectMeta: metav1.ObjectMeta{ 169 Name: "testcluster", 170 Namespace: "default", 171 }, 172 Spec: clusterv1.ClusterSpec{ 173 InfrastructureRef: &corev1.ObjectReference{ 174 Name: "testcluster", 175 Namespace: "default", 176 }, 177 }, 178 } 179 180 fakeClient := fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(tc.machinePool, machinePool, azureCluster, cluster).Build() 181 err := tc.machinePool.SetIdentityDefaults(fakeClient) 182 if tc.wantErr { 183 g.Expect(err).To(HaveOccurred()) 184 } else { 185 g.Expect(err).NotTo(HaveOccurred()) 186 g.Expect(tc.machinePool.Spec.RoleAssignmentName).To(Equal(tc.expectedRoleAssignmentName)) 187 g.Expect(tc.machinePool.Spec.SystemAssignedIdentityRole).To(Equal(tc.expectedSystemAssignedIdentityRole)) 188 } 189 }) 190 } 191 } 192 193 func TestAzureMachinePool_SetDiagnosticsDefaults(t *testing.T) { 194 g := NewWithT(t) 195 196 type test struct { 197 machinePool *AzureMachinePool 198 } 199 200 bootDiagnosticsDefault := &infrav1.BootDiagnostics{ 201 StorageAccountType: infrav1.ManagedDiagnosticsStorage, 202 } 203 204 managedStorageDiagnostics := test{machinePool: &AzureMachinePool{ 205 Spec: AzureMachinePoolSpec{ 206 Template: AzureMachinePoolMachineTemplate{ 207 Diagnostics: &infrav1.Diagnostics{ 208 Boot: &infrav1.BootDiagnostics{ 209 StorageAccountType: infrav1.ManagedDiagnosticsStorage, 210 }, 211 }, 212 }, 213 }, 214 }} 215 216 disabledStorageDiagnostics := test{machinePool: &AzureMachinePool{ 217 Spec: AzureMachinePoolSpec{ 218 Template: AzureMachinePoolMachineTemplate{ 219 Diagnostics: &infrav1.Diagnostics{ 220 Boot: &infrav1.BootDiagnostics{ 221 StorageAccountType: infrav1.DisabledDiagnosticsStorage, 222 }, 223 }, 224 }, 225 }, 226 }} 227 228 userManagedDiagnostics := test{machinePool: &AzureMachinePool{ 229 Spec: AzureMachinePoolSpec{ 230 Template: AzureMachinePoolMachineTemplate{ 231 Diagnostics: &infrav1.Diagnostics{ 232 Boot: &infrav1.BootDiagnostics{ 233 StorageAccountType: infrav1.UserManagedDiagnosticsStorage, 234 UserManaged: &infrav1.UserManagedBootDiagnostics{ 235 StorageAccountURI: "https://fakeurl", 236 }, 237 }, 238 }, 239 }, 240 }, 241 }} 242 243 nilDiagnostics := test{machinePool: &AzureMachinePool{ 244 Spec: AzureMachinePoolSpec{ 245 Template: AzureMachinePoolMachineTemplate{ 246 Diagnostics: nil, 247 }, 248 }, 249 }} 250 251 // Test that when no diagnostics are specified, the defaults are set correctly 252 nilBootDiagnostics := test{machinePool: &AzureMachinePool{ 253 Spec: AzureMachinePoolSpec{ 254 Template: AzureMachinePoolMachineTemplate{ 255 Diagnostics: &infrav1.Diagnostics{}, 256 }, 257 }, 258 }} 259 260 nilBootDiagnostics.machinePool.SetDiagnosticsDefaults() 261 g.Expect(nilBootDiagnostics.machinePool.Spec.Template.Diagnostics.Boot).To(Equal(bootDiagnosticsDefault)) 262 263 managedStorageDiagnostics.machinePool.SetDiagnosticsDefaults() 264 g.Expect(managedStorageDiagnostics.machinePool.Spec.Template.Diagnostics.Boot.StorageAccountType).To(Equal(infrav1.ManagedDiagnosticsStorage)) 265 266 disabledStorageDiagnostics.machinePool.SetDiagnosticsDefaults() 267 g.Expect(disabledStorageDiagnostics.machinePool.Spec.Template.Diagnostics.Boot.StorageAccountType).To(Equal(infrav1.DisabledDiagnosticsStorage)) 268 269 userManagedDiagnostics.machinePool.SetDiagnosticsDefaults() 270 g.Expect(userManagedDiagnostics.machinePool.Spec.Template.Diagnostics.Boot.StorageAccountType).To(Equal(infrav1.UserManagedDiagnosticsStorage)) 271 272 nilDiagnostics.machinePool.SetDiagnosticsDefaults() 273 g.Expect(nilDiagnostics.machinePool.Spec.Template.Diagnostics.Boot.StorageAccountType).To(Equal(infrav1.ManagedDiagnosticsStorage)) 274 } 275 276 func TestAzureMachinePool_SetSpotEvictionPolicyDefaults(t *testing.T) { 277 g := NewWithT(t) 278 279 type test struct { 280 machinePool *AzureMachinePool 281 } 282 283 // test to Ensure the default policy is set to Deallocate if EvictionPolicy is nil 284 defaultEvictionPolicy := infrav1.SpotEvictionPolicyDeallocate 285 nilDiffDiskSettingsPolicy := test{machinePool: &AzureMachinePool{ 286 Spec: AzureMachinePoolSpec{ 287 Template: AzureMachinePoolMachineTemplate{ 288 SpotVMOptions: &infrav1.SpotVMOptions{ 289 EvictionPolicy: nil, 290 }, 291 }, 292 }, 293 }} 294 nilDiffDiskSettingsPolicy.machinePool.SetSpotEvictionPolicyDefaults() 295 g.Expect(nilDiffDiskSettingsPolicy.machinePool.Spec.Template.SpotVMOptions.EvictionPolicy).To(Equal(&defaultEvictionPolicy)) 296 297 // test to Ensure the default policy is set to Delete if diffDiskSettings option is set to "Local" 298 expectedEvictionPolicy := infrav1.SpotEvictionPolicyDelete 299 diffDiskSettingsPolicy := test{machinePool: &AzureMachinePool{ 300 Spec: AzureMachinePoolSpec{ 301 Template: AzureMachinePoolMachineTemplate{ 302 SpotVMOptions: &infrav1.SpotVMOptions{}, 303 OSDisk: infrav1.OSDisk{ 304 DiffDiskSettings: &infrav1.DiffDiskSettings{ 305 Option: "Local", 306 }, 307 }, 308 }, 309 }, 310 }} 311 diffDiskSettingsPolicy.machinePool.SetSpotEvictionPolicyDefaults() 312 g.Expect(diffDiskSettingsPolicy.machinePool.Spec.Template.SpotVMOptions.EvictionPolicy).To(Equal(&expectedEvictionPolicy)) 313 } 314 315 func TestAzureMachinePool_SetNetworkInterfacesDefaults(t *testing.T) { 316 testCases := []struct { 317 name string 318 machinePool *AzureMachinePool 319 want *AzureMachinePool 320 }{ 321 { 322 name: "defaulting webhook updates MachinePool with deprecated subnetName field", 323 machinePool: &AzureMachinePool{ 324 Spec: AzureMachinePoolSpec{ 325 Template: AzureMachinePoolMachineTemplate{ 326 SubnetName: "test-subnet", 327 }, 328 }, 329 }, 330 want: &AzureMachinePool{ 331 Spec: AzureMachinePoolSpec{ 332 Template: AzureMachinePoolMachineTemplate{ 333 SubnetName: "", 334 NetworkInterfaces: []infrav1.NetworkInterface{ 335 { 336 SubnetName: "test-subnet", 337 PrivateIPConfigs: 1, 338 }, 339 }, 340 }, 341 }, 342 }, 343 }, 344 { 345 name: "defaulting webhook updates MachinePool with deprecated acceleratedNetworking field", 346 machinePool: &AzureMachinePool{ 347 Spec: AzureMachinePoolSpec{ 348 Template: AzureMachinePoolMachineTemplate{ 349 SubnetName: "test-subnet", 350 AcceleratedNetworking: ptr.To(true), 351 }, 352 }, 353 }, 354 want: &AzureMachinePool{ 355 Spec: AzureMachinePoolSpec{ 356 Template: AzureMachinePoolMachineTemplate{ 357 SubnetName: "", 358 AcceleratedNetworking: nil, 359 NetworkInterfaces: []infrav1.NetworkInterface{ 360 { 361 SubnetName: "test-subnet", 362 PrivateIPConfigs: 1, 363 AcceleratedNetworking: ptr.To(true), 364 }, 365 }, 366 }, 367 }, 368 }, 369 }, 370 { 371 name: "defaulting webhook does nothing if both new and deprecated subnetName fields are set", 372 machinePool: &AzureMachinePool{ 373 Spec: AzureMachinePoolSpec{ 374 Template: AzureMachinePoolMachineTemplate{ 375 SubnetName: "test-subnet", 376 NetworkInterfaces: []infrav1.NetworkInterface{{ 377 SubnetName: "test-subnet", 378 }}, 379 }, 380 }, 381 }, 382 want: &AzureMachinePool{ 383 Spec: AzureMachinePoolSpec{ 384 Template: AzureMachinePoolMachineTemplate{ 385 SubnetName: "test-subnet", 386 AcceleratedNetworking: nil, 387 NetworkInterfaces: []infrav1.NetworkInterface{ 388 { 389 SubnetName: "test-subnet", 390 }, 391 }, 392 }, 393 }, 394 }, 395 }, 396 } 397 398 for _, tc := range testCases { 399 t.Run(tc.name, func(t *testing.T) { 400 g := NewWithT(t) 401 tc.machinePool.SetNetworkInterfacesDefaults() 402 g.Expect(tc.machinePool).To(Equal(tc.want)) 403 }) 404 } 405 } 406 407 func createMachinePoolWithSSHPublicKey(sshPublicKey string) *AzureMachinePool { 408 return hardcodedAzureMachinePoolWithSSHKey(sshPublicKey) 409 } 410 411 func hardcodedAzureMachinePoolWithSSHKey(sshPublicKey string) *AzureMachinePool { 412 return &AzureMachinePool{ 413 Spec: AzureMachinePoolSpec{ 414 Template: AzureMachinePoolMachineTemplate{ 415 SSHPublicKey: sshPublicKey, 416 }, 417 }, 418 ObjectMeta: metav1.ObjectMeta{ 419 Name: "testmachinepool", 420 }, 421 } 422 }