sigs.k8s.io/cluster-api-provider-azure@v1.14.3/azure/services/resourceskus/sku.go (about)

     1  /*
     2  Copyright 2020 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 resourceskus
    18  
    19  import (
    20  	"strconv"
    21  	"strings"
    22  
    23  	"github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5"
    24  	"github.com/pkg/errors"
    25  	"k8s.io/utils/ptr"
    26  )
    27  
    28  // SKU is a thin layer over the Azure resource SKU API to better introspect capabilities.
    29  type SKU armcompute.ResourceSKU
    30  
    31  // ResourceType models available resource types as a set of known string constants.
    32  type ResourceType string
    33  
    34  const (
    35  	// VirtualMachines is a convenience constant to filter resource SKUs to only include VMs.
    36  	VirtualMachines ResourceType = "virtualMachines"
    37  	// Disks is a convenience constant to filter resource SKUs to only include disks.
    38  	Disks ResourceType = "disks"
    39  	// AvailabilitySets is a convenience constant to filter resource SKUs to only include availability sets.
    40  	AvailabilitySets ResourceType = "availabilitySets"
    41  )
    42  
    43  // Supported models an enum of possible boolean values for resource support in the Azure API.
    44  type Supported string
    45  
    46  const (
    47  	// CapabilitySupported is the value returned by this API from Azure when the capability is supported.
    48  	CapabilitySupported Supported = "True"
    49  	// CapabilityUnsupported is the value returned by this API from Azure when the capability is unsupported.
    50  	CapabilityUnsupported Supported = "False"
    51  )
    52  
    53  const (
    54  	// EphemeralOSDisk identifies the capability for ephemeral os support.
    55  	EphemeralOSDisk = "EphemeralOSDiskSupported"
    56  	// AcceleratedNetworking identifies the capability for accelerated networking support.
    57  	AcceleratedNetworking = "AcceleratedNetworkingEnabled"
    58  	// VCPUs identifies the capability for the number of vCPUS.
    59  	VCPUs = "vCPUs"
    60  	// MemoryGB identifies the capability for memory Size.
    61  	MemoryGB = "MemoryGB"
    62  	// MinimumVCPUS is the minimum vCPUS allowed.
    63  	MinimumVCPUS = 2
    64  	// MinimumMemory is the minimum memory allowed.
    65  	MinimumMemory = 2
    66  	// EncryptionAtHost identifies the capability for encryption at host.
    67  	EncryptionAtHost = "EncryptionAtHostSupported"
    68  	// MaximumPlatformFaultDomainCount identifies the maximum fault domain count for an availability set in a region.
    69  	MaximumPlatformFaultDomainCount = "MaximumPlatformFaultDomainCount"
    70  	// UltraSSDAvailable identifies the capability for the support of UltraSSD data disks.
    71  	UltraSSDAvailable = "UltraSSDAvailable"
    72  	// TrustedLaunchDisabled identifies the absence of the trusted launch capability.
    73  	TrustedLaunchDisabled = "TrustedLaunchDisabled"
    74  	// ConfidentialComputingType identifies the capability for confidentical computing.
    75  	ConfidentialComputingType = "ConfidentialComputingType"
    76  	// CPUArchitectureType identifies the capability for cpu architecture.
    77  	CPUArchitectureType = "CpuArchitectureType"
    78  )
    79  
    80  // HasCapability return true for a capability which can be either
    81  // supported or not. Examples include "EphemeralOSDiskSupported",
    82  // "UltraSSDAvavailable" "EncryptionAtHostSupported",
    83  // "AcceleratedNetworkingEnabled", and "RdmaEnabled".
    84  func (s SKU) HasCapability(name string) bool {
    85  	if s.Capabilities != nil {
    86  		for _, capability := range s.Capabilities {
    87  			if capability.Name != nil && *capability.Name == name {
    88  				if capability.Value != nil && strings.EqualFold(*capability.Value, string(CapabilitySupported)) {
    89  					return true
    90  				}
    91  			}
    92  		}
    93  	}
    94  	return false
    95  }
    96  
    97  // HasCapabilityWithCapacity returns true when the provided resource
    98  // exposes a numeric capability and the maximum value exposed by that
    99  // capability exceeds the value requested by the user. Examples include
   100  // "MaxResourceVolumeMB", "OSVhdSizeMB", "vCPUs",
   101  // "MemoryGB","MaxDataDiskCount", "CombinedTempDiskAndCachedIOPS",
   102  // "CombinedTempDiskAndCachedReadBytesPerSecond",
   103  // "CombinedTempDiskAndCachedWriteBytesPerSecond", "UncachedDiskIOPS",
   104  // and "UncachedDiskBytesPerSecond".
   105  func (s SKU) HasCapabilityWithCapacity(name string, value int64) (bool, error) {
   106  	if s.Capabilities == nil {
   107  		return false, nil
   108  	}
   109  
   110  	for _, capability := range s.Capabilities {
   111  		if capability.Name == nil || *capability.Name != name || capability.Value == nil {
   112  			continue
   113  		}
   114  
   115  		intVal, err := strconv.ParseInt(*capability.Value, 10, 64)
   116  		if err != nil {
   117  			return false, errors.Wrapf(err, "failed to parse string '%s' as int64", *capability.Value)
   118  		}
   119  
   120  		if intVal >= value {
   121  			return true, nil
   122  		}
   123  	}
   124  
   125  	return false, nil
   126  }
   127  
   128  // GetCapability gets the value assigned to the given capability.
   129  // Eg. MaximumPlatformFaultDomainCount -> "3" will return "3" for the capability "MaximumPlatformFaultDomainCount".
   130  func (s SKU) GetCapability(name string) (string, bool) {
   131  	if s.Capabilities != nil {
   132  		for _, capability := range s.Capabilities {
   133  			if capability.Name != nil && *capability.Name == name {
   134  				return *capability.Value, true
   135  			}
   136  		}
   137  	}
   138  	return "", false
   139  }
   140  
   141  // HasLocationCapability returns true if the provided resource supports the location capability.
   142  func (s SKU) HasLocationCapability(capabilityName, location, zone string) bool {
   143  	if s.LocationInfo == nil {
   144  		return false
   145  	}
   146  
   147  	for _, info := range s.LocationInfo {
   148  		if info.Location == nil || *info.Location != location || info.ZoneDetails == nil {
   149  			continue
   150  		}
   151  
   152  		for _, zoneDetail := range info.ZoneDetails {
   153  			if zoneDetail.Capabilities == nil {
   154  				continue
   155  			}
   156  
   157  			for _, capability := range zoneDetail.Capabilities {
   158  				if capability.Name != nil && *capability.Name == capabilityName {
   159  					for _, name := range zoneDetail.Name {
   160  						if ptr.Deref(name, "") == zone {
   161  							return true
   162  						}
   163  					}
   164  
   165  					return false
   166  				}
   167  			}
   168  		}
   169  	}
   170  	return false
   171  }