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