sigs.k8s.io/cluster-api-provider-azure@v1.17.0/azure/converters/vmss.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 converters 18 19 import ( 20 "regexp" 21 22 "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5" 23 "k8s.io/utils/ptr" 24 azprovider "sigs.k8s.io/cloud-provider-azure/pkg/provider" 25 infrav1 "sigs.k8s.io/cluster-api-provider-azure/api/v1beta1" 26 "sigs.k8s.io/cluster-api-provider-azure/azure" 27 ) 28 29 const ( 30 // RegExpStrCommunityGalleryID is a regexp string used for matching community gallery IDs and capturing specific values. 31 RegExpStrCommunityGalleryID = `/CommunityGalleries/(?P<gallery>.*)/Images/(?P<name>.*)/Versions/(?P<version>.*)` 32 // RegExpStrComputeGalleryID is a regexp string used for matching compute gallery IDs and capturing specific values. 33 RegExpStrComputeGalleryID = `/subscriptions/(?P<subID>.*)/resourceGroups/(?P<rg>.*)/providers/Microsoft.Compute/galleries/(?P<gallery>.*)/images/(?P<name>.*)/versions/(?P<version>.*)` 34 ) 35 36 // SDKToVMSS converts an Azure SDK VirtualMachineScaleSet to the AzureMachinePool type. 37 func SDKToVMSS(sdkvmss armcompute.VirtualMachineScaleSet, sdkinstances []armcompute.VirtualMachineScaleSetVM) azure.VMSS { 38 vmss := azure.VMSS{ 39 ID: ptr.Deref(sdkvmss.ID, ""), 40 Name: ptr.Deref(sdkvmss.Name, ""), 41 State: infrav1.ProvisioningState(ptr.Deref(sdkvmss.Properties.ProvisioningState, "")), 42 } 43 44 if sdkvmss.SKU != nil { 45 vmss.Sku = ptr.Deref(sdkvmss.SKU.Name, "") 46 vmss.Capacity = ptr.Deref[int64](sdkvmss.SKU.Capacity, 0) 47 } 48 49 for _, zone := range sdkvmss.Zones { 50 vmss.Zones = append(vmss.Zones, *zone) 51 } 52 53 if len(sdkvmss.Tags) > 0 { 54 vmss.Tags = MapToTags(sdkvmss.Tags) 55 } 56 57 if len(sdkinstances) > 0 { 58 vmss.Instances = make([]azure.VMSSVM, len(sdkinstances)) 59 orchestrationMode := ptr.Deref(sdkvmss.Properties.OrchestrationMode, "") 60 for i, vm := range sdkinstances { 61 vmss.Instances[i] = *SDKToVMSSVM(vm) 62 vmss.Instances[i].OrchestrationMode = infrav1.OrchestrationModeType(orchestrationMode) 63 } 64 } 65 66 if sdkvmss.Properties.VirtualMachineProfile != nil && 67 sdkvmss.Properties.VirtualMachineProfile.StorageProfile != nil && 68 sdkvmss.Properties.VirtualMachineProfile.StorageProfile.ImageReference != nil { 69 imageRef := sdkvmss.Properties.VirtualMachineProfile.StorageProfile.ImageReference 70 vmss.Image = SDKImageToImage(imageRef, sdkvmss.Plan != nil) 71 } 72 73 return vmss 74 } 75 76 // SDKVMToVMSSVM converts an Azure SDK VM to a VMSS VM. 77 func SDKVMToVMSSVM(sdkInstance armcompute.VirtualMachine, mode infrav1.OrchestrationModeType) *azure.VMSSVM { 78 instance := azure.VMSSVM{ 79 ID: ptr.Deref(sdkInstance.ID, ""), 80 } 81 82 if sdkInstance.Properties == nil { 83 return &instance 84 } 85 86 instance.State = infrav1.Creating 87 if sdkInstance.Properties.ProvisioningState != nil { 88 instance.State = infrav1.ProvisioningState(ptr.Deref(sdkInstance.Properties.ProvisioningState, "")) 89 } 90 91 if sdkInstance.Properties.OSProfile != nil && sdkInstance.Properties.OSProfile.ComputerName != nil { 92 instance.Name = *sdkInstance.Properties.OSProfile.ComputerName 93 } 94 95 if sdkInstance.Properties.StorageProfile != nil && sdkInstance.Properties.StorageProfile.ImageReference != nil { 96 imageRef := sdkInstance.Properties.StorageProfile.ImageReference 97 instance.Image = SDKImageToImage(imageRef, sdkInstance.Plan != nil) 98 } 99 100 if len(sdkInstance.Zones) > 0 { 101 // An instance should have only 1 zone, so use the first item of the slice. 102 instance.AvailabilityZone = *sdkInstance.Zones[0] 103 } 104 105 instance.OrchestrationMode = mode 106 107 return &instance 108 } 109 110 // SDKToVMSSVM converts an Azure SDK VirtualMachineScaleSetVM into an infrav1exp.VMSSVM. 111 func SDKToVMSSVM(sdkInstance armcompute.VirtualMachineScaleSetVM) *azure.VMSSVM { 112 // Convert resourceGroup Name ID ( ProviderID in capz objects ) 113 var convertedID string 114 convertedID, err := azprovider.ConvertResourceGroupNameToLower(ptr.Deref(sdkInstance.ID, "")) 115 if err != nil { 116 convertedID = ptr.Deref(sdkInstance.ID, "") 117 } 118 119 instance := azure.VMSSVM{ 120 ID: convertedID, 121 InstanceID: ptr.Deref(sdkInstance.InstanceID, ""), 122 } 123 124 if sdkInstance.Properties == nil { 125 return &instance 126 } 127 128 instance.State = infrav1.Creating 129 if sdkInstance.Properties.ProvisioningState != nil { 130 instance.State = infrav1.ProvisioningState(ptr.Deref(sdkInstance.Properties.ProvisioningState, "")) 131 } 132 133 if sdkInstance.Properties.OSProfile != nil && sdkInstance.Properties.OSProfile.ComputerName != nil { 134 instance.Name = *sdkInstance.Properties.OSProfile.ComputerName 135 } 136 137 if sdkInstance.Resources != nil { 138 for _, r := range sdkInstance.Resources { 139 if r.Properties.ProvisioningState != nil && r.Name != nil && 140 (*r.Name == azure.BootstrappingExtensionLinux || *r.Name == azure.BootstrappingExtensionWindows) { 141 instance.BootstrappingState = infrav1.ProvisioningState(ptr.Deref(r.Properties.ProvisioningState, "")) 142 break 143 } 144 } 145 } 146 147 if sdkInstance.Properties.StorageProfile != nil && sdkInstance.Properties.StorageProfile.ImageReference != nil { 148 imageRef := sdkInstance.Properties.StorageProfile.ImageReference 149 instance.Image = SDKImageToImage(imageRef, sdkInstance.Plan != nil) 150 } 151 152 if len(sdkInstance.Zones) > 0 { 153 // an instance should only have 1 zone, so we select the first item of the slice 154 instance.AvailabilityZone = *sdkInstance.Zones[0] 155 } 156 157 return &instance 158 } 159 160 // SDKImageToImage converts a SDK image reference to infrav1.Image. 161 func SDKImageToImage(sdkImageRef *armcompute.ImageReference, isThirdPartyImage bool) infrav1.Image { 162 if sdkImageRef.ID != nil { 163 return IDImageRefToImage(*sdkImageRef.ID) 164 } 165 // community gallery image 166 if sdkImageRef.CommunityGalleryImageID != nil { 167 return cgImageRefToImage(*sdkImageRef.CommunityGalleryImageID) 168 } 169 // shared gallery image 170 if sdkImageRef.SharedGalleryImageID != nil { 171 return sgImageRefToImage(*sdkImageRef.SharedGalleryImageID) 172 } 173 // marketplace image 174 return mpImageRefToImage(sdkImageRef, isThirdPartyImage) 175 } 176 177 // GetOrchestrationMode returns the compute.OrchestrationMode for the given infrav1.OrchestrationModeType. 178 func GetOrchestrationMode(modeType infrav1.OrchestrationModeType) armcompute.OrchestrationMode { 179 if modeType == infrav1.FlexibleOrchestrationMode { 180 return armcompute.OrchestrationModeFlexible 181 } 182 return armcompute.OrchestrationModeUniform 183 } 184 185 // IDImageRefToImage converts an ID to a infrav1.Image with ComputerGallery set or ID, depending on the structure of the ID. 186 func IDImageRefToImage(id string) infrav1.Image { 187 // compute gallery image 188 if ok, params := getParams(RegExpStrComputeGalleryID, id); ok { 189 return infrav1.Image{ 190 ComputeGallery: &infrav1.AzureComputeGalleryImage{ 191 Gallery: params["gallery"], 192 Name: params["name"], 193 Version: params["version"], 194 SubscriptionID: ptr.To(params["subID"]), 195 ResourceGroup: ptr.To(params["rg"]), 196 }, 197 } 198 } 199 200 // specific image 201 return infrav1.Image{ 202 ID: &id, 203 } 204 } 205 206 // mpImageRefToImage converts a marketplace gallery ImageReference to an infrav1.Image. 207 func mpImageRefToImage(sdkImageRef *armcompute.ImageReference, isThirdPartyImage bool) infrav1.Image { 208 return infrav1.Image{ 209 Marketplace: &infrav1.AzureMarketplaceImage{ 210 ImagePlan: infrav1.ImagePlan{ 211 Publisher: ptr.Deref(sdkImageRef.Publisher, ""), 212 Offer: ptr.Deref(sdkImageRef.Offer, ""), 213 SKU: ptr.Deref(sdkImageRef.SKU, ""), 214 }, 215 Version: ptr.Deref(sdkImageRef.Version, ""), 216 ThirdPartyImage: isThirdPartyImage, 217 }, 218 } 219 } 220 221 // cgImageRefToImage converts a community gallery ImageReference to an infrav1.Image. 222 func cgImageRefToImage(id string) infrav1.Image { 223 if ok, params := getParams(RegExpStrCommunityGalleryID, id); ok { 224 return infrav1.Image{ 225 ComputeGallery: &infrav1.AzureComputeGalleryImage{ 226 Gallery: params["gallery"], 227 Name: params["name"], 228 Version: params["version"], 229 }, 230 } 231 } 232 return infrav1.Image{} 233 } 234 235 // sgImageRefToImage converts a shared gallery ImageReference to an infrav1.Image. 236 func sgImageRefToImage(id string) infrav1.Image { 237 if ok, params := getParams(RegExpStrComputeGalleryID, id); ok { 238 return infrav1.Image{ 239 SharedGallery: &infrav1.AzureSharedGalleryImage{ 240 SubscriptionID: params["subID"], 241 ResourceGroup: params["rg"], 242 Gallery: params["gallery"], 243 Name: params["name"], 244 Version: params["version"], 245 }, 246 } 247 } 248 return infrav1.Image{} 249 } 250 251 func getParams(regStr, str string) (matched bool, params map[string]string) { 252 re := regexp.MustCompile(regStr) 253 match := re.FindAllStringSubmatch(str, -1) 254 255 if len(match) == 1 { 256 params = make(map[string]string) 257 for i, name := range re.SubexpNames() { 258 if i > 0 && i <= len(match[0]) { 259 params[name] = match[0][i] 260 } 261 } 262 matched = true 263 } 264 265 return matched, params 266 }