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  }