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  }