sigs.k8s.io/cluster-api-provider-azure@v1.14.3/exp/api/v1beta1/azuremachinepool_default.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 "encoding/base64" 21 "fmt" 22 23 "github.com/pkg/errors" 24 "golang.org/x/crypto/ssh" 25 kerrors "k8s.io/apimachinery/pkg/util/errors" 26 "k8s.io/apimachinery/pkg/util/uuid" 27 infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1" 28 azureutil "sigs.k8s.io/cluster-api-provider-azure/util/azure" 29 utilSSH "sigs.k8s.io/cluster-api-provider-azure/util/ssh" 30 "sigs.k8s.io/controller-runtime/pkg/client" 31 ) 32 33 // SetDefaults sets the default values for an AzureMachinePool. 34 func (amp *AzureMachinePool) SetDefaults(client client.Client) error { 35 var errs []error 36 if err := amp.SetDefaultSSHPublicKey(); err != nil { 37 errs = append(errs, errors.Wrap(err, "failed to set default SSH public key")) 38 } 39 40 if err := amp.SetIdentityDefaults(client); err != nil { 41 errs = append(errs, errors.Wrap(err, "failed to set default managed identity defaults")) 42 } 43 amp.SetDiagnosticsDefaults() 44 amp.SetNetworkInterfacesDefaults() 45 46 return kerrors.NewAggregate(errs) 47 } 48 49 // SetDefaultSSHPublicKey sets the default SSHPublicKey for an AzureMachinePool. 50 func (amp *AzureMachinePool) SetDefaultSSHPublicKey() error { 51 if sshKeyData := amp.Spec.Template.SSHPublicKey; sshKeyData == "" { 52 _, publicRsaKey, err := utilSSH.GenerateSSHKey() 53 if err != nil { 54 return err 55 } 56 57 amp.Spec.Template.SSHPublicKey = base64.StdEncoding.EncodeToString(ssh.MarshalAuthorizedKey(publicRsaKey)) 58 } 59 return nil 60 } 61 62 // SetIdentityDefaults sets the defaults for VMSS Identity. 63 func (amp *AzureMachinePool) SetIdentityDefaults(client client.Client) error { 64 // Ensure the deprecated fields and new fields are not populated simultaneously 65 if amp.Spec.RoleAssignmentName != "" && amp.Spec.SystemAssignedIdentityRole != nil && amp.Spec.SystemAssignedIdentityRole.Name != "" { 66 // Both the deprecated and the new fields are both set, return without changes 67 // and reject the request in the validating webhook which runs later. 68 return nil 69 } 70 if amp.Spec.Identity == infrav1.VMIdentitySystemAssigned { 71 machinePool, err := azureutil.FindParentMachinePoolWithRetry(amp.Name, client, 5) 72 if err != nil { 73 return errors.Wrap(err, "failed to find parent machine pool") 74 } 75 76 ownerAzureClusterName, ownerAzureClusterNamespace, err := infrav1.GetOwnerAzureClusterNameAndNamespace(client, machinePool.Spec.ClusterName, machinePool.Namespace, 5) 77 if err != nil { 78 return errors.Wrap(err, "failed to get owner cluster") 79 } 80 81 subscriptionID, err := infrav1.GetSubscriptionID(client, ownerAzureClusterName, ownerAzureClusterNamespace, 5) 82 if err != nil { 83 return errors.Wrap(err, "failed to get subscription ID") 84 } 85 86 if amp.Spec.SystemAssignedIdentityRole == nil { 87 amp.Spec.SystemAssignedIdentityRole = &infrav1.SystemAssignedIdentityRole{} 88 } 89 if amp.Spec.RoleAssignmentName != "" { 90 amp.Spec.SystemAssignedIdentityRole.Name = amp.Spec.RoleAssignmentName 91 amp.Spec.RoleAssignmentName = "" 92 } else if amp.Spec.SystemAssignedIdentityRole.Name == "" { 93 amp.Spec.SystemAssignedIdentityRole.Name = string(uuid.NewUUID()) 94 } 95 if amp.Spec.SystemAssignedIdentityRole.Scope == "" { 96 // Default scope to the subscription. 97 amp.Spec.SystemAssignedIdentityRole.Scope = fmt.Sprintf("/subscriptions/%s/", subscriptionID) 98 } 99 if amp.Spec.SystemAssignedIdentityRole.DefinitionID == "" { 100 // Default role definition ID to Contributor role. 101 amp.Spec.SystemAssignedIdentityRole.DefinitionID = fmt.Sprintf("/subscriptions/%s/providers/Microsoft.Authorization/roleDefinitions/%s", subscriptionID, infrav1.ContributorRoleID) 102 } 103 } 104 return nil 105 } 106 107 // SetSpotEvictionPolicyDefaults sets the defaults for the spot VM eviction policy. 108 func (amp *AzureMachinePool) SetSpotEvictionPolicyDefaults() { 109 if amp.Spec.Template.SpotVMOptions != nil && amp.Spec.Template.SpotVMOptions.EvictionPolicy == nil { 110 defaultPolicy := infrav1.SpotEvictionPolicyDeallocate 111 if amp.Spec.Template.OSDisk.DiffDiskSettings != nil && amp.Spec.Template.OSDisk.DiffDiskSettings.Option == "Local" { 112 defaultPolicy = infrav1.SpotEvictionPolicyDelete 113 } 114 amp.Spec.Template.SpotVMOptions.EvictionPolicy = &defaultPolicy 115 } 116 } 117 118 // SetDiagnosticsDefaults sets the defaults for Diagnostic settings for an AzureMachinePool. 119 func (amp *AzureMachinePool) SetDiagnosticsDefaults() { 120 bootDefault := &infrav1.BootDiagnostics{ 121 StorageAccountType: infrav1.ManagedDiagnosticsStorage, 122 } 123 124 if amp.Spec.Template.Diagnostics == nil { 125 amp.Spec.Template.Diagnostics = &infrav1.Diagnostics{ 126 Boot: bootDefault, 127 } 128 } 129 130 if amp.Spec.Template.Diagnostics.Boot == nil { 131 amp.Spec.Template.Diagnostics.Boot = bootDefault 132 } 133 } 134 135 // SetNetworkInterfacesDefaults sets the defaults for the network interfaces. 136 func (amp *AzureMachinePool) SetNetworkInterfacesDefaults() { 137 // Ensure the deprecated fields and new fields are not populated simultaneously 138 if (amp.Spec.Template.SubnetName != "" || amp.Spec.Template.AcceleratedNetworking != nil) && len(amp.Spec.Template.NetworkInterfaces) > 0 { 139 // Both the deprecated and the new fields are both set, return without changes 140 // and reject the request in the validating webhook which runs later. 141 return 142 } 143 144 if len(amp.Spec.Template.NetworkInterfaces) == 0 { 145 amp.Spec.Template.NetworkInterfaces = []infrav1.NetworkInterface{ 146 { 147 SubnetName: amp.Spec.Template.SubnetName, 148 AcceleratedNetworking: amp.Spec.Template.AcceleratedNetworking, 149 }, 150 } 151 amp.Spec.Template.SubnetName = "" 152 amp.Spec.Template.AcceleratedNetworking = nil 153 } 154 155 // Ensure that PrivateIPConfigs defaults to 1 if not specified. 156 for i := 0; i < len(amp.Spec.Template.NetworkInterfaces); i++ { 157 if amp.Spec.Template.NetworkInterfaces[i].PrivateIPConfigs == 0 { 158 amp.Spec.Template.NetworkInterfaces[i].PrivateIPConfigs = 1 159 } 160 } 161 }