pkg/engine/virtualmachines.go (536 lines of code) (raw):

// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. package engine import ( "encoding/json" "fmt" "strconv" "strings" "github.com/Azure/aks-engine-azurestack/pkg/api" "github.com/Azure/aks-engine-azurestack/pkg/helpers/to" "github.com/Azure/azure-sdk-for-go/profiles/2020-09-01/compute" ) func CreateMasterVM(cs *api.ContainerService) VirtualMachineARM { hasAvailabilityZones := cs.Properties.MasterProfile.HasAvailabilityZones() isStorageAccount := cs.Properties.MasterProfile.IsStorageAccount() kubernetesConfig := cs.Properties.OrchestratorProfile.KubernetesConfig var useManagedIdentity, userAssignedIDEnabled bool if kubernetesConfig != nil { useManagedIdentity = to.Bool(kubernetesConfig.UseManagedIdentity) userAssignedIDEnabled = kubernetesConfig.UserAssignedIDEnabled() } var dependencies []string dependentNIC := "[concat('Microsoft.Network/networkInterfaces/', variables('masterVMNamePrefix'), 'nic-', copyIndex(variables('masterOffset')))]" dependencies = append(dependencies, dependentNIC) if !hasAvailabilityZones { dependencies = append(dependencies, "[concat('Microsoft.Compute/availabilitySets/',variables('masterAvailabilitySet'))]") } if isStorageAccount { dependencies = append(dependencies, "[variables('masterStorageAccountName')]") } armResource := ARMResource{ APIVersion: "[variables('apiVersionCompute')]", Copy: map[string]string{ "count": "[sub(variables('masterCount'), variables('masterOffset'))]", "name": "vmLoopNode", }, DependsOn: dependencies, } vmTags := map[string]*string{ "creationSource": to.StringPtr("[concat(parameters('generatorCode'), '-', variables('masterVMNamePrefix'), copyIndex(variables('masterOffset')))]"), "resourceNameSuffix": to.StringPtr("[parameters('nameSuffix')]"), "orchestrator": to.StringPtr("[variables('orchestratorNameVersionTag')]"), "aksEngineVersion": to.StringPtr("[parameters('aksEngineVersion')]"), "poolName": to.StringPtr("master"), } virtualMachine := compute.VirtualMachine{ Location: to.StringPtr("[variables('location')]"), Name: to.StringPtr("[concat(variables('masterVMNamePrefix'), copyIndex(variables('masterOffset')))]"), Tags: vmTags, Type: to.StringPtr("Microsoft.Compute/virtualMachines"), } addCustomTagsToVM(cs.Properties.MasterProfile.CustomVMTags, &virtualMachine) if hasAvailabilityZones { virtualMachine.Zones = &[]string{ "[string(parameters('availabilityZones')[mod(copyIndex(variables('masterOffset')), length(parameters('availabilityZones')))])]", } } if useManagedIdentity { identity := &compute.VirtualMachineIdentity{} if userAssignedIDEnabled { identity.Type = compute.ResourceIdentityTypeUserAssigned identity.UserAssignedIdentities = map[string]*compute.VirtualMachineIdentityUserAssignedIdentitiesValue{ "[variables('userAssignedIDReference')]": {}, } } else { identity.Type = compute.ResourceIdentityTypeSystemAssigned } virtualMachine.Identity = identity } vmProperties := &compute.VirtualMachineProperties{} if !hasAvailabilityZones { vmProperties.AvailabilitySet = &compute.SubResource{ ID: to.StringPtr("[resourceId('Microsoft.Compute/availabilitySets',variables('masterAvailabilitySet'))]"), } } vmProperties.HardwareProfile = &compute.HardwareProfile{ VMSize: compute.VirtualMachineSizeTypes(cs.Properties.MasterProfile.VMSize), } vmProperties.NetworkProfile = &compute.NetworkProfile{ NetworkInterfaces: &[]compute.NetworkInterfaceReference{ { ID: to.StringPtr("[resourceId('Microsoft.Network/networkInterfaces',concat(variables('masterVMNamePrefix'),'nic-', copyIndex(variables('masterOffset'))))]"), }, }, } osProfile := &compute.OSProfile{ AdminUsername: to.StringPtr("[parameters('linuxAdminUsername')]"), ComputerName: to.StringPtr("[concat(variables('masterVMNamePrefix'), copyIndex(variables('masterOffset')))]"), LinuxConfiguration: &compute.LinuxConfiguration{ DisablePasswordAuthentication: to.BoolPtr(true), }, } linuxProfile := cs.Properties.LinuxProfile if linuxProfile != nil && len(linuxProfile.SSH.PublicKeys) > 1 { publicKeyPath := "[variables('sshKeyPath')]" var publicKeys []compute.SSHPublicKey for _, publicKey := range linuxProfile.SSH.PublicKeys { publicKeyTrimmed := strings.TrimSpace(publicKey.KeyData) publicKeys = append(publicKeys, compute.SSHPublicKey{ Path: &publicKeyPath, KeyData: &publicKeyTrimmed, }) } osProfile.LinuxConfiguration.SSH = &compute.SSHConfiguration{ PublicKeys: &publicKeys, } } else { osProfile.LinuxConfiguration.SSH = &compute.SSHConfiguration{ PublicKeys: &[]compute.SSHPublicKey{ { KeyData: to.StringPtr("[parameters('sshRSAPublicKey')]"), Path: to.StringPtr("[variables('sshKeyPath')]"), }, }, } } t, err := InitializeTemplateGenerator(Context{}) customDataStr := getCustomDataFromJSON(t.GetMasterCustomDataJSONObject(cs)) osProfile.CustomData = to.StringPtr(customDataStr) if err != nil { panic(err) } if linuxProfile != nil && linuxProfile.HasSecrets() { vsg := getVaultSecretGroup(linuxProfile) osProfile.Secrets = &vsg } vmProperties.OsProfile = osProfile storageProfile := &compute.StorageProfile{} imageRef := cs.Properties.MasterProfile.ImageRef etcdSizeGB, _ := strconv.ParseInt(kubernetesConfig.EtcdDiskSizeGB, 10, 32) if !cs.Properties.MasterProfile.HasCosmosEtcd() { dataDisk := compute.DataDisk{ CreateOption: compute.DiskCreateOptionTypesEmpty, DiskSizeGB: to.Int32Ptr(int32(etcdSizeGB)), Lun: to.Int32Ptr(0), Name: to.StringPtr("[concat(variables('masterVMNamePrefix'), copyIndex(variables('masterOffset')),'-etcddisk')]"), } if cs.Properties.MasterProfile.IsStorageAccount() { dataDisk.Vhd = &compute.VirtualHardDisk{ URI: to.StringPtr("[concat(reference(concat('Microsoft.Storage/storageAccounts/',variables('masterStorageAccountName')),variables('apiVersionStorage')).primaryEndpoints.blob,'vhds/', variables('masterVMNamePrefix'),copyIndex(variables('masterOffset')),'-etcddisk.vhd')]"), } } storageProfile.DataDisks = &[]compute.DataDisk{ dataDisk, } } imgReference := &compute.ImageReference{} if cs.Properties.MasterProfile.HasImageRef() { if cs.Properties.MasterProfile.HasImageGallery() { imgReference.ID = to.StringPtr(fmt.Sprintf("[concat('/subscriptions/', '%s', '/resourceGroups/', parameters('osImageResourceGroup'), '/providers/Microsoft.Compute/galleries/', '%s', '/images/', parameters('osImageName'), '/versions/', '%s')]", imageRef.SubscriptionID, imageRef.Gallery, imageRef.Version)) } else { imgReference.ID = to.StringPtr("[resourceId(parameters('osImageResourceGroup'), 'Microsoft.Compute/images', parameters('osImageName'))]") } } else { imgReference.Offer = to.StringPtr("[parameters('osImageOffer')]") imgReference.Publisher = to.StringPtr("[parameters('osImagePublisher')]") imgReference.Sku = to.StringPtr("[parameters('osImageSku')]") imgReference.Version = to.StringPtr("[parameters('osImageVersion')]") } osDisk := &compute.OSDisk{ Caching: compute.CachingTypes(cs.Properties.MasterProfile.OSDiskCachingType), CreateOption: compute.DiskCreateOptionTypesFromImage, } if isStorageAccount { osDisk.Name = to.StringPtr("[concat(variables('masterVMNamePrefix'), copyIndex(variables('masterOffset')),'-osdisk')]") osDisk.Vhd = &compute.VirtualHardDisk{ URI: to.StringPtr("[concat(reference(concat('Microsoft.Storage/storageAccounts/',variables('masterStorageAccountName')),variables('apiVersionStorage')).primaryEndpoints.blob,'vhds/',variables('masterVMNamePrefix'),copyIndex(variables('masterOffset')),'-osdisk.vhd')]"), } } if cs.Properties.MasterProfile.OSDiskSizeGB > 0 { osDisk.DiskSizeGB = to.Int32Ptr(int32(cs.Properties.MasterProfile.OSDiskSizeGB)) } if to.Bool(cs.Properties.MasterProfile.UltraSSDEnabled) { vmProperties.AdditionalCapabilities = &compute.AdditionalCapabilities{ UltraSSDEnabled: to.BoolPtr(true), } } storageProfile.OsDisk = osDisk storageProfile.ImageReference = imgReference vmProperties.StorageProfile = storageProfile virtualMachine.VirtualMachineProperties = vmProperties return VirtualMachineARM{ ARMResource: armResource, VirtualMachine: virtualMachine, } } func createJumpboxVirtualMachine(cs *api.ContainerService) VirtualMachineARM { armResource := ARMResource{ APIVersion: "[variables('apiVersionCompute')]", DependsOn: []string{ "[concat('Microsoft.Network/networkInterfaces/', variables('jumpboxNetworkInterfaceName'))]", }, } kubernetesConfig := cs.Properties.OrchestratorProfile.KubernetesConfig vm := compute.VirtualMachine{ Location: to.StringPtr("[variables('location')]"), Name: to.StringPtr("[parameters('jumpboxVMName')]"), Type: to.StringPtr("Microsoft.Compute/virtualMachines"), } storageProfile := compute.StorageProfile{ ImageReference: &compute.ImageReference{ Publisher: to.StringPtr("Canonical"), Offer: to.StringPtr("UbuntuServer"), Sku: to.StringPtr("16.04-LTS"), Version: to.StringPtr("latest"), }, DataDisks: &[]compute.DataDisk{}, } var jumpBoxIsManagedDisks bool if kubernetesConfig != nil && kubernetesConfig.PrivateCluster != nil { jumpBoxIsManagedDisks = kubernetesConfig.PrivateJumpboxProvision() && kubernetesConfig.PrivateCluster.JumpboxProfile.StorageProfile == api.ManagedDisks } if jumpBoxIsManagedDisks { storageProfile.OsDisk = &compute.OSDisk{ CreateOption: compute.DiskCreateOptionTypesFromImage, DiskSizeGB: to.Int32Ptr(int32(kubernetesConfig.PrivateCluster.JumpboxProfile.OSDiskSizeGB)), ManagedDisk: &compute.ManagedDiskParameters{ StorageAccountType: "[variables('vmSizesMap')[parameters('jumpboxVMSize')].storageAccountType]", }, } } else { storageProfile.OsDisk = &compute.OSDisk{ CreateOption: compute.DiskCreateOptionTypesFromImage, Vhd: &compute.VirtualHardDisk{ URI: to.StringPtr("[concat(reference(concat('Microsoft.Storage/storageAccounts/',variables('jumpboxStorageAccountName')),variables('apiVersionStorage')).primaryEndpoints.blob,'vhds/',parameters('jumpboxVMName'),'jumpboxdisk.vhd')]"), }, Name: to.StringPtr("[variables('jumpboxOSDiskName')]"), } } t, err := InitializeTemplateGenerator(Context{}) if err != nil { panic(err) } customDataStr := getCustomDataFromJSON(t.GetJumpboxCustomDataJSON(cs)) vmProperties := compute.VirtualMachineProperties{ HardwareProfile: &compute.HardwareProfile{ VMSize: "[parameters('jumpboxVMSize')]", }, OsProfile: &compute.OSProfile{ ComputerName: to.StringPtr("[parameters('jumpboxVMName')]"), AdminUsername: to.StringPtr("[parameters('jumpboxUsername')]"), LinuxConfiguration: &compute.LinuxConfiguration{ DisablePasswordAuthentication: to.BoolPtr(true), SSH: &compute.SSHConfiguration{ PublicKeys: &[]compute.SSHPublicKey{ { Path: to.StringPtr("[concat('/home/', parameters('jumpboxUsername'), '/.ssh/authorized_keys')]"), KeyData: to.StringPtr("[parameters('jumpboxPublicKey')]"), }, }, }, }, CustomData: to.StringPtr(customDataStr), }, NetworkProfile: &compute.NetworkProfile{ NetworkInterfaces: &[]compute.NetworkInterfaceReference{ { ID: to.StringPtr("[resourceId('Microsoft.Network/networkInterfaces', variables('jumpboxNetworkInterfaceName'))]"), }, }, }, StorageProfile: &storageProfile, } vm.VirtualMachineProperties = &vmProperties return VirtualMachineARM{ ARMResource: armResource, VirtualMachine: vm, } } func createAgentAvailabilitySetVM(cs *api.ContainerService, profile *api.AgentPoolProfile) VirtualMachineARM { var dependencies []string isStorageAccount := profile.IsStorageAccount() hasDisks := profile.HasDisks() kubernetesConfig := cs.Properties.OrchestratorProfile.KubernetesConfig var useManagedIdentity, userAssignedIDEnabled bool if kubernetesConfig != nil { useManagedIdentity = to.Bool(kubernetesConfig.UseManagedIdentity) userAssignedIDEnabled = kubernetesConfig.UserAssignedIDEnabled() } if isStorageAccount { storageDep := fmt.Sprintf("[concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(div(copyIndex(variables('%[1]sOffset')),variables('maxVMsPerStorageAccount')),variables('%[1]sStorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(div(copyIndex(variables('%[1]sOffset')),variables('maxVMsPerStorageAccount')),variables('%[1]sStorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('%[1]sAccountName'))]", profile.Name) dependencies = append(dependencies, storageDep) if hasDisks { dataDiskDep := fmt.Sprintf("[concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(add(div(copyIndex(variables('%[1]sOffset')),variables('maxVMsPerStorageAccount')),variables('%[1]sStorageAccountOffset')),variables('dataStorageAccountPrefixSeed')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(add(div(copyIndex(variables('%[1]sOffset')),variables('maxVMsPerStorageAccount')),variables('%[1]sStorageAccountOffset')),variables('dataStorageAccountPrefixSeed')),variables('storageAccountPrefixesCount'))],variables('%[1]sDataAccountName'))]", profile.Name) dependencies = append(dependencies, dataDiskDep) } } dependencies = append(dependencies, fmt.Sprintf("[concat('Microsoft.Network/networkInterfaces/', variables('%[1]sVMNamePrefix'), 'nic-', copyIndex(variables('%[1]sOffset')))]", profile.Name)) dependencies = append(dependencies, fmt.Sprintf("[concat('Microsoft.Compute/availabilitySets/', variables('%[1]sAvailabilitySet'))]", profile.Name)) if profile.IsWindows() { windowsProfile := cs.Properties.WindowsProfile // Add dependency for Image resource created by createWindowsImage() if windowsProfile.HasCustomImage() { dependencies = append(dependencies, fmt.Sprintf("%sCustomWindowsImage", profile.Name)) } } tags := map[string]*string{ "creationSource": to.StringPtr(fmt.Sprintf("[concat(parameters('generatorCode'), '-', variables('%[1]sVMNamePrefix'), copyIndex(variables('%[1]sOffset')))]", profile.Name)), "orchestrator": to.StringPtr("[variables('orchestratorNameVersionTag')]"), "aksEngineVersion": to.StringPtr("[parameters('aksEngineVersion')]"), "poolName": to.StringPtr(profile.Name), } if profile.IsWindows() { tags["resourceNameSuffix"] = to.StringPtr("[variables('winResourceNamePrefix')]") } else { tags["resourceNameSuffix"] = to.StringPtr("[parameters('nameSuffix')]") } armResource := ARMResource{ APIVersion: "[variables('apiVersionCompute')]", DependsOn: dependencies, Copy: map[string]string{ "count": fmt.Sprintf("[sub(variables('%[1]sCount'), variables('%[1]sOffset'))]", profile.Name), "name": "vmLoopNode", }, } virtualMachine := compute.VirtualMachine{ Location: to.StringPtr("[variables('location')]"), Name: to.StringPtr(fmt.Sprintf("[concat(variables('%[1]sVMNamePrefix'), copyIndex(variables('%[1]sOffset')))]", profile.Name)), Type: to.StringPtr("Microsoft.Compute/virtualMachines"), VirtualMachineProperties: &compute.VirtualMachineProperties{ NetworkProfile: &compute.NetworkProfile{ NetworkInterfaces: &[]compute.NetworkInterfaceReference{ { ID: to.StringPtr(fmt.Sprintf("[resourceId('Microsoft.Network/networkInterfaces',concat(variables('%[1]sVMNamePrefix'), 'nic-', copyIndex(variables('%[1]sOffset'))))]", profile.Name)), }, }, }, }, Tags: tags, } if profile.IsFlatcar() { virtualMachine.Plan = &compute.Plan{ Publisher: to.StringPtr(fmt.Sprintf("[parameters('%sosImagePublisher')]", profile.Name)), Name: to.StringPtr(fmt.Sprintf("[parameters('%sosImageSKU')]", profile.Name)), Product: to.StringPtr(fmt.Sprintf("[parameters('%sosImageOffer')]", profile.Name)), } } addCustomTagsToVM(profile.CustomVMTags, &virtualMachine) if useManagedIdentity { if userAssignedIDEnabled && !profile.IsWindows() { virtualMachine.Identity = &compute.VirtualMachineIdentity{ Type: compute.ResourceIdentityTypeUserAssigned, UserAssignedIdentities: map[string]*compute.VirtualMachineIdentityUserAssignedIdentitiesValue{ "[variables('userAssignedIDReference')]": {}, }, } } else { virtualMachine.Identity = &compute.VirtualMachineIdentity{ Type: compute.ResourceIdentityTypeSystemAssigned, } } } virtualMachine.AvailabilitySet = &compute.SubResource{ ID: to.StringPtr(fmt.Sprintf("[resourceId('Microsoft.Compute/availabilitySets',variables('%sAvailabilitySet'))]", profile.Name)), } vmSize := fmt.Sprintf("[variables('%sVMSize')]", profile.Name) virtualMachine.HardwareProfile = &compute.HardwareProfile{ VMSize: compute.VirtualMachineSizeTypes(vmSize), } osProfile := compute.OSProfile{ ComputerName: to.StringPtr(fmt.Sprintf("[concat(variables('%[1]sVMNamePrefix'), copyIndex(variables('%[1]sOffset')))]", profile.Name)), } t, err := InitializeTemplateGenerator(Context{}) if !profile.IsWindows() { osProfile.AdminUsername = to.StringPtr("[parameters('linuxAdminUsername')]") osProfile.LinuxConfiguration = &compute.LinuxConfiguration{ DisablePasswordAuthentication: to.BoolPtr(true), } linuxProfile := cs.Properties.LinuxProfile if linuxProfile != nil && len(linuxProfile.SSH.PublicKeys) > 1 { publicKeyPath := "[variables('sshKeyPath')]" publicKeys := []compute.SSHPublicKey{} for _, publicKey := range linuxProfile.SSH.PublicKeys { publicKeyTrimmed := strings.TrimSpace(publicKey.KeyData) publicKeys = append(publicKeys, compute.SSHPublicKey{ Path: &publicKeyPath, KeyData: &publicKeyTrimmed, }) } osProfile.LinuxConfiguration.SSH = &compute.SSHConfiguration{ PublicKeys: &publicKeys, } } else { osProfile.LinuxConfiguration.SSH = &compute.SSHConfiguration{ PublicKeys: &[]compute.SSHPublicKey{ { KeyData: to.StringPtr("[parameters('sshRSAPublicKey')]"), Path: to.StringPtr("[variables('sshKeyPath')]"), }, }, } } if err != nil { panic(err) } agentCustomData := getCustomDataFromJSON(t.GetKubernetesLinuxNodeCustomDataJSONObject(cs, profile)) osProfile.CustomData = to.StringPtr(agentCustomData) if linuxProfile != nil && linuxProfile.HasSecrets() { vsg := getVaultSecretGroup(linuxProfile) osProfile.Secrets = &vsg } } else { osProfile.AdminUsername = to.StringPtr("[parameters('windowsAdminUsername')]") osProfile.AdminPassword = to.StringPtr("[parameters('windowsAdminPassword')]") osProfile.WindowsConfiguration = &compute.WindowsConfiguration{ EnableAutomaticUpdates: to.BoolPtr(cs.Properties.WindowsProfile.GetEnableWindowsUpdate()), } agentCustomData := getCustomDataFromJSON(t.GetKubernetesWindowsNodeCustomDataJSONObject(cs, profile)) osProfile.CustomData = to.StringPtr(agentCustomData) if cs.Properties.WindowsProfile.HasEnableAHUB() { licenseType := api.WindowsLicenseTypeNone if cs.Properties.WindowsProfile.GetEnableAHUB() { licenseType = api.WindowsLicenseTypeServer } virtualMachine.LicenseType = &licenseType } } virtualMachine.OsProfile = &osProfile storageProfile := compute.StorageProfile{} if profile.IsWindows() { storageProfile.ImageReference = createWindowsImageReference(profile.Name, cs.Properties.WindowsProfile) if profile.HasDisks() { storageProfile.DataDisks = getArmDataDisks(profile) } } else { imageRef := profile.ImageRef if profile.HasImageRef() { if profile.HasImageGallery() { storageProfile.ImageReference = &compute.ImageReference{ ID: to.StringPtr(fmt.Sprintf("[concat('/subscriptions/', '%s', '/resourceGroups/', parameters('%sosImageResourceGroup'), '/providers/Microsoft.Compute/galleries/', '%s', '/images/', parameters('%sosImageName'), '/versions/', '%s')]", imageRef.SubscriptionID, profile.Name, imageRef.Gallery, profile.Name, imageRef.Version)), } } else { storageProfile.ImageReference = &compute.ImageReference{ ID: to.StringPtr(fmt.Sprintf("[resourceId(variables('%[1]sosImageResourceGroup'), 'Microsoft.Compute/images', variables('%[1]sosImageName'))]", profile.Name)), } } } else { storageProfile.ImageReference = &compute.ImageReference{ Offer: to.StringPtr(fmt.Sprintf("[variables('%sosImageOffer')]", profile.Name)), Publisher: to.StringPtr(fmt.Sprintf("[variables('%sosImagePublisher')]", profile.Name)), Sku: to.StringPtr(fmt.Sprintf("[variables('%sosImageSKU')]", profile.Name)), Version: to.StringPtr(fmt.Sprintf("[variables('%sosImageVersion')]", profile.Name)), } storageProfile.DataDisks = getArmDataDisks(profile) } } osDisk := compute.OSDisk{ CreateOption: compute.DiskCreateOptionTypesFromImage, Caching: compute.CachingTypes(profile.OSDiskCachingType), } if profile.IsStorageAccount() { osDisk.Name = to.StringPtr(fmt.Sprintf("[concat(variables('%[1]sVMNamePrefix'), copyIndex(variables('%[1]sOffset')),'-osdisk')]", profile.Name)) osDisk.Vhd = &compute.VirtualHardDisk{ URI: to.StringPtr(fmt.Sprintf("[concat(reference(concat('Microsoft.Storage/storageAccounts/',variables('storageAccountPrefixes')[mod(add(div(copyIndex(variables('%[1]sOffset')),variables('maxVMsPerStorageAccount')),variables('%[1]sStorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(div(copyIndex(variables('%[1]sOffset')),variables('maxVMsPerStorageAccount')),variables('%[1]sStorageAccountOffset')),variables('storageAccountPrefixesCount'))],variables('%[1]sAccountName')),variables('apiVersionStorage')).primaryEndpoints.blob,'osdisk/', variables('%[1]sVMNamePrefix'), copyIndex(variables('%[1]sOffset')), '-osdisk.vhd')]", profile.Name)), } } if profile.IsEphemeral() { osDisk.DiffDiskSettings = &compute.DiffDiskSettings{ Option: compute.Local, } } if profile.OSDiskSizeGB > 0 { osDisk.DiskSizeGB = to.Int32Ptr(int32(profile.OSDiskSizeGB)) } if profile.DiskEncryptionSetID != "" { osDisk.ManagedDisk = &compute.ManagedDiskParameters{ DiskEncryptionSet: &compute.DiskEncryptionSetParameters{ID: to.StringPtr(profile.DiskEncryptionSetID)}, } } if to.Bool(profile.UltraSSDEnabled) { virtualMachine.AdditionalCapabilities = &compute.AdditionalCapabilities{ UltraSSDEnabled: to.BoolPtr(true), } } storageProfile.OsDisk = &osDisk virtualMachine.StorageProfile = &storageProfile return VirtualMachineARM{ ARMResource: armResource, VirtualMachine: virtualMachine, } } func getArmDataDisks(profile *api.AgentPoolProfile) *[]compute.DataDisk { var dataDisks []compute.DataDisk for i, diskSize := range profile.DiskSizesGB { dataDisk := compute.DataDisk{ DiskSizeGB: to.Int32Ptr(int32(diskSize)), Lun: to.Int32Ptr(int32(i)), CreateOption: compute.DiskCreateOptionTypesEmpty, Caching: compute.CachingTypes(profile.DataDiskCachingType), } if profile.StorageProfile == api.StorageAccount { dataDisk.Name = to.StringPtr(fmt.Sprintf("[concat(variables('%sVMNamePrefix'), copyIndex(),'-datadisk%d')]", profile.Name, i)) dataDisk.Vhd = &compute.VirtualHardDisk{ URI: to.StringPtr(fmt.Sprintf("[concat('http://',variables('storageAccountPrefixes')[mod(add(add(div(copyIndex(),variables('maxVMsPerStorageAccount')),variables('%sStorageAccountOffset')),variables('dataStorageAccountPrefixSeed')),variables('storageAccountPrefixesCount'))],variables('storageAccountPrefixes')[div(add(add(div(copyIndex(),variables('maxVMsPerStorageAccount')),variables('%sStorageAccountOffset')),variables('dataStorageAccountPrefixSeed')),variables('storageAccountPrefixesCount'))],variables('%sDataAccountName'),'.blob.core.windows.net/vhds/',variables('%sVMNamePrefix'),copyIndex(), '--datadisk%d.vhd')]", profile.Name, profile.Name, profile.Name, profile.Name, i)), } } dataDisks = append(dataDisks, dataDisk) } return &dataDisks } func getCustomDataFromJSON(jsonStr string) string { var customDataObj map[string]string err := json.Unmarshal([]byte(jsonStr), &customDataObj) if err != nil { panic(err) } return customDataObj["customData"] } func getVaultSecretGroup(linuxProfile *api.LinuxProfile) []compute.VaultSecretGroup { var vaultSecretGroups []compute.VaultSecretGroup if linuxProfile.HasSecrets() { for idx, lVault := range linuxProfile.Secrets { computeVault := compute.VaultSecretGroup{ SourceVault: &compute.SubResource{ ID: to.StringPtr(fmt.Sprintf("[parameters('linuxKeyVaultID%d')]", idx)), }, } var vaultCerts []compute.VaultCertificate for certIdx := range lVault.VaultCertificates { vaultCert := compute.VaultCertificate{ CertificateURL: to.StringPtr(fmt.Sprintf("[parameters('linuxKeyVaultID%dCertificateURL%d')]", idx, certIdx)), } vaultCerts = append(vaultCerts, vaultCert) } computeVault.VaultCertificates = &vaultCerts vaultSecretGroups = append(vaultSecretGroups, computeVault) } } return vaultSecretGroups } func addCustomTagsToVM(tags map[string]string, vm *compute.VirtualMachine) { for key, value := range tags { _, found := vm.Tags[key] if !found { vm.Tags[key] = to.StringPtr(value) } } }