From 514c56b9234d7cd9225bad1ac3f244ef235a1545 Mon Sep 17 00:00:00 2001 From: MrMCake Date: Sun, 30 Oct 2022 22:48:27 +0100 Subject: [PATCH 01/30] Added sorting --- .../privateClouds/clusters/deploy.bicep | 36 ++-- .../clusters/placementPolicies/deploy.bicep | 8 +- .../Microsoft.AVS/privateClouds/deploy.bicep | 184 +++++++++--------- .../scriptExecutions/deploy.bicep | 10 +- .../dhcpConfigurations/deploy.bicep | 2 +- .../workloadNetworks/dnsServices/deploy.bicep | 6 +- .../workloadNetworks/dnsZones/deploy.bicep | 6 +- .../portMirroringProfiles/deploy.bicep | 2 +- .../workloadNetworks/segments/deploy.bicep | 4 +- .../private/module/Set-ModuleTemplate.ps1 | 37 +++- 10 files changed, 156 insertions(+), 139 deletions(-) diff --git a/modules/Microsoft.AVS/privateClouds/clusters/deploy.bicep b/modules/Microsoft.AVS/privateClouds/clusters/deploy.bicep index bae652c848..9d61a96654 100644 --- a/modules/Microsoft.AVS/privateClouds/clusters/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/clusters/deploy.bicep @@ -55,36 +55,36 @@ resource cluster 'Microsoft.AVS/privateClouds/clusters@2022-05-01' = { name: name sku: sku properties: { - hosts: hosts clusterSize: clusterSize + hosts: hosts } } -module cluster_datastores 'datastores/deploy.bicep' = [for (datastore, index) in datastores: { -name: '${uniqueString(deployment().name)}-cluster-datastore-${index}' -params: { +module cluster_placementPolicies 'placementPolicies/deploy.bicep' = [for (placementPolicy, index) in placementPolicies: { + name: '${uniqueString(deployment().name)}-cluster-placementPolicy-${index}' + params: { privateCloudName: privateCloudName clusterName: name - name: datastore.name - diskPoolVolume: contains(datastore, 'diskPoolVolume') ? datastore.diskPoolVolume : {} - netAppVolume: contains(datastore, 'netAppVolume') ? datastore.netAppVolume : {} + affinityStrength: contains(placementPolicy, 'affinityStrength') ? placementPolicy.affinityStrength : '' + azureHybridBenefitType: contains(placementPolicy, 'azureHybridBenefitType') ? placementPolicy.azureHybridBenefitType : '' + displayName: contains(placementPolicy, 'displayName') ? placementPolicy.displayName : '' + hostMembers: contains(placementPolicy, 'hostMembers') ? placementPolicy.hostMembers : [] + name: placementPolicy.name + state: contains(placementPolicy, 'state') ? placementPolicy.state : '' + type: contains(placementPolicy, 'type') ? placementPolicy.type : '' + vmMembers: contains(placementPolicy, 'vmMembers') ? placementPolicy.vmMembers : [] enableDefaultTelemetry: enableReferencedModulesTelemetry } }] -module cluster_placementPolicies 'placementPolicies/deploy.bicep' = [for (placementPolicy, index) in placementPolicies: { -name: '${uniqueString(deployment().name)}-cluster-placementPolicy-${index}' -params: { +module cluster_datastores 'datastores/deploy.bicep' = [for (datastore, index) in datastores: { + name: '${uniqueString(deployment().name)}-cluster-datastore-${index}' + params: { privateCloudName: privateCloudName clusterName: name - name: placementPolicy.name - state: contains(placementPolicy, 'state') ? placementPolicy.state : '' - type: contains(placementPolicy, 'type') ? placementPolicy.type : '' - displayName: contains(placementPolicy, 'displayName') ? placementPolicy.displayName : '' - affinityStrength: contains(placementPolicy, 'affinityStrength') ? placementPolicy.affinityStrength : '' - azureHybridBenefitType: contains(placementPolicy, 'azureHybridBenefitType') ? placementPolicy.azureHybridBenefitType : '' - vmMembers: contains(placementPolicy, 'vmMembers') ? placementPolicy.vmMembers : [] - hostMembers: contains(placementPolicy, 'hostMembers') ? placementPolicy.hostMembers : [] + diskPoolVolume: contains(datastore, 'diskPoolVolume') ? datastore.diskPoolVolume : {} + name: datastore.name + netAppVolume: contains(datastore, 'netAppVolume') ? datastore.netAppVolume : {} enableDefaultTelemetry: enableReferencedModulesTelemetry } }] diff --git a/modules/Microsoft.AVS/privateClouds/clusters/placementPolicies/deploy.bicep b/modules/Microsoft.AVS/privateClouds/clusters/placementPolicies/deploy.bicep index c89da36d8b..b0d1902a9b 100644 --- a/modules/Microsoft.AVS/privateClouds/clusters/placementPolicies/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/clusters/placementPolicies/deploy.bicep @@ -80,13 +80,13 @@ resource placementPolicy 'Microsoft.AVS/privateClouds/clusters/placementPolicies parent: privateCloud::cluster name: name properties: { - state: state - type: type - displayName: displayName affinityStrength: affinityStrength azureHybridBenefitType: azureHybridBenefitType - vmMembers: vmMembers + displayName: displayName hostMembers: hostMembers + state: state + type: type + vmMembers: vmMembers } } diff --git a/modules/Microsoft.AVS/privateClouds/deploy.bicep b/modules/Microsoft.AVS/privateClouds/deploy.bicep index 9a83001e24..a8141f0bd5 100644 --- a/modules/Microsoft.AVS/privateClouds/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/deploy.bicep @@ -194,22 +194,22 @@ resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (ena resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' = { - name: name identity: identity - sku: sku location: location + name: name + sku: sku tags: tags properties: { - secondaryCircuit: secondaryCircuit - nsxtPassword: nsxtPassword - vcenterPassword: vcenterPassword - networkBlock: networkBlock + availability: availability circuit: circuit + encryption: encryption identitySources: identitySources internet: internet - encryption: encryption - availability: availability managementCluster: managementCluster + networkBlock: networkBlock + nsxtPassword: nsxtPassword + secondaryCircuit: secondaryCircuit + vcenterPassword: vcenterPassword } } @@ -235,180 +235,180 @@ resource keyVault_lock 'Microsoft.Authorization/locks@2017-04-01' = if (!empty(l scope: privateCloud } -module privateCloud_hcxEnterpriseSites 'hcxEnterpriseSites/deploy.bicep' = [for (hcxEnterpriseSite, index) in hcxEnterpriseSites: { -name: '${uniqueString(deployment().name, location)}-privateCloud-hcxEnterpriseSite-${index}' -params: { +module privateCloud_authorizations 'authorizations/deploy.bicep' = [for (authorization, index) in authorizations: { + name: '${uniqueString(deployment().name, location)}-privateCloud-authorization-${index}' + params: { privateCloudName: name - name: hcxEnterpriseSite.name + name: authorization.name enableDefaultTelemetry: enableReferencedModulesTelemetry } }] -module privateCloud_globalReachConnections 'globalReachConnections/deploy.bicep' = [for (globalReachConnection, index) in globalReachConnections: { -name: '${uniqueString(deployment().name, location)}-privateCloud-globalReachConnection-${index}' -params: { +module privateCloud_cloudLinks 'cloudLinks/deploy.bicep' = [for (cloudLink, index) in cloudLinks: { + name: '${uniqueString(deployment().name, location)}-privateCloud-cloudLink-${index}' + params: { privateCloudName: name - name: globalReachConnection.name - authorizationKey: contains(globalReachConnection, 'authorizationKey') ? globalReachConnection.authorizationKey : '' - expressRouteId: contains(globalReachConnection, 'expressRouteId') ? globalReachConnection.expressRouteId : '' - peerExpressRouteCircuit: contains(globalReachConnection, 'peerExpressRouteCircuit') ? globalReachConnection.peerExpressRouteCircuit : '' + linkedCloud: contains(cloudLink, 'linkedCloud') ? cloudLink.linkedCloud : '' + name: cloudLink.name enableDefaultTelemetry: enableReferencedModulesTelemetry } }] -module privateCloud_clusters 'clusters/deploy.bicep' = [for (cluster, index) in clusters: { -name: '${uniqueString(deployment().name, location)}-privateCloud-cluster-${index}' -params: { +module privateCloud_addons 'addons/deploy.bicep' = [for (addon, index) in addons: { + name: '${uniqueString(deployment().name, location)}-privateCloud-addon-${index}' + params: { privateCloudName: name - name: cluster.name - sku: cluster.sku - hosts: contains(cluster, 'hosts') ? cluster.hosts : [] - clusterSize: contains(cluster, 'clusterSize') ? cluster.clusterSize : + addonType: contains(addon, 'addonType') ? addon.addonType : '' + name: addon.name enableDefaultTelemetry: enableReferencedModulesTelemetry } }] -module privateCloud_authorizations 'authorizations/deploy.bicep' = [for (authorization, index) in authorizations: { -name: '${uniqueString(deployment().name, location)}-privateCloud-authorization-${index}' -params: { +module privateCloud_globalReachConnections 'globalReachConnections/deploy.bicep' = [for (globalReachConnection, index) in globalReachConnections: { + name: '${uniqueString(deployment().name, location)}-privateCloud-globalReachConnection-${index}' + params: { privateCloudName: name - name: authorization.name + authorizationKey: contains(globalReachConnection, 'authorizationKey') ? globalReachConnection.authorizationKey : '' + expressRouteId: contains(globalReachConnection, 'expressRouteId') ? globalReachConnection.expressRouteId : '' + name: globalReachConnection.name + peerExpressRouteCircuit: contains(globalReachConnection, 'peerExpressRouteCircuit') ? globalReachConnection.peerExpressRouteCircuit : '' enableDefaultTelemetry: enableReferencedModulesTelemetry } }] -module privateCloud_cloudLinks 'cloudLinks/deploy.bicep' = [for (cloudLink, index) in cloudLinks: { -name: '${uniqueString(deployment().name, location)}-privateCloud-cloudLink-${index}' -params: { +module privateCloud_hcxEnterpriseSites 'hcxEnterpriseSites/deploy.bicep' = [for (hcxEnterpriseSite, index) in hcxEnterpriseSites: { + name: '${uniqueString(deployment().name, location)}-privateCloud-hcxEnterpriseSite-${index}' + params: { privateCloudName: name - name: cloudLink.name - linkedCloud: contains(cloudLink, 'linkedCloud') ? cloudLink.linkedCloud : '' + name: hcxEnterpriseSite.name enableDefaultTelemetry: enableReferencedModulesTelemetry } }] -module privateCloud_addons 'addons/deploy.bicep' = [for (addon, index) in addons: { -name: '${uniqueString(deployment().name, location)}-privateCloud-addon-${index}' -params: { +module privateCloud_clusters 'clusters/deploy.bicep' = [for (cluster, index) in clusters: { + name: '${uniqueString(deployment().name, location)}-privateCloud-cluster-${index}' + params: { privateCloudName: name - name: addon.name - addonType: contains(addon, 'addonType') ? addon.addonType : '' + clusterSize: contains(cluster, 'clusterSize') ? cluster.clusterSize : + hosts: contains(cluster, 'hosts') ? cluster.hosts : [] + name: cluster.name + sku: cluster.sku enableDefaultTelemetry: enableReferencedModulesTelemetry } }] module privateCloud_scriptExecutions 'scriptExecutions/deploy.bicep' = [for (scriptExecution, index) in scriptExecutions: { -name: '${uniqueString(deployment().name, location)}-privateCloud-scriptExecution-${index}' -params: { + name: '${uniqueString(deployment().name, location)}-privateCloud-scriptExecution-${index}' + params: { privateCloudName: name - name: scriptExecution.name - scriptCmdletId: contains(scriptExecution, 'scriptCmdletId') ? scriptExecution.scriptCmdletId : '' failureReason: contains(scriptExecution, 'failureReason') ? scriptExecution.failureReason : '' - output: contains(scriptExecution, 'output') ? scriptExecution.output : [] + hiddenParameters: contains(scriptExecution, 'hiddenParameters') ? scriptExecution.hiddenParameters : [] + name: scriptExecution.name namedOutputs: contains(scriptExecution, 'namedOutputs') ? scriptExecution.namedOutputs : {} - timeout: contains(scriptExecution, 'timeout') ? scriptExecution.timeout : '' - retention: contains(scriptExecution, 'retention') ? scriptExecution.retention : '' + output: contains(scriptExecution, 'output') ? scriptExecution.output : [] parameters: contains(scriptExecution, 'parameters') ? scriptExecution.parameters : [] - hiddenParameters: contains(scriptExecution, 'hiddenParameters') ? scriptExecution.hiddenParameters : [] + retention: contains(scriptExecution, 'retention') ? scriptExecution.retention : '' + scriptCmdletId: contains(scriptExecution, 'scriptCmdletId') ? scriptExecution.scriptCmdletId : '' + timeout: contains(scriptExecution, 'timeout') ? scriptExecution.timeout : '' enableDefaultTelemetry: enableReferencedModulesTelemetry } }] -module workloadNetworks_privateCloud_publicIPs 'workloadNetworks/publicIPs/deploy.bicep' = [for (publicIP, index) in publicIPs: { -name: '${uniqueString(deployment().name, location)}-privateCloud-publicIP-${index}' -params: { +module workloadNetworks_privateCloud_dnsServices 'workloadNetworks/dnsServices/deploy.bicep' = [for (dnsService, index) in dnsServices: { + name: '${uniqueString(deployment().name, location)}-privateCloud-dnsService-${index}' + params: { privateCloudName: name workloadNetworkName: 'default' - name: publicIP.name - displayName: contains(publicIP, 'displayName') ? publicIP.displayName : '' - numberOfPublicIPs: contains(publicIP, 'numberOfPublicIPs') ? publicIP.numberOfPublicIPs : + defaultDnsZone: contains(dnsService, 'defaultDnsZone') ? dnsService.defaultDnsZone : '' + displayName: contains(dnsService, 'displayName') ? dnsService.displayName : '' + dnsServiceIp: contains(dnsService, 'dnsServiceIp') ? dnsService.dnsServiceIp : '' + fqdnZones: contains(dnsService, 'fqdnZones') ? dnsService.fqdnZones : [] + logLevel: contains(dnsService, 'logLevel') ? dnsService.logLevel : '' + name: dnsService.name + revision: contains(dnsService, 'revision') ? dnsService.revision : enableDefaultTelemetry: enableReferencedModulesTelemetry } }] -module workloadNetworks_privateCloud_dhcpConfigurations 'workloadNetworks/dhcpConfigurations/deploy.bicep' = [for (dhcpConfiguration, index) in dhcpConfigurations: { -name: '${uniqueString(deployment().name, location)}-privateCloud-dhcpConfiguration-${index}' -params: { +module workloadNetworks_privateCloud_segments 'workloadNetworks/segments/deploy.bicep' = [for (segment, index) in segments: { + name: '${uniqueString(deployment().name, location)}-privateCloud-segment-${index}' + params: { privateCloudName: name workloadNetworkName: 'default' - name: dhcpConfiguration.name - displayName: contains(dhcpConfiguration, 'displayName') ? dhcpConfiguration.displayName : '' - dhcpType: contains(dhcpConfiguration, 'dhcpType') ? dhcpConfiguration.dhcpType : '' - revision: contains(dhcpConfiguration, 'revision') ? dhcpConfiguration.revision : + connectedGateway: contains(segment, 'connectedGateway') ? segment.connectedGateway : '' + displayName: contains(segment, 'displayName') ? segment.displayName : '' + name: segment.name + revision: contains(segment, 'revision') ? segment.revision : + subnet: contains(segment, 'subnet') ? segment.subnet : {} enableDefaultTelemetry: enableReferencedModulesTelemetry } }] module workloadNetworks_privateCloud_dnsZones 'workloadNetworks/dnsZones/deploy.bicep' = [for (dnsZone, index) in dnsZones: { -name: '${uniqueString(deployment().name, location)}-privateCloud-dnsZone-${index}' -params: { + name: '${uniqueString(deployment().name, location)}-privateCloud-dnsZone-${index}' + params: { privateCloudName: name workloadNetworkName: 'default' - name: dnsZone.name - revision: contains(dnsZone, 'revision') ? dnsZone.revision : displayName: contains(dnsZone, 'displayName') ? dnsZone.displayName : '' - dnsServices: contains(dnsZone, 'dnsServices') ? dnsZone.dnsServices : dnsServerIps: contains(dnsZone, 'dnsServerIps') ? dnsZone.dnsServerIps : [] - sourceIp: contains(dnsZone, 'sourceIp') ? dnsZone.sourceIp : '' + dnsServices: contains(dnsZone, 'dnsServices') ? dnsZone.dnsServices : domain: contains(dnsZone, 'domain') ? dnsZone.domain : [] + name: dnsZone.name + revision: contains(dnsZone, 'revision') ? dnsZone.revision : + sourceIp: contains(dnsZone, 'sourceIp') ? dnsZone.sourceIp : '' enableDefaultTelemetry: enableReferencedModulesTelemetry } }] -module workloadNetworks_privateCloud_dnsServices 'workloadNetworks/dnsServices/deploy.bicep' = [for (dnsService, index) in dnsServices: { -name: '${uniqueString(deployment().name, location)}-privateCloud-dnsService-${index}' -params: { +module workloadNetworks_privateCloud_publicIPs 'workloadNetworks/publicIPs/deploy.bicep' = [for (publicIP, index) in publicIPs: { + name: '${uniqueString(deployment().name, location)}-privateCloud-publicIP-${index}' + params: { privateCloudName: name workloadNetworkName: 'default' - name: dnsService.name - logLevel: contains(dnsService, 'logLevel') ? dnsService.logLevel : '' - fqdnZones: contains(dnsService, 'fqdnZones') ? dnsService.fqdnZones : [] - defaultDnsZone: contains(dnsService, 'defaultDnsZone') ? dnsService.defaultDnsZone : '' - dnsServiceIp: contains(dnsService, 'dnsServiceIp') ? dnsService.dnsServiceIp : '' - revision: contains(dnsService, 'revision') ? dnsService.revision : - displayName: contains(dnsService, 'displayName') ? dnsService.displayName : '' + displayName: contains(publicIP, 'displayName') ? publicIP.displayName : '' + name: publicIP.name + numberOfPublicIPs: contains(publicIP, 'numberOfPublicIPs') ? publicIP.numberOfPublicIPs : enableDefaultTelemetry: enableReferencedModulesTelemetry } }] module workloadNetworks_privateCloud_vmGroups 'workloadNetworks/vmGroups/deploy.bicep' = [for (vmGroup, index) in vmGroups: { -name: '${uniqueString(deployment().name, location)}-privateCloud-vmGroup-${index}' -params: { + name: '${uniqueString(deployment().name, location)}-privateCloud-vmGroup-${index}' + params: { privateCloudName: name workloadNetworkName: 'default' - name: vmGroup.name displayName: contains(vmGroup, 'displayName') ? vmGroup.displayName : '' members: contains(vmGroup, 'members') ? vmGroup.members : [] + name: vmGroup.name revision: contains(vmGroup, 'revision') ? vmGroup.revision : enableDefaultTelemetry: enableReferencedModulesTelemetry } }] module workloadNetworks_privateCloud_portMirroringProfiles 'workloadNetworks/portMirroringProfiles/deploy.bicep' = [for (portMirroringProfile, index) in portMirroringProfiles: { -name: '${uniqueString(deployment().name, location)}-privateCloud-portMirroringProfile-${index}' -params: { + name: '${uniqueString(deployment().name, location)}-privateCloud-portMirroringProfile-${index}' + params: { privateCloudName: name workloadNetworkName: 'default' - name: portMirroringProfile.name destination: contains(portMirroringProfile, 'destination') ? portMirroringProfile.destination : '' + direction: contains(portMirroringProfile, 'direction') ? portMirroringProfile.direction : '' displayName: contains(portMirroringProfile, 'displayName') ? portMirroringProfile.displayName : '' + name: portMirroringProfile.name revision: contains(portMirroringProfile, 'revision') ? portMirroringProfile.revision : - direction: contains(portMirroringProfile, 'direction') ? portMirroringProfile.direction : '' source: contains(portMirroringProfile, 'source') ? portMirroringProfile.source : '' enableDefaultTelemetry: enableReferencedModulesTelemetry } }] -module workloadNetworks_privateCloud_segments 'workloadNetworks/segments/deploy.bicep' = [for (segment, index) in segments: { -name: '${uniqueString(deployment().name, location)}-privateCloud-segment-${index}' -params: { +module workloadNetworks_privateCloud_dhcpConfigurations 'workloadNetworks/dhcpConfigurations/deploy.bicep' = [for (dhcpConfiguration, index) in dhcpConfigurations: { + name: '${uniqueString(deployment().name, location)}-privateCloud-dhcpConfiguration-${index}' + params: { privateCloudName: name workloadNetworkName: 'default' - name: segment.name - subnet: contains(segment, 'subnet') ? segment.subnet : {} - displayName: contains(segment, 'displayName') ? segment.displayName : '' - revision: contains(segment, 'revision') ? segment.revision : - connectedGateway: contains(segment, 'connectedGateway') ? segment.connectedGateway : '' + dhcpType: contains(dhcpConfiguration, 'dhcpType') ? dhcpConfiguration.dhcpType : '' + displayName: contains(dhcpConfiguration, 'displayName') ? dhcpConfiguration.displayName : '' + name: dhcpConfiguration.name + revision: contains(dhcpConfiguration, 'revision') ? dhcpConfiguration.revision : enableDefaultTelemetry: enableReferencedModulesTelemetry } }] diff --git a/modules/Microsoft.AVS/privateClouds/scriptExecutions/deploy.bicep b/modules/Microsoft.AVS/privateClouds/scriptExecutions/deploy.bicep index a6cd4363f4..cee7e032dc 100644 --- a/modules/Microsoft.AVS/privateClouds/scriptExecutions/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/scriptExecutions/deploy.bicep @@ -61,14 +61,14 @@ resource scriptExecution 'Microsoft.AVS/privateClouds/scriptExecutions@2022-05-0 parent: privateCloud name: name properties: { - scriptCmdletId: scriptCmdletId failureReason: failureReason - output: output + hiddenParameters: hiddenParameters namedOutputs: namedOutputs - timeout: timeout - retention: retention + output: output parameters: parameters - hiddenParameters: hiddenParameters + retention: retention + scriptCmdletId: scriptCmdletId + timeout: timeout } } diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dhcpConfigurations/deploy.bicep b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dhcpConfigurations/deploy.bicep index c4e9108831..e9c991cbfb 100644 --- a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dhcpConfigurations/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dhcpConfigurations/deploy.bicep @@ -56,8 +56,8 @@ resource dhcpConfiguration 'Microsoft.AVS/privateClouds/workloadNetworks/dhcpCon parent: privateCloud::workloadNetwork name: name properties: { - displayName: displayName dhcpType: dhcpType + displayName: displayName revision: revision } } diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsServices/deploy.bicep b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsServices/deploy.bicep index 624e21bea9..2577fcb9d0 100644 --- a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsServices/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsServices/deploy.bicep @@ -68,12 +68,12 @@ resource dnsService 'Microsoft.AVS/privateClouds/workloadNetworks/dnsServices@20 parent: privateCloud::workloadNetwork name: name properties: { - logLevel: logLevel - fqdnZones: fqdnZones defaultDnsZone: defaultDnsZone + displayName: displayName dnsServiceIp: dnsServiceIp + fqdnZones: fqdnZones + logLevel: logLevel revision: revision - displayName: displayName } } diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsZones/deploy.bicep b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsZones/deploy.bicep index 261c32a0b2..cf49f14eeb 100644 --- a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsZones/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsZones/deploy.bicep @@ -61,12 +61,12 @@ resource dnsZone 'Microsoft.AVS/privateClouds/workloadNetworks/dnsZones@2022-05- parent: privateCloud::workloadNetwork name: name properties: { - revision: revision displayName: displayName - dnsServices: dnsServices dnsServerIps: dnsServerIps - sourceIp: sourceIp + dnsServices: dnsServices domain: domain + revision: revision + sourceIp: sourceIp } } diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/portMirroringProfiles/deploy.bicep b/modules/Microsoft.AVS/privateClouds/workloadNetworks/portMirroringProfiles/deploy.bicep index c5640ff762..df7e3b5f86 100644 --- a/modules/Microsoft.AVS/privateClouds/workloadNetworks/portMirroringProfiles/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/workloadNetworks/portMirroringProfiles/deploy.bicep @@ -64,9 +64,9 @@ resource portMirroringProfile 'Microsoft.AVS/privateClouds/workloadNetworks/port name: name properties: { destination: destination + direction: direction displayName: displayName revision: revision - direction: direction source: source } } diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/segments/deploy.bicep b/modules/Microsoft.AVS/privateClouds/workloadNetworks/segments/deploy.bicep index f788ca34ad..bbed596cbf 100644 --- a/modules/Microsoft.AVS/privateClouds/workloadNetworks/segments/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/workloadNetworks/segments/deploy.bicep @@ -55,10 +55,10 @@ resource segment 'Microsoft.AVS/privateClouds/workloadNetworks/segments@2022-05- parent: privateCloud::workloadNetwork name: name properties: { - subnet: subnet + connectedGateway: connectedGateway displayName: displayName revision: revision - connectedGateway: connectedGateway + subnet: subnet } } diff --git a/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 b/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 index 0dc5b4a72a..6960cf7c92 100644 --- a/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 +++ b/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 @@ -60,7 +60,7 @@ function Set-ModuleTemplate { ##################### # Existing template (if any) - $existingTemplateContent = Resolve-ExistingTemplateContent -TemplateFilePath $templateFilePath + $existingTemplateContent = @() # Resolve-ExistingTemplateContent -TemplateFilePath $templateFilePath # Collect child-resource information $linkedChildren = $fullmoduleData | Where-Object { @@ -175,20 +175,37 @@ function Set-ModuleTemplate { # Create collected parameters # --------------------------- - # TODO: Only update parameters that are not already defines # First the required foreach ($parameter in ($parametersToAdd | Where-Object { $_.required } | Sort-Object -Property 'Name')) { - $templateContent += Get-FormattedModuleParameter -ParameterData $parameter + if ($existingTemplateContent.parameters.name -notcontains $parameter.name) { + $templateContent += Get-FormattedModuleParameter -ParameterData $parameter + } else { + $templateContent += ($existingTemplateContent.parameters | Where-Object { $_.name -eq $parameter.name }).content + } } # Then the conditional foreach ($parameter in ($parametersToAdd | Where-Object { -not $_.required -and $_.description -like 'Conditional. *' } | Sort-Object -Property 'Name')) { - $templateContent += Get-FormattedModuleParameter -ParameterData $parameter + if ($existingTemplateContent.parameters.name -notcontains $parameter.name) { + $templateContent += Get-FormattedModuleParameter -ParameterData $parameter + } else { + $templateContent += ($existingTemplateContent.parameters | Where-Object { $_.name -eq $parameter.name }).content + } } # Then the rest foreach ($parameter in ($parametersToAdd | Where-Object { -not $_.required -and $_.description -notlike 'Conditional. *' } | Sort-Object -Property 'Name')) { - $templateContent += Get-FormattedModuleParameter -ParameterData $parameter + if ($existingTemplateContent.parameters.name -notcontains $parameter.name) { + $templateContent += Get-FormattedModuleParameter -ParameterData $parameter + } else { + $templateContent += ($existingTemplateContent.parameters | Where-Object { $_.name -eq $parameter.name }).content + } } + # TODO: Add additional parameters at the end? + foreach ($extraParameter in ($existingTemplateContent.parameters | Where-Object { $parametersToAdd.name -notcontains $_.name })) { + $templateContent += $extraParameter.content + } + + ################# ## VARIABLES ## ################# @@ -272,12 +289,12 @@ function Set-ModuleTemplate { $templateContent += (' parent: {0}' -f (($parentResourceTypes | ForEach-Object { Get-ResourceTypeSingularName -ResourceType $_ }) -join '::')) } - foreach ($parameter in ($ModuleData.parameters | Where-Object { $_.level -eq 0 -and $_.name -ne 'properties' })) { + foreach ($parameter in ($ModuleData.parameters | Where-Object { $_.level -eq 0 -and $_.name -ne 'properties' } | Sort-Object -Property 'name')) { $templateContent += ' {0}: {0}' -f $parameter.name } $templateContent += ' properties: {' - foreach ($parameter in ($ModuleData.parameters | Where-Object { $_.level -eq 1 -and $_.Parent -eq 'properties' })) { + foreach ($parameter in ($ModuleData.parameters | Where-Object { $_.level -eq 1 -and $_.Parent -eq 'properties' } | Sort-Object -Property 'name')) { $templateContent += ' {0}: {0}' -f $parameter.name } @@ -306,8 +323,8 @@ function Set-ModuleTemplate { $templateContent += @( "module $($hasProxyParent ? "$($proxyParentName)_" : '')$($resourceTypeSingular)_$($childResourceType) '$($hasProxyParent ? "$proxyParentName/" : '')$($childResourceType)/deploy.bicep' = [for ($($childResourceTypeSingular), index) in $($childResourceType): {", - "name: '`${uniqueString(deployment().name$($locationParameterExists ? ', location' : ''))}-$($resourceTypeSingular)-$($childResourceTypeSingular)-`${index}'", - 'params: {' + " name: '`${uniqueString(deployment().name$($locationParameterExists ? ', location' : ''))}-$($resourceTypeSingular)-$($childResourceTypeSingular)-`${index}'", + ' params: {' ) # All param names of parents @@ -325,7 +342,7 @@ function Set-ModuleTemplate { # Add primary child parameters $allParam = $dataBlock.data.parameters + $dataBlock.data.additionalParameters - foreach ($parameter in ($allParam | Where-Object { $_.Level -in @(0, 1) -and $_.name -ne 'properties' -and ([String]::IsNullOrEmpty($_.Parent) -or $_.Parent -eq 'properties') })) { + foreach ($parameter in (($allParam | Where-Object { $_.Level -in @(0, 1) -and $_.name -ne 'properties' -and ([String]::IsNullOrEmpty($_.Parent) -or $_.Parent -eq 'properties') }) | Sort-Object -Property 'Name')) { $wouldBeParameter = Get-FormattedModuleParameter -ParameterData $parameter | Where-Object { $_ -like 'param *' } | ForEach-Object { $_ -replace 'param ', '' } $wouldBeParamElem = $wouldBeParameter -split ' = ' $parameter.name = ($wouldBeParamElem -split ' ')[0] From 8967314be0729b9f4b61e8167d247d4041ed7bc3 Mon Sep 17 00:00:00 2001 From: MrMCake Date: Mon, 31 Oct 2022 09:13:36 +0100 Subject: [PATCH 02/30] Added cleanup & adjusted indents --- .../privateClouds/addons/deploy.bicep | 3 +- .../privateClouds/authorizations/deploy.bicep | 3 +- .../privateClouds/cloudLinks/deploy.bicep | 3 +- .../clusters/datastores/deploy.bicep | 4 +-- .../privateClouds/clusters/deploy.bicep | 5 ++-- .../clusters/placementPolicies/deploy.bicep | 4 +-- .../globalReachConnections/deploy.bicep | 3 +- .../hcxEnterpriseSites/deploy.bicep | 3 +- .../scriptExecutions/deploy.bicep | 3 +- .../dhcpConfigurations/deploy.bicep | 4 +-- .../workloadNetworks/dnsServices/deploy.bicep | 4 +-- .../workloadNetworks/dnsZones/deploy.bicep | 4 +-- .../portMirroringProfiles/deploy.bicep | 4 +-- .../workloadNetworks/publicIPs/deploy.bicep | 4 +-- .../workloadNetworks/segments/deploy.bicep | 4 +-- .../workloadNetworks/vmGroups/deploy.bicep | 4 +-- .../private/module/Read-DeclarationBlock.ps1 | 29 +++++++++++++++++-- .../private/module/Set-ModuleTemplate.ps1 | 10 +++++-- 18 files changed, 59 insertions(+), 39 deletions(-) diff --git a/modules/Microsoft.AVS/privateClouds/addons/deploy.bicep b/modules/Microsoft.AVS/privateClouds/addons/deploy.bicep index a80226314d..d2c95dfbef 100644 --- a/modules/Microsoft.AVS/privateClouds/addons/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/addons/deploy.bicep @@ -38,8 +38,7 @@ resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (ena } resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { - name: privateCloudName - + name: privateCloudName } resource addon 'Microsoft.AVS/privateClouds/addons@2022-05-01' = { diff --git a/modules/Microsoft.AVS/privateClouds/authorizations/deploy.bicep b/modules/Microsoft.AVS/privateClouds/authorizations/deploy.bicep index 4a8ded2c4d..e0e58207f4 100644 --- a/modules/Microsoft.AVS/privateClouds/authorizations/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/authorizations/deploy.bicep @@ -29,8 +29,7 @@ resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (ena } resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { - name: privateCloudName - + name: privateCloudName } resource authorization 'Microsoft.AVS/privateClouds/authorizations@2022-05-01' = { diff --git a/modules/Microsoft.AVS/privateClouds/cloudLinks/deploy.bicep b/modules/Microsoft.AVS/privateClouds/cloudLinks/deploy.bicep index ebab64d956..64dfd7c608 100644 --- a/modules/Microsoft.AVS/privateClouds/cloudLinks/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/cloudLinks/deploy.bicep @@ -32,8 +32,7 @@ resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (ena } resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { - name: privateCloudName - + name: privateCloudName } resource cloudLink 'Microsoft.AVS/privateClouds/cloudLinks@2022-05-01' = { diff --git a/modules/Microsoft.AVS/privateClouds/clusters/datastores/deploy.bicep b/modules/Microsoft.AVS/privateClouds/clusters/datastores/deploy.bicep index 4cdaad642f..2e451c8fc4 100644 --- a/modules/Microsoft.AVS/privateClouds/clusters/datastores/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/clusters/datastores/deploy.bicep @@ -38,10 +38,10 @@ resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (ena } resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { - name: privateCloudName + name: privateCloudName resource cluster 'clusters@2022-05-01' existing = { - name: clusterName + name: clusterName } } diff --git a/modules/Microsoft.AVS/privateClouds/clusters/deploy.bicep b/modules/Microsoft.AVS/privateClouds/clusters/deploy.bicep index 9d61a96654..af0d2275e3 100644 --- a/modules/Microsoft.AVS/privateClouds/clusters/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/clusters/deploy.bicep @@ -12,7 +12,7 @@ param sku object param privateCloudName string @description('Optional. The cluster size') -param clusterSize int = +param clusterSize int = @description('Optional. The datastores to create as part of the cluster.') param datastores array = [] @@ -46,8 +46,7 @@ resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (ena } resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { - name: privateCloudName - + name: privateCloudName } resource cluster 'Microsoft.AVS/privateClouds/clusters@2022-05-01' = { diff --git a/modules/Microsoft.AVS/privateClouds/clusters/placementPolicies/deploy.bicep b/modules/Microsoft.AVS/privateClouds/clusters/placementPolicies/deploy.bicep index b0d1902a9b..1e8306fa61 100644 --- a/modules/Microsoft.AVS/privateClouds/clusters/placementPolicies/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/clusters/placementPolicies/deploy.bicep @@ -69,10 +69,10 @@ resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (ena } resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { - name: privateCloudName + name: privateCloudName resource cluster 'clusters@2022-05-01' existing = { - name: clusterName + name: clusterName } } diff --git a/modules/Microsoft.AVS/privateClouds/globalReachConnections/deploy.bicep b/modules/Microsoft.AVS/privateClouds/globalReachConnections/deploy.bicep index dbbef58424..88751df8a4 100644 --- a/modules/Microsoft.AVS/privateClouds/globalReachConnections/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/globalReachConnections/deploy.bicep @@ -38,8 +38,7 @@ resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (ena } resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { - name: privateCloudName - + name: privateCloudName } resource globalReachConnection 'Microsoft.AVS/privateClouds/globalReachConnections@2022-05-01' = { diff --git a/modules/Microsoft.AVS/privateClouds/hcxEnterpriseSites/deploy.bicep b/modules/Microsoft.AVS/privateClouds/hcxEnterpriseSites/deploy.bicep index e04501fd24..d56ad0fbfe 100644 --- a/modules/Microsoft.AVS/privateClouds/hcxEnterpriseSites/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/hcxEnterpriseSites/deploy.bicep @@ -29,8 +29,7 @@ resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (ena } resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { - name: privateCloudName - + name: privateCloudName } resource hcxEnterpriseSite 'Microsoft.AVS/privateClouds/hcxEnterpriseSites@2022-05-01' = { diff --git a/modules/Microsoft.AVS/privateClouds/scriptExecutions/deploy.bicep b/modules/Microsoft.AVS/privateClouds/scriptExecutions/deploy.bicep index cee7e032dc..05580b8e4a 100644 --- a/modules/Microsoft.AVS/privateClouds/scriptExecutions/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/scriptExecutions/deploy.bicep @@ -53,8 +53,7 @@ resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (ena } resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { - name: privateCloudName - + name: privateCloudName } resource scriptExecution 'Microsoft.AVS/privateClouds/scriptExecutions@2022-05-01' = { diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dhcpConfigurations/deploy.bicep b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dhcpConfigurations/deploy.bicep index e9c991cbfb..aba2a2dd20 100644 --- a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dhcpConfigurations/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dhcpConfigurations/deploy.bicep @@ -45,10 +45,10 @@ resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (ena } resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { - name: privateCloudName + name: privateCloudName resource workloadNetwork 'workloadNetworks@2022-05-01' existing = { - name: workloadNetworkName + name: workloadNetworkName } } diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsServices/deploy.bicep b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsServices/deploy.bicep index 2577fcb9d0..bbf23153a9 100644 --- a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsServices/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsServices/deploy.bicep @@ -57,10 +57,10 @@ resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (ena } resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { - name: privateCloudName + name: privateCloudName resource workloadNetwork 'workloadNetworks@2022-05-01' existing = { - name: workloadNetworkName + name: workloadNetworkName } } diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsZones/deploy.bicep b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsZones/deploy.bicep index cf49f14eeb..022554371b 100644 --- a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsZones/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsZones/deploy.bicep @@ -50,10 +50,10 @@ resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (ena } resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { - name: privateCloudName + name: privateCloudName resource workloadNetwork 'workloadNetworks@2022-05-01' existing = { - name: workloadNetworkName + name: workloadNetworkName } } diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/portMirroringProfiles/deploy.bicep b/modules/Microsoft.AVS/privateClouds/workloadNetworks/portMirroringProfiles/deploy.bicep index df7e3b5f86..7a502300b7 100644 --- a/modules/Microsoft.AVS/privateClouds/workloadNetworks/portMirroringProfiles/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/workloadNetworks/portMirroringProfiles/deploy.bicep @@ -52,10 +52,10 @@ resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (ena } resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { - name: privateCloudName + name: privateCloudName resource workloadNetwork 'workloadNetworks@2022-05-01' existing = { - name: workloadNetworkName + name: workloadNetworkName } } diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/publicIPs/deploy.bicep b/modules/Microsoft.AVS/privateClouds/workloadNetworks/publicIPs/deploy.bicep index 3adcd1a2b6..719b59b666 100644 --- a/modules/Microsoft.AVS/privateClouds/workloadNetworks/publicIPs/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/workloadNetworks/publicIPs/deploy.bicep @@ -38,10 +38,10 @@ resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (ena } resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { - name: privateCloudName + name: privateCloudName resource workloadNetwork 'workloadNetworks@2022-05-01' existing = { - name: workloadNetworkName + name: workloadNetworkName } } diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/segments/deploy.bicep b/modules/Microsoft.AVS/privateClouds/workloadNetworks/segments/deploy.bicep index bbed596cbf..29ba3acec1 100644 --- a/modules/Microsoft.AVS/privateClouds/workloadNetworks/segments/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/workloadNetworks/segments/deploy.bicep @@ -44,10 +44,10 @@ resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (ena } resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { - name: privateCloudName + name: privateCloudName resource workloadNetwork 'workloadNetworks@2022-05-01' existing = { - name: workloadNetworkName + name: workloadNetworkName } } diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/vmGroups/deploy.bicep b/modules/Microsoft.AVS/privateClouds/workloadNetworks/vmGroups/deploy.bicep index 5e848b5a70..83b5b8c41c 100644 --- a/modules/Microsoft.AVS/privateClouds/workloadNetworks/vmGroups/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/workloadNetworks/vmGroups/deploy.bicep @@ -41,10 +41,10 @@ resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (ena } resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { - name: privateCloudName + name: privateCloudName resource workloadNetwork 'workloadNetworks@2022-05-01' existing = { - name: workloadNetworkName + name: workloadNetworkName } } diff --git a/utilities/tools/REST2CARML/private/module/Read-DeclarationBlock.ps1 b/utilities/tools/REST2CARML/private/module/Read-DeclarationBlock.ps1 index 33742fae5c..69fa5f7704 100644 --- a/utilities/tools/REST2CARML/private/module/Read-DeclarationBlock.ps1 +++ b/utilities/tools/REST2CARML/private/module/Read-DeclarationBlock.ps1 @@ -51,8 +51,8 @@ function Read-DeclarationBlock { '^module .+$', '^output .+$', '^//.*$', - '^@.+$', - '^\s*$' + '^@.+$'#, + #'^\s*$' ) ######################################### @@ -72,7 +72,25 @@ function Read-DeclarationBlock { ######################################################################################################################## foreach ($declarationIndex in $declarationIndexes) { switch ($DeclarationType) { - { $PSItem -in @('param', 'output') } { + { $PSItem -in @('param') } { + # Let's go 'up' until the declarations end + $declarationStartIndex = $declarationIndex + while ($DeclarationContent[$declarationStartIndex] -eq $DeclarationContent[$declarationIndex] -or (($newLogicIdentifiersUp | Where-Object { $DeclarationContent[$declarationStartIndex] -match $_ }).Count -eq 0 -and $declarationStartIndex -ne 0)) { + $declarationStartIndex-- + } + # Logic always counts one too far + $declarationStartIndex++ + + # The declaration line is always the last line of the block + $declarationEndIndex = $declarationIndex + while ($DeclarationContent[$declarationEndIndex] -eq $DeclarationContent[$declarationIndex] -or (($newLogicIdentifiersDown | Where-Object { $DeclarationContent[$declarationEndIndex] -match $_ }).Count -eq 0 -and $declarationEndIndex -ne $DeclarationContent.Count)) { + $declarationEndIndex++ + } + # Logic always counts one too far + $declarationEndIndex-- + break + } + { $PSItem -in @('output') } { # Let's go 'up' until the declarations end $declarationStartIndex = $declarationIndex while ($DeclarationContent[$declarationStartIndex] -eq $DeclarationContent[$declarationIndex] -or (($newLogicIdentifiersUp | Where-Object { $DeclarationContent[$declarationStartIndex] -match $_ }).Count -eq 0 -and $declarationStartIndex -ne 0)) { @@ -100,6 +118,11 @@ function Read-DeclarationBlock { } } + # Trim empty lines from the end + while ([String]::IsNullOrEmpty($templateContent[$declarationEndIndex])) { + $declarationEndIndex-- + } + $existingBlocks += @{ content = $templateContent[$declarationStartIndex .. $declarationEndIndex] startIndex = $declarationStartIndex diff --git a/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 b/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 index 6960cf7c92..d338b42228 100644 --- a/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 +++ b/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 @@ -60,7 +60,7 @@ function Set-ModuleTemplate { ##################### # Existing template (if any) - $existingTemplateContent = @() # Resolve-ExistingTemplateContent -TemplateFilePath $templateFilePath + $existingTemplateContent = Resolve-ExistingTemplateContent -TemplateFilePath $templateFilePath # Collect child-resource information $linkedChildren = $fullmoduleData | Where-Object { @@ -181,6 +181,7 @@ function Set-ModuleTemplate { $templateContent += Get-FormattedModuleParameter -ParameterData $parameter } else { $templateContent += ($existingTemplateContent.parameters | Where-Object { $_.name -eq $parameter.name }).content + $templateContent += '' } } # Then the conditional @@ -189,6 +190,7 @@ function Set-ModuleTemplate { $templateContent += Get-FormattedModuleParameter -ParameterData $parameter } else { $templateContent += ($existingTemplateContent.parameters | Where-Object { $_.name -eq $parameter.name }).content + $templateContent += '' } } # Then the rest @@ -197,12 +199,14 @@ function Set-ModuleTemplate { $templateContent += Get-FormattedModuleParameter -ParameterData $parameter } else { $templateContent += ($existingTemplateContent.parameters | Where-Object { $_.name -eq $parameter.name }).content + $templateContent += '' } } # TODO: Add additional parameters at the end? foreach ($extraParameter in ($existingTemplateContent.parameters | Where-Object { $parametersToAdd.name -notcontains $_.name })) { $templateContent += $extraParameter.content + $templateContent += '' } @@ -263,9 +267,9 @@ function Set-ModuleTemplate { $parentResourceAPI = Split-Path (Split-Path $parentJSONPath -Parent) -Leaf $templateContent += @( "$(' ' * $existingResourceIndent)resource $($singularParent) '$($levedParentResourceType)@$($parentResourceAPI)' existing = {", - "$(' ' * $existingResourceIndent) name: $($singularParent)Name" + "$(' ' * $existingResourceIndent) name: $($singularParent)Name" ) - if ($parentResourceType -ne $orderedParentResourceTypes[-1]) { + if ($parentResourceType -ne (@() + $orderedParentResourceTypes)[-1]) { # Only add an empty line if there is more content to add $templateContent += '' } From eb22193e92f5bb6d75fed6a7cb6218feab8a9480 Mon Sep 17 00:00:00 2001 From: MrMCake Date: Mon, 31 Oct 2022 09:31:24 +0100 Subject: [PATCH 03/30] Additinoal functional updates --- .../privateClouds/addons/deploy.bicep | 1 - .../privateClouds/authorizations/deploy.bicep | 1 - .../privateClouds/cloudLinks/deploy.bicep | 1 - .../clusters/datastores/deploy.bicep | 1 - .../privateClouds/clusters/deploy.bicep | 1 - .../clusters/placementPolicies/deploy.bicep | 1 - modules/Microsoft.AVS/privateClouds/deploy.bicep | 1 - .../globalReachConnections/deploy.bicep | 1 - .../hcxEnterpriseSites/deploy.bicep | 1 - .../privateClouds/scriptExecutions/deploy.bicep | 1 - .../dhcpConfigurations/deploy.bicep | 1 - .../workloadNetworks/dnsServices/deploy.bicep | 1 - .../workloadNetworks/dnsZones/deploy.bicep | 1 - .../portMirroringProfiles/deploy.bicep | 1 - .../workloadNetworks/publicIPs/deploy.bicep | 1 - .../workloadNetworks/segments/deploy.bicep | 1 - .../workloadNetworks/vmGroups/deploy.bicep | 1 - .../private/module/Set-ModuleTemplate.ps1 | 16 +++++++++++++++- 18 files changed, 15 insertions(+), 18 deletions(-) diff --git a/modules/Microsoft.AVS/privateClouds/addons/deploy.bicep b/modules/Microsoft.AVS/privateClouds/addons/deploy.bicep index d2c95dfbef..597f3dca3b 100644 --- a/modules/Microsoft.AVS/privateClouds/addons/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/addons/deploy.bicep @@ -20,7 +20,6 @@ param addonType string = '' @description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') param enableDefaultTelemetry bool = true - // =============== // // Deployments // // =============== // diff --git a/modules/Microsoft.AVS/privateClouds/authorizations/deploy.bicep b/modules/Microsoft.AVS/privateClouds/authorizations/deploy.bicep index e0e58207f4..508635ef94 100644 --- a/modules/Microsoft.AVS/privateClouds/authorizations/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/authorizations/deploy.bicep @@ -11,7 +11,6 @@ param privateCloudName string @description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') param enableDefaultTelemetry bool = true - // =============== // // Deployments // // =============== // diff --git a/modules/Microsoft.AVS/privateClouds/cloudLinks/deploy.bicep b/modules/Microsoft.AVS/privateClouds/cloudLinks/deploy.bicep index 64dfd7c608..8948ad6f16 100644 --- a/modules/Microsoft.AVS/privateClouds/cloudLinks/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/cloudLinks/deploy.bicep @@ -14,7 +14,6 @@ param enableDefaultTelemetry bool = true @description('Optional. Identifier of the other private cloud participating in the link.') param linkedCloud string = '' - // =============== // // Deployments // // =============== // diff --git a/modules/Microsoft.AVS/privateClouds/clusters/datastores/deploy.bicep b/modules/Microsoft.AVS/privateClouds/clusters/datastores/deploy.bicep index 2e451c8fc4..85bcc45cd9 100644 --- a/modules/Microsoft.AVS/privateClouds/clusters/datastores/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/clusters/datastores/deploy.bicep @@ -20,7 +20,6 @@ param enableDefaultTelemetry bool = true @description('Optional. An Azure NetApp Files volume from Microsoft.NetApp provider') param netAppVolume object = {} - // =============== // // Deployments // // =============== // diff --git a/modules/Microsoft.AVS/privateClouds/clusters/deploy.bicep b/modules/Microsoft.AVS/privateClouds/clusters/deploy.bicep index af0d2275e3..bc4e5059dc 100644 --- a/modules/Microsoft.AVS/privateClouds/clusters/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/clusters/deploy.bicep @@ -28,7 +28,6 @@ param placementPolicies array = [] var enableReferencedModulesTelemetry = false - // =============== // // Deployments // // =============== // diff --git a/modules/Microsoft.AVS/privateClouds/clusters/placementPolicies/deploy.bicep b/modules/Microsoft.AVS/privateClouds/clusters/placementPolicies/deploy.bicep index 1e8306fa61..bb78b7de40 100644 --- a/modules/Microsoft.AVS/privateClouds/clusters/placementPolicies/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/clusters/placementPolicies/deploy.bicep @@ -51,7 +51,6 @@ param type string = '' @description('Optional. Virtual machine members list') param vmMembers array = [] - // =============== // // Deployments // // =============== // diff --git a/modules/Microsoft.AVS/privateClouds/deploy.bicep b/modules/Microsoft.AVS/privateClouds/deploy.bicep index a8141f0bd5..258c9de77d 100644 --- a/modules/Microsoft.AVS/privateClouds/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/deploy.bicep @@ -175,7 +175,6 @@ var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { var enableReferencedModulesTelemetry = false - // =============== // // Deployments // // =============== // diff --git a/modules/Microsoft.AVS/privateClouds/globalReachConnections/deploy.bicep b/modules/Microsoft.AVS/privateClouds/globalReachConnections/deploy.bicep index 88751df8a4..bd98d9ca91 100644 --- a/modules/Microsoft.AVS/privateClouds/globalReachConnections/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/globalReachConnections/deploy.bicep @@ -20,7 +20,6 @@ param expressRouteId string = '' @description('Optional. Identifier of the ExpressRoute Circuit to peer with in the global reach connection') param peerExpressRouteCircuit string = '' - // =============== // // Deployments // // =============== // diff --git a/modules/Microsoft.AVS/privateClouds/hcxEnterpriseSites/deploy.bicep b/modules/Microsoft.AVS/privateClouds/hcxEnterpriseSites/deploy.bicep index d56ad0fbfe..f7206b8c05 100644 --- a/modules/Microsoft.AVS/privateClouds/hcxEnterpriseSites/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/hcxEnterpriseSites/deploy.bicep @@ -11,7 +11,6 @@ param privateCloudName string @description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') param enableDefaultTelemetry bool = true - // =============== // // Deployments // // =============== // diff --git a/modules/Microsoft.AVS/privateClouds/scriptExecutions/deploy.bicep b/modules/Microsoft.AVS/privateClouds/scriptExecutions/deploy.bicep index 05580b8e4a..5422b3033b 100644 --- a/modules/Microsoft.AVS/privateClouds/scriptExecutions/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/scriptExecutions/deploy.bicep @@ -35,7 +35,6 @@ param scriptCmdletId string = '' @description('Optional. Time limit for execution') param timeout string = '' - // =============== // // Deployments // // =============== // diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dhcpConfigurations/deploy.bicep b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dhcpConfigurations/deploy.bicep index aba2a2dd20..39ec347746 100644 --- a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dhcpConfigurations/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dhcpConfigurations/deploy.bicep @@ -27,7 +27,6 @@ param revision int = @description('Optional. The name of the parent workloadNetworks. Required if the template is used in a standalone deployment.') param workloadNetworkName string = 'default' - // =============== // // Deployments // // =============== // diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsServices/deploy.bicep b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsServices/deploy.bicep index bbf23153a9..1364785293 100644 --- a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsServices/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsServices/deploy.bicep @@ -39,7 +39,6 @@ param revision int = @description('Optional. The name of the parent workloadNetworks. Required if the template is used in a standalone deployment.') param workloadNetworkName string = 'default' - // =============== // // Deployments // // =============== // diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsZones/deploy.bicep b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsZones/deploy.bicep index 022554371b..6e610bb3e9 100644 --- a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsZones/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsZones/deploy.bicep @@ -32,7 +32,6 @@ param sourceIp string = '' @description('Optional. The name of the parent workloadNetworks. Required if the template is used in a standalone deployment.') param workloadNetworkName string = 'default' - // =============== // // Deployments // // =============== // diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/portMirroringProfiles/deploy.bicep b/modules/Microsoft.AVS/privateClouds/workloadNetworks/portMirroringProfiles/deploy.bicep index 7a502300b7..5eb37963af 100644 --- a/modules/Microsoft.AVS/privateClouds/workloadNetworks/portMirroringProfiles/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/workloadNetworks/portMirroringProfiles/deploy.bicep @@ -34,7 +34,6 @@ param source string = '' @description('Optional. The name of the parent workloadNetworks. Required if the template is used in a standalone deployment.') param workloadNetworkName string = 'default' - // =============== // // Deployments // // =============== // diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/publicIPs/deploy.bicep b/modules/Microsoft.AVS/privateClouds/workloadNetworks/publicIPs/deploy.bicep index 719b59b666..f424a34ab5 100644 --- a/modules/Microsoft.AVS/privateClouds/workloadNetworks/publicIPs/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/workloadNetworks/publicIPs/deploy.bicep @@ -20,7 +20,6 @@ param numberOfPublicIPs int = @description('Optional. The name of the parent workloadNetworks. Required if the template is used in a standalone deployment.') param workloadNetworkName string = 'default' - // =============== // // Deployments // // =============== // diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/segments/deploy.bicep b/modules/Microsoft.AVS/privateClouds/workloadNetworks/segments/deploy.bicep index 29ba3acec1..ed80042d91 100644 --- a/modules/Microsoft.AVS/privateClouds/workloadNetworks/segments/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/workloadNetworks/segments/deploy.bicep @@ -26,7 +26,6 @@ param subnet object = {} @description('Optional. The name of the parent workloadNetworks. Required if the template is used in a standalone deployment.') param workloadNetworkName string = 'default' - // =============== // // Deployments // // =============== // diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/vmGroups/deploy.bicep b/modules/Microsoft.AVS/privateClouds/workloadNetworks/vmGroups/deploy.bicep index 83b5b8c41c..7efe5c6a16 100644 --- a/modules/Microsoft.AVS/privateClouds/workloadNetworks/vmGroups/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/workloadNetworks/vmGroups/deploy.bicep @@ -23,7 +23,6 @@ param revision int = @description('Optional. The name of the parent workloadNetworks. Required if the template is used in a standalone deployment.') param workloadNetworkName string = 'default' - // =============== // // Deployments // // =============== // diff --git a/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 b/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 index d338b42228..e58293fcb4 100644 --- a/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 +++ b/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 @@ -214,6 +214,11 @@ function Set-ModuleTemplate { ## VARIABLES ## ################# + # Add a space in between the new section and the previous one in case no space exists + if (-not [String]::IsNullOrEmpty($templateContent[-1])) { + $templateContent += '' + } + foreach ($variable in $ModuleData.variables) { $templateContent += $variable } @@ -231,8 +236,12 @@ function Set-ModuleTemplate { $locationParameterExists = ($templateContent | Where-Object { $_ -like 'param location *' }).Count -gt 0 + # Add a space in between the new section and the previous one in case no space exists + if (-not [String]::IsNullOrEmpty($templateContent[-1])) { + $templateContent += '' + } + $templateContent += @( - '' '// =============== //' '// Deployments //' '// =============== //' @@ -386,6 +395,11 @@ function Set-ModuleTemplate { ## Create template outputs section ## ####################################### + # Add a space in between the new section and the previous one in case no space exists + if (-not [String]::IsNullOrEmpty($templateContent[-1])) { + $templateContent += '' + } + # Output header comment $templateContent += @( '// =========== //' From ef016b63dcbfad285ceed5142d0c41898b370256 Mon Sep 17 00:00:00 2001 From: MrMCake Date: Mon, 31 Oct 2022 09:32:41 +0100 Subject: [PATCH 04/30] Update to latest --- .../tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 b/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 index e58293fcb4..2b13172216 100644 --- a/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 +++ b/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 @@ -203,7 +203,7 @@ function Set-ModuleTemplate { } } - # TODO: Add additional parameters at the end? + # Add additional parameters at the end? foreach ($extraParameter in ($existingTemplateContent.parameters | Where-Object { $parametersToAdd.name -notcontains $_.name })) { $templateContent += $extraParameter.content $templateContent += '' From ce53943c078daa3ac5edb67a0cfe66049e05235b Mon Sep 17 00:00:00 2001 From: MrMCake Date: Mon, 31 Oct 2022 09:32:48 +0100 Subject: [PATCH 05/30] Update to latest --- .../tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 b/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 index 2b13172216..e10da1ccf2 100644 --- a/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 +++ b/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 @@ -203,7 +203,7 @@ function Set-ModuleTemplate { } } - # Add additional parameters at the end? + # Add additional parameters at the end foreach ($extraParameter in ($existingTemplateContent.parameters | Where-Object { $parametersToAdd.name -notcontains $_.name })) { $templateContent += $extraParameter.content $templateContent += '' From a6a0d8a49b404fe211a55112b595e9204f7e92b5 Mon Sep 17 00:00:00 2001 From: MrMCake Date: Tue, 1 Nov 2022 14:20:35 +0100 Subject: [PATCH 06/30] Enabled variable idempotency --- .../extension/Set-DiagnosticModuleData.ps1 | 50 ++++++++++--------- .../private/module/Set-ModuleTemplate.ps1 | 35 ++++++++++--- 2 files changed, 56 insertions(+), 29 deletions(-) diff --git a/utilities/tools/REST2CARML/private/extension/Set-DiagnosticModuleData.ps1 b/utilities/tools/REST2CARML/private/extension/Set-DiagnosticModuleData.ps1 index d783e0530e..265b48497b 100644 --- a/utilities/tools/REST2CARML/private/extension/Set-DiagnosticModuleData.ps1 +++ b/utilities/tools/REST2CARML/private/extension/Set-DiagnosticModuleData.ps1 @@ -112,18 +112,20 @@ function Set-DiagnosticModuleData { ) } ) - $ModuleData.variables += @( - 'var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: {' - ' category: metric' - ' timeGrain: null' - ' enabled: true' - ' retentionPolicy: {' - ' enabled: true' - ' days: diagnosticLogsRetentionInDays' - ' }' - '}]' - '' - ) + $ModuleData.variables += @{ + name = 'diagnosticsMetrics' + content = @( + 'var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: {' + ' category: metric' + ' timeGrain: null' + ' enabled: true' + ' retentionPolicy: {' + ' enabled: true' + ' days: diagnosticLogsRetentionInDays' + ' }' + '}]' + ) + } $diagnosticResource += ' metrics: diagnosticsMetrics' } @@ -140,17 +142,19 @@ function Set-DiagnosticModuleData { default = $diagnosticOptions.Logs } ) - $ModuleData.variables += @( - 'var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: {' - ' category: category' - ' enabled: true' - ' retentionPolicy: {' - ' enabled: true' - ' days: diagnosticLogsRetentionInDays' - ' }' - '}]' - '' - ) + $ModuleData.variables += @{ + name = 'diagnosticsLogs' + content = @( + 'var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: {' + ' category: category' + ' enabled: true' + ' retentionPolicy: {' + ' enabled: true' + ' days: diagnosticLogsRetentionInDays' + ' }' + '}]' + ) + } $diagnosticResource += ' logs: diagnosticsLogs' } diff --git a/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 b/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 index e10da1ccf2..ccecca34a1 100644 --- a/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 +++ b/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 @@ -175,6 +175,9 @@ function Set-ModuleTemplate { # Create collected parameters # --------------------------- + # Note: If there already is a template and a given parameter was already specified, we use the existing declaration instead of generating a new one + # as it may have custom logic / default values, etc. + # First the required foreach ($parameter in ($parametersToAdd | Where-Object { $_.required } | Sort-Object -Property 'Name')) { if ($existingTemplateContent.parameters.name -notcontains $parameter.name) { @@ -203,7 +206,7 @@ function Set-ModuleTemplate { } } - # Add additional parameters at the end + # Add additional parameters to only exist in a pre-existing template at the end foreach ($extraParameter in ($existingTemplateContent.parameters | Where-Object { $parametersToAdd.name -notcontains $_.name })) { $templateContent += $extraParameter.content $templateContent += '' @@ -220,16 +223,36 @@ function Set-ModuleTemplate { } foreach ($variable in $ModuleData.variables) { - $templateContent += $variable + if ($existingTemplateContent.variables.name -notcontains $variable.name) { + $templateContent += $variable.content + } else { + $matchingExistingVar = $existingTemplateContent.variables | Where-Object { $_.name -eq $variable.name } + $templateContent += $matchingExistingVar.content + } + $templateContent += '' } + # Add telemetry variable if ($linkedChildren.Count -gt 0) { - $templateContent += @( - 'var enableReferencedModulesTelemetry = false' - '' - ) + if ($existingTemplateContent.variables.name -notcontains 'enableReferencedModulesTelemetry') { + $templateContent += @( + 'var enableReferencedModulesTelemetry = false' + '' + ) + } else { + $matchingExistingVar = $existingTemplateContent.variables | Where-Object { $_.name -eq 'enableReferencedModulesTelemetry' } + $templateContent += $matchingExistingVar.content + } + $templateContent += '' } + # Add additional parameters to only exist in a pre-existing template at the end + foreach ($extraVariable in ($existingTemplateContent.variables | Where-Object { $ModuleData.variables.name -notcontains $_.name -and $_.name -ne 'enableReferencedModulesTelemetry' })) { + $templateContent += $extraVariable.content + $templateContent += '' + } + + ################### ## DEPLOYMENTS ## ################### From e98709ea85bb016c6bbfad59d23862da4529d18e Mon Sep 17 00:00:00 2001 From: MrMCake Date: Tue, 1 Nov 2022 14:34:54 +0100 Subject: [PATCH 07/30] Add regions --- .../REST2CARML/private/module/Set-ModuleTemplate.ps1 | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 b/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 index ccecca34a1..c2e3bf5dff 100644 --- a/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 +++ b/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 @@ -58,6 +58,7 @@ function Set-ModuleTemplate { ##################### ## Collect Data # ##################### + #region data # Existing template (if any) $existingTemplateContent = Resolve-ExistingTemplateContent -TemplateFilePath $templateFilePath @@ -100,11 +101,12 @@ function Set-ModuleTemplate { $hasAProxyParent = $FullModuleData.identifier -notContains ((Split-Path $FullResourceType -Parent) -replace '\\', '/') $parentProxyName = $hasAProxyParent ? ($UrlPath -split '\/')[-3] : '' $proxyParentType = Split-Path (Split-Path $FullResourceType -Parent) -Leaf + #endregion ################## ## PARAMETERS ## ################## - + #region parameters $targetScope = Get-TargetScope -UrlPath $UrlPath $templateContent = ($targetScope -ne 'resourceGroup') ? @( @@ -211,12 +213,12 @@ function Set-ModuleTemplate { $templateContent += $extraParameter.content $templateContent += '' } - + #endregion ################# ## VARIABLES ## ################# - + #region variables # Add a space in between the new section and the previous one in case no space exists if (-not [String]::IsNullOrEmpty($templateContent[-1])) { $templateContent += '' @@ -251,7 +253,7 @@ function Set-ModuleTemplate { $templateContent += $extraVariable.content $templateContent += '' } - + #endregion ################### ## DEPLOYMENTS ## From 6de4e46735b5a03ad1a312e3e7b919adeee6fd54 Mon Sep 17 00:00:00 2001 From: MrMCake Date: Tue, 1 Nov 2022 15:20:18 +0100 Subject: [PATCH 08/30] Enabled idempotency for resource deployment --- .../Microsoft.AVS/privateClouds/deploy.bicep | 142 +++++++++--------- .../private/module/Expand-DeploymentBlock.ps1 | 19 +++ .../private/module/Set-ModuleTemplate.ps1 | 19 ++- 3 files changed, 107 insertions(+), 73 deletions(-) diff --git a/modules/Microsoft.AVS/privateClouds/deploy.bicep b/modules/Microsoft.AVS/privateClouds/deploy.bicep index 258c9de77d..80357f8f13 100644 --- a/modules/Microsoft.AVS/privateClouds/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/deploy.bicep @@ -234,11 +234,19 @@ resource keyVault_lock 'Microsoft.Authorization/locks@2017-04-01' = if (!empty(l scope: privateCloud } -module privateCloud_authorizations 'authorizations/deploy.bicep' = [for (authorization, index) in authorizations: { - name: '${uniqueString(deployment().name, location)}-privateCloud-authorization-${index}' +module privateCloud_scriptExecutions 'scriptExecutions/deploy.bicep' = [for (scriptExecution, index) in scriptExecutions: { + name: '${uniqueString(deployment().name, location)}-privateCloud-scriptExecution-${index}' params: { privateCloudName: name - name: authorization.name + failureReason: contains(scriptExecution, 'failureReason') ? scriptExecution.failureReason : '' + hiddenParameters: contains(scriptExecution, 'hiddenParameters') ? scriptExecution.hiddenParameters : [] + name: scriptExecution.name + namedOutputs: contains(scriptExecution, 'namedOutputs') ? scriptExecution.namedOutputs : {} + output: contains(scriptExecution, 'output') ? scriptExecution.output : [] + parameters: contains(scriptExecution, 'parameters') ? scriptExecution.parameters : [] + retention: contains(scriptExecution, 'retention') ? scriptExecution.retention : '' + scriptCmdletId: contains(scriptExecution, 'scriptCmdletId') ? scriptExecution.scriptCmdletId : '' + timeout: contains(scriptExecution, 'timeout') ? scriptExecution.timeout : '' enableDefaultTelemetry: enableReferencedModulesTelemetry } }] @@ -253,78 +261,66 @@ module privateCloud_cloudLinks 'cloudLinks/deploy.bicep' = [for (cloudLink, inde } }] -module privateCloud_addons 'addons/deploy.bicep' = [for (addon, index) in addons: { - name: '${uniqueString(deployment().name, location)}-privateCloud-addon-${index}' +module privateCloud_authorizations 'authorizations/deploy.bicep' = [for (authorization, index) in authorizations: { + name: '${uniqueString(deployment().name, location)}-privateCloud-authorization-${index}' params: { privateCloudName: name - addonType: contains(addon, 'addonType') ? addon.addonType : '' - name: addon.name + name: authorization.name enableDefaultTelemetry: enableReferencedModulesTelemetry } }] -module privateCloud_globalReachConnections 'globalReachConnections/deploy.bicep' = [for (globalReachConnection, index) in globalReachConnections: { - name: '${uniqueString(deployment().name, location)}-privateCloud-globalReachConnection-${index}' +module privateCloud_clusters 'clusters/deploy.bicep' = [for (cluster, index) in clusters: { + name: '${uniqueString(deployment().name, location)}-privateCloud-cluster-${index}' params: { privateCloudName: name - authorizationKey: contains(globalReachConnection, 'authorizationKey') ? globalReachConnection.authorizationKey : '' - expressRouteId: contains(globalReachConnection, 'expressRouteId') ? globalReachConnection.expressRouteId : '' - name: globalReachConnection.name - peerExpressRouteCircuit: contains(globalReachConnection, 'peerExpressRouteCircuit') ? globalReachConnection.peerExpressRouteCircuit : '' + clusterSize: contains(cluster, 'clusterSize') ? cluster.clusterSize : + hosts: contains(cluster, 'hosts') ? cluster.hosts : [] + name: cluster.name + sku: cluster.sku enableDefaultTelemetry: enableReferencedModulesTelemetry } }] -module privateCloud_hcxEnterpriseSites 'hcxEnterpriseSites/deploy.bicep' = [for (hcxEnterpriseSite, index) in hcxEnterpriseSites: { - name: '${uniqueString(deployment().name, location)}-privateCloud-hcxEnterpriseSite-${index}' +module privateCloud_addons 'addons/deploy.bicep' = [for (addon, index) in addons: { + name: '${uniqueString(deployment().name, location)}-privateCloud-addon-${index}' params: { privateCloudName: name - name: hcxEnterpriseSite.name + addonType: contains(addon, 'addonType') ? addon.addonType : '' + name: addon.name enableDefaultTelemetry: enableReferencedModulesTelemetry } }] -module privateCloud_clusters 'clusters/deploy.bicep' = [for (cluster, index) in clusters: { - name: '${uniqueString(deployment().name, location)}-privateCloud-cluster-${index}' +module privateCloud_hcxEnterpriseSites 'hcxEnterpriseSites/deploy.bicep' = [for (hcxEnterpriseSite, index) in hcxEnterpriseSites: { + name: '${uniqueString(deployment().name, location)}-privateCloud-hcxEnterpriseSite-${index}' params: { privateCloudName: name - clusterSize: contains(cluster, 'clusterSize') ? cluster.clusterSize : - hosts: contains(cluster, 'hosts') ? cluster.hosts : [] - name: cluster.name - sku: cluster.sku + name: hcxEnterpriseSite.name enableDefaultTelemetry: enableReferencedModulesTelemetry } }] -module privateCloud_scriptExecutions 'scriptExecutions/deploy.bicep' = [for (scriptExecution, index) in scriptExecutions: { - name: '${uniqueString(deployment().name, location)}-privateCloud-scriptExecution-${index}' +module privateCloud_globalReachConnections 'globalReachConnections/deploy.bicep' = [for (globalReachConnection, index) in globalReachConnections: { + name: '${uniqueString(deployment().name, location)}-privateCloud-globalReachConnection-${index}' params: { privateCloudName: name - failureReason: contains(scriptExecution, 'failureReason') ? scriptExecution.failureReason : '' - hiddenParameters: contains(scriptExecution, 'hiddenParameters') ? scriptExecution.hiddenParameters : [] - name: scriptExecution.name - namedOutputs: contains(scriptExecution, 'namedOutputs') ? scriptExecution.namedOutputs : {} - output: contains(scriptExecution, 'output') ? scriptExecution.output : [] - parameters: contains(scriptExecution, 'parameters') ? scriptExecution.parameters : [] - retention: contains(scriptExecution, 'retention') ? scriptExecution.retention : '' - scriptCmdletId: contains(scriptExecution, 'scriptCmdletId') ? scriptExecution.scriptCmdletId : '' - timeout: contains(scriptExecution, 'timeout') ? scriptExecution.timeout : '' + authorizationKey: contains(globalReachConnection, 'authorizationKey') ? globalReachConnection.authorizationKey : '' + expressRouteId: contains(globalReachConnection, 'expressRouteId') ? globalReachConnection.expressRouteId : '' + name: globalReachConnection.name + peerExpressRouteCircuit: contains(globalReachConnection, 'peerExpressRouteCircuit') ? globalReachConnection.peerExpressRouteCircuit : '' enableDefaultTelemetry: enableReferencedModulesTelemetry } }] -module workloadNetworks_privateCloud_dnsServices 'workloadNetworks/dnsServices/deploy.bicep' = [for (dnsService, index) in dnsServices: { - name: '${uniqueString(deployment().name, location)}-privateCloud-dnsService-${index}' +module workloadNetworks_privateCloud_publicIPs 'workloadNetworks/publicIPs/deploy.bicep' = [for (publicIP, index) in publicIPs: { + name: '${uniqueString(deployment().name, location)}-privateCloud-publicIP-${index}' params: { privateCloudName: name workloadNetworkName: 'default' - defaultDnsZone: contains(dnsService, 'defaultDnsZone') ? dnsService.defaultDnsZone : '' - displayName: contains(dnsService, 'displayName') ? dnsService.displayName : '' - dnsServiceIp: contains(dnsService, 'dnsServiceIp') ? dnsService.dnsServiceIp : '' - fqdnZones: contains(dnsService, 'fqdnZones') ? dnsService.fqdnZones : [] - logLevel: contains(dnsService, 'logLevel') ? dnsService.logLevel : '' - name: dnsService.name - revision: contains(dnsService, 'revision') ? dnsService.revision : + displayName: contains(publicIP, 'displayName') ? publicIP.displayName : '' + name: publicIP.name + numberOfPublicIPs: contains(publicIP, 'numberOfPublicIPs') ? publicIP.numberOfPublicIPs : enableDefaultTelemetry: enableReferencedModulesTelemetry } }] @@ -343,30 +339,17 @@ module workloadNetworks_privateCloud_segments 'workloadNetworks/segments/deploy. } }] -module workloadNetworks_privateCloud_dnsZones 'workloadNetworks/dnsZones/deploy.bicep' = [for (dnsZone, index) in dnsZones: { - name: '${uniqueString(deployment().name, location)}-privateCloud-dnsZone-${index}' - params: { - privateCloudName: name - workloadNetworkName: 'default' - displayName: contains(dnsZone, 'displayName') ? dnsZone.displayName : '' - dnsServerIps: contains(dnsZone, 'dnsServerIps') ? dnsZone.dnsServerIps : [] - dnsServices: contains(dnsZone, 'dnsServices') ? dnsZone.dnsServices : - domain: contains(dnsZone, 'domain') ? dnsZone.domain : [] - name: dnsZone.name - revision: contains(dnsZone, 'revision') ? dnsZone.revision : - sourceIp: contains(dnsZone, 'sourceIp') ? dnsZone.sourceIp : '' - enableDefaultTelemetry: enableReferencedModulesTelemetry - } -}] - -module workloadNetworks_privateCloud_publicIPs 'workloadNetworks/publicIPs/deploy.bicep' = [for (publicIP, index) in publicIPs: { - name: '${uniqueString(deployment().name, location)}-privateCloud-publicIP-${index}' +module workloadNetworks_privateCloud_portMirroringProfiles 'workloadNetworks/portMirroringProfiles/deploy.bicep' = [for (portMirroringProfile, index) in portMirroringProfiles: { + name: '${uniqueString(deployment().name, location)}-privateCloud-portMirroringProfile-${index}' params: { privateCloudName: name workloadNetworkName: 'default' - displayName: contains(publicIP, 'displayName') ? publicIP.displayName : '' - name: publicIP.name - numberOfPublicIPs: contains(publicIP, 'numberOfPublicIPs') ? publicIP.numberOfPublicIPs : + destination: contains(portMirroringProfile, 'destination') ? portMirroringProfile.destination : '' + direction: contains(portMirroringProfile, 'direction') ? portMirroringProfile.direction : '' + displayName: contains(portMirroringProfile, 'displayName') ? portMirroringProfile.displayName : '' + name: portMirroringProfile.name + revision: contains(portMirroringProfile, 'revision') ? portMirroringProfile.revision : + source: contains(portMirroringProfile, 'source') ? portMirroringProfile.source : '' enableDefaultTelemetry: enableReferencedModulesTelemetry } }] @@ -384,17 +367,18 @@ module workloadNetworks_privateCloud_vmGroups 'workloadNetworks/vmGroups/deploy. } }] -module workloadNetworks_privateCloud_portMirroringProfiles 'workloadNetworks/portMirroringProfiles/deploy.bicep' = [for (portMirroringProfile, index) in portMirroringProfiles: { - name: '${uniqueString(deployment().name, location)}-privateCloud-portMirroringProfile-${index}' +module workloadNetworks_privateCloud_dnsServices 'workloadNetworks/dnsServices/deploy.bicep' = [for (dnsService, index) in dnsServices: { + name: '${uniqueString(deployment().name, location)}-privateCloud-dnsService-${index}' params: { privateCloudName: name workloadNetworkName: 'default' - destination: contains(portMirroringProfile, 'destination') ? portMirroringProfile.destination : '' - direction: contains(portMirroringProfile, 'direction') ? portMirroringProfile.direction : '' - displayName: contains(portMirroringProfile, 'displayName') ? portMirroringProfile.displayName : '' - name: portMirroringProfile.name - revision: contains(portMirroringProfile, 'revision') ? portMirroringProfile.revision : - source: contains(portMirroringProfile, 'source') ? portMirroringProfile.source : '' + defaultDnsZone: contains(dnsService, 'defaultDnsZone') ? dnsService.defaultDnsZone : '' + displayName: contains(dnsService, 'displayName') ? dnsService.displayName : '' + dnsServiceIp: contains(dnsService, 'dnsServiceIp') ? dnsService.dnsServiceIp : '' + fqdnZones: contains(dnsService, 'fqdnZones') ? dnsService.fqdnZones : [] + logLevel: contains(dnsService, 'logLevel') ? dnsService.logLevel : '' + name: dnsService.name + revision: contains(dnsService, 'revision') ? dnsService.revision : enableDefaultTelemetry: enableReferencedModulesTelemetry } }] @@ -412,6 +396,22 @@ module workloadNetworks_privateCloud_dhcpConfigurations 'workloadNetworks/dhcpCo } }] +module workloadNetworks_privateCloud_dnsZones 'workloadNetworks/dnsZones/deploy.bicep' = [for (dnsZone, index) in dnsZones: { + name: '${uniqueString(deployment().name, location)}-privateCloud-dnsZone-${index}' + params: { + privateCloudName: name + workloadNetworkName: 'default' + displayName: contains(dnsZone, 'displayName') ? dnsZone.displayName : '' + dnsServerIps: contains(dnsZone, 'dnsServerIps') ? dnsZone.dnsServerIps : [] + dnsServices: contains(dnsZone, 'dnsServices') ? dnsZone.dnsServices : + domain: contains(dnsZone, 'domain') ? dnsZone.domain : [] + name: dnsZone.name + revision: contains(dnsZone, 'revision') ? dnsZone.revision : + sourceIp: contains(dnsZone, 'sourceIp') ? dnsZone.sourceIp : '' + enableDefaultTelemetry: enableReferencedModulesTelemetry + } +}] + // =========== // // Outputs // // =========== // diff --git a/utilities/tools/REST2CARML/private/module/Expand-DeploymentBlock.ps1 b/utilities/tools/REST2CARML/private/module/Expand-DeploymentBlock.ps1 index 6ddf91616b..d229daccc6 100644 --- a/utilities/tools/REST2CARML/private/module/Expand-DeploymentBlock.ps1 +++ b/utilities/tools/REST2CARML/private/module/Expand-DeploymentBlock.ps1 @@ -30,6 +30,25 @@ function Expand-DeploymentBlock { $relevantProperties = $DeclarationBlock.content | Where-Object { (Get-LineIndentation $_) -eq $topLevelIndent -and $_ -notlike "*$($NestedType): {*" -and $_ -like '*:*' } $topLevelElementNames = $relevantProperties | ForEach-Object { ($_ -split ':')[0].Trim() } + ########################################### + ## Collect specification information ## + ########################################### + switch ($NestedType) { + 'properties' { + $declarationElem = $declarationBlock.content[0] -split ' ' + $DeclarationBlock['resourceName'] = $declarationElem[1] + $DeclarationBlock['resourceType'] = ($declarationElem[2] -split '@')[0].Trim("'") + $DeclarationBlock['resourceVersion'] = (($declarationElem[2] -split '@')[1])[0..9] -join '' # The date always has 10 characters + break + } + 'params' { + $declarationElem = $declarationBlock.content[0] -split ' ' + $DeclarationBlock['moduleName'] = $declarationElem[1] + $DeclarationBlock['modulePath'] = $declarationElem[2].Trim("'") + break + } + } + #################################### ## Collect top level elements ## #################################### diff --git a/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 b/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 index c2e3bf5dff..afcbbecc0c 100644 --- a/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 +++ b/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 @@ -261,6 +261,10 @@ function Set-ModuleTemplate { $locationParameterExists = ($templateContent | Where-Object { $_ -like 'param location *' }).Count -gt 0 + $matchingExistingResource = $existingTemplateContent.resources | Where-Object { + $_.resourceType -eq $FullResourceType -and $_.resourceName -eq $resourceTypeSingular + } + # Add a space in between the new section and the previous one in case no space exists if (-not [String]::IsNullOrEmpty($templateContent[-1])) { $templateContent += '' @@ -328,12 +332,22 @@ function Set-ModuleTemplate { } foreach ($parameter in ($ModuleData.parameters | Where-Object { $_.level -eq 0 -and $_.name -ne 'properties' } | Sort-Object -Property 'name')) { - $templateContent += ' {0}: {0}' -f $parameter.name + if ($matchingExistingResource.topLevelElements.name -notcontains $parameter.name) { + $templateContent += ' {0}: {0}' -f $parameter.name + } else { + $existingProperty = $matchingExistingResource.topLevelElements | Where-Object { $_.name -eq $parameter.name } + $templateContent += $existingProperty.content + } } $templateContent += ' properties: {' foreach ($parameter in ($ModuleData.parameters | Where-Object { $_.level -eq 1 -and $_.Parent -eq 'properties' } | Sort-Object -Property 'name')) { - $templateContent += ' {0}: {0}' -f $parameter.name + if ($matchingExistingResource.nestedElements.name -notcontains $parameter.name) { + $templateContent += ' {0}: {0}' -f $parameter.name + } else { + $existingProperty = $matchingExistingResource.nestedElements | Where-Object { $_.name -eq $parameter.name } + $templateContent += $existingProperty.content + } } $templateContent += @( @@ -381,6 +395,7 @@ function Set-ModuleTemplate { # Add primary child parameters $allParam = $dataBlock.data.parameters + $dataBlock.data.additionalParameters foreach ($parameter in (($allParam | Where-Object { $_.Level -in @(0, 1) -and $_.name -ne 'properties' -and ([String]::IsNullOrEmpty($_.Parent) -or $_.Parent -eq 'properties') }) | Sort-Object -Property 'Name')) { + # TODO: Make idempotent $wouldBeParameter = Get-FormattedModuleParameter -ParameterData $parameter | Where-Object { $_ -like 'param *' } | ForEach-Object { $_ -replace 'param ', '' } $wouldBeParamElem = $wouldBeParameter -split ' = ' $parameter.name = ($wouldBeParamElem -split ' ')[0] From 1316319cffd3d666158a3a9c49d6021ef5cfe61d Mon Sep 17 00:00:00 2001 From: MrMCake Date: Tue, 1 Nov 2022 15:48:15 +0100 Subject: [PATCH 09/30] Added additional logic for idempotency --- .../private/module/Set-ModuleTemplate.ps1 | 54 ++++++++++++++++--- 1 file changed, 46 insertions(+), 8 deletions(-) diff --git a/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 b/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 index afcbbecc0c..a111e9aa87 100644 --- a/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 +++ b/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 @@ -258,6 +258,7 @@ function Set-ModuleTemplate { ################### ## DEPLOYMENTS ## ################### + #region resources & modules $locationParameterExists = ($templateContent | Where-Object { $_ -like 'param location *' }).Count -gt 0 @@ -356,6 +357,7 @@ function Set-ModuleTemplate { '' ) + # TODO: Add 'other' resources? Like those where we reference 'existing' # Add additional resources such as extensions (like RBAC) # ------------------------------------------------------- @@ -373,38 +375,69 @@ function Set-ModuleTemplate { $proxyParentName = Split-Path (Split-Path $dataBlock.identifier -Parent) -Leaf } + $moduleName = '{0}{1}_{2}' -f ($hasProxyParent ? "$($proxyParentName)_" : ''), $resourceTypeSingular, $childResourceType + $modulePath = '{0}{1}/deploy.bicep' -f ($hasProxyParent ? "$proxyParentName/" : ''), $childResourceType + + $matchingModule = $existingTemplateContent.modules | Where-Object { $_.moduleName -eq $moduleName -and $_.modulePath -eq $modulePath } + + # TODO: Also consider 'singular' children (if we can detect it) $templateContent += @( - "module $($hasProxyParent ? "$($proxyParentName)_" : '')$($resourceTypeSingular)_$($childResourceType) '$($hasProxyParent ? "$proxyParentName/" : '')$($childResourceType)/deploy.bicep' = [for ($($childResourceTypeSingular), index) in $($childResourceType): {", - " name: '`${uniqueString(deployment().name$($locationParameterExists ? ', location' : ''))}-$($resourceTypeSingular)-$($childResourceTypeSingular)-`${index}'", - ' params: {' + "module $moduleName '$modulePath' = [for ($($childResourceTypeSingular), index) in $($childResourceType): {" ) + if ($matchingModule.topLevelElements.name -notcontains 'name') { + $templateContent += " name: '`${uniqueString(deployment().name$($locationParameterExists ? ', location' : ''))}-$($resourceTypeSingular)-$($childResourceTypeSingular)-`${index}'" + } else { + $existingParam = $matchingModule.topLevelElements | Where-Object { $_.name -eq 'name' } + $templateContent += $existingParam.content + } + + $templateContent += ' params: {' + $templateContent += @() + + $alreadyAddedParams = @() + # All param names of parents foreach ($parentResourceType in $parentResourceTypes) { - $templateContent += ' {0}Name: {0}Name' -f ((Get-ResourceTypeSingularName -ResourceType $parentResourceType) -split '/')[-1] + $parentParamName = ((Get-ResourceTypeSingularName -ResourceType $parentResourceType) -split '/')[-1] + $templateContent += ' {0}Name: {0}Name' -f $parentParamName + $alreadyAddedParams += $parentParamName } # Itself - $templateContent += ' {0}Name: name' -f ((Get-ResourceTypeSingularName -ResourceType ($FullResourceType -split '/')[-1]) -split '/')[-1] + $selfParamName = ((Get-ResourceTypeSingularName -ResourceType ($FullResourceType -split '/')[-1]) -split '/')[-1] + $templateContent += ' {0}Name: name' -f $selfParamName + $alreadyAddedParams += $selfParamName # Any proxy default if any if ($hasProxyParent) { $proxyDefaultValue = ($dataBlock.metadata.urlPath -split '\/')[-3] - $templateContent += " {0}Name: '{1}'" -f (Get-ResourceTypeSingularName -ResourceType ($proxyParentName -split '/')[-1]), $proxyDefaultValue + $proxyParamName = Get-ResourceTypeSingularName -ResourceType ($proxyParentName -split '/')[-1] + $templateContent += " {0}Name: '{1}'" -f $proxyParamName, $proxyDefaultValue + $alreadyAddedParams += $proxyParamName } # Add primary child parameters $allParam = $dataBlock.data.parameters + $dataBlock.data.additionalParameters foreach ($parameter in (($allParam | Where-Object { $_.Level -in @(0, 1) -and $_.name -ne 'properties' -and ([String]::IsNullOrEmpty($_.Parent) -or $_.Parent -eq 'properties') }) | Sort-Object -Property 'Name')) { - # TODO: Make idempotent $wouldBeParameter = Get-FormattedModuleParameter -ParameterData $parameter | Where-Object { $_ -like 'param *' } | ForEach-Object { $_ -replace 'param ', '' } $wouldBeParamElem = $wouldBeParameter -split ' = ' $parameter.name = ($wouldBeParamElem -split ' ')[0] + + if ($matchingModule.nestedElements.name -notcontains $parameter.name) { + $existingParam = $matchingModule.nestedElements | Where-Object { $_.name -eq $parameter.name } + if ($alreadyAddedParams -notcontains $existingParam.name) { + $templateContent += $existingParam.content + } + continue + } + if ($wouldBeParamElem.count -gt 1) { # With default if ($parameter.name -eq 'lock') { # Special handling as we pass the parameter down to the child - $templateContent += " lock: contains($($childResourceTypeSingular), 'lock') ? $($childResourceTypeSingular).lock : lock" + $templateContent += " $($parameter.name): contains($($childResourceTypeSingular), 'lock') ? $($childResourceTypeSingular).lock : lock" + $alreadyAddedParams += $parameter.name continue } @@ -416,9 +449,11 @@ function Set-ModuleTemplate { } $templateContent += " $($parameter.name): contains($($childResourceTypeSingular), '$($parameter.name)') ? $($childResourceTypeSingular).$($parameter.name) : $($wouldBeParamValue)" + $alreadyAddedParams += $parameter.name } else { # No default $templateContent += " $($parameter.name): $($childResourceTypeSingular).$($parameter.name)" + $alreadyAddedParams += $parameter.name } } @@ -430,6 +465,7 @@ function Set-ModuleTemplate { '' ) } + #endregion ####################################### ## Create template outputs section ## @@ -440,6 +476,8 @@ function Set-ModuleTemplate { $templateContent += '' } + # TODO: Make idempotent + # Output header comment $templateContent += @( '// =========== //' From 2077533df6799ff3fc5b142479b1920d2891600e Mon Sep 17 00:00:00 2001 From: MrMCake Date: Tue, 1 Nov 2022 20:03:47 +0100 Subject: [PATCH 10/30] Further updates to idempotency --- .../extension/Set-DiagnosticModuleData.ps1 | 27 +++++---- .../private/extension/Set-LockModuleData.ps1 | 25 +++++---- .../Set-PrivateEndpointModuleData.ps1 | 47 ++++++++-------- .../Set-RoleAssignmentsModuleData.ps1 | 33 ++++++----- .../private/module/Expand-DeploymentBlock.ps1 | 10 ++-- .../REST2CARML/private/module/Set-Module.ps1 | 2 +- .../private/module/Set-ModuleTemplate.ps1 | 56 +++++++++++++++++-- .../private/specs/Resolve-ModuleData.ps1 | 1 + 8 files changed, 129 insertions(+), 72 deletions(-) diff --git a/utilities/tools/REST2CARML/private/extension/Set-DiagnosticModuleData.ps1 b/utilities/tools/REST2CARML/private/extension/Set-DiagnosticModuleData.ps1 index 265b48497b..1f49f77633 100644 --- a/utilities/tools/REST2CARML/private/extension/Set-DiagnosticModuleData.ps1 +++ b/utilities/tools/REST2CARML/private/extension/Set-DiagnosticModuleData.ps1 @@ -85,15 +85,18 @@ function Set-DiagnosticModuleData { } ) - $diagnosticResource = @( - "resource $($resourceTypeSingular)_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) {" - ' name: diagnosticSettingsName' - ' properties: {' - ' storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null' - ' workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null' - ' eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null' - ' eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null' - ) + $diagnosticResource = @{ + name = "$($resourceTypeSingular)_diagnosticSettings" + content = @( + "resource $($resourceTypeSingular)_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) {" + ' name: diagnosticSettingsName' + ' properties: {' + ' storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null' + ' workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null' + ' eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null' + ' eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null' + ) + } # Metric-specific if ($diagnosticOptions.Metrics) { @@ -127,7 +130,7 @@ function Set-DiagnosticModuleData { ) } - $diagnosticResource += ' metrics: diagnosticsMetrics' + $diagnosticResource.content += ' metrics: diagnosticsMetrics' } # Log-specific @@ -156,10 +159,10 @@ function Set-DiagnosticModuleData { ) } - $diagnosticResource += ' logs: diagnosticsLogs' + $diagnosticResource.content += ' logs: diagnosticsLogs' } - $diagnosticResource += @( + $diagnosticResource.content += @( ' }' " scope: $resourceTypeSingular" '}' diff --git a/utilities/tools/REST2CARML/private/extension/Set-LockModuleData.ps1 b/utilities/tools/REST2CARML/private/extension/Set-LockModuleData.ps1 index e15e939f06..81dad1fa8e 100644 --- a/utilities/tools/REST2CARML/private/extension/Set-LockModuleData.ps1 +++ b/utilities/tools/REST2CARML/private/extension/Set-LockModuleData.ps1 @@ -60,17 +60,20 @@ function Set-LockModuleData { } ) - $ModuleData.resources += @( - "resource keyVault_lock 'Microsoft.Authorization/locks@2017-04-01' = if (!empty(lock)) {" - " name: '`${$resourceTypeSingular.name}-`${lock}-lock'" - ' properties: {' - ' level: any(lock)' - " notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.'" - ' }' - ' scope: {0}' -f $resourceTypeSingular - '}' - '' - ) + $ModuleData.resources += @{ + name = "$($resourceTypeSingular)_lock" + content = @( + "resource @($resourceTypeSingular)_lock 'Microsoft.Authorization/locks@2017-04-01' = if (!empty(lock)) {" + " name: '`${$resourceTypeSingular.name}-`${lock}-lock'" + ' properties: {' + ' level: any(lock)' + " notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.'" + ' }' + ' scope: {0}' -f $resourceTypeSingular + '}' + '' + ) + } } end { diff --git a/utilities/tools/REST2CARML/private/extension/Set-PrivateEndpointModuleData.ps1 b/utilities/tools/REST2CARML/private/extension/Set-PrivateEndpointModuleData.ps1 index 7a5ebd8d10..26769e9011 100644 --- a/utilities/tools/REST2CARML/private/extension/Set-PrivateEndpointModuleData.ps1 +++ b/utilities/tools/REST2CARML/private/extension/Set-PrivateEndpointModuleData.ps1 @@ -61,28 +61,31 @@ function Set-PrivateEndpointModuleData { } ) - $ModuleData.resources += @( - "module $($resourceTypeSingular)_privateEndpoints '../../Microsoft.Network/privateEndpoints/deploy.bicep' = [for (privateEndpoint,index) in privateEndpoints: {" - " name: '`${uniqueString(deployment().name, location)}-$resourceTypeSingular-PrivateEndpoint-`${index}'" - ' params: {' - ' groupIds: [' - ' privateEndpoint.service' - ' ]' - " name: contains(privateEndpoint,'name') ? privateEndpoint.name : 'pe-`${last(split($resourceTypeSingular.id, '/'))}-`${privateEndpoint.service}-`${index}'" - ' serviceResourceId: {0}.id' -f $resourceTypeSingular - ' subnetResourceId: privateEndpoint.subnetResourceId' - ' enableDefaultTelemetry: enableReferencedModulesTelemetry' - " location: reference(split(privateEndpoint.subnetResourceId,'/subnets/')[0], '2020-06-01', 'Full').location" - " lock: contains(privateEndpoint,'lock') ? privateEndpoint.lock : lock" - " privateDnsZoneGroup: contains(privateEndpoint,'privateDnsZoneGroup') ? privateEndpoint.privateDnsZoneGroup : {}" - " roleAssignments: contains(privateEndpoint,'roleAssignments') ? privateEndpoint.roleAssignments : []" - " tags: contains(privateEndpoint,'tags') ? privateEndpoint.tags : {}" - " manualPrivateLinkServiceConnections: contains(privateEndpoint,'manualPrivateLinkServiceConnections') ? privateEndpoint.manualPrivateLinkServiceConnections : []" - " customDnsConfigs: contains(privateEndpoint,'customDnsConfigs') ? privateEndpoint.customDnsConfigs : []" - ' }' - '}]' - '' - ) + $ModuleData.modules += @{ + name = "$($resourceTypeSingular)_privateEndpoints" + content = @( + "module $($resourceTypeSingular)_privateEndpoints '../../Microsoft.Network/privateEndpoints/deploy.bicep' = [for (privateEndpoint,index) in privateEndpoints: {" + " name: '`${uniqueString(deployment().name, location)}-$resourceTypeSingular-PrivateEndpoint-`${index}'" + ' params: {' + ' groupIds: [' + ' privateEndpoint.service' + ' ]' + " name: contains(privateEndpoint,'name') ? privateEndpoint.name : 'pe-`${last(split($resourceTypeSingular.id, '/'))}-`${privateEndpoint.service}-`${index}'" + ' serviceResourceId: {0}.id' -f $resourceTypeSingular + ' subnetResourceId: privateEndpoint.subnetResourceId' + ' enableDefaultTelemetry: enableReferencedModulesTelemetry' + " location: reference(split(privateEndpoint.subnetResourceId,'/subnets/')[0], '2020-06-01', 'Full').location" + " lock: contains(privateEndpoint,'lock') ? privateEndpoint.lock : lock" + " privateDnsZoneGroup: contains(privateEndpoint,'privateDnsZoneGroup') ? privateEndpoint.privateDnsZoneGroup : {}" + " roleAssignments: contains(privateEndpoint,'roleAssignments') ? privateEndpoint.roleAssignments : []" + " tags: contains(privateEndpoint,'tags') ? privateEndpoint.tags : {}" + " manualPrivateLinkServiceConnections: contains(privateEndpoint,'manualPrivateLinkServiceConnections') ? privateEndpoint.manualPrivateLinkServiceConnections : []" + " customDnsConfigs: contains(privateEndpoint,'customDnsConfigs') ? privateEndpoint.customDnsConfigs : []" + ' }' + '}]' + '' + ) + } } end { diff --git a/utilities/tools/REST2CARML/private/extension/Set-RoleAssignmentsModuleData.ps1 b/utilities/tools/REST2CARML/private/extension/Set-RoleAssignmentsModuleData.ps1 index 84d3776761..106f0fd537 100644 --- a/utilities/tools/REST2CARML/private/extension/Set-RoleAssignmentsModuleData.ps1 +++ b/utilities/tools/REST2CARML/private/extension/Set-RoleAssignmentsModuleData.ps1 @@ -71,21 +71,24 @@ function Set-RoleAssignmentsModuleData { } ) - $ModuleData.resources += @( - "module $($resourceTypeSingular)_roleAssignments '.bicep/nested_roleAssignments.bicep' = [for (roleAssignment,index) in roleAssignments: {" - " name: '`${uniqueString(deployment().name, location)}-$resourceTypeSingular-Rbac-`${index}'" - ' params: {' - " description: contains(roleAssignment,'description') ? roleAssignment.description : ''" - ' principalIds: roleAssignment.principalIds' - " principalType: contains(roleAssignment,'principalType') ? roleAssignment.principalType : ''" - ' roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName' - " condition: contains(roleAssignment,'condition') ? roleAssignment.condition : ''" - " delegatedManagedIdentityResourceId: contains(roleAssignment,'delegatedManagedIdentityResourceId') ? roleAssignment.delegatedManagedIdentityResourceId : ''" - " resourceId: $resourceTypeSingular.id" - ' }' - '}]' - '' - ) + $ModuleData.modules += @{ + name = "$($resourceTypeSingular)_roleAssignments" + content = @( + "module $($resourceTypeSingular)_roleAssignments '.bicep/nested_roleAssignments.bicep' = [for (roleAssignment,index) in roleAssignments: {" + " name: '`${uniqueString(deployment().name, location)}-$resourceTypeSingular-Rbac-`${index}'" + ' params: {' + " description: contains(roleAssignment,'description') ? roleAssignment.description : ''" + ' principalIds: roleAssignment.principalIds' + " principalType: contains(roleAssignment,'principalType') ? roleAssignment.principalType : ''" + ' roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName' + " condition: contains(roleAssignment,'condition') ? roleAssignment.condition : ''" + " delegatedManagedIdentityResourceId: contains(roleAssignment,'delegatedManagedIdentityResourceId') ? roleAssignment.delegatedManagedIdentityResourceId : ''" + " resourceId: $resourceTypeSingular.id" + ' }' + '}]' + '' + ) + } $fileContent = @() $rawContent = Get-Content -Path (Join-Path $script:src 'nested_roleAssignments.bicep') -Raw diff --git a/utilities/tools/REST2CARML/private/module/Expand-DeploymentBlock.ps1 b/utilities/tools/REST2CARML/private/module/Expand-DeploymentBlock.ps1 index d229daccc6..9733b356ee 100644 --- a/utilities/tools/REST2CARML/private/module/Expand-DeploymentBlock.ps1 +++ b/utilities/tools/REST2CARML/private/module/Expand-DeploymentBlock.ps1 @@ -36,15 +36,15 @@ function Expand-DeploymentBlock { switch ($NestedType) { 'properties' { $declarationElem = $declarationBlock.content[0] -split ' ' - $DeclarationBlock['resourceName'] = $declarationElem[1] - $DeclarationBlock['resourceType'] = ($declarationElem[2] -split '@')[0].Trim("'") - $DeclarationBlock['resourceVersion'] = (($declarationElem[2] -split '@')[1])[0..9] -join '' # The date always has 10 characters + $DeclarationBlock['name'] = $declarationElem[1] + $DeclarationBlock['type'] = ($declarationElem[2] -split '@')[0].Trim("'") + $DeclarationBlock['version'] = (($declarationElem[2] -split '@')[1])[0..9] -join '' # The date always has 10 characters break } 'params' { $declarationElem = $declarationBlock.content[0] -split ' ' - $DeclarationBlock['moduleName'] = $declarationElem[1] - $DeclarationBlock['modulePath'] = $declarationElem[2].Trim("'") + $DeclarationBlock['name'] = $declarationElem[1] + $DeclarationBlock['path'] = $declarationElem[2].Trim("'") break } } diff --git a/utilities/tools/REST2CARML/private/module/Set-Module.ps1 b/utilities/tools/REST2CARML/private/module/Set-Module.ps1 index b58bfe2e06..b3d4644210 100644 --- a/utilities/tools/REST2CARML/private/module/Set-Module.ps1 +++ b/utilities/tools/REST2CARML/private/module/Set-Module.ps1 @@ -112,7 +112,7 @@ function Set-Module { Set-ModuleReadMe -TemplateFilePath $templatePath -Verbose:$false } } catch { - Write-Warning "Invocation of 'Set-ModuleReadMe' fuction for template in path [$templatePath] failed. Please review the template and re-run the command `Set-ModuleReadMe -TemplateFilePath '$templatePath'``" + Write-Warning "Invocation of 'Set-ModuleReadMe' function for template in path [$templatePath] failed. Please review the template and re-run the command `Set-ModuleReadMe -TemplateFilePath '$templatePath'``" } } diff --git a/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 b/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 index a111e9aa87..dbe676ceaa 100644 --- a/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 +++ b/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 @@ -81,7 +81,10 @@ function Set-ModuleTemplate { # If the child's parent's parentUrlPath is empty, this parent has no PUT rest command which indicates it cannot be created independently [String]::IsNullOrEmpty($_.metadata.parentUrlPath) } - $linkedChildren += $indirectChildren + + if ($indirectChildren) { + $linkedChildren += $indirectChildren + } # Collect parent resources to use for parent type references $typeElem = $FullResourceType -split '/' @@ -357,12 +360,28 @@ function Set-ModuleTemplate { '' ) - # TODO: Add 'other' resources? Like those where we reference 'existing' + # If a template already exists, add 'extra' resources that are not yet part of the template content + # ------------------------------------------------------------------------------------------------- + $preExistingExtraResources = $existingTemplateContent.resources | Where-Object { + $_.resourceName -notIn ($ModuleData.resources.name + 'defaultTelemetry' + $resourceTypeSingular) + } + foreach ($resource in $preExistingExtraResources) { + $templateContent += $resource.content + $templateContent += '' + } - # Add additional resources such as extensions (like RBAC) - # ------------------------------------------------------- + # Add additional resources such as extensions (like DiagnosticSettigs) + # -------------------------------------------------------------------- # Other collected resources - $templateContent += $ModuleData.resources + foreach ($additionalResource in $ModuleData.resources) { + if ($existingTemplateContent.resources.resourceName -notcontains $additionalResource.name) { + $templateContent += $additionalResource.content + } else { + $existingResource = $existingTemplateContent.resources | Where-Object { $_.resourceName -eq $additionalResource.name } + $templateContent += $existingResource.content + $templateContent += '' + } + } # Add child-module references # --------------------------- @@ -378,7 +397,7 @@ function Set-ModuleTemplate { $moduleName = '{0}{1}_{2}' -f ($hasProxyParent ? "$($proxyParentName)_" : ''), $resourceTypeSingular, $childResourceType $modulePath = '{0}{1}/deploy.bicep' -f ($hasProxyParent ? "$proxyParentName/" : ''), $childResourceType - $matchingModule = $existingTemplateContent.modules | Where-Object { $_.moduleName -eq $moduleName -and $_.modulePath -eq $modulePath } + $matchingModule = $existingTemplateContent.modules | Where-Object { $_.name -eq $moduleName -and $_.path -eq $modulePath } # TODO: Also consider 'singular' children (if we can detect it) $templateContent += @( @@ -465,6 +484,25 @@ function Set-ModuleTemplate { '' ) } + + # TODO : Add other module references + # ---------------------------------- + foreach ($additionalResource in $ModuleData.modules) { + if ($existingTemplateContent.modules.name -notcontains $additionalResource.name) { + $templateContent += $additionalResource.content + } else { + $existingResource = $existingTemplateContent.modules | Where-Object { $_.name -eq $additionalResource.name } + $templateContent += $existingResource.content + $templateContent += '' + } + } + + # TODO: Extra extra modules + # $preExistingExtraModules = $existingTemplateContent.modules | Where-Object { $_.name -notIn $ModuleData.modules.name } + # foreach ($preExistingMdoule in $preExistingExtraModules) { + # # Beware: The pre-existing content also contains e.g. 'linkedChildren' we add as part of the template generation + # } + #endregion ####################################### @@ -500,6 +538,12 @@ function Set-ModuleTemplate { ) } + # Extra outputs + foreach ($output in $existingTemplateContent.outputs | Where-Object { $_.name -notin @('name', 'resourceId', 'resourceGroupName') }) { + $templateContent += $output.content + $templateContent += '' + } + # Update file # ----------- Set-Content -Path $templateFilePath -Value ($templateContent | Out-String).TrimEnd() -Force diff --git a/utilities/tools/REST2CARML/private/specs/Resolve-ModuleData.ps1 b/utilities/tools/REST2CARML/private/specs/Resolve-ModuleData.ps1 index 62ebfec41d..146ae7f5f2 100644 --- a/utilities/tools/REST2CARML/private/specs/Resolve-ModuleData.ps1 +++ b/utilities/tools/REST2CARML/private/specs/Resolve-ModuleData.ps1 @@ -72,6 +72,7 @@ function Resolve-ModuleData { parameters = $filteredList additionalParameters = @() resources = @() + modules = @() variables = @() outputs = @() additionalFiles = @() From 9ce4b51856ee9886d369fd63ab76ea44b5a643ef Mon Sep 17 00:00:00 2001 From: MrMCake Date: Wed, 2 Nov 2022 18:11:02 +0100 Subject: [PATCH 11/30] Fixed typo --- ....maintenance.maintenanceconfigurations.yml | 40 +++++ ....maintenance.maintenanceconfigurations.yml | 145 ++++++++++++++++++ .../.bicep/nested_roleAssignments.bicep | 69 +++++++++ .../.test/common/deploy.bicep | 0 .../.test/min/deploy.bicep | 0 .../maintenanceConfigurations/deploy.bicep | 118 ++++++++++++++ .../maintenanceConfigurations/version.json | 4 + .../private/extension/Set-LockModuleData.ps1 | 2 +- 8 files changed, 377 insertions(+), 1 deletion(-) create mode 100644 .azuredevops/modulePipelines/ms.maintenance.maintenanceconfigurations.yml create mode 100644 .github/workflows/ms.maintenance.maintenanceconfigurations.yml create mode 100644 modules/Microsoft.Maintenance/maintenanceConfigurations/.bicep/nested_roleAssignments.bicep create mode 100644 modules/Microsoft.Maintenance/maintenanceConfigurations/.test/common/deploy.bicep create mode 100644 modules/Microsoft.Maintenance/maintenanceConfigurations/.test/min/deploy.bicep create mode 100644 modules/Microsoft.Maintenance/maintenanceConfigurations/deploy.bicep create mode 100644 modules/Microsoft.Maintenance/maintenanceConfigurations/version.json diff --git a/.azuredevops/modulePipelines/ms.maintenance.maintenanceconfigurations.yml b/.azuredevops/modulePipelines/ms.maintenance.maintenanceconfigurations.yml new file mode 100644 index 0000000000..4655a2fbd3 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.maintenance.maintenanceconfigurations.yml @@ -0,0 +1,40 @@ +name: 'Maintenance - MaintenanceConfigurations' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +pr: none + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.maintenance.maintenanceconfigurations.yml' + - '/.azuredevops/pipelineTemplates/*.yml' + - '/modules/Microsoft.Maintenance/maintenanceConfigurations/*' + - '/utilities/pipelines/*' + exclude: + - '/utilities/pipelines/dependencies/*' + - '/**/*.md' + +variables: + - template: '../../settings.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/modules/Microsoft.Maintenance/maintenanceConfigurations' + +stages: + - template: /.azuredevops/pipelineTemplates/stages.module.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + prerelease: '${{ parameters.prerelease }}' \ No newline at end of file diff --git a/.github/workflows/ms.maintenance.maintenanceconfigurations.yml b/.github/workflows/ms.maintenance.maintenanceconfigurations.yml new file mode 100644 index 0000000000..e27a1ad683 --- /dev/null +++ b/.github/workflows/ms.maintenance.maintenanceconfigurations.yml @@ -0,0 +1,145 @@ +name: 'Maintenance: MaintenanceConfigurations' + +on: + workflow_dispatch: + inputs: + removeDeployment: + type: boolean + description: 'Remove deployed module' + required: false + default: true + prerelease: + type: boolean + description: 'Publish prerelease module' + required: false + default: false + push: + branches: + - main + paths: + - '.github/actions/templates/**' + - '.github/workflows/ms.maintenance.maintenanceconfigurations.yml' + - 'modules/Microsoft.Maintenance/maintenanceConfigurations/**' + - 'utilities/pipelines/**' + - '!utilities/pipelines/dependencies/**' + - '!*/**/readme.md' + +env: + variablesPath: 'settings.yml' + modulePath: 'modules/Microsoft.Maintenance/maintenanceConfigurations' + workflowPath: '.github/workflows/ms.maintenance.maintenanceconfigurations.yml' + AZURE_CREDENTIALS: ${{ secrets.AZURE_CREDENTIALS }} + ARM_SUBSCRIPTION_ID: '${{ secrets.ARM_SUBSCRIPTION_ID }}' + ARM_MGMTGROUP_ID: '${{ secrets.ARM_MGMTGROUP_ID }}' + ARM_TENANT_ID: '${{ secrets.ARM_TENANT_ID }}' + TOKEN_NAMEPREFIX: '${{ secrets.TOKEN_NAMEPREFIX }}' + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-20.04 + name: 'Initialize pipeline' + steps: + - name: 'Checkout' + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: 'Set input parameters to output variables' + id: get-workflow-param + uses: ./.github/actions/templates/getWorkflowInput + with: + workflowPath: '${{ env.workflowPath}}' + - name: 'Get parameter file paths' + id: get-module-test-file-paths + uses: ./.github/actions/templates/getModuleTestFiles + with: + modulePath: '${{ env.modulePath }}' + outputs: + removeDeployment: ${{ steps.get-workflow-param.outputs.removeDeployment }} + moduleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.moduleTestFilePaths }} + + ######################### + # Static validation # + ######################### + job_module_pester_validation: + runs-on: ubuntu-20.04 + name: 'Static validation' + steps: + - name: 'Checkout' + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Set environment variables + uses: ./.github/actions/templates/setEnvironmentVariables + with: + variablesPath: ${{ env.variablesPath }} + - name: 'Run tests' + uses: ./.github/actions/templates/validateModulePester + with: + modulePath: '${{ env.modulePath }}' + moduleTestFilePath: '${{ env.moduleTestFilePath }}' + + ############################# + # Deployment validation # + ############################# + job_module_deploy_validation: + runs-on: ubuntu-20.04 + name: 'Deployment validation' + needs: + - job_initialize_pipeline + - job_module_pester_validation + strategy: + fail-fast: false + matrix: + moduleTestFilePaths: ${{ fromJSON(needs.job_initialize_pipeline.outputs.moduleTestFilePaths) }} + steps: + - name: 'Checkout' + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Set environment variables + uses: ./.github/actions/templates/setEnvironmentVariables + with: + variablesPath: ${{ env.variablesPath }} + - name: 'Using test file [${{ matrix.moduleTestFilePaths }}]' + uses: ./.github/actions/templates/validateModuleDeployment + with: + templateFilePath: '${{ env.modulePath }}/${{ matrix.moduleTestFilePaths }}' + location: '${{ env.location }}' + resourceGroupName: '${{ env.resourceGroupName }}' + subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' + managementGroupId: '${{ secrets.ARM_MGMTGROUP_ID }}' + removeDeployment: '${{ needs.job_initialize_pipeline.outputs.removeDeployment }}' + + ################## + # Publishing # + ################## + job_publish_module: + name: 'Publishing' + if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master' || github.event.inputs.prerelease == 'true' + runs-on: ubuntu-20.04 + needs: + - job_module_deploy_validation + steps: + - name: 'Checkout' + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Set environment variables + uses: ./.github/actions/templates/setEnvironmentVariables + with: + variablesPath: ${{ env.variablesPath }} + - name: 'Publishing' + uses: ./.github/actions/templates/publishModule + with: + templateFilePath: '${{ env.modulePath }}/deploy.bicep' + templateSpecsRGName: '${{ env.templateSpecsRGName }}' + templateSpecsRGLocation: '${{ env.templateSpecsRGLocation }}' + templateSpecsDescription: '${{ env.templateSpecsDescription }}' + templateSpecsDoPublish: '${{ env.templateSpecsDoPublish }}' + bicepRegistryName: '${{ env.bicepRegistryName }}' + bicepRegistryRGName: '${{ env.bicepRegistryRGName }}' + bicepRegistryRgLocation: '${{ env.bicepRegistryRgLocation }}' + bicepRegistryDoPublish: '${{ env.bicepRegistryDoPublish }}' \ No newline at end of file diff --git a/modules/Microsoft.Maintenance/maintenanceConfigurations/.bicep/nested_roleAssignments.bicep b/modules/Microsoft.Maintenance/maintenanceConfigurations/.bicep/nested_roleAssignments.bicep new file mode 100644 index 0000000000..5710d6c99b --- /dev/null +++ b/modules/Microsoft.Maintenance/maintenanceConfigurations/.bicep/nested_roleAssignments.bicep @@ -0,0 +1,69 @@ +@sys.description('Required. The IDs of the principals to assign the role to.') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead.') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to.') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. The description of the role assignment.') +param description string = '' + +@sys.description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container"') +param condition string = '' + +@sys.description('Optional. Version of the condition.') +@allowed([ + '2.0' +]) +param conditionVersion string = '2.0' + +@sys.description('Optional. Id of the delegated managed identity resource.') +param delegatedManagedIdentityResourceId string = '' + +var builtInRoleNames = { + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','36243c78-bf99-498c-9df9-86d9f8d28608') + 'Role Based Access Control Administrator (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','f58310d9-a9f6-439a-9e8d-f62e7b41a168') + 'Scheduled Patching Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','cd08ab90-6b14-449c-ad9a-8f8e549482c6') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource maintenanceConfiguration 'Microsoft.Maintenance/maintenanceConfigurations@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for principalId in principalIds: { + name: guid(maintenanceConfiguration.id, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? any(principalType) : null + condition: !empty(condition) ? condition : null + conditionVersion: !empty(conditionVersion) && !empty(condition) ? conditionVersion : null + delegatedManagedIdentityResourceId: !empty(delegatedManagedIdentityResourceId) ? delegatedManagedIdentityResourceId : null + } + scope: maintenanceConfiguration +}] \ No newline at end of file diff --git a/modules/Microsoft.Maintenance/maintenanceConfigurations/.test/common/deploy.bicep b/modules/Microsoft.Maintenance/maintenanceConfigurations/.test/common/deploy.bicep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/Microsoft.Maintenance/maintenanceConfigurations/.test/min/deploy.bicep b/modules/Microsoft.Maintenance/maintenanceConfigurations/.test/min/deploy.bicep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/Microsoft.Maintenance/maintenanceConfigurations/deploy.bicep b/modules/Microsoft.Maintenance/maintenanceConfigurations/deploy.bicep new file mode 100644 index 0000000000..5a0bbfb081 --- /dev/null +++ b/modules/Microsoft.Maintenance/maintenanceConfigurations/deploy.bicep @@ -0,0 +1,118 @@ +// ============== // +// Parameters // +// ============== // + +@description('Required. Maintenance Configuration Name') +param name string + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Gets or sets extensionProperties of the maintenanceConfiguration') +param extensionProperties object = {} + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@description('Optional. Specify the type of lock.') +@allowed([ + '' + 'CanNotDelete' + 'ReadOnly' +]) +param lock string = '' + +@description('Optional. Gets or sets maintenanceScope of the configuration') +@allowed([ + 'Host' + 'OSImage' + 'Extension' + 'InGuestPatch' + 'SQLDB' + 'SQLManagedInstance' +]) +param maintenanceScope string = '' + +@description('Optional. Definition of a MaintenanceWindow') +param maintenanceWindow object = {} + +@description('Optional. Gets or sets namespace of the resource') +param namespace string = '' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') +param roleAssignments array = [] + +@description('Optional. Gets or sets tags of the resource') +param tags object = {} + +@description('Optional. Gets or sets the visibility of the configuration. The default value is \'Custom\'') +@allowed([ + 'Custom' + 'Public' +]) +param visibility string = '' + +// =============== // +// Deployments // +// =============== // + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + + +resource maintenanceConfiguration 'Microsoft.Maintenance/maintenanceConfigurations@2021-05-01' = { + location: location + name: name + tags: tags + properties: { + extensionProperties: extensionProperties + maintenanceScope: maintenanceScope + maintenanceWindow: maintenanceWindow + namespace: namespace + visibility: visibility + } +} + +resource @(maintenanceConfiguration)_lock 'Microsoft.Authorization/locks@2017-04-01' = if (!empty(lock)) { + name: '${maintenanceConfiguration.name}-${lock}-lock' + properties: { + level: any(lock) + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: maintenanceConfiguration +} + +module maintenanceConfiguration_roleAssignments '.bicep/nested_roleAssignments.bicep' = [for (roleAssignment,index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-maintenanceConfiguration-Rbac-${index}' + params: { + description: contains(roleAssignment,'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment,'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + condition: contains(roleAssignment,'condition') ? roleAssignment.condition : '' + delegatedManagedIdentityResourceId: contains(roleAssignment,'delegatedManagedIdentityResourceId') ? roleAssignment.delegatedManagedIdentityResourceId : '' + resourceId: maintenanceConfiguration.id + } +}] + +// =========== // +// Outputs // +// =========== // + +@description('The name of the maintenanceConfiguration.') +output name string = maintenanceConfiguration.name + +@description('The resource ID of the maintenanceConfiguration.') +output resourceId string = maintenanceConfiguration.id + +@description('The name of the resource group the maintenanceConfiguration was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.Maintenance/maintenanceConfigurations/version.json b/modules/Microsoft.Maintenance/maintenanceConfigurations/version.json new file mode 100644 index 0000000000..41f66cc990 --- /dev/null +++ b/modules/Microsoft.Maintenance/maintenanceConfigurations/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/utilities/tools/REST2CARML/private/extension/Set-LockModuleData.ps1 b/utilities/tools/REST2CARML/private/extension/Set-LockModuleData.ps1 index 81dad1fa8e..bf7f7033d1 100644 --- a/utilities/tools/REST2CARML/private/extension/Set-LockModuleData.ps1 +++ b/utilities/tools/REST2CARML/private/extension/Set-LockModuleData.ps1 @@ -63,7 +63,7 @@ function Set-LockModuleData { $ModuleData.resources += @{ name = "$($resourceTypeSingular)_lock" content = @( - "resource @($resourceTypeSingular)_lock 'Microsoft.Authorization/locks@2017-04-01' = if (!empty(lock)) {" + "resource $($resourceTypeSingular)_lock 'Microsoft.Authorization/locks@2017-04-01' = if (!empty(lock)) {" " name: '`${$resourceTypeSingular.name}-`${lock}-lock'" ' properties: {' ' level: any(lock)' From 08b1124608b54daf0cf7810ecdbf6819cebd094d Mon Sep 17 00:00:00 2001 From: MrMCake Date: Wed, 2 Nov 2022 20:41:49 +0100 Subject: [PATCH 12/30] Update to latest --- ....maintenance.maintenanceconfigurations.yml | 2 +- ....maintenance.maintenanceconfigurations.yml | 2 +- .../.bicep/nested_roleAssignments.bicep | 69 ---------- .../.test/common/deploy.bicep | 0 .../.test/min/deploy.bicep | 0 .../maintenanceConfigurations/deploy.bicep | 118 ------------------ .../maintenanceConfigurations/version.json | 4 - 7 files changed, 2 insertions(+), 193 deletions(-) delete mode 100644 modules/Microsoft.Maintenance/maintenanceConfigurations/.bicep/nested_roleAssignments.bicep delete mode 100644 modules/Microsoft.Maintenance/maintenanceConfigurations/.test/common/deploy.bicep delete mode 100644 modules/Microsoft.Maintenance/maintenanceConfigurations/.test/min/deploy.bicep delete mode 100644 modules/Microsoft.Maintenance/maintenanceConfigurations/deploy.bicep delete mode 100644 modules/Microsoft.Maintenance/maintenanceConfigurations/version.json diff --git a/.azuredevops/modulePipelines/ms.maintenance.maintenanceconfigurations.yml b/.azuredevops/modulePipelines/ms.maintenance.maintenanceconfigurations.yml index 4655a2fbd3..ca5076934a 100644 --- a/.azuredevops/modulePipelines/ms.maintenance.maintenanceconfigurations.yml +++ b/.azuredevops/modulePipelines/ms.maintenance.maintenanceconfigurations.yml @@ -37,4 +37,4 @@ stages: - template: /.azuredevops/pipelineTemplates/stages.module.yml parameters: removeDeployment: '${{ parameters.removeDeployment }}' - prerelease: '${{ parameters.prerelease }}' \ No newline at end of file + prerelease: '${{ parameters.prerelease }}' diff --git a/.github/workflows/ms.maintenance.maintenanceconfigurations.yml b/.github/workflows/ms.maintenance.maintenanceconfigurations.yml index e27a1ad683..01a93d71a8 100644 --- a/.github/workflows/ms.maintenance.maintenanceconfigurations.yml +++ b/.github/workflows/ms.maintenance.maintenanceconfigurations.yml @@ -142,4 +142,4 @@ jobs: bicepRegistryName: '${{ env.bicepRegistryName }}' bicepRegistryRGName: '${{ env.bicepRegistryRGName }}' bicepRegistryRgLocation: '${{ env.bicepRegistryRgLocation }}' - bicepRegistryDoPublish: '${{ env.bicepRegistryDoPublish }}' \ No newline at end of file + bicepRegistryDoPublish: '${{ env.bicepRegistryDoPublish }}' diff --git a/modules/Microsoft.Maintenance/maintenanceConfigurations/.bicep/nested_roleAssignments.bicep b/modules/Microsoft.Maintenance/maintenanceConfigurations/.bicep/nested_roleAssignments.bicep deleted file mode 100644 index 5710d6c99b..0000000000 --- a/modules/Microsoft.Maintenance/maintenanceConfigurations/.bicep/nested_roleAssignments.bicep +++ /dev/null @@ -1,69 +0,0 @@ -@sys.description('Required. The IDs of the principals to assign the role to.') -param principalIds array - -@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead.') -param roleDefinitionIdOrName string - -@sys.description('Required. The resource ID of the resource to apply the role assignment to.') -param resourceId string - -@sys.description('Optional. The principal type of the assigned principal ID.') -@allowed([ - 'ServicePrincipal' - 'Group' - 'User' - 'ForeignGroup' - 'Device' - '' -]) -param principalType string = '' - -@sys.description('Optional. The description of the role assignment.') -param description string = '' - -@sys.description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container"') -param condition string = '' - -@sys.description('Optional. Version of the condition.') -@allowed([ - '2.0' -]) -param conditionVersion string = '2.0' - -@sys.description('Optional. Id of the delegated managed identity resource.') -param delegatedManagedIdentityResourceId string = '' - -var builtInRoleNames = { - 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','b24988ac-6180-42a0-ab88-20f7382dd24c') - 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','92aaf0da-9dab-42b6-94a3-d43ce8d16293') - 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','73c42c96-874c-492b-b04d-ab87d138a893') - 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','641177b8-a67a-45b9-a033-47bc880bb21e') - 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','c7393b34-138c-406f-901b-d8cf2b17e6ae') - 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','b9331d33-8a36-4f8c-b097-4f54124fdb44') - 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','749f88d5-cbae-40b8-bcfc-e573ddc772fa') - 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','43d0d8ad-25c7-4714-9337-8ba259a9fe05') - 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','8e3af657-a8ff-443c-a75c-2fe8c4bcb635') - 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','acdd72a7-3385-48ef-bd42-f606fba81ae7') - 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','36243c78-bf99-498c-9df9-86d9f8d28608') - 'Role Based Access Control Administrator (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'Scheduled Patching Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','cd08ab90-6b14-449c-ad9a-8f8e549482c6') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') -} - -resource maintenanceConfiguration 'Microsoft.Maintenance/maintenanceConfigurations@2021-05-01' existing = { - name: last(split(resourceId, '/')) -} - -resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for principalId in principalIds: { - name: guid(maintenanceConfiguration.id, principalId, roleDefinitionIdOrName) - properties: { - description: description - roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName - principalId: principalId - principalType: !empty(principalType) ? any(principalType) : null - condition: !empty(condition) ? condition : null - conditionVersion: !empty(conditionVersion) && !empty(condition) ? conditionVersion : null - delegatedManagedIdentityResourceId: !empty(delegatedManagedIdentityResourceId) ? delegatedManagedIdentityResourceId : null - } - scope: maintenanceConfiguration -}] \ No newline at end of file diff --git a/modules/Microsoft.Maintenance/maintenanceConfigurations/.test/common/deploy.bicep b/modules/Microsoft.Maintenance/maintenanceConfigurations/.test/common/deploy.bicep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/modules/Microsoft.Maintenance/maintenanceConfigurations/.test/min/deploy.bicep b/modules/Microsoft.Maintenance/maintenanceConfigurations/.test/min/deploy.bicep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/modules/Microsoft.Maintenance/maintenanceConfigurations/deploy.bicep b/modules/Microsoft.Maintenance/maintenanceConfigurations/deploy.bicep deleted file mode 100644 index 5a0bbfb081..0000000000 --- a/modules/Microsoft.Maintenance/maintenanceConfigurations/deploy.bicep +++ /dev/null @@ -1,118 +0,0 @@ -// ============== // -// Parameters // -// ============== // - -@description('Required. Maintenance Configuration Name') -param name string - -@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') -param enableDefaultTelemetry bool = true - -@description('Optional. Gets or sets extensionProperties of the maintenanceConfiguration') -param extensionProperties object = {} - -@description('Optional. Location for all Resources.') -param location string = resourceGroup().location - -@description('Optional. Specify the type of lock.') -@allowed([ - '' - 'CanNotDelete' - 'ReadOnly' -]) -param lock string = '' - -@description('Optional. Gets or sets maintenanceScope of the configuration') -@allowed([ - 'Host' - 'OSImage' - 'Extension' - 'InGuestPatch' - 'SQLDB' - 'SQLManagedInstance' -]) -param maintenanceScope string = '' - -@description('Optional. Definition of a MaintenanceWindow') -param maintenanceWindow object = {} - -@description('Optional. Gets or sets namespace of the resource') -param namespace string = '' - -@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') -param roleAssignments array = [] - -@description('Optional. Gets or sets tags of the resource') -param tags object = {} - -@description('Optional. Gets or sets the visibility of the configuration. The default value is \'Custom\'') -@allowed([ - 'Custom' - 'Public' -]) -param visibility string = '' - -// =============== // -// Deployments // -// =============== // - -resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - } - } -} - - -resource maintenanceConfiguration 'Microsoft.Maintenance/maintenanceConfigurations@2021-05-01' = { - location: location - name: name - tags: tags - properties: { - extensionProperties: extensionProperties - maintenanceScope: maintenanceScope - maintenanceWindow: maintenanceWindow - namespace: namespace - visibility: visibility - } -} - -resource @(maintenanceConfiguration)_lock 'Microsoft.Authorization/locks@2017-04-01' = if (!empty(lock)) { - name: '${maintenanceConfiguration.name}-${lock}-lock' - properties: { - level: any(lock) - notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' - } - scope: maintenanceConfiguration -} - -module maintenanceConfiguration_roleAssignments '.bicep/nested_roleAssignments.bicep' = [for (roleAssignment,index) in roleAssignments: { - name: '${uniqueString(deployment().name, location)}-maintenanceConfiguration-Rbac-${index}' - params: { - description: contains(roleAssignment,'description') ? roleAssignment.description : '' - principalIds: roleAssignment.principalIds - principalType: contains(roleAssignment,'principalType') ? roleAssignment.principalType : '' - roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName - condition: contains(roleAssignment,'condition') ? roleAssignment.condition : '' - delegatedManagedIdentityResourceId: contains(roleAssignment,'delegatedManagedIdentityResourceId') ? roleAssignment.delegatedManagedIdentityResourceId : '' - resourceId: maintenanceConfiguration.id - } -}] - -// =========== // -// Outputs // -// =========== // - -@description('The name of the maintenanceConfiguration.') -output name string = maintenanceConfiguration.name - -@description('The resource ID of the maintenanceConfiguration.') -output resourceId string = maintenanceConfiguration.id - -@description('The name of the resource group the maintenanceConfiguration was created in.') -output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.Maintenance/maintenanceConfigurations/version.json b/modules/Microsoft.Maintenance/maintenanceConfigurations/version.json deleted file mode 100644 index 41f66cc990..0000000000 --- a/modules/Microsoft.Maintenance/maintenanceConfigurations/version.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "0.1" -} From 2d109df7dc42d0947b6c59d6448f413da6e07b23 Mon Sep 17 00:00:00 2001 From: MrMCake Date: Wed, 2 Nov 2022 22:41:47 +0100 Subject: [PATCH 13/30] Update to latest --- .../REST2CARML/private/module/Get-FormattedModuleParameter.ps1 | 1 + 1 file changed, 1 insertion(+) diff --git a/utilities/tools/REST2CARML/private/module/Get-FormattedModuleParameter.ps1 b/utilities/tools/REST2CARML/private/module/Get-FormattedModuleParameter.ps1 index 90dc3a0522..5e37188b7d 100644 --- a/utilities/tools/REST2CARML/private/module/Get-FormattedModuleParameter.ps1 +++ b/utilities/tools/REST2CARML/private/module/Get-FormattedModuleParameter.ps1 @@ -24,6 +24,7 @@ function Get-FormattedModuleParameter { # description (optional) # ---------------------- + # TODO: Add logic to always add a finishing '.' if missing if ($ParameterData.description) { # For the description we have to escape any single quote that is not already escaped (i.e., negative lookbehind) if ($ParameterData.description -match '^\w+\. .+' ) { From 788f74d16b1a6721ab8f008e037ef51dd6901b30 Mon Sep 17 00:00:00 2001 From: MrMCake Date: Wed, 2 Nov 2022 22:46:08 +0100 Subject: [PATCH 14/30] Update to latest --- .../tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 | 2 ++ 1 file changed, 2 insertions(+) diff --git a/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 b/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 index dbe676ceaa..bd55e48307 100644 --- a/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 +++ b/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 @@ -538,6 +538,8 @@ function Set-ModuleTemplate { ) } + # TODO: Add location output if applicable (pester tests for it too) + # Extra outputs foreach ($output in $existingTemplateContent.outputs | Where-Object { $_.name -notin @('name', 'resourceId', 'resourceGroupName') }) { $templateContent += $output.content From f7469738269f1a8eaf0b6bc935a2633bb4ea3510 Mon Sep 17 00:00:00 2001 From: MrMCake Date: Thu, 3 Nov 2022 17:00:18 +0100 Subject: [PATCH 15/30] Added loc --- .../.bicep/nested_roleAssignments.bicep | 69 ++++++++++ .../.test/common/deploy.bicep | 0 .../.test/min/deploy.bicep | 0 .../maintenanceConfigurations/deploy.bicep | 118 ++++++++++++++++++ .../maintenanceConfigurations/version.json | 4 + .../private/module/Set-ModuleTemplate.ps1 | 9 +- 6 files changed, 199 insertions(+), 1 deletion(-) create mode 100644 modules/Microsoft.Maintenance/maintenanceConfigurations/.bicep/nested_roleAssignments.bicep create mode 100644 modules/Microsoft.Maintenance/maintenanceConfigurations/.test/common/deploy.bicep create mode 100644 modules/Microsoft.Maintenance/maintenanceConfigurations/.test/min/deploy.bicep create mode 100644 modules/Microsoft.Maintenance/maintenanceConfigurations/deploy.bicep create mode 100644 modules/Microsoft.Maintenance/maintenanceConfigurations/version.json diff --git a/modules/Microsoft.Maintenance/maintenanceConfigurations/.bicep/nested_roleAssignments.bicep b/modules/Microsoft.Maintenance/maintenanceConfigurations/.bicep/nested_roleAssignments.bicep new file mode 100644 index 0000000000..5710d6c99b --- /dev/null +++ b/modules/Microsoft.Maintenance/maintenanceConfigurations/.bicep/nested_roleAssignments.bicep @@ -0,0 +1,69 @@ +@sys.description('Required. The IDs of the principals to assign the role to.') +param principalIds array + +@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead.') +param roleDefinitionIdOrName string + +@sys.description('Required. The resource ID of the resource to apply the role assignment to.') +param resourceId string + +@sys.description('Optional. The principal type of the assigned principal ID.') +@allowed([ + 'ServicePrincipal' + 'Group' + 'User' + 'ForeignGroup' + 'Device' + '' +]) +param principalType string = '' + +@sys.description('Optional. The description of the role assignment.') +param description string = '' + +@sys.description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container"') +param condition string = '' + +@sys.description('Optional. Version of the condition.') +@allowed([ + '2.0' +]) +param conditionVersion string = '2.0' + +@sys.description('Optional. Id of the delegated managed identity resource.') +param delegatedManagedIdentityResourceId string = '' + +var builtInRoleNames = { + 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','b24988ac-6180-42a0-ab88-20f7382dd24c') + 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','92aaf0da-9dab-42b6-94a3-d43ce8d16293') + 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','73c42c96-874c-492b-b04d-ab87d138a893') + 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','641177b8-a67a-45b9-a033-47bc880bb21e') + 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','c7393b34-138c-406f-901b-d8cf2b17e6ae') + 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','b9331d33-8a36-4f8c-b097-4f54124fdb44') + 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','749f88d5-cbae-40b8-bcfc-e573ddc772fa') + 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','43d0d8ad-25c7-4714-9337-8ba259a9fe05') + 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','8e3af657-a8ff-443c-a75c-2fe8c4bcb635') + 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','acdd72a7-3385-48ef-bd42-f606fba81ae7') + 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','36243c78-bf99-498c-9df9-86d9f8d28608') + 'Role Based Access Control Administrator (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','f58310d9-a9f6-439a-9e8d-f62e7b41a168') + 'Scheduled Patching Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','cd08ab90-6b14-449c-ad9a-8f8e549482c6') + 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') +} + +resource maintenanceConfiguration 'Microsoft.Maintenance/maintenanceConfigurations@2021-05-01' existing = { + name: last(split(resourceId, '/')) +} + +resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for principalId in principalIds: { + name: guid(maintenanceConfiguration.id, principalId, roleDefinitionIdOrName) + properties: { + description: description + roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName + principalId: principalId + principalType: !empty(principalType) ? any(principalType) : null + condition: !empty(condition) ? condition : null + conditionVersion: !empty(conditionVersion) && !empty(condition) ? conditionVersion : null + delegatedManagedIdentityResourceId: !empty(delegatedManagedIdentityResourceId) ? delegatedManagedIdentityResourceId : null + } + scope: maintenanceConfiguration +}] \ No newline at end of file diff --git a/modules/Microsoft.Maintenance/maintenanceConfigurations/.test/common/deploy.bicep b/modules/Microsoft.Maintenance/maintenanceConfigurations/.test/common/deploy.bicep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/Microsoft.Maintenance/maintenanceConfigurations/.test/min/deploy.bicep b/modules/Microsoft.Maintenance/maintenanceConfigurations/.test/min/deploy.bicep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/Microsoft.Maintenance/maintenanceConfigurations/deploy.bicep b/modules/Microsoft.Maintenance/maintenanceConfigurations/deploy.bicep new file mode 100644 index 0000000000..fa15de1c74 --- /dev/null +++ b/modules/Microsoft.Maintenance/maintenanceConfigurations/deploy.bicep @@ -0,0 +1,118 @@ +// ============== // +// Parameters // +// ============== // + +@description('Required. Maintenance Configuration Name') +param name string + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Gets or sets extensionProperties of the maintenanceConfiguration') +param extensionProperties object = {} + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@description('Optional. Specify the type of lock.') +@allowed([ + '' + 'CanNotDelete' + 'ReadOnly' +]) +param lock string = '' + +@description('Optional. Gets or sets maintenanceScope of the configuration') +@allowed([ + 'Host' + 'OSImage' + 'Extension' + 'InGuestPatch' + 'SQLDB' + 'SQLManagedInstance' +]) +param maintenanceScope string = '' + +@description('Optional. Definition of a MaintenanceWindow') +param maintenanceWindow object = {} + +@description('Optional. Gets or sets namespace of the resource') +param namespace string = '' + +@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') +param roleAssignments array = [] + +@description('Optional. Gets or sets tags of the resource') +param tags object = {} + +@description('Optional. Gets or sets the visibility of the configuration. The default value is \'Custom\'') +@allowed([ + 'Custom' + 'Public' +]) +param visibility string = '' + +// =============== // +// Deployments // +// =============== // + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + + +resource maintenanceConfiguration 'Microsoft.Maintenance/maintenanceConfigurations@2021-05-01' = { + location: location + name: name + tags: tags + properties: { + extensionProperties: extensionProperties + maintenanceScope: maintenanceScope + maintenanceWindow: maintenanceWindow + namespace: namespace + visibility: visibility + } +} + +resource maintenanceConfiguration_lock 'Microsoft.Authorization/locks@2017-04-01' = if (!empty(lock)) { + name: '${maintenanceConfiguration.name}-${lock}-lock' + properties: { + level: any(lock) + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: maintenanceConfiguration +} + +module maintenanceConfiguration_roleAssignments '.bicep/nested_roleAssignments.bicep' = [for (roleAssignment,index) in roleAssignments: { + name: '${uniqueString(deployment().name, location)}-maintenanceConfiguration-Rbac-${index}' + params: { + description: contains(roleAssignment,'description') ? roleAssignment.description : '' + principalIds: roleAssignment.principalIds + principalType: contains(roleAssignment,'principalType') ? roleAssignment.principalType : '' + roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName + condition: contains(roleAssignment,'condition') ? roleAssignment.condition : '' + delegatedManagedIdentityResourceId: contains(roleAssignment,'delegatedManagedIdentityResourceId') ? roleAssignment.delegatedManagedIdentityResourceId : '' + resourceId: maintenanceConfiguration.id + } +}] + +// =========== // +// Outputs // +// =========== // + +@description('The name of the maintenanceConfiguration.') +output name string = maintenanceConfiguration.name + +@description('The resource ID of the maintenanceConfiguration.') +output resourceId string = maintenanceConfiguration.id + +@description('The name of the resource group the maintenanceConfiguration was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.Maintenance/maintenanceConfigurations/version.json b/modules/Microsoft.Maintenance/maintenanceConfigurations/version.json new file mode 100644 index 0000000000..41f66cc990 --- /dev/null +++ b/modules/Microsoft.Maintenance/maintenanceConfigurations/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 b/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 index bd55e48307..132ad47e68 100644 --- a/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 +++ b/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 @@ -538,7 +538,14 @@ function Set-ModuleTemplate { ) } - # TODO: Add location output if applicable (pester tests for it too) + # If the main resource has a location property, an output should be returned too + if ($ModuleData.parametersToAdd.name -contains 'location' -and $ModuleData.parametersToAdd['location'].defaultValue -ne 'global') { + $templateContent += @( + "@description('The location the resource was deployed into.')" + 'output location string = {0}.location' -f $resourceTypeSingular + '' + ) + } # Extra outputs foreach ($output in $existingTemplateContent.outputs | Where-Object { $_.name -notin @('name', 'resourceId', 'resourceGroupName') }) { From dc2326437492550f545d57601edccf5f3a4d6cef Mon Sep 17 00:00:00 2001 From: MrMCake Date: Thu, 3 Nov 2022 17:16:17 +0100 Subject: [PATCH 16/30] Update to latest --- .../.bicep/nested_roleAssignments.bicep | 69 ---------- .../.test/common/deploy.bicep | 0 .../.test/min/deploy.bicep | 0 .../maintenanceConfigurations/deploy.bicep | 118 ------------------ .../maintenanceConfigurations/version.json | 4 - .../private/module/Set-ModuleTemplate.ps1 | 36 ++++++ 6 files changed, 36 insertions(+), 191 deletions(-) delete mode 100644 modules/Microsoft.Maintenance/maintenanceConfigurations/.bicep/nested_roleAssignments.bicep delete mode 100644 modules/Microsoft.Maintenance/maintenanceConfigurations/.test/common/deploy.bicep delete mode 100644 modules/Microsoft.Maintenance/maintenanceConfigurations/.test/min/deploy.bicep delete mode 100644 modules/Microsoft.Maintenance/maintenanceConfigurations/deploy.bicep delete mode 100644 modules/Microsoft.Maintenance/maintenanceConfigurations/version.json diff --git a/modules/Microsoft.Maintenance/maintenanceConfigurations/.bicep/nested_roleAssignments.bicep b/modules/Microsoft.Maintenance/maintenanceConfigurations/.bicep/nested_roleAssignments.bicep deleted file mode 100644 index 5710d6c99b..0000000000 --- a/modules/Microsoft.Maintenance/maintenanceConfigurations/.bicep/nested_roleAssignments.bicep +++ /dev/null @@ -1,69 +0,0 @@ -@sys.description('Required. The IDs of the principals to assign the role to.') -param principalIds array - -@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead.') -param roleDefinitionIdOrName string - -@sys.description('Required. The resource ID of the resource to apply the role assignment to.') -param resourceId string - -@sys.description('Optional. The principal type of the assigned principal ID.') -@allowed([ - 'ServicePrincipal' - 'Group' - 'User' - 'ForeignGroup' - 'Device' - '' -]) -param principalType string = '' - -@sys.description('Optional. The description of the role assignment.') -param description string = '' - -@sys.description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container"') -param condition string = '' - -@sys.description('Optional. Version of the condition.') -@allowed([ - '2.0' -]) -param conditionVersion string = '2.0' - -@sys.description('Optional. Id of the delegated managed identity resource.') -param delegatedManagedIdentityResourceId string = '' - -var builtInRoleNames = { - 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','b24988ac-6180-42a0-ab88-20f7382dd24c') - 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','92aaf0da-9dab-42b6-94a3-d43ce8d16293') - 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','73c42c96-874c-492b-b04d-ab87d138a893') - 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','641177b8-a67a-45b9-a033-47bc880bb21e') - 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','c7393b34-138c-406f-901b-d8cf2b17e6ae') - 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','b9331d33-8a36-4f8c-b097-4f54124fdb44') - 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','749f88d5-cbae-40b8-bcfc-e573ddc772fa') - 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','43d0d8ad-25c7-4714-9337-8ba259a9fe05') - 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','8e3af657-a8ff-443c-a75c-2fe8c4bcb635') - 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','acdd72a7-3385-48ef-bd42-f606fba81ae7') - 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','36243c78-bf99-498c-9df9-86d9f8d28608') - 'Role Based Access Control Administrator (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'Scheduled Patching Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','cd08ab90-6b14-449c-ad9a-8f8e549482c6') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions','18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') -} - -resource maintenanceConfiguration 'Microsoft.Maintenance/maintenanceConfigurations@2021-05-01' existing = { - name: last(split(resourceId, '/')) -} - -resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for principalId in principalIds: { - name: guid(maintenanceConfiguration.id, principalId, roleDefinitionIdOrName) - properties: { - description: description - roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName - principalId: principalId - principalType: !empty(principalType) ? any(principalType) : null - condition: !empty(condition) ? condition : null - conditionVersion: !empty(conditionVersion) && !empty(condition) ? conditionVersion : null - delegatedManagedIdentityResourceId: !empty(delegatedManagedIdentityResourceId) ? delegatedManagedIdentityResourceId : null - } - scope: maintenanceConfiguration -}] \ No newline at end of file diff --git a/modules/Microsoft.Maintenance/maintenanceConfigurations/.test/common/deploy.bicep b/modules/Microsoft.Maintenance/maintenanceConfigurations/.test/common/deploy.bicep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/modules/Microsoft.Maintenance/maintenanceConfigurations/.test/min/deploy.bicep b/modules/Microsoft.Maintenance/maintenanceConfigurations/.test/min/deploy.bicep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/modules/Microsoft.Maintenance/maintenanceConfigurations/deploy.bicep b/modules/Microsoft.Maintenance/maintenanceConfigurations/deploy.bicep deleted file mode 100644 index fa15de1c74..0000000000 --- a/modules/Microsoft.Maintenance/maintenanceConfigurations/deploy.bicep +++ /dev/null @@ -1,118 +0,0 @@ -// ============== // -// Parameters // -// ============== // - -@description('Required. Maintenance Configuration Name') -param name string - -@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') -param enableDefaultTelemetry bool = true - -@description('Optional. Gets or sets extensionProperties of the maintenanceConfiguration') -param extensionProperties object = {} - -@description('Optional. Location for all Resources.') -param location string = resourceGroup().location - -@description('Optional. Specify the type of lock.') -@allowed([ - '' - 'CanNotDelete' - 'ReadOnly' -]) -param lock string = '' - -@description('Optional. Gets or sets maintenanceScope of the configuration') -@allowed([ - 'Host' - 'OSImage' - 'Extension' - 'InGuestPatch' - 'SQLDB' - 'SQLManagedInstance' -]) -param maintenanceScope string = '' - -@description('Optional. Definition of a MaintenanceWindow') -param maintenanceWindow object = {} - -@description('Optional. Gets or sets namespace of the resource') -param namespace string = '' - -@description('Optional. Array of role assignment objects that contain the \'roleDefinitionIdOrName\' and \'principalId\' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: \'/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11\'.') -param roleAssignments array = [] - -@description('Optional. Gets or sets tags of the resource') -param tags object = {} - -@description('Optional. Gets or sets the visibility of the configuration. The default value is \'Custom\'') -@allowed([ - 'Custom' - 'Public' -]) -param visibility string = '' - -// =============== // -// Deployments // -// =============== // - -resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - } - } -} - - -resource maintenanceConfiguration 'Microsoft.Maintenance/maintenanceConfigurations@2021-05-01' = { - location: location - name: name - tags: tags - properties: { - extensionProperties: extensionProperties - maintenanceScope: maintenanceScope - maintenanceWindow: maintenanceWindow - namespace: namespace - visibility: visibility - } -} - -resource maintenanceConfiguration_lock 'Microsoft.Authorization/locks@2017-04-01' = if (!empty(lock)) { - name: '${maintenanceConfiguration.name}-${lock}-lock' - properties: { - level: any(lock) - notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' - } - scope: maintenanceConfiguration -} - -module maintenanceConfiguration_roleAssignments '.bicep/nested_roleAssignments.bicep' = [for (roleAssignment,index) in roleAssignments: { - name: '${uniqueString(deployment().name, location)}-maintenanceConfiguration-Rbac-${index}' - params: { - description: contains(roleAssignment,'description') ? roleAssignment.description : '' - principalIds: roleAssignment.principalIds - principalType: contains(roleAssignment,'principalType') ? roleAssignment.principalType : '' - roleDefinitionIdOrName: roleAssignment.roleDefinitionIdOrName - condition: contains(roleAssignment,'condition') ? roleAssignment.condition : '' - delegatedManagedIdentityResourceId: contains(roleAssignment,'delegatedManagedIdentityResourceId') ? roleAssignment.delegatedManagedIdentityResourceId : '' - resourceId: maintenanceConfiguration.id - } -}] - -// =========== // -// Outputs // -// =========== // - -@description('The name of the maintenanceConfiguration.') -output name string = maintenanceConfiguration.name - -@description('The resource ID of the maintenanceConfiguration.') -output resourceId string = maintenanceConfiguration.id - -@description('The name of the resource group the maintenanceConfiguration was created in.') -output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.Maintenance/maintenanceConfigurations/version.json b/modules/Microsoft.Maintenance/maintenanceConfigurations/version.json deleted file mode 100644 index 41f66cc990..0000000000 --- a/modules/Microsoft.Maintenance/maintenanceConfigurations/version.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "0.1" -} diff --git a/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 b/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 index 132ad47e68..542ccd4966 100644 --- a/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 +++ b/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 @@ -514,7 +514,43 @@ function Set-ModuleTemplate { $templateContent += '' } + $defaultOutputs = @( + @{ + name = 'name' + type = 'string' + content = @( + "@description('The name of the $resourceTypeSingular.')" + "output name string = $resourceTypeSingular.name" + ) + }, + @{ + name = 'resourceId' + type = 'string' + content = @( + "@description('The resource ID of the $resourceTypeSingular.')" + "output resourceId string = $resourceTypeSingular.id" + ) + } + ) + + if ($targetScope -eq 'resourceGroup') { + $defaultOutputs += @{ + name = 'resourceGroupName' + type = 'string' + content = @( + "@description('The name of the resource group the $resourceTypeSingular was created in.')" + 'output resourceGroupName string = resourceGroup().name' + ) + } + } + # TODO: Make idempotent + $outputsToAdd = -not $existingTemplateContent ? @() : $existingTemplateContent.outputs + foreach ($default in $defaultOutputs) { + if ($outputsToAdd.name -notcontains $default.name) { + $outputsToAdd += $default + } + } # Output header comment $templateContent += @( From c5c82847abbab7fced37bdb9848fcc05dc400112 Mon Sep 17 00:00:00 2001 From: MrMCake Date: Thu, 3 Nov 2022 17:17:43 +0100 Subject: [PATCH 17/30] Update to latest --- ....maintenance.maintenanceconfigurations.yml | 40 ----- ....maintenance.maintenanceconfigurations.yml | 145 ------------------ 2 files changed, 185 deletions(-) delete mode 100644 .azuredevops/modulePipelines/ms.maintenance.maintenanceconfigurations.yml delete mode 100644 .github/workflows/ms.maintenance.maintenanceconfigurations.yml diff --git a/.azuredevops/modulePipelines/ms.maintenance.maintenanceconfigurations.yml b/.azuredevops/modulePipelines/ms.maintenance.maintenanceconfigurations.yml deleted file mode 100644 index ca5076934a..0000000000 --- a/.azuredevops/modulePipelines/ms.maintenance.maintenanceconfigurations.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: 'Maintenance - MaintenanceConfigurations' - -parameters: - - name: removeDeployment - displayName: Remove deployed module - type: boolean - default: true - - name: prerelease - displayName: Publish prerelease module - type: boolean - default: false - -pr: none - -trigger: - batch: true - branches: - include: - - main - paths: - include: - - '/.azuredevops/modulePipelines/ms.maintenance.maintenanceconfigurations.yml' - - '/.azuredevops/pipelineTemplates/*.yml' - - '/modules/Microsoft.Maintenance/maintenanceConfigurations/*' - - '/utilities/pipelines/*' - exclude: - - '/utilities/pipelines/dependencies/*' - - '/**/*.md' - -variables: - - template: '../../settings.yml' - - group: 'PLATFORM_VARIABLES' - - name: modulePath - value: '/modules/Microsoft.Maintenance/maintenanceConfigurations' - -stages: - - template: /.azuredevops/pipelineTemplates/stages.module.yml - parameters: - removeDeployment: '${{ parameters.removeDeployment }}' - prerelease: '${{ parameters.prerelease }}' diff --git a/.github/workflows/ms.maintenance.maintenanceconfigurations.yml b/.github/workflows/ms.maintenance.maintenanceconfigurations.yml deleted file mode 100644 index 01a93d71a8..0000000000 --- a/.github/workflows/ms.maintenance.maintenanceconfigurations.yml +++ /dev/null @@ -1,145 +0,0 @@ -name: 'Maintenance: MaintenanceConfigurations' - -on: - workflow_dispatch: - inputs: - removeDeployment: - type: boolean - description: 'Remove deployed module' - required: false - default: true - prerelease: - type: boolean - description: 'Publish prerelease module' - required: false - default: false - push: - branches: - - main - paths: - - '.github/actions/templates/**' - - '.github/workflows/ms.maintenance.maintenanceconfigurations.yml' - - 'modules/Microsoft.Maintenance/maintenanceConfigurations/**' - - 'utilities/pipelines/**' - - '!utilities/pipelines/dependencies/**' - - '!*/**/readme.md' - -env: - variablesPath: 'settings.yml' - modulePath: 'modules/Microsoft.Maintenance/maintenanceConfigurations' - workflowPath: '.github/workflows/ms.maintenance.maintenanceconfigurations.yml' - AZURE_CREDENTIALS: ${{ secrets.AZURE_CREDENTIALS }} - ARM_SUBSCRIPTION_ID: '${{ secrets.ARM_SUBSCRIPTION_ID }}' - ARM_MGMTGROUP_ID: '${{ secrets.ARM_MGMTGROUP_ID }}' - ARM_TENANT_ID: '${{ secrets.ARM_TENANT_ID }}' - TOKEN_NAMEPREFIX: '${{ secrets.TOKEN_NAMEPREFIX }}' - -jobs: - ########################### - # Initialize pipeline # - ########################### - job_initialize_pipeline: - runs-on: ubuntu-20.04 - name: 'Initialize pipeline' - steps: - - name: 'Checkout' - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - name: 'Set input parameters to output variables' - id: get-workflow-param - uses: ./.github/actions/templates/getWorkflowInput - with: - workflowPath: '${{ env.workflowPath}}' - - name: 'Get parameter file paths' - id: get-module-test-file-paths - uses: ./.github/actions/templates/getModuleTestFiles - with: - modulePath: '${{ env.modulePath }}' - outputs: - removeDeployment: ${{ steps.get-workflow-param.outputs.removeDeployment }} - moduleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.moduleTestFilePaths }} - - ######################### - # Static validation # - ######################### - job_module_pester_validation: - runs-on: ubuntu-20.04 - name: 'Static validation' - steps: - - name: 'Checkout' - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - name: Set environment variables - uses: ./.github/actions/templates/setEnvironmentVariables - with: - variablesPath: ${{ env.variablesPath }} - - name: 'Run tests' - uses: ./.github/actions/templates/validateModulePester - with: - modulePath: '${{ env.modulePath }}' - moduleTestFilePath: '${{ env.moduleTestFilePath }}' - - ############################# - # Deployment validation # - ############################# - job_module_deploy_validation: - runs-on: ubuntu-20.04 - name: 'Deployment validation' - needs: - - job_initialize_pipeline - - job_module_pester_validation - strategy: - fail-fast: false - matrix: - moduleTestFilePaths: ${{ fromJSON(needs.job_initialize_pipeline.outputs.moduleTestFilePaths) }} - steps: - - name: 'Checkout' - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - name: Set environment variables - uses: ./.github/actions/templates/setEnvironmentVariables - with: - variablesPath: ${{ env.variablesPath }} - - name: 'Using test file [${{ matrix.moduleTestFilePaths }}]' - uses: ./.github/actions/templates/validateModuleDeployment - with: - templateFilePath: '${{ env.modulePath }}/${{ matrix.moduleTestFilePaths }}' - location: '${{ env.location }}' - resourceGroupName: '${{ env.resourceGroupName }}' - subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' - managementGroupId: '${{ secrets.ARM_MGMTGROUP_ID }}' - removeDeployment: '${{ needs.job_initialize_pipeline.outputs.removeDeployment }}' - - ################## - # Publishing # - ################## - job_publish_module: - name: 'Publishing' - if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master' || github.event.inputs.prerelease == 'true' - runs-on: ubuntu-20.04 - needs: - - job_module_deploy_validation - steps: - - name: 'Checkout' - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - name: Set environment variables - uses: ./.github/actions/templates/setEnvironmentVariables - with: - variablesPath: ${{ env.variablesPath }} - - name: 'Publishing' - uses: ./.github/actions/templates/publishModule - with: - templateFilePath: '${{ env.modulePath }}/deploy.bicep' - templateSpecsRGName: '${{ env.templateSpecsRGName }}' - templateSpecsRGLocation: '${{ env.templateSpecsRGLocation }}' - templateSpecsDescription: '${{ env.templateSpecsDescription }}' - templateSpecsDoPublish: '${{ env.templateSpecsDoPublish }}' - bicepRegistryName: '${{ env.bicepRegistryName }}' - bicepRegistryRGName: '${{ env.bicepRegistryRGName }}' - bicepRegistryRgLocation: '${{ env.bicepRegistryRgLocation }}' - bicepRegistryDoPublish: '${{ env.bicepRegistryDoPublish }}' From f6020c8a2648df1c0a5af99af09b28618c978cd8 Mon Sep 17 00:00:00 2001 From: MrMCake Date: Thu, 3 Nov 2022 17:23:56 +0100 Subject: [PATCH 18/30] Update to latest --- .../modulePipelines/ms.avs.privateclouds.yml | 40 -- .github/workflows/ms.avs.privateclouds.yml | 145 ------ .../.bicep/nested_roleAssignments.bicep | 68 --- .../privateClouds/.test/common/deploy.bicep | 0 .../privateClouds/.test/min/deploy.bicep | 0 .../privateClouds/addons/deploy.bicep | 62 --- .../privateClouds/addons/version.json | 4 - .../privateClouds/authorizations/deploy.bicep | 52 --- .../privateClouds/authorizations/readme.md | 54 --- .../privateClouds/authorizations/version.json | 4 - .../privateClouds/cloudLinks/deploy.bicep | 56 --- .../privateClouds/cloudLinks/readme.md | 55 --- .../privateClouds/cloudLinks/version.json | 4 - .../clusters/datastores/deploy.bicep | 67 --- .../clusters/datastores/readme.md | 57 --- .../clusters/datastores/version.json | 4 - .../privateClouds/clusters/deploy.bicep | 101 ----- .../clusters/placementPolicies/deploy.bicep | 103 ----- .../clusters/placementPolicies/version.json | 4 - .../privateClouds/clusters/version.json | 4 - .../Microsoft.AVS/privateClouds/deploy.bicep | 426 ------------------ .../globalReachConnections/deploy.bicep | 64 --- .../globalReachConnections/readme.md | 57 --- .../globalReachConnections/version.json | 4 - .../hcxEnterpriseSites/deploy.bicep | 52 --- .../hcxEnterpriseSites/readme.md | 54 --- .../hcxEnterpriseSites/version.json | 4 - modules/Microsoft.AVS/privateClouds/readme.md | 181 -------- .../scriptExecutions/deploy.bicep | 84 ---- .../privateClouds/scriptExecutions/readme.md | 62 --- .../scriptExecutions/version.json | 4 - .../Microsoft.AVS/privateClouds/version.json | 4 - .../dhcpConfigurations/deploy.bicep | 75 --- .../dhcpConfigurations/version.json | 4 - .../workloadNetworks/dnsServices/deploy.bicep | 90 ---- .../workloadNetworks/dnsServices/version.json | 4 - .../workloadNetworks/dnsZones/deploy.bicep | 83 ---- .../workloadNetworks/dnsZones/version.json | 4 - .../portMirroringProfiles/deploy.bicep | 84 ---- .../portMirroringProfiles/version.json | 4 - .../workloadNetworks/publicIPs/deploy.bicep | 67 --- .../workloadNetworks/publicIPs/version.json | 4 - .../workloadNetworks/segments/deploy.bicep | 75 --- .../workloadNetworks/segments/version.json | 4 - .../workloadNetworks/vmGroups/deploy.bicep | 71 --- .../workloadNetworks/vmGroups/version.json | 4 - 46 files changed, 2453 deletions(-) delete mode 100644 .azuredevops/modulePipelines/ms.avs.privateclouds.yml delete mode 100644 .github/workflows/ms.avs.privateclouds.yml delete mode 100644 modules/Microsoft.AVS/privateClouds/.bicep/nested_roleAssignments.bicep delete mode 100644 modules/Microsoft.AVS/privateClouds/.test/common/deploy.bicep delete mode 100644 modules/Microsoft.AVS/privateClouds/.test/min/deploy.bicep delete mode 100644 modules/Microsoft.AVS/privateClouds/addons/deploy.bicep delete mode 100644 modules/Microsoft.AVS/privateClouds/addons/version.json delete mode 100644 modules/Microsoft.AVS/privateClouds/authorizations/deploy.bicep delete mode 100644 modules/Microsoft.AVS/privateClouds/authorizations/readme.md delete mode 100644 modules/Microsoft.AVS/privateClouds/authorizations/version.json delete mode 100644 modules/Microsoft.AVS/privateClouds/cloudLinks/deploy.bicep delete mode 100644 modules/Microsoft.AVS/privateClouds/cloudLinks/readme.md delete mode 100644 modules/Microsoft.AVS/privateClouds/cloudLinks/version.json delete mode 100644 modules/Microsoft.AVS/privateClouds/clusters/datastores/deploy.bicep delete mode 100644 modules/Microsoft.AVS/privateClouds/clusters/datastores/readme.md delete mode 100644 modules/Microsoft.AVS/privateClouds/clusters/datastores/version.json delete mode 100644 modules/Microsoft.AVS/privateClouds/clusters/deploy.bicep delete mode 100644 modules/Microsoft.AVS/privateClouds/clusters/placementPolicies/deploy.bicep delete mode 100644 modules/Microsoft.AVS/privateClouds/clusters/placementPolicies/version.json delete mode 100644 modules/Microsoft.AVS/privateClouds/clusters/version.json delete mode 100644 modules/Microsoft.AVS/privateClouds/deploy.bicep delete mode 100644 modules/Microsoft.AVS/privateClouds/globalReachConnections/deploy.bicep delete mode 100644 modules/Microsoft.AVS/privateClouds/globalReachConnections/readme.md delete mode 100644 modules/Microsoft.AVS/privateClouds/globalReachConnections/version.json delete mode 100644 modules/Microsoft.AVS/privateClouds/hcxEnterpriseSites/deploy.bicep delete mode 100644 modules/Microsoft.AVS/privateClouds/hcxEnterpriseSites/readme.md delete mode 100644 modules/Microsoft.AVS/privateClouds/hcxEnterpriseSites/version.json delete mode 100644 modules/Microsoft.AVS/privateClouds/readme.md delete mode 100644 modules/Microsoft.AVS/privateClouds/scriptExecutions/deploy.bicep delete mode 100644 modules/Microsoft.AVS/privateClouds/scriptExecutions/readme.md delete mode 100644 modules/Microsoft.AVS/privateClouds/scriptExecutions/version.json delete mode 100644 modules/Microsoft.AVS/privateClouds/version.json delete mode 100644 modules/Microsoft.AVS/privateClouds/workloadNetworks/dhcpConfigurations/deploy.bicep delete mode 100644 modules/Microsoft.AVS/privateClouds/workloadNetworks/dhcpConfigurations/version.json delete mode 100644 modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsServices/deploy.bicep delete mode 100644 modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsServices/version.json delete mode 100644 modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsZones/deploy.bicep delete mode 100644 modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsZones/version.json delete mode 100644 modules/Microsoft.AVS/privateClouds/workloadNetworks/portMirroringProfiles/deploy.bicep delete mode 100644 modules/Microsoft.AVS/privateClouds/workloadNetworks/portMirroringProfiles/version.json delete mode 100644 modules/Microsoft.AVS/privateClouds/workloadNetworks/publicIPs/deploy.bicep delete mode 100644 modules/Microsoft.AVS/privateClouds/workloadNetworks/publicIPs/version.json delete mode 100644 modules/Microsoft.AVS/privateClouds/workloadNetworks/segments/deploy.bicep delete mode 100644 modules/Microsoft.AVS/privateClouds/workloadNetworks/segments/version.json delete mode 100644 modules/Microsoft.AVS/privateClouds/workloadNetworks/vmGroups/deploy.bicep delete mode 100644 modules/Microsoft.AVS/privateClouds/workloadNetworks/vmGroups/version.json diff --git a/.azuredevops/modulePipelines/ms.avs.privateclouds.yml b/.azuredevops/modulePipelines/ms.avs.privateclouds.yml deleted file mode 100644 index 9e3bec03f2..0000000000 --- a/.azuredevops/modulePipelines/ms.avs.privateclouds.yml +++ /dev/null @@ -1,40 +0,0 @@ -name: 'AVS - PrivateClouds' - -parameters: - - name: removeDeployment - displayName: Remove deployed module - type: boolean - default: true - - name: prerelease - displayName: Publish prerelease module - type: boolean - default: false - -pr: none - -trigger: - batch: true - branches: - include: - - main - paths: - include: - - '/.azuredevops/modulePipelines/ms.avs.privateclouds.yml' - - '/.azuredevops/pipelineTemplates/*.yml' - - '/modules/Microsoft.AVS/privateClouds/*' - - '/utilities/pipelines/*' - exclude: - - '/utilities/pipelines/dependencies/*' - - '/**/*.md' - -variables: - - template: '../../settings.yml' - - group: 'PLATFORM_VARIABLES' - - name: modulePath - value: '/modules/Microsoft.AVS/privateClouds' - -stages: - - template: /.azuredevops/pipelineTemplates/stages.module.yml - parameters: - removeDeployment: '${{ parameters.removeDeployment }}' - prerelease: '${{ parameters.prerelease }}' diff --git a/.github/workflows/ms.avs.privateclouds.yml b/.github/workflows/ms.avs.privateclouds.yml deleted file mode 100644 index 15e86296b0..0000000000 --- a/.github/workflows/ms.avs.privateclouds.yml +++ /dev/null @@ -1,145 +0,0 @@ -name: 'AVS: PrivateClouds' - -on: - workflow_dispatch: - inputs: - removeDeployment: - type: boolean - description: 'Remove deployed module' - required: false - default: true - prerelease: - type: boolean - description: 'Publish prerelease module' - required: false - default: false - push: - branches: - - main - paths: - - '.github/actions/templates/**' - - '.github/workflows/ms.avs.privateclouds.yml' - - 'modules/Microsoft.AVS/privateClouds/**' - - 'utilities/pipelines/**' - - '!utilities/pipelines/dependencies/**' - - '!*/**/readme.md' - -env: - variablesPath: 'settings.yml' - modulePath: 'modules/Microsoft.AVS/privateClouds' - workflowPath: '.github/workflows/ms.avs.privateclouds.yml' - AZURE_CREDENTIALS: ${{ secrets.AZURE_CREDENTIALS }} - ARM_SUBSCRIPTION_ID: '${{ secrets.ARM_SUBSCRIPTION_ID }}' - ARM_MGMTGROUP_ID: '${{ secrets.ARM_MGMTGROUP_ID }}' - ARM_TENANT_ID: '${{ secrets.ARM_TENANT_ID }}' - TOKEN_NAMEPREFIX: '${{ secrets.TOKEN_NAMEPREFIX }}' - -jobs: - ########################### - # Initialize pipeline # - ########################### - job_initialize_pipeline: - runs-on: ubuntu-20.04 - name: 'Initialize pipeline' - steps: - - name: 'Checkout' - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - name: 'Set input parameters to output variables' - id: get-workflow-param - uses: ./.github/actions/templates/getWorkflowInput - with: - workflowPath: '${{ env.workflowPath}}' - - name: 'Get parameter file paths' - id: get-module-test-file-paths - uses: ./.github/actions/templates/getModuleTestFiles - with: - modulePath: '${{ env.modulePath }}' - outputs: - removeDeployment: ${{ steps.get-workflow-param.outputs.removeDeployment }} - moduleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.moduleTestFilePaths }} - - ######################### - # Static validation # - ######################### - job_module_pester_validation: - runs-on: ubuntu-20.04 - name: 'Static validation' - steps: - - name: 'Checkout' - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - name: Set environment variables - uses: ./.github/actions/templates/setEnvironmentVariables - with: - variablesPath: ${{ env.variablesPath }} - - name: 'Run tests' - uses: ./.github/actions/templates/validateModulePester - with: - modulePath: '${{ env.modulePath }}' - moduleTestFilePath: '${{ env.moduleTestFilePath }}' - - ############################# - # Deployment validation # - ############################# - job_module_deploy_validation: - runs-on: ubuntu-20.04 - name: 'Deployment validation' - needs: - - job_initialize_pipeline - - job_module_pester_validation - strategy: - fail-fast: false - matrix: - moduleTestFilePaths: ${{ fromJSON(needs.job_initialize_pipeline.outputs.moduleTestFilePaths) }} - steps: - - name: 'Checkout' - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - name: Set environment variables - uses: ./.github/actions/templates/setEnvironmentVariables - with: - variablesPath: ${{ env.variablesPath }} - - name: 'Using test file [${{ matrix.moduleTestFilePaths }}]' - uses: ./.github/actions/templates/validateModuleDeployment - with: - templateFilePath: '${{ env.modulePath }}/${{ matrix.moduleTestFilePaths }}' - location: '${{ env.location }}' - resourceGroupName: '${{ env.resourceGroupName }}' - subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' - managementGroupId: '${{ secrets.ARM_MGMTGROUP_ID }}' - removeDeployment: '${{ needs.job_initialize_pipeline.outputs.removeDeployment }}' - - ################## - # Publishing # - ################## - job_publish_module: - name: 'Publishing' - if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master' || github.event.inputs.prerelease == 'true' - runs-on: ubuntu-20.04 - needs: - - job_module_deploy_validation - steps: - - name: 'Checkout' - uses: actions/checkout@v2 - with: - fetch-depth: 0 - - name: Set environment variables - uses: ./.github/actions/templates/setEnvironmentVariables - with: - variablesPath: ${{ env.variablesPath }} - - name: 'Publishing' - uses: ./.github/actions/templates/publishModule - with: - templateFilePath: '${{ env.modulePath }}/deploy.bicep' - templateSpecsRGName: '${{ env.templateSpecsRGName }}' - templateSpecsRGLocation: '${{ env.templateSpecsRGLocation }}' - templateSpecsDescription: '${{ env.templateSpecsDescription }}' - templateSpecsDoPublish: '${{ env.templateSpecsDoPublish }}' - bicepRegistryName: '${{ env.bicepRegistryName }}' - bicepRegistryRGName: '${{ env.bicepRegistryRGName }}' - bicepRegistryRgLocation: '${{ env.bicepRegistryRgLocation }}' - bicepRegistryDoPublish: '${{ env.bicepRegistryDoPublish }}' diff --git a/modules/Microsoft.AVS/privateClouds/.bicep/nested_roleAssignments.bicep b/modules/Microsoft.AVS/privateClouds/.bicep/nested_roleAssignments.bicep deleted file mode 100644 index 33195bef44..0000000000 --- a/modules/Microsoft.AVS/privateClouds/.bicep/nested_roleAssignments.bicep +++ /dev/null @@ -1,68 +0,0 @@ -@sys.description('Required. The IDs of the principals to assign the role to.') -param principalIds array - -@sys.description('Required. The name of the role to assign. If it cannot be found you can specify the role definition ID instead.') -param roleDefinitionIdOrName string - -@sys.description('Required. The resource ID of the resource to apply the role assignment to.') -param resourceId string - -@sys.description('Optional. The principal type of the assigned principal ID.') -@allowed([ - 'ServicePrincipal' - 'Group' - 'User' - 'ForeignGroup' - 'Device' - '' -]) -param principalType string = '' - -@sys.description('Optional. The description of the role assignment.') -param description string = '' - -@sys.description('Optional. The conditions on the role assignment. This limits the resources it can be assigned to. e.g.: @Resource[Microsoft.Storage/storageAccounts/blobServices/containers:ContainerName] StringEqualsIgnoreCase "foo_storage_container"') -param condition string = '' - -@sys.description('Optional. Version of the condition.') -@allowed([ - '2.0' -]) -param conditionVersion string = '2.0' - -@sys.description('Optional. Id of the delegated managed identity resource.') -param delegatedManagedIdentityResourceId string = '' - -var builtInRoleNames = { - 'Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c') - 'Log Analytics Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '92aaf0da-9dab-42b6-94a3-d43ce8d16293') - 'Log Analytics Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '73c42c96-874c-492b-b04d-ab87d138a893') - 'Managed Application Contributor Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '641177b8-a67a-45b9-a033-47bc880bb21e') - 'Managed Application Operator Role': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'c7393b34-138c-406f-901b-d8cf2b17e6ae') - 'Managed Applications Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b9331d33-8a36-4f8c-b097-4f54124fdb44') - 'Monitoring Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '749f88d5-cbae-40b8-bcfc-e573ddc772fa') - 'Monitoring Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '43d0d8ad-25c7-4714-9337-8ba259a9fe05') - 'Owner': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '8e3af657-a8ff-443c-a75c-2fe8c4bcb635') - 'Reader': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'acdd72a7-3385-48ef-bd42-f606fba81ae7') - 'Resource Policy Contributor': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '36243c78-bf99-498c-9df9-86d9f8d28608') - 'Role Based Access Control Administrator (Preview)': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'f58310d9-a9f6-439a-9e8d-f62e7b41a168') - 'User Access Administrator': subscriptionResourceId('Microsoft.Authorization/roleDefinitions', '18d7d88d-d35e-4fb5-a5c3-7773c20a72d9') -} - -resource privateCloud 'Microsoft.AVS/privateClouds@2021-12-01' existing = { - name: last(split(resourceId, '/')) -} - -resource roleAssignment 'Microsoft.Authorization/roleAssignments@2022-04-01' = [for principalId in principalIds: { - name: guid(privateCloud.id, principalId, roleDefinitionIdOrName) - properties: { - description: description - roleDefinitionId: contains(builtInRoleNames, roleDefinitionIdOrName) ? builtInRoleNames[roleDefinitionIdOrName] : roleDefinitionIdOrName - principalId: principalId - principalType: !empty(principalType) ? any(principalType) : null - condition: !empty(condition) ? condition : null - conditionVersion: !empty(conditionVersion) && !empty(condition) ? conditionVersion : null - delegatedManagedIdentityResourceId: !empty(delegatedManagedIdentityResourceId) ? delegatedManagedIdentityResourceId : null - } - scope: privateCloud -}] diff --git a/modules/Microsoft.AVS/privateClouds/.test/common/deploy.bicep b/modules/Microsoft.AVS/privateClouds/.test/common/deploy.bicep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/modules/Microsoft.AVS/privateClouds/.test/min/deploy.bicep b/modules/Microsoft.AVS/privateClouds/.test/min/deploy.bicep deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/modules/Microsoft.AVS/privateClouds/addons/deploy.bicep b/modules/Microsoft.AVS/privateClouds/addons/deploy.bicep deleted file mode 100644 index 597f3dca3b..0000000000 --- a/modules/Microsoft.AVS/privateClouds/addons/deploy.bicep +++ /dev/null @@ -1,62 +0,0 @@ -// ============== // -// Parameters // -// ============== // - -@description('Required. Name of the addon for the private cloud') -param name string - -@description('Conditional. The name of the parent privateClouds. Required if the template is used in a standalone deployment.') -param privateCloudName string - -@description('Optional. The type of private cloud addon') -@allowed([ - 'SRM' - 'VR' - 'HCX' - 'Arc' -]) -param addonType string = '' - -@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') -param enableDefaultTelemetry bool = true - -// =============== // -// Deployments // -// =============== // - -resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - } - } -} - -resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { - name: privateCloudName -} - -resource addon 'Microsoft.AVS/privateClouds/addons@2022-05-01' = { - parent: privateCloud - name: name - properties: { - addonType: addonType - } -} - -// =========== // -// Outputs // -// =========== // - -@description('The name of the addon.') -output name string = addon.name - -@description('The resource ID of the addon.') -output resourceId string = addon.id - -@description('The name of the resource group the addon was created in.') -output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.AVS/privateClouds/addons/version.json b/modules/Microsoft.AVS/privateClouds/addons/version.json deleted file mode 100644 index 41f66cc990..0000000000 --- a/modules/Microsoft.AVS/privateClouds/addons/version.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "0.1" -} diff --git a/modules/Microsoft.AVS/privateClouds/authorizations/deploy.bicep b/modules/Microsoft.AVS/privateClouds/authorizations/deploy.bicep deleted file mode 100644 index 508635ef94..0000000000 --- a/modules/Microsoft.AVS/privateClouds/authorizations/deploy.bicep +++ /dev/null @@ -1,52 +0,0 @@ -// ============== // -// Parameters // -// ============== // - -@description('Required. Name of the ExpressRoute Circuit Authorization in the private cloud') -param name string - -@description('Conditional. The name of the parent privateClouds. Required if the template is used in a standalone deployment.') -param privateCloudName string - -@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') -param enableDefaultTelemetry bool = true - -// =============== // -// Deployments // -// =============== // - -resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - } - } -} - -resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { - name: privateCloudName -} - -resource authorization 'Microsoft.AVS/privateClouds/authorizations@2022-05-01' = { - parent: privateCloud - name: name - properties: { - } -} - -// =========== // -// Outputs // -// =========== // - -@description('The name of the authorization.') -output name string = authorization.name - -@description('The resource ID of the authorization.') -output resourceId string = authorization.id - -@description('The name of the resource group the authorization was created in.') -output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.AVS/privateClouds/authorizations/readme.md b/modules/Microsoft.AVS/privateClouds/authorizations/readme.md deleted file mode 100644 index 89ab5af150..0000000000 --- a/modules/Microsoft.AVS/privateClouds/authorizations/readme.md +++ /dev/null @@ -1,54 +0,0 @@ -# AVS PrivateClouds Authorizations `[Microsoft.AVS/privateClouds/authorizations]` - -This module deploys AVS PrivateClouds Authorizations. -// TODO: Replace Resource and fill in description - -## Navigation - -- [Resource Types](#Resource-Types) -- [Parameters](#Parameters) -- [Outputs](#Outputs) -- [Cross-referenced modules](#Cross-referenced-modules) - -## Resource Types - -| Resource Type | API Version | -| :-- | :-- | -| `Microsoft.AVS/privateClouds/authorizations` | [2022-05-01](https://docs.microsoft.com/en-us/azure/templates/Microsoft.AVS/privateClouds/authorizations) | - -## Parameters - -**Required parameters** - -| Parameter Name | Type | Description | -| :-- | :-- | :-- | -| `name` | string | Name of the ExpressRoute Circuit Authorization in the private cloud | - -**Conditional parameters** - -| Parameter Name | Type | Description | -| :-- | :-- | :-- | -| `privateCloudName` | string | The name of the parent privateClouds. Required if the template is used in a standalone deployment. | - -**Optional parameters** - -| Parameter Name | Type | Default Value | Description | -| :-- | :-- | :-- | :-- | -| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | - - -### Parameter Usage: `` - -// TODO: Fill in Parameter usage - -## Outputs - -| Output Name | Type | Description | -| :-- | :-- | :-- | -| `name` | string | The name of the authorization. | -| `resourceGroupName` | string | The name of the resource group the authorization was created in. | -| `resourceId` | string | The resource ID of the authorization. | - -## Cross-referenced modules - -_None_ diff --git a/modules/Microsoft.AVS/privateClouds/authorizations/version.json b/modules/Microsoft.AVS/privateClouds/authorizations/version.json deleted file mode 100644 index 41f66cc990..0000000000 --- a/modules/Microsoft.AVS/privateClouds/authorizations/version.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "0.1" -} diff --git a/modules/Microsoft.AVS/privateClouds/cloudLinks/deploy.bicep b/modules/Microsoft.AVS/privateClouds/cloudLinks/deploy.bicep deleted file mode 100644 index 8948ad6f16..0000000000 --- a/modules/Microsoft.AVS/privateClouds/cloudLinks/deploy.bicep +++ /dev/null @@ -1,56 +0,0 @@ -// ============== // -// Parameters // -// ============== // - -@description('Required. Name of the cloud link resource') -param name string - -@description('Conditional. The name of the parent privateClouds. Required if the template is used in a standalone deployment.') -param privateCloudName string - -@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') -param enableDefaultTelemetry bool = true - -@description('Optional. Identifier of the other private cloud participating in the link.') -param linkedCloud string = '' - -// =============== // -// Deployments // -// =============== // - -resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - } - } -} - -resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { - name: privateCloudName -} - -resource cloudLink 'Microsoft.AVS/privateClouds/cloudLinks@2022-05-01' = { - parent: privateCloud - name: name - properties: { - linkedCloud: linkedCloud - } -} - -// =========== // -// Outputs // -// =========== // - -@description('The name of the cloudLink.') -output name string = cloudLink.name - -@description('The resource ID of the cloudLink.') -output resourceId string = cloudLink.id - -@description('The name of the resource group the cloudLink was created in.') -output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.AVS/privateClouds/cloudLinks/readme.md b/modules/Microsoft.AVS/privateClouds/cloudLinks/readme.md deleted file mode 100644 index 163ef46d6e..0000000000 --- a/modules/Microsoft.AVS/privateClouds/cloudLinks/readme.md +++ /dev/null @@ -1,55 +0,0 @@ -# AVS PrivateClouds CloudLinks `[Microsoft.AVS/privateClouds/cloudLinks]` - -This module deploys AVS PrivateClouds CloudLinks. -// TODO: Replace Resource and fill in description - -## Navigation - -- [Resource Types](#Resource-Types) -- [Parameters](#Parameters) -- [Outputs](#Outputs) -- [Cross-referenced modules](#Cross-referenced-modules) - -## Resource Types - -| Resource Type | API Version | -| :-- | :-- | -| `Microsoft.AVS/privateClouds/cloudLinks` | [2022-05-01](https://docs.microsoft.com/en-us/azure/templates/Microsoft.AVS/privateClouds/cloudLinks) | - -## Parameters - -**Required parameters** - -| Parameter Name | Type | Description | -| :-- | :-- | :-- | -| `name` | string | Name of the cloud link resource | - -**Conditional parameters** - -| Parameter Name | Type | Description | -| :-- | :-- | :-- | -| `privateCloudName` | string | The name of the parent privateClouds. Required if the template is used in a standalone deployment. | - -**Optional parameters** - -| Parameter Name | Type | Default Value | Description | -| :-- | :-- | :-- | :-- | -| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | -| `linkedCloud` | string | `''` | Identifier of the other private cloud participating in the link. | - - -### Parameter Usage: `` - -// TODO: Fill in Parameter usage - -## Outputs - -| Output Name | Type | Description | -| :-- | :-- | :-- | -| `name` | string | The name of the cloudLink. | -| `resourceGroupName` | string | The name of the resource group the cloudLink was created in. | -| `resourceId` | string | The resource ID of the cloudLink. | - -## Cross-referenced modules - -_None_ diff --git a/modules/Microsoft.AVS/privateClouds/cloudLinks/version.json b/modules/Microsoft.AVS/privateClouds/cloudLinks/version.json deleted file mode 100644 index 41f66cc990..0000000000 --- a/modules/Microsoft.AVS/privateClouds/cloudLinks/version.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "0.1" -} diff --git a/modules/Microsoft.AVS/privateClouds/clusters/datastores/deploy.bicep b/modules/Microsoft.AVS/privateClouds/clusters/datastores/deploy.bicep deleted file mode 100644 index 85bcc45cd9..0000000000 --- a/modules/Microsoft.AVS/privateClouds/clusters/datastores/deploy.bicep +++ /dev/null @@ -1,67 +0,0 @@ -// ============== // -// Parameters // -// ============== // - -@description('Required. Name of the datastore in the private cloud cluster') -param name string - -@description('Conditional. The name of the parent clusters. Required if the template is used in a standalone deployment.') -param clusterName string - -@description('Conditional. The name of the parent privateClouds. Required if the template is used in a standalone deployment.') -param privateCloudName string - -@description('Optional. An iSCSI volume from Microsoft.StoragePool provider') -param diskPoolVolume object = {} - -@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') -param enableDefaultTelemetry bool = true - -@description('Optional. An Azure NetApp Files volume from Microsoft.NetApp provider') -param netAppVolume object = {} - -// =============== // -// Deployments // -// =============== // - -resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - } - } -} - -resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { - name: privateCloudName - - resource cluster 'clusters@2022-05-01' existing = { - name: clusterName - } -} - -resource datastore 'Microsoft.AVS/privateClouds/clusters/datastores@2022-05-01' = { - parent: privateCloud::cluster - name: name - properties: { - diskPoolVolume: diskPoolVolume - netAppVolume: netAppVolume - } -} - -// =========== // -// Outputs // -// =========== // - -@description('The name of the datastore.') -output name string = datastore.name - -@description('The resource ID of the datastore.') -output resourceId string = datastore.id - -@description('The name of the resource group the datastore was created in.') -output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.AVS/privateClouds/clusters/datastores/readme.md b/modules/Microsoft.AVS/privateClouds/clusters/datastores/readme.md deleted file mode 100644 index dcecf01a6c..0000000000 --- a/modules/Microsoft.AVS/privateClouds/clusters/datastores/readme.md +++ /dev/null @@ -1,57 +0,0 @@ -# AVS PrivateClouds Clusters Datastores `[Microsoft.AVS/privateClouds/clusters/datastores]` - -This module deploys AVS PrivateClouds Clusters Datastores. -// TODO: Replace Resource and fill in description - -## Navigation - -- [Resource Types](#Resource-Types) -- [Parameters](#Parameters) -- [Outputs](#Outputs) -- [Cross-referenced modules](#Cross-referenced-modules) - -## Resource Types - -| Resource Type | API Version | -| :-- | :-- | -| `Microsoft.AVS/privateClouds/clusters/datastores` | [2022-05-01](https://docs.microsoft.com/en-us/azure/templates/Microsoft.AVS/privateClouds/clusters/datastores) | - -## Parameters - -**Required parameters** - -| Parameter Name | Type | Description | -| :-- | :-- | :-- | -| `name` | string | Name of the datastore in the private cloud cluster | - -**Conditional parameters** - -| Parameter Name | Type | Description | -| :-- | :-- | :-- | -| `clusterName` | string | The name of the parent clusters. Required if the template is used in a standalone deployment. | -| `privateCloudName` | string | The name of the parent privateClouds. Required if the template is used in a standalone deployment. | - -**Optional parameters** - -| Parameter Name | Type | Default Value | Description | -| :-- | :-- | :-- | :-- | -| `diskPoolVolume` | object | `{object}` | An iSCSI volume from Microsoft.StoragePool provider | -| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | -| `netAppVolume` | object | `{object}` | An Azure NetApp Files volume from Microsoft.NetApp provider | - - -### Parameter Usage: `` - -// TODO: Fill in Parameter usage - -## Outputs - -| Output Name | Type | Description | -| :-- | :-- | :-- | -| `name` | string | The name of the datastore. | -| `resourceGroupName` | string | The name of the resource group the datastore was created in. | -| `resourceId` | string | The resource ID of the datastore. | - -## Cross-referenced modules - -_None_ diff --git a/modules/Microsoft.AVS/privateClouds/clusters/datastores/version.json b/modules/Microsoft.AVS/privateClouds/clusters/datastores/version.json deleted file mode 100644 index 41f66cc990..0000000000 --- a/modules/Microsoft.AVS/privateClouds/clusters/datastores/version.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "0.1" -} diff --git a/modules/Microsoft.AVS/privateClouds/clusters/deploy.bicep b/modules/Microsoft.AVS/privateClouds/clusters/deploy.bicep deleted file mode 100644 index bc4e5059dc..0000000000 --- a/modules/Microsoft.AVS/privateClouds/clusters/deploy.bicep +++ /dev/null @@ -1,101 +0,0 @@ -// ============== // -// Parameters // -// ============== // - -@description('Required. Name of the cluster in the private cloud') -param name string - -@description('Required. The resource model definition representing SKU') -param sku object - -@description('Conditional. The name of the parent privateClouds. Required if the template is used in a standalone deployment.') -param privateCloudName string - -@description('Optional. The cluster size') -param clusterSize int = - -@description('Optional. The datastores to create as part of the cluster.') -param datastores array = [] - -@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') -param enableDefaultTelemetry bool = true - -@description('Optional. The hosts') -param hosts array = [] - -@description('Optional. The placementPolicies to create as part of the cluster.') -param placementPolicies array = [] - -var enableReferencedModulesTelemetry = false - -// =============== // -// Deployments // -// =============== // - -resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - } - } -} - -resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { - name: privateCloudName -} - -resource cluster 'Microsoft.AVS/privateClouds/clusters@2022-05-01' = { - parent: privateCloud - name: name - sku: sku - properties: { - clusterSize: clusterSize - hosts: hosts - } -} - -module cluster_placementPolicies 'placementPolicies/deploy.bicep' = [for (placementPolicy, index) in placementPolicies: { - name: '${uniqueString(deployment().name)}-cluster-placementPolicy-${index}' - params: { - privateCloudName: privateCloudName - clusterName: name - affinityStrength: contains(placementPolicy, 'affinityStrength') ? placementPolicy.affinityStrength : '' - azureHybridBenefitType: contains(placementPolicy, 'azureHybridBenefitType') ? placementPolicy.azureHybridBenefitType : '' - displayName: contains(placementPolicy, 'displayName') ? placementPolicy.displayName : '' - hostMembers: contains(placementPolicy, 'hostMembers') ? placementPolicy.hostMembers : [] - name: placementPolicy.name - state: contains(placementPolicy, 'state') ? placementPolicy.state : '' - type: contains(placementPolicy, 'type') ? placementPolicy.type : '' - vmMembers: contains(placementPolicy, 'vmMembers') ? placementPolicy.vmMembers : [] - enableDefaultTelemetry: enableReferencedModulesTelemetry - } -}] - -module cluster_datastores 'datastores/deploy.bicep' = [for (datastore, index) in datastores: { - name: '${uniqueString(deployment().name)}-cluster-datastore-${index}' - params: { - privateCloudName: privateCloudName - clusterName: name - diskPoolVolume: contains(datastore, 'diskPoolVolume') ? datastore.diskPoolVolume : {} - name: datastore.name - netAppVolume: contains(datastore, 'netAppVolume') ? datastore.netAppVolume : {} - enableDefaultTelemetry: enableReferencedModulesTelemetry - } -}] - -// =========== // -// Outputs // -// =========== // - -@description('The name of the cluster.') -output name string = cluster.name - -@description('The resource ID of the cluster.') -output resourceId string = cluster.id - -@description('The name of the resource group the cluster was created in.') -output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.AVS/privateClouds/clusters/placementPolicies/deploy.bicep b/modules/Microsoft.AVS/privateClouds/clusters/placementPolicies/deploy.bicep deleted file mode 100644 index bb78b7de40..0000000000 --- a/modules/Microsoft.AVS/privateClouds/clusters/placementPolicies/deploy.bicep +++ /dev/null @@ -1,103 +0,0 @@ -// ============== // -// Parameters // -// ============== // - -@description('Required. Name of the VMware vSphere Distributed Resource Scheduler (DRS) placement policy') -param name string - -@description('Conditional. The name of the parent clusters. Required if the template is used in a standalone deployment.') -param clusterName string - -@description('Conditional. The name of the parent privateClouds. Required if the template is used in a standalone deployment.') -param privateCloudName string - -@description('Optional. VM-Host placement policy affinity strength (should/must)') -@allowed([ - 'Should' - 'Must' -]) -param affinityStrength string = '' - -@description('Optional. Placement policy hosts opt-in Azure Hybrid Benefit type') -@allowed([ - 'SqlHost' - 'None' -]) -param azureHybridBenefitType string = '' - -@description('Optional. Display name of the placement policy') -param displayName string = '' - -@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') -param enableDefaultTelemetry bool = true - -@description('Optional. Host members list') -param hostMembers array = [] - -@description('Optional. Whether the placement policy is enabled or disabled') -@allowed([ - 'Enabled' - 'Disabled' -]) -param state string = '' - -@description('Optional. placement policy type') -@allowed([ - 'VmVm' - 'VmHost' -]) -param type string = '' - -@description('Optional. Virtual machine members list') -param vmMembers array = [] - -// =============== // -// Deployments // -// =============== // - -resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - } - } -} - -resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { - name: privateCloudName - - resource cluster 'clusters@2022-05-01' existing = { - name: clusterName - } -} - -resource placementPolicy 'Microsoft.AVS/privateClouds/clusters/placementPolicies@2022-05-01' = { - parent: privateCloud::cluster - name: name - properties: { - affinityStrength: affinityStrength - azureHybridBenefitType: azureHybridBenefitType - displayName: displayName - hostMembers: hostMembers - state: state - type: type - vmMembers: vmMembers - } -} - -// =========== // -// Outputs // -// =========== // - -@description('The name of the placementPolicy.') -output name string = placementPolicy.name - -@description('The resource ID of the placementPolicy.') -output resourceId string = placementPolicy.id - -@description('The name of the resource group the placementPolicy was created in.') -output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.AVS/privateClouds/clusters/placementPolicies/version.json b/modules/Microsoft.AVS/privateClouds/clusters/placementPolicies/version.json deleted file mode 100644 index 41f66cc990..0000000000 --- a/modules/Microsoft.AVS/privateClouds/clusters/placementPolicies/version.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "0.1" -} diff --git a/modules/Microsoft.AVS/privateClouds/clusters/version.json b/modules/Microsoft.AVS/privateClouds/clusters/version.json deleted file mode 100644 index 41f66cc990..0000000000 --- a/modules/Microsoft.AVS/privateClouds/clusters/version.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "0.1" -} diff --git a/modules/Microsoft.AVS/privateClouds/deploy.bicep b/modules/Microsoft.AVS/privateClouds/deploy.bicep deleted file mode 100644 index 80357f8f13..0000000000 --- a/modules/Microsoft.AVS/privateClouds/deploy.bicep +++ /dev/null @@ -1,426 +0,0 @@ -// ============== // -// Parameters // -// ============== // - -@description('Required. Name of the private cloud') -param name string - -@description('Required. The resource model definition representing SKU') -param sku object - -@description('Optional. The addons to create as part of the privateCloud.') -param addons array = [] - -@description('Optional. The authorizations to create as part of the privateCloud.') -param authorizations array = [] - -@description('Optional. The properties describing private cloud availability zone distribution') -param availability object = {} - -@description('Optional. An ExpressRoute Circuit') -param circuit object = {} - -@description('Optional. The cloudLinks to create as part of the privateCloud.') -param cloudLinks array = [] - -@description('Optional. The clusters to create as part of the privateCloud.') -param clusters array = [] - -@description('Optional. The dhcpConfigurations to create as part of the privateCloud.') -param dhcpConfigurations array = [] - -@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') -param diagnosticEventHubAuthorizationRuleId string = '' - -@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub.') -param diagnosticEventHubName string = '' - -@description('Optional. The name of logs that will be streamed.') -@allowed([ - 'CapacityLatest' - 'DiskUsedPercentage' - 'EffectiveCpuAverage' - 'EffectiveMemAverage' - 'OverheadAverage' - 'TotalMbAverage' - 'UsageAverage' - 'UsedLatest' -]) -param diagnosticLogCategoriesToEnable array = [ - 'CapacityLatest' - 'DiskUsedPercentage' - 'EffectiveCpuAverage' - 'EffectiveMemAverage' - 'OverheadAverage' - 'TotalMbAverage' - 'UsageAverage' - 'UsedLatest' -] - -@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') -param diagnosticLogsRetentionInDays int = 365 - -@description('Optional. The name of metrics that will be streamed.') -@allowed([ - 'AllMetrics' -]) -param diagnosticMetricsToEnable array = [ - 'AllMetrics' -] - -@description('Optional. The name of the diagnostic setting, if deployed.') -param diagnosticSettingsName string = '${name}-diagnosticSettings' - -@description('Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub.') -param diagnosticStorageAccountId string = '' - -@description('Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub.') -param diagnosticWorkspaceId string = '' - -@description('Optional. The dnsServices to create as part of the privateCloud.') -param dnsServices array = [] - -@description('Optional. The dnsZones to create as part of the privateCloud.') -param dnsZones array = [] - -@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') -param enableDefaultTelemetry bool = true - -@description('Optional. The properties of customer managed encryption key') -param encryption object = {} - -@description('Optional. The globalReachConnections to create as part of the privateCloud.') -param globalReachConnections array = [] - -@description('Optional. The hcxEnterpriseSites to create as part of the privateCloud.') -param hcxEnterpriseSites array = [] - -@description('Optional. Identity for the virtual machine.') -param identity object = {} - -@description('Optional. vCenter Single Sign On Identity Sources') -param identitySources array = [] - -@description('Optional. Connectivity to internet is enabled or disabled') -@allowed([ - 'Enabled' - 'Disabled' -]) -param internet string = 'Disabled' - -@description('Optional. Location for all Resources.') -param location string = resourceGroup().location - -@description('Optional. Specify the type of lock.') -@allowed([ - '' - 'CanNotDelete' - 'ReadOnly' -]) -param lock string = '' - -@description('Optional. The properties of a management cluster') -param managementCluster object = {} - -@description('Optional. The block of addresses should be unique across VNet in your subscription as well as on-premise. Make sure the CIDR format is conformed to (A.B.C.D/X) where A,B,C,D are between 0 and 255, and X is between 0 and 22') -param networkBlock string = '' - -@description('Optional. Optionally, set the NSX-T Manager password when the private cloud is created') -@secure() -param nsxtPassword string = '' - -@description('Optional. The portMirroringProfiles to create as part of the privateCloud.') -param portMirroringProfiles array = [] - -@description('Optional. The publicIPs to create as part of the privateCloud.') -param publicIPs array = [] - -@description('Optional. The scriptExecutions to create as part of the privateCloud.') -param scriptExecutions array = [] - -@description('Optional. An ExpressRoute Circuit') -param secondaryCircuit object = {} - -@description('Optional. The segments to create as part of the privateCloud.') -param segments array = [] - -@description('Optional. Resource tags') -param tags object = {} - -@description('Optional. Optionally, set the vCenter admin password when the private cloud is created') -@secure() -param vcenterPassword string = '' - -@description('Optional. The vmGroups to create as part of the privateCloud.') -param vmGroups array = [] - -var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { - category: metric - timeGrain: null - enabled: true - retentionPolicy: { - enabled: true - days: diagnosticLogsRetentionInDays - } -}] - -var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { - category: category - enabled: true - retentionPolicy: { - enabled: true - days: diagnosticLogsRetentionInDays - } -}] - -var enableReferencedModulesTelemetry = false - -// =============== // -// Deployments // -// =============== // - -resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - } - } -} - - -resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' = { - identity: identity - location: location - name: name - sku: sku - tags: tags - properties: { - availability: availability - circuit: circuit - encryption: encryption - identitySources: identitySources - internet: internet - managementCluster: managementCluster - networkBlock: networkBlock - nsxtPassword: nsxtPassword - secondaryCircuit: secondaryCircuit - vcenterPassword: vcenterPassword - } -} - -resource privateCloud_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { - name: diagnosticSettingsName - properties: { - storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null - workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null - eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null - eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null - metrics: diagnosticsMetrics - logs: diagnosticsLogs - } - scope: privateCloud -} - -resource keyVault_lock 'Microsoft.Authorization/locks@2017-04-01' = if (!empty(lock)) { - name: '${privateCloud.name}-${lock}-lock' - properties: { - level: any(lock) - notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' - } - scope: privateCloud -} - -module privateCloud_scriptExecutions 'scriptExecutions/deploy.bicep' = [for (scriptExecution, index) in scriptExecutions: { - name: '${uniqueString(deployment().name, location)}-privateCloud-scriptExecution-${index}' - params: { - privateCloudName: name - failureReason: contains(scriptExecution, 'failureReason') ? scriptExecution.failureReason : '' - hiddenParameters: contains(scriptExecution, 'hiddenParameters') ? scriptExecution.hiddenParameters : [] - name: scriptExecution.name - namedOutputs: contains(scriptExecution, 'namedOutputs') ? scriptExecution.namedOutputs : {} - output: contains(scriptExecution, 'output') ? scriptExecution.output : [] - parameters: contains(scriptExecution, 'parameters') ? scriptExecution.parameters : [] - retention: contains(scriptExecution, 'retention') ? scriptExecution.retention : '' - scriptCmdletId: contains(scriptExecution, 'scriptCmdletId') ? scriptExecution.scriptCmdletId : '' - timeout: contains(scriptExecution, 'timeout') ? scriptExecution.timeout : '' - enableDefaultTelemetry: enableReferencedModulesTelemetry - } -}] - -module privateCloud_cloudLinks 'cloudLinks/deploy.bicep' = [for (cloudLink, index) in cloudLinks: { - name: '${uniqueString(deployment().name, location)}-privateCloud-cloudLink-${index}' - params: { - privateCloudName: name - linkedCloud: contains(cloudLink, 'linkedCloud') ? cloudLink.linkedCloud : '' - name: cloudLink.name - enableDefaultTelemetry: enableReferencedModulesTelemetry - } -}] - -module privateCloud_authorizations 'authorizations/deploy.bicep' = [for (authorization, index) in authorizations: { - name: '${uniqueString(deployment().name, location)}-privateCloud-authorization-${index}' - params: { - privateCloudName: name - name: authorization.name - enableDefaultTelemetry: enableReferencedModulesTelemetry - } -}] - -module privateCloud_clusters 'clusters/deploy.bicep' = [for (cluster, index) in clusters: { - name: '${uniqueString(deployment().name, location)}-privateCloud-cluster-${index}' - params: { - privateCloudName: name - clusterSize: contains(cluster, 'clusterSize') ? cluster.clusterSize : - hosts: contains(cluster, 'hosts') ? cluster.hosts : [] - name: cluster.name - sku: cluster.sku - enableDefaultTelemetry: enableReferencedModulesTelemetry - } -}] - -module privateCloud_addons 'addons/deploy.bicep' = [for (addon, index) in addons: { - name: '${uniqueString(deployment().name, location)}-privateCloud-addon-${index}' - params: { - privateCloudName: name - addonType: contains(addon, 'addonType') ? addon.addonType : '' - name: addon.name - enableDefaultTelemetry: enableReferencedModulesTelemetry - } -}] - -module privateCloud_hcxEnterpriseSites 'hcxEnterpriseSites/deploy.bicep' = [for (hcxEnterpriseSite, index) in hcxEnterpriseSites: { - name: '${uniqueString(deployment().name, location)}-privateCloud-hcxEnterpriseSite-${index}' - params: { - privateCloudName: name - name: hcxEnterpriseSite.name - enableDefaultTelemetry: enableReferencedModulesTelemetry - } -}] - -module privateCloud_globalReachConnections 'globalReachConnections/deploy.bicep' = [for (globalReachConnection, index) in globalReachConnections: { - name: '${uniqueString(deployment().name, location)}-privateCloud-globalReachConnection-${index}' - params: { - privateCloudName: name - authorizationKey: contains(globalReachConnection, 'authorizationKey') ? globalReachConnection.authorizationKey : '' - expressRouteId: contains(globalReachConnection, 'expressRouteId') ? globalReachConnection.expressRouteId : '' - name: globalReachConnection.name - peerExpressRouteCircuit: contains(globalReachConnection, 'peerExpressRouteCircuit') ? globalReachConnection.peerExpressRouteCircuit : '' - enableDefaultTelemetry: enableReferencedModulesTelemetry - } -}] - -module workloadNetworks_privateCloud_publicIPs 'workloadNetworks/publicIPs/deploy.bicep' = [for (publicIP, index) in publicIPs: { - name: '${uniqueString(deployment().name, location)}-privateCloud-publicIP-${index}' - params: { - privateCloudName: name - workloadNetworkName: 'default' - displayName: contains(publicIP, 'displayName') ? publicIP.displayName : '' - name: publicIP.name - numberOfPublicIPs: contains(publicIP, 'numberOfPublicIPs') ? publicIP.numberOfPublicIPs : - enableDefaultTelemetry: enableReferencedModulesTelemetry - } -}] - -module workloadNetworks_privateCloud_segments 'workloadNetworks/segments/deploy.bicep' = [for (segment, index) in segments: { - name: '${uniqueString(deployment().name, location)}-privateCloud-segment-${index}' - params: { - privateCloudName: name - workloadNetworkName: 'default' - connectedGateway: contains(segment, 'connectedGateway') ? segment.connectedGateway : '' - displayName: contains(segment, 'displayName') ? segment.displayName : '' - name: segment.name - revision: contains(segment, 'revision') ? segment.revision : - subnet: contains(segment, 'subnet') ? segment.subnet : {} - enableDefaultTelemetry: enableReferencedModulesTelemetry - } -}] - -module workloadNetworks_privateCloud_portMirroringProfiles 'workloadNetworks/portMirroringProfiles/deploy.bicep' = [for (portMirroringProfile, index) in portMirroringProfiles: { - name: '${uniqueString(deployment().name, location)}-privateCloud-portMirroringProfile-${index}' - params: { - privateCloudName: name - workloadNetworkName: 'default' - destination: contains(portMirroringProfile, 'destination') ? portMirroringProfile.destination : '' - direction: contains(portMirroringProfile, 'direction') ? portMirroringProfile.direction : '' - displayName: contains(portMirroringProfile, 'displayName') ? portMirroringProfile.displayName : '' - name: portMirroringProfile.name - revision: contains(portMirroringProfile, 'revision') ? portMirroringProfile.revision : - source: contains(portMirroringProfile, 'source') ? portMirroringProfile.source : '' - enableDefaultTelemetry: enableReferencedModulesTelemetry - } -}] - -module workloadNetworks_privateCloud_vmGroups 'workloadNetworks/vmGroups/deploy.bicep' = [for (vmGroup, index) in vmGroups: { - name: '${uniqueString(deployment().name, location)}-privateCloud-vmGroup-${index}' - params: { - privateCloudName: name - workloadNetworkName: 'default' - displayName: contains(vmGroup, 'displayName') ? vmGroup.displayName : '' - members: contains(vmGroup, 'members') ? vmGroup.members : [] - name: vmGroup.name - revision: contains(vmGroup, 'revision') ? vmGroup.revision : - enableDefaultTelemetry: enableReferencedModulesTelemetry - } -}] - -module workloadNetworks_privateCloud_dnsServices 'workloadNetworks/dnsServices/deploy.bicep' = [for (dnsService, index) in dnsServices: { - name: '${uniqueString(deployment().name, location)}-privateCloud-dnsService-${index}' - params: { - privateCloudName: name - workloadNetworkName: 'default' - defaultDnsZone: contains(dnsService, 'defaultDnsZone') ? dnsService.defaultDnsZone : '' - displayName: contains(dnsService, 'displayName') ? dnsService.displayName : '' - dnsServiceIp: contains(dnsService, 'dnsServiceIp') ? dnsService.dnsServiceIp : '' - fqdnZones: contains(dnsService, 'fqdnZones') ? dnsService.fqdnZones : [] - logLevel: contains(dnsService, 'logLevel') ? dnsService.logLevel : '' - name: dnsService.name - revision: contains(dnsService, 'revision') ? dnsService.revision : - enableDefaultTelemetry: enableReferencedModulesTelemetry - } -}] - -module workloadNetworks_privateCloud_dhcpConfigurations 'workloadNetworks/dhcpConfigurations/deploy.bicep' = [for (dhcpConfiguration, index) in dhcpConfigurations: { - name: '${uniqueString(deployment().name, location)}-privateCloud-dhcpConfiguration-${index}' - params: { - privateCloudName: name - workloadNetworkName: 'default' - dhcpType: contains(dhcpConfiguration, 'dhcpType') ? dhcpConfiguration.dhcpType : '' - displayName: contains(dhcpConfiguration, 'displayName') ? dhcpConfiguration.displayName : '' - name: dhcpConfiguration.name - revision: contains(dhcpConfiguration, 'revision') ? dhcpConfiguration.revision : - enableDefaultTelemetry: enableReferencedModulesTelemetry - } -}] - -module workloadNetworks_privateCloud_dnsZones 'workloadNetworks/dnsZones/deploy.bicep' = [for (dnsZone, index) in dnsZones: { - name: '${uniqueString(deployment().name, location)}-privateCloud-dnsZone-${index}' - params: { - privateCloudName: name - workloadNetworkName: 'default' - displayName: contains(dnsZone, 'displayName') ? dnsZone.displayName : '' - dnsServerIps: contains(dnsZone, 'dnsServerIps') ? dnsZone.dnsServerIps : [] - dnsServices: contains(dnsZone, 'dnsServices') ? dnsZone.dnsServices : - domain: contains(dnsZone, 'domain') ? dnsZone.domain : [] - name: dnsZone.name - revision: contains(dnsZone, 'revision') ? dnsZone.revision : - sourceIp: contains(dnsZone, 'sourceIp') ? dnsZone.sourceIp : '' - enableDefaultTelemetry: enableReferencedModulesTelemetry - } -}] - -// =========== // -// Outputs // -// =========== // - -@description('The name of the privateCloud.') -output name string = privateCloud.name - -@description('The resource ID of the privateCloud.') -output resourceId string = privateCloud.id - -@description('The name of the resource group the privateCloud was created in.') -output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.AVS/privateClouds/globalReachConnections/deploy.bicep b/modules/Microsoft.AVS/privateClouds/globalReachConnections/deploy.bicep deleted file mode 100644 index bd98d9ca91..0000000000 --- a/modules/Microsoft.AVS/privateClouds/globalReachConnections/deploy.bicep +++ /dev/null @@ -1,64 +0,0 @@ -// ============== // -// Parameters // -// ============== // - -@description('Required. Name of the global reach connection in the private cloud') -param name string - -@description('Conditional. The name of the parent privateClouds. Required if the template is used in a standalone deployment.') -param privateCloudName string - -@description('Optional. Authorization key from the peer express route used for the global reach connection') -param authorizationKey string = '' - -@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') -param enableDefaultTelemetry bool = true - -@description('Optional. The ID of the Private Cloud\'s ExpressRoute Circuit that is participating in the global reach connection') -param expressRouteId string = '' - -@description('Optional. Identifier of the ExpressRoute Circuit to peer with in the global reach connection') -param peerExpressRouteCircuit string = '' - -// =============== // -// Deployments // -// =============== // - -resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - } - } -} - -resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { - name: privateCloudName -} - -resource globalReachConnection 'Microsoft.AVS/privateClouds/globalReachConnections@2022-05-01' = { - parent: privateCloud - name: name - properties: { - authorizationKey: authorizationKey - expressRouteId: expressRouteId - peerExpressRouteCircuit: peerExpressRouteCircuit - } -} - -// =========== // -// Outputs // -// =========== // - -@description('The name of the globalReachConnection.') -output name string = globalReachConnection.name - -@description('The resource ID of the globalReachConnection.') -output resourceId string = globalReachConnection.id - -@description('The name of the resource group the globalReachConnection was created in.') -output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.AVS/privateClouds/globalReachConnections/readme.md b/modules/Microsoft.AVS/privateClouds/globalReachConnections/readme.md deleted file mode 100644 index 3da1c7294f..0000000000 --- a/modules/Microsoft.AVS/privateClouds/globalReachConnections/readme.md +++ /dev/null @@ -1,57 +0,0 @@ -# AVS PrivateClouds GlobalReachConnections `[Microsoft.AVS/privateClouds/globalReachConnections]` - -This module deploys AVS PrivateClouds GlobalReachConnections. -// TODO: Replace Resource and fill in description - -## Navigation - -- [Resource Types](#Resource-Types) -- [Parameters](#Parameters) -- [Outputs](#Outputs) -- [Cross-referenced modules](#Cross-referenced-modules) - -## Resource Types - -| Resource Type | API Version | -| :-- | :-- | -| `Microsoft.AVS/privateClouds/globalReachConnections` | [2022-05-01](https://docs.microsoft.com/en-us/azure/templates/Microsoft.AVS/privateClouds/globalReachConnections) | - -## Parameters - -**Required parameters** - -| Parameter Name | Type | Description | -| :-- | :-- | :-- | -| `name` | string | Name of the global reach connection in the private cloud | - -**Conditional parameters** - -| Parameter Name | Type | Description | -| :-- | :-- | :-- | -| `privateCloudName` | string | The name of the parent privateClouds. Required if the template is used in a standalone deployment. | - -**Optional parameters** - -| Parameter Name | Type | Default Value | Description | -| :-- | :-- | :-- | :-- | -| `authorizationKey` | string | `''` | Authorization key from the peer express route used for the global reach connection | -| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | -| `expressRouteId` | string | `''` | The ID of the Private Cloud's ExpressRoute Circuit that is participating in the global reach connection | -| `peerExpressRouteCircuit` | string | `''` | Identifier of the ExpressRoute Circuit to peer with in the global reach connection | - - -### Parameter Usage: `` - -// TODO: Fill in Parameter usage - -## Outputs - -| Output Name | Type | Description | -| :-- | :-- | :-- | -| `name` | string | The name of the globalReachConnection. | -| `resourceGroupName` | string | The name of the resource group the globalReachConnection was created in. | -| `resourceId` | string | The resource ID of the globalReachConnection. | - -## Cross-referenced modules - -_None_ diff --git a/modules/Microsoft.AVS/privateClouds/globalReachConnections/version.json b/modules/Microsoft.AVS/privateClouds/globalReachConnections/version.json deleted file mode 100644 index 41f66cc990..0000000000 --- a/modules/Microsoft.AVS/privateClouds/globalReachConnections/version.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "0.1" -} diff --git a/modules/Microsoft.AVS/privateClouds/hcxEnterpriseSites/deploy.bicep b/modules/Microsoft.AVS/privateClouds/hcxEnterpriseSites/deploy.bicep deleted file mode 100644 index f7206b8c05..0000000000 --- a/modules/Microsoft.AVS/privateClouds/hcxEnterpriseSites/deploy.bicep +++ /dev/null @@ -1,52 +0,0 @@ -// ============== // -// Parameters // -// ============== // - -@description('Required. Name of the HCX Enterprise Site in the private cloud') -param name string - -@description('Conditional. The name of the parent privateClouds. Required if the template is used in a standalone deployment.') -param privateCloudName string - -@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') -param enableDefaultTelemetry bool = true - -// =============== // -// Deployments // -// =============== // - -resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - } - } -} - -resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { - name: privateCloudName -} - -resource hcxEnterpriseSite 'Microsoft.AVS/privateClouds/hcxEnterpriseSites@2022-05-01' = { - parent: privateCloud - name: name - properties: { - } -} - -// =========== // -// Outputs // -// =========== // - -@description('The name of the hcxEnterpriseSite.') -output name string = hcxEnterpriseSite.name - -@description('The resource ID of the hcxEnterpriseSite.') -output resourceId string = hcxEnterpriseSite.id - -@description('The name of the resource group the hcxEnterpriseSite was created in.') -output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.AVS/privateClouds/hcxEnterpriseSites/readme.md b/modules/Microsoft.AVS/privateClouds/hcxEnterpriseSites/readme.md deleted file mode 100644 index 7a0a111fdf..0000000000 --- a/modules/Microsoft.AVS/privateClouds/hcxEnterpriseSites/readme.md +++ /dev/null @@ -1,54 +0,0 @@ -# AVS PrivateClouds HcxEnterpriseSites `[Microsoft.AVS/privateClouds/hcxEnterpriseSites]` - -This module deploys AVS PrivateClouds HcxEnterpriseSites. -// TODO: Replace Resource and fill in description - -## Navigation - -- [Resource Types](#Resource-Types) -- [Parameters](#Parameters) -- [Outputs](#Outputs) -- [Cross-referenced modules](#Cross-referenced-modules) - -## Resource Types - -| Resource Type | API Version | -| :-- | :-- | -| `Microsoft.AVS/privateClouds/hcxEnterpriseSites` | [2022-05-01](https://docs.microsoft.com/en-us/azure/templates/Microsoft.AVS/privateClouds/hcxEnterpriseSites) | - -## Parameters - -**Required parameters** - -| Parameter Name | Type | Description | -| :-- | :-- | :-- | -| `name` | string | Name of the HCX Enterprise Site in the private cloud | - -**Conditional parameters** - -| Parameter Name | Type | Description | -| :-- | :-- | :-- | -| `privateCloudName` | string | The name of the parent privateClouds. Required if the template is used in a standalone deployment. | - -**Optional parameters** - -| Parameter Name | Type | Default Value | Description | -| :-- | :-- | :-- | :-- | -| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | - - -### Parameter Usage: `` - -// TODO: Fill in Parameter usage - -## Outputs - -| Output Name | Type | Description | -| :-- | :-- | :-- | -| `name` | string | The name of the hcxEnterpriseSite. | -| `resourceGroupName` | string | The name of the resource group the hcxEnterpriseSite was created in. | -| `resourceId` | string | The resource ID of the hcxEnterpriseSite. | - -## Cross-referenced modules - -_None_ diff --git a/modules/Microsoft.AVS/privateClouds/hcxEnterpriseSites/version.json b/modules/Microsoft.AVS/privateClouds/hcxEnterpriseSites/version.json deleted file mode 100644 index 41f66cc990..0000000000 --- a/modules/Microsoft.AVS/privateClouds/hcxEnterpriseSites/version.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "0.1" -} diff --git a/modules/Microsoft.AVS/privateClouds/readme.md b/modules/Microsoft.AVS/privateClouds/readme.md deleted file mode 100644 index 51d26ff306..0000000000 --- a/modules/Microsoft.AVS/privateClouds/readme.md +++ /dev/null @@ -1,181 +0,0 @@ -# AVS PrivateClouds `[Microsoft.AVS/privateClouds]` - -This module deploys AVS PrivateClouds. -// TODO: Replace Resource and fill in description - -## Navigation - -- [Resource Types](#Resource-Types) -- [Parameters](#Parameters) -- [Outputs](#Outputs) -- [Cross-referenced modules](#Cross-referenced-modules) -- [Deployment examples](#Deployment-examples) - -## Resource Types - -| Resource Type | API Version | -| :-- | :-- | -| `Microsoft.Authorization/locks` | [2017-04-01](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2017-04-01/locks) | -| `Microsoft.Authorization/roleAssignments` | [2022-04-01](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Authorization/2022-04-01/roleAssignments) | -| `Microsoft.AVS/privateClouds` | [2021-12-01](https://docs.microsoft.com/en-us/azure/templates/Microsoft.AVS/2021-12-01/privateClouds) | -| `Microsoft.Insights/diagnosticSettings` | [2021-05-01-preview](https://docs.microsoft.com/en-us/azure/templates/Microsoft.Insights/2021-05-01-preview/diagnosticSettings) | - -## Parameters - -**Required parameters** -| Parameter Name | Type | Description | -| :-- | :-- | :-- | -| `name` | string | Name of the private cloud | -| `sku` | object | The private cloud SKU | - -**Optional parameters** -| Parameter Name | Type | Default Value | Allowed Values | Description | -| :-- | :-- | :-- | :-- | :-- | -| `availability` | object | | | Properties describing how the cloud is distributed across availability zones | -| `circuit` | object | | | An ExpressRoute Circuit | -| `diagnosticEventHubAuthorizationRuleId` | string | | | Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to. | -| `diagnosticEventHubName` | string | | | Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub. | -| `diagnosticLogCategoriesToEnable` | array | `[CapacityLatest, DiskUsedPercentage, EffectiveCpuAverage, EffectiveMemAverage, OverheadAverage, TotalMbAverage, UsageAverage, UsedLatest]` | `[CapacityLatest, DiskUsedPercentage, EffectiveCpuAverage, EffectiveMemAverage, OverheadAverage, TotalMbAverage, UsageAverage, UsedLatest]` | The name of logs that will be streamed. | -| `diagnosticLogsRetentionInDays` | int | `365` | | Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely. | -| `diagnosticMetricsToEnable` | array | `[AllMetrics]` | `[AllMetrics]` | The name of metrics that will be streamed. | -| `diagnosticSettingsName` | string | `[format('{0}-diagnosticSettings', parameters('name'))]` | | The name of the diagnostic setting, if deployed. | -| `diagnosticStorageAccountId` | string | | | Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub. | -| `diagnosticWorkspaceId` | string | | | Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub. | -| `enableDefaultTelemetry` | bool | `True` | | Enable telemetry via the Customer Usage Attribution ID (GUID). | -| `encryption` | object | | | Customer managed key encryption, can be enabled or disabled | -| `identity` | object | | | The identity of the private cloud, if configured. | -| `identitySources` | array | | | vCenter Single Sign On Identity Sources | -| `internet` | string | `'Disabled'` | `[Disabled, Enabled]` | Connectivity to internet is enabled or disabled | -| `location` | string | `[resourceGroup().location]` | | Location for all Resources. | -| `lock` | string | | `[CanNotDelete, ReadOnly]` | Specify the type of lock. | -| `managementCluster` | object | | | The default cluster used for management | -| `networkBlock` | string | | | The block of addresses should be unique across VNet in your subscription as well as on-premise. Make sure the CIDR format is conformed to (A.B.C.D/X) where A,B,C,D are between 0 and 255, and X is between 0 and 22 | -| `nsxtPassword` | secureString | | | Optionally, set the NSX-T Manager password when the private cloud is created | -| `roleAssignments` | array | | | Array of role assignment objects that contain the 'roleDefinitionIdOrName' and 'principalId' to define RBAC role assignments on this resource. In the roleDefinitionIdOrName attribute, you can provide either the display name of the role definition, or its fully qualified ID in the following format: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11'. | -| `secondaryCircuit` | object | | | A secondary expressRoute circuit from a separate AZ. Only present in a stretched private cloud | -| `tags` | object | | | Resource tags | -| `vcenterPassword` | secureString | | | Optionally, set the vCenter admin password when the private cloud is created | - - -### Parameter Usage: `` - -// TODO: Fill in Parameter usage - -### Parameter Usage: `roleAssignments` - -Create a role assignment for the given resource. If you want to assign a service principal / managed identity that is created in the same deployment, make sure to also specify the `'principalType'` parameter and set it to `'ServicePrincipal'`. This will ensure the role assignment waits for the principal's propagation in Azure. - -
- -Parameter JSON format - -```json -"roleAssignments": { - "value": [ - { - "roleDefinitionIdOrName": "Reader", - "description": "Reader Role Assignment", - "principalIds": [ - "12345678-1234-1234-1234-123456789012", // object 1 - "78945612-1234-1234-1234-123456789012" // object 2 - ] - }, - { - "roleDefinitionIdOrName": "/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11", - "principalIds": [ - "12345678-1234-1234-1234-123456789012" // object 1 - ], - "principalType": "ServicePrincipal" - } - ] -} -``` - -
- -
- -Bicep format - -```bicep -roleAssignments: [ - { - roleDefinitionIdOrName: 'Reader' - description: 'Reader Role Assignment' - principalIds: [ - '12345678-1234-1234-1234-123456789012' // object 1 - '78945612-1234-1234-1234-123456789012' // object 2 - ] - } - { - roleDefinitionIdOrName: '/providers/Microsoft.Authorization/roleDefinitions/c2f4ef07-c644-48eb-af81-4b1b4947fb11' - principalIds: [ - '12345678-1234-1234-1234-123456789012' // object 1 - ] - principalType: 'ServicePrincipal' - } -] -``` - -
-

- -### Parameter Usage: `tags` - -Tag names and tag values can be provided as needed. A tag can be left without a value. - -

- -Parameter JSON format - -```json -"tags": { - "value": { - "Environment": "Non-Prod", - "Contact": "test.user@testcompany.com", - "PurchaseOrder": "1234", - "CostCenter": "7890", - "ServiceName": "DeploymentValidation", - "Role": "DeploymentValidation" - } -} -``` - -
- -
- -Bicep format - -```bicep -tags: { - Environment: 'Non-Prod' - Contact: 'test.user@testcompany.com' - PurchaseOrder: '1234' - CostCenter: '7890' - ServiceName: 'DeploymentValidation' - Role: 'DeploymentValidation' -} -``` - -
-

- -## Outputs - -| Output Name | Type | Description | -| :-- | :-- | :-- | -| `name` | string | The name of the privateCloud. | -| `resourceGroupName` | string | The name of the resource group the privateCloud was created in. | -| `resourceId` | string | The resource ID of the privateCloud. | - -## Cross-referenced modules - -_None_ - -## Deployment examples - -The following module usage examples are retrieved from the content of the files hosted in the module's `.test` folder. - >**Note**: The name of each example is based on the name of the file from which it is taken. - - >**Note**: Each example lists all the required parameters first, followed by the rest - each in alphabetical order. diff --git a/modules/Microsoft.AVS/privateClouds/scriptExecutions/deploy.bicep b/modules/Microsoft.AVS/privateClouds/scriptExecutions/deploy.bicep deleted file mode 100644 index 5422b3033b..0000000000 --- a/modules/Microsoft.AVS/privateClouds/scriptExecutions/deploy.bicep +++ /dev/null @@ -1,84 +0,0 @@ -// ============== // -// Parameters // -// ============== // - -@description('Required. Name of the user-invoked script execution resource') -param name string - -@description('Conditional. The name of the parent privateClouds. Required if the template is used in a standalone deployment.') -param privateCloudName string - -@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') -param enableDefaultTelemetry bool = true - -@description('Optional. Error message if the script was able to run, but if the script itself had errors or powershell threw an exception') -param failureReason string = '' - -@description('Optional. Parameters that will be hidden/not visible to ARM, such as passwords and credentials') -param hiddenParameters array = [] - -@description('Optional. User-defined dictionary.') -param namedOutputs object = {} - -@description('Optional. Standard output stream from the powershell execution') -param output array = [] - -@description('Optional. Parameters the script will accept') -param parameters array = [] - -@description('Optional. Time to live for the resource. If not provided, will be available for 60 days') -param retention string = '' - -@description('Optional. A reference to the script cmdlet resource if user is running a AVS script') -param scriptCmdletId string = '' - -@description('Optional. Time limit for execution') -param timeout string = '' - -// =============== // -// Deployments // -// =============== // - -resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - } - } -} - -resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { - name: privateCloudName -} - -resource scriptExecution 'Microsoft.AVS/privateClouds/scriptExecutions@2022-05-01' = { - parent: privateCloud - name: name - properties: { - failureReason: failureReason - hiddenParameters: hiddenParameters - namedOutputs: namedOutputs - output: output - parameters: parameters - retention: retention - scriptCmdletId: scriptCmdletId - timeout: timeout - } -} - -// =========== // -// Outputs // -// =========== // - -@description('The name of the scriptExecution.') -output name string = scriptExecution.name - -@description('The resource ID of the scriptExecution.') -output resourceId string = scriptExecution.id - -@description('The name of the resource group the scriptExecution was created in.') -output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.AVS/privateClouds/scriptExecutions/readme.md b/modules/Microsoft.AVS/privateClouds/scriptExecutions/readme.md deleted file mode 100644 index 50ea7501f0..0000000000 --- a/modules/Microsoft.AVS/privateClouds/scriptExecutions/readme.md +++ /dev/null @@ -1,62 +0,0 @@ -# AVS PrivateClouds ScriptExecutions `[Microsoft.AVS/privateClouds/scriptExecutions]` - -This module deploys AVS PrivateClouds ScriptExecutions. -// TODO: Replace Resource and fill in description - -## Navigation - -- [Resource Types](#Resource-Types) -- [Parameters](#Parameters) -- [Outputs](#Outputs) -- [Cross-referenced modules](#Cross-referenced-modules) - -## Resource Types - -| Resource Type | API Version | -| :-- | :-- | -| `Microsoft.AVS/privateClouds/scriptExecutions` | [2022-05-01](https://docs.microsoft.com/en-us/azure/templates/Microsoft.AVS/privateClouds/scriptExecutions) | - -## Parameters - -**Required parameters** - -| Parameter Name | Type | Description | -| :-- | :-- | :-- | -| `name` | string | Name of the user-invoked script execution resource | - -**Conditional parameters** - -| Parameter Name | Type | Description | -| :-- | :-- | :-- | -| `privateCloudName` | string | The name of the parent privateClouds. Required if the template is used in a standalone deployment. | - -**Optional parameters** - -| Parameter Name | Type | Default Value | Description | -| :-- | :-- | :-- | :-- | -| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | -| `failureReason` | string | `''` | Error message if the script was able to run, but if the script itself had errors or powershell threw an exception | -| `hiddenParameters` | array | `[]` | Parameters that will be hidden/not visible to ARM, such as passwords and credentials | -| `namedOutputs` | object | `{object}` | User-defined dictionary. | -| `output` | array | `[]` | Standard output stream from the powershell execution | -| `parameters` | array | `[]` | Parameters the script will accept | -| `retention` | string | `''` | Time to live for the resource. If not provided, will be available for 60 days | -| `scriptCmdletId` | string | `''` | A reference to the script cmdlet resource if user is running a AVS script | -| `timeout` | string | `''` | Time limit for execution | - - -### Parameter Usage: `` - -// TODO: Fill in Parameter usage - -## Outputs - -| Output Name | Type | Description | -| :-- | :-- | :-- | -| `name` | string | The name of the scriptExecution. | -| `resourceGroupName` | string | The name of the resource group the scriptExecution was created in. | -| `resourceId` | string | The resource ID of the scriptExecution. | - -## Cross-referenced modules - -_None_ diff --git a/modules/Microsoft.AVS/privateClouds/scriptExecutions/version.json b/modules/Microsoft.AVS/privateClouds/scriptExecutions/version.json deleted file mode 100644 index 41f66cc990..0000000000 --- a/modules/Microsoft.AVS/privateClouds/scriptExecutions/version.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "0.1" -} diff --git a/modules/Microsoft.AVS/privateClouds/version.json b/modules/Microsoft.AVS/privateClouds/version.json deleted file mode 100644 index 41f66cc990..0000000000 --- a/modules/Microsoft.AVS/privateClouds/version.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "0.1" -} diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dhcpConfigurations/deploy.bicep b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dhcpConfigurations/deploy.bicep deleted file mode 100644 index 39ec347746..0000000000 --- a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dhcpConfigurations/deploy.bicep +++ /dev/null @@ -1,75 +0,0 @@ -// ============== // -// Parameters // -// ============== // - -@description('Required. NSX DHCP identifier. Generally the same as the DHCP display name') -param name string - -@description('Conditional. The name of the parent privateClouds. Required if the template is used in a standalone deployment.') -param privateCloudName string - -@description('Optional. Type of DHCP: SERVER or RELAY.') -@allowed([ - 'SERVER' - 'RELAY' -]) -param dhcpType string = '' - -@description('Optional. Display name of the DHCP entity.') -param displayName string = '' - -@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') -param enableDefaultTelemetry bool = true - -@description('Optional. NSX revision number.') -param revision int = - -@description('Optional. The name of the parent workloadNetworks. Required if the template is used in a standalone deployment.') -param workloadNetworkName string = 'default' - -// =============== // -// Deployments // -// =============== // - -resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - } - } -} - -resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { - name: privateCloudName - - resource workloadNetwork 'workloadNetworks@2022-05-01' existing = { - name: workloadNetworkName - } -} - -resource dhcpConfiguration 'Microsoft.AVS/privateClouds/workloadNetworks/dhcpConfigurations@2022-05-01' = { - parent: privateCloud::workloadNetwork - name: name - properties: { - dhcpType: dhcpType - displayName: displayName - revision: revision - } -} - -// =========== // -// Outputs // -// =========== // - -@description('The name of the dhcpConfiguration.') -output name string = dhcpConfiguration.name - -@description('The resource ID of the dhcpConfiguration.') -output resourceId string = dhcpConfiguration.id - -@description('The name of the resource group the dhcpConfiguration was created in.') -output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dhcpConfigurations/version.json b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dhcpConfigurations/version.json deleted file mode 100644 index 41f66cc990..0000000000 --- a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dhcpConfigurations/version.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "0.1" -} diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsServices/deploy.bicep b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsServices/deploy.bicep deleted file mode 100644 index 1364785293..0000000000 --- a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsServices/deploy.bicep +++ /dev/null @@ -1,90 +0,0 @@ -// ============== // -// Parameters // -// ============== // - -@description('Required. NSX DNS Service identifier. Generally the same as the DNS Service\'s display name') -param name string - -@description('Conditional. The name of the parent privateClouds. Required if the template is used in a standalone deployment.') -param privateCloudName string - -@description('Optional. Default DNS zone of the DNS Service.') -param defaultDnsZone string = '' - -@description('Optional. Display name of the DNS Service.') -param displayName string = '' - -@description('Optional. DNS service IP of the DNS Service.') -param dnsServiceIp string = '' - -@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') -param enableDefaultTelemetry bool = true - -@description('Optional. FQDN zones of the DNS Service.') -param fqdnZones array = [] - -@description('Optional. DNS Service log level.') -@allowed([ - 'DEBUG' - 'INFO' - 'WARNING' - 'ERROR' - 'FATAL' -]) -param logLevel string = '' - -@description('Optional. NSX revision number.') -param revision int = - -@description('Optional. The name of the parent workloadNetworks. Required if the template is used in a standalone deployment.') -param workloadNetworkName string = 'default' - -// =============== // -// Deployments // -// =============== // - -resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - } - } -} - -resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { - name: privateCloudName - - resource workloadNetwork 'workloadNetworks@2022-05-01' existing = { - name: workloadNetworkName - } -} - -resource dnsService 'Microsoft.AVS/privateClouds/workloadNetworks/dnsServices@2022-05-01' = { - parent: privateCloud::workloadNetwork - name: name - properties: { - defaultDnsZone: defaultDnsZone - displayName: displayName - dnsServiceIp: dnsServiceIp - fqdnZones: fqdnZones - logLevel: logLevel - revision: revision - } -} - -// =========== // -// Outputs // -// =========== // - -@description('The name of the dnsService.') -output name string = dnsService.name - -@description('The resource ID of the dnsService.') -output resourceId string = dnsService.id - -@description('The name of the resource group the dnsService was created in.') -output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsServices/version.json b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsServices/version.json deleted file mode 100644 index 41f66cc990..0000000000 --- a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsServices/version.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "0.1" -} diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsZones/deploy.bicep b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsZones/deploy.bicep deleted file mode 100644 index 6e610bb3e9..0000000000 --- a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsZones/deploy.bicep +++ /dev/null @@ -1,83 +0,0 @@ -// ============== // -// Parameters // -// ============== // - -@description('Required. NSX DNS Zone identifier. Generally the same as the DNS Zone\'s display name') -param name string - -@description('Conditional. The name of the parent privateClouds. Required if the template is used in a standalone deployment.') -param privateCloudName string - -@description('Optional. Display name of the DNS Zone.') -param displayName string = '' - -@description('Optional. DNS Server IP array of the DNS Zone.') -param dnsServerIps array = [] - -@description('Optional. Number of DNS Services using the DNS zone.') -param dnsServices int = - -@description('Optional. Domain names of the DNS Zone.') -param domain array = [] - -@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') -param enableDefaultTelemetry bool = true - -@description('Optional. NSX revision number.') -param revision int = - -@description('Optional. Source IP of the DNS Zone.') -param sourceIp string = '' - -@description('Optional. The name of the parent workloadNetworks. Required if the template is used in a standalone deployment.') -param workloadNetworkName string = 'default' - -// =============== // -// Deployments // -// =============== // - -resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - } - } -} - -resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { - name: privateCloudName - - resource workloadNetwork 'workloadNetworks@2022-05-01' existing = { - name: workloadNetworkName - } -} - -resource dnsZone 'Microsoft.AVS/privateClouds/workloadNetworks/dnsZones@2022-05-01' = { - parent: privateCloud::workloadNetwork - name: name - properties: { - displayName: displayName - dnsServerIps: dnsServerIps - dnsServices: dnsServices - domain: domain - revision: revision - sourceIp: sourceIp - } -} - -// =========== // -// Outputs // -// =========== // - -@description('The name of the dnsZone.') -output name string = dnsZone.name - -@description('The resource ID of the dnsZone.') -output resourceId string = dnsZone.id - -@description('The name of the resource group the dnsZone was created in.') -output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsZones/version.json b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsZones/version.json deleted file mode 100644 index 41f66cc990..0000000000 --- a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsZones/version.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "0.1" -} diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/portMirroringProfiles/deploy.bicep b/modules/Microsoft.AVS/privateClouds/workloadNetworks/portMirroringProfiles/deploy.bicep deleted file mode 100644 index 5eb37963af..0000000000 --- a/modules/Microsoft.AVS/privateClouds/workloadNetworks/portMirroringProfiles/deploy.bicep +++ /dev/null @@ -1,84 +0,0 @@ -// ============== // -// Parameters // -// ============== // - -@description('Required. NSX Port Mirroring identifier. Generally the same as the Port Mirroring display name') -param name string - -@description('Conditional. The name of the parent privateClouds. Required if the template is used in a standalone deployment.') -param privateCloudName string - -@description('Optional. Destination VM Group.') -param destination string = '' - -@description('Optional. Direction of port mirroring profile.') -@allowed([ - 'INGRESS' - 'EGRESS' - 'BIDIRECTIONAL' -]) -param direction string = '' - -@description('Optional. Display name of the port mirroring profile.') -param displayName string = '' - -@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') -param enableDefaultTelemetry bool = true - -@description('Optional. NSX revision number.') -param revision int = - -@description('Optional. Source VM Group.') -param source string = '' - -@description('Optional. The name of the parent workloadNetworks. Required if the template is used in a standalone deployment.') -param workloadNetworkName string = 'default' - -// =============== // -// Deployments // -// =============== // - -resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - } - } -} - -resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { - name: privateCloudName - - resource workloadNetwork 'workloadNetworks@2022-05-01' existing = { - name: workloadNetworkName - } -} - -resource portMirroringProfile 'Microsoft.AVS/privateClouds/workloadNetworks/portMirroringProfiles@2022-05-01' = { - parent: privateCloud::workloadNetwork - name: name - properties: { - destination: destination - direction: direction - displayName: displayName - revision: revision - source: source - } -} - -// =========== // -// Outputs // -// =========== // - -@description('The name of the portMirroringProfile.') -output name string = portMirroringProfile.name - -@description('The resource ID of the portMirroringProfile.') -output resourceId string = portMirroringProfile.id - -@description('The name of the resource group the portMirroringProfile was created in.') -output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/portMirroringProfiles/version.json b/modules/Microsoft.AVS/privateClouds/workloadNetworks/portMirroringProfiles/version.json deleted file mode 100644 index 41f66cc990..0000000000 --- a/modules/Microsoft.AVS/privateClouds/workloadNetworks/portMirroringProfiles/version.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "0.1" -} diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/publicIPs/deploy.bicep b/modules/Microsoft.AVS/privateClouds/workloadNetworks/publicIPs/deploy.bicep deleted file mode 100644 index f424a34ab5..0000000000 --- a/modules/Microsoft.AVS/privateClouds/workloadNetworks/publicIPs/deploy.bicep +++ /dev/null @@ -1,67 +0,0 @@ -// ============== // -// Parameters // -// ============== // - -@description('Required. NSX Public IP Block identifier. Generally the same as the Public IP Block\'s display name') -param name string - -@description('Conditional. The name of the parent privateClouds. Required if the template is used in a standalone deployment.') -param privateCloudName string - -@description('Optional. Display name of the Public IP Block.') -param displayName string = '' - -@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') -param enableDefaultTelemetry bool = true - -@description('Optional. Number of Public IPs requested.') -param numberOfPublicIPs int = - -@description('Optional. The name of the parent workloadNetworks. Required if the template is used in a standalone deployment.') -param workloadNetworkName string = 'default' - -// =============== // -// Deployments // -// =============== // - -resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - } - } -} - -resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { - name: privateCloudName - - resource workloadNetwork 'workloadNetworks@2022-05-01' existing = { - name: workloadNetworkName - } -} - -resource publicIP 'Microsoft.AVS/privateClouds/workloadNetworks/publicIPs@2022-05-01' = { - parent: privateCloud::workloadNetwork - name: name - properties: { - displayName: displayName - numberOfPublicIPs: numberOfPublicIPs - } -} - -// =========== // -// Outputs // -// =========== // - -@description('The name of the publicIP.') -output name string = publicIP.name - -@description('The resource ID of the publicIP.') -output resourceId string = publicIP.id - -@description('The name of the resource group the publicIP was created in.') -output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/publicIPs/version.json b/modules/Microsoft.AVS/privateClouds/workloadNetworks/publicIPs/version.json deleted file mode 100644 index 41f66cc990..0000000000 --- a/modules/Microsoft.AVS/privateClouds/workloadNetworks/publicIPs/version.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "0.1" -} diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/segments/deploy.bicep b/modules/Microsoft.AVS/privateClouds/workloadNetworks/segments/deploy.bicep deleted file mode 100644 index ed80042d91..0000000000 --- a/modules/Microsoft.AVS/privateClouds/workloadNetworks/segments/deploy.bicep +++ /dev/null @@ -1,75 +0,0 @@ -// ============== // -// Parameters // -// ============== // - -@description('Required. NSX Segment identifier. Generally the same as the Segment\'s display name') -param name string - -@description('Conditional. The name of the parent privateClouds. Required if the template is used in a standalone deployment.') -param privateCloudName string - -@description('Optional. Gateway which to connect segment to.') -param connectedGateway string = '' - -@description('Optional. Display name of the segment.') -param displayName string = '' - -@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') -param enableDefaultTelemetry bool = true - -@description('Optional. NSX revision number.') -param revision int = - -@description('Optional. Subnet configuration for segment') -param subnet object = {} - -@description('Optional. The name of the parent workloadNetworks. Required if the template is used in a standalone deployment.') -param workloadNetworkName string = 'default' - -// =============== // -// Deployments // -// =============== // - -resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - } - } -} - -resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { - name: privateCloudName - - resource workloadNetwork 'workloadNetworks@2022-05-01' existing = { - name: workloadNetworkName - } -} - -resource segment 'Microsoft.AVS/privateClouds/workloadNetworks/segments@2022-05-01' = { - parent: privateCloud::workloadNetwork - name: name - properties: { - connectedGateway: connectedGateway - displayName: displayName - revision: revision - subnet: subnet - } -} - -// =========== // -// Outputs // -// =========== // - -@description('The name of the segment.') -output name string = segment.name - -@description('The resource ID of the segment.') -output resourceId string = segment.id - -@description('The name of the resource group the segment was created in.') -output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/segments/version.json b/modules/Microsoft.AVS/privateClouds/workloadNetworks/segments/version.json deleted file mode 100644 index 41f66cc990..0000000000 --- a/modules/Microsoft.AVS/privateClouds/workloadNetworks/segments/version.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "0.1" -} diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/vmGroups/deploy.bicep b/modules/Microsoft.AVS/privateClouds/workloadNetworks/vmGroups/deploy.bicep deleted file mode 100644 index 7efe5c6a16..0000000000 --- a/modules/Microsoft.AVS/privateClouds/workloadNetworks/vmGroups/deploy.bicep +++ /dev/null @@ -1,71 +0,0 @@ -// ============== // -// Parameters // -// ============== // - -@description('Required. NSX VM Group identifier. Generally the same as the VM Group\'s display name') -param name string - -@description('Conditional. The name of the parent privateClouds. Required if the template is used in a standalone deployment.') -param privateCloudName string - -@description('Optional. Display name of the VM group.') -param displayName string = '' - -@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') -param enableDefaultTelemetry bool = true - -@description('Optional. Virtual machine members of this group.') -param members array = [] - -@description('Optional. NSX revision number.') -param revision int = - -@description('Optional. The name of the parent workloadNetworks. Required if the template is used in a standalone deployment.') -param workloadNetworkName string = 'default' - -// =============== // -// Deployments // -// =============== // - -resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { - name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' - properties: { - mode: 'Incremental' - template: { - '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' - contentVersion: '1.0.0.0' - resources: [] - } - } -} - -resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { - name: privateCloudName - - resource workloadNetwork 'workloadNetworks@2022-05-01' existing = { - name: workloadNetworkName - } -} - -resource vmGroup 'Microsoft.AVS/privateClouds/workloadNetworks/vmGroups@2022-05-01' = { - parent: privateCloud::workloadNetwork - name: name - properties: { - displayName: displayName - members: members - revision: revision - } -} - -// =========== // -// Outputs // -// =========== // - -@description('The name of the vmGroup.') -output name string = vmGroup.name - -@description('The resource ID of the vmGroup.') -output resourceId string = vmGroup.id - -@description('The name of the resource group the vmGroup was created in.') -output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/vmGroups/version.json b/modules/Microsoft.AVS/privateClouds/workloadNetworks/vmGroups/version.json deleted file mode 100644 index 41f66cc990..0000000000 --- a/modules/Microsoft.AVS/privateClouds/workloadNetworks/vmGroups/version.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "0.1" -} From 41da9d398fd98c6ff271c90662f08a9cab7c0ba9 Mon Sep 17 00:00:00 2001 From: MrMCake Date: Thu, 3 Nov 2022 18:18:12 +0100 Subject: [PATCH 19/30] Update to latest --- .../private/module/Set-ModuleTemplate.ps1 | 40 +++++++------------ 1 file changed, 14 insertions(+), 26 deletions(-) diff --git a/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 b/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 index 542ccd4966..fe0fe2ac58 100644 --- a/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 +++ b/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 @@ -544,7 +544,19 @@ function Set-ModuleTemplate { } } - # TODO: Make idempotent + # If the main resource has a location property, an output should be returned too + if ($ModuleData.parametersToAdd.name -contains 'location' -and $ModuleData.parametersToAdd['location'].defaultValue -ne 'global') { + $defaultOutputs += @{ + name = 'location' + type = 'string' + content = @( + "@description('The location the resource was deployed into.')" + '{0}.location' -f $resourceTypeSingular + ) + } + } + + # Extra outputs $outputsToAdd = -not $existingTemplateContent ? @() : $existingTemplateContent.outputs foreach ($default in $defaultOutputs) { if ($outputsToAdd.name -notcontains $default.name) { @@ -558,33 +570,9 @@ function Set-ModuleTemplate { '// Outputs //' '// =========== //' '' - "@description('The name of the $resourceTypeSingular.')" - "output name string = $resourceTypeSingular.name" - '' - "@description('The resource ID of the $resourceTypeSingular.')" - "output resourceId string = $resourceTypeSingular.id" - '' ) - if ($targetScope -eq 'resourceGroup') { - $templateContent += @( - "@description('The name of the resource group the $resourceTypeSingular was created in.')" - 'output resourceGroupName string = resourceGroup().name' - '' - ) - } - - # If the main resource has a location property, an output should be returned too - if ($ModuleData.parametersToAdd.name -contains 'location' -and $ModuleData.parametersToAdd['location'].defaultValue -ne 'global') { - $templateContent += @( - "@description('The location the resource was deployed into.')" - 'output location string = {0}.location' -f $resourceTypeSingular - '' - ) - } - - # Extra outputs - foreach ($output in $existingTemplateContent.outputs | Where-Object { $_.name -notin @('name', 'resourceId', 'resourceGroupName') }) { + foreach ($output in $outputsToAdd) { $templateContent += $output.content $templateContent += '' } From 1fcdb7fea752489319957be6e9dce247bead8f87 Mon Sep 17 00:00:00 2001 From: MrMCake Date: Sat, 5 Nov 2022 18:54:26 +0100 Subject: [PATCH 20/30] Started extraction --- .../module/Set-ModuleOutputContent.ps1 | 109 +++++++ .../private/module/Set-ModuleTemplate.ps1 | 305 ++++++++++-------- .../private/specs/Resolve-ModuleData.ps1 | 10 +- 3 files changed, 289 insertions(+), 135 deletions(-) create mode 100644 utilities/tools/REST2CARML/private/module/Set-ModuleOutputContent.ps1 diff --git a/utilities/tools/REST2CARML/private/module/Set-ModuleOutputContent.ps1 b/utilities/tools/REST2CARML/private/module/Set-ModuleOutputContent.ps1 new file mode 100644 index 0000000000..b2e69954ca --- /dev/null +++ b/utilities/tools/REST2CARML/private/module/Set-ModuleOutputContent.ps1 @@ -0,0 +1,109 @@ +function Get-ModuleOutputContent { + + [CmdletBinding()] + param ( + [Parameter()] + [Parameter(Mandatory = $true)] + [string] $FullResourceType, + + [Parameter(Mandatory = $true)] + [string] $UrlPath, + + [Parameter(Mandatory = $true)] + [array] $ModuleData, + + [Parameter(Mandatory = $false)] + [array] $ExistingTemplateContent = @() + ) + + begin { + Write-Debug ('{0} entered' -f $MyInvocation.MyCommand) + } + + process { + + ##################### + ## Collect Data # + ##################### + + $providerNamespace = ($FullResourceType -split '/')[0] + $resourceType = $FullResourceType -replace "$providerNamespace/", '' + + # Get the singular version of the current resource type for proper naming + $resourceTypeSingular = ((Get-ResourceTypeSingularName -ResourceType $resourceType) -split '/')[-1] + + $targetScope = Get-TargetScope -UrlPath $UrlPath + + #################### + ## Set Outputs # + #################### + $defaultOutputs = @( + @{ + name = 'name' + type = 'string' + content = @( + "@description('The name of the $resourceTypeSingular.')" + "output name string = $resourceTypeSingular.name" + ) + }, + @{ + name = 'resourceId' + type = 'string' + content = @( + "@description('The resource ID of the $resourceTypeSingular.')" + "output resourceId string = $resourceTypeSingular.id" + ) + } + ) + + if ($targetScope -eq 'resourceGroup') { + $defaultOutputs += @{ + name = 'resourceGroupName' + type = 'string' + content = @( + "@description('The name of the resource group the $resourceTypeSingular was created in.')" + 'output resourceGroupName string = resourceGroup().name' + ) + } + } + + # If the main resource has a location property, an output should be returned too + if ($ModuleData.parametersToAdd.name -contains 'location' -and $ModuleData.parametersToAdd['location'].defaultValue -ne 'global') { + $defaultOutputs += @{ + name = 'location' + type = 'string' + content = @( + "@description('The location the resource was deployed into.')" + '{0}.location' -f $resourceTypeSingular + ) + } + } + + # Extra outputs + $outputsToAdd = -not $ExistingTemplateContent ? @() : $ExistingTemplateContent.outputs + foreach ($default in $defaultOutputs) { + if ($outputsToAdd.name -notcontains $default.name) { + $outputsToAdd += $default + } + } + + # Output header comment + $templateContent = @( + '// =========== //' + '// Outputs //' + '// =========== //' + '' + ) + + foreach ($output in $outputsToAdd) { + $templateContent += $output.content + $templateContent += '' + } + + + } + + end { + Write-Debug ('{0} exited' -f $MyInvocation.MyCommand) + } +} diff --git a/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 b/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 index fe0fe2ac58..b57d4a03e4 100644 --- a/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 +++ b/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 @@ -47,19 +47,18 @@ function Set-ModuleTemplate { begin { Write-Debug ('{0} entered' -f $MyInvocation.MyCommand) - - $templateFilePath = Join-Path $script:repoRoot 'modules' $FullResourceType 'deploy.bicep' - $providerNamespace = ($FullResourceType -split '/')[0] - $resourceType = $FullResourceType -replace "$providerNamespace/", '' } process { - ##################### ## Collect Data # ##################### #region data + $templateFilePath = Join-Path $script:repoRoot 'modules' $FullResourceType 'deploy.bicep' + $providerNamespace = ($FullResourceType -split '/')[0] + $resourceType = $FullResourceType -replace "$providerNamespace/", '' + # Existing template (if any) $existingTemplateContent = Resolve-ExistingTemplateContent -TemplateFilePath $templateFilePath @@ -71,7 +70,8 @@ function Set-ModuleTemplate { (($_.identifier -split '/').Count -eq (($FullResourceType -split '/').Count + 1) ) } - ## Add indirect child (via proxy resource) (i.e. it's a nested-nested resources who's parent has no individual specification/JSONFilePath). TODO: Is that always true? What if the data is specified in one file?x` + ## Add indirect child (via proxy resource) (i.e. it's a nested-nested resources who's parent has no individual specification/JSONFilePath). + # TODO: Is that always true? What if the data is specified in one file? $indirectChildren = $FullModuleData | Where-Object { # Is nested $_.identifier -like "$FullResourceType/*" -and @@ -387,7 +387,6 @@ function Set-ModuleTemplate { # --------------------------- foreach ($dataBlock in $linkedChildren) { $childResourceType = ($dataBlock.identifier -split '/')[-1] - $childResourceTypeSingular = Get-ResourceTypeSingularName -ResourceType $childResourceType $hasProxyParent = [String]::IsNullOrEmpty($dataBlock.metadata.parentUrlPath) if ($hasProxyParent) { @@ -399,90 +398,179 @@ function Set-ModuleTemplate { $matchingModule = $existingTemplateContent.modules | Where-Object { $_.name -eq $moduleName -and $_.path -eq $modulePath } - # TODO: Also consider 'singular' children (if we can detect it) - $templateContent += @( - "module $moduleName '$modulePath' = [for ($($childResourceTypeSingular), index) in $($childResourceType): {" - ) + # Differentiate 'singular' children (like 'blobservices') vs. 'multiple' chilren (like 'containers') + if ($ModuleData.isSingleton) { + $templateContent += @( + "module $moduleName '$modulePath' = {" + ) - if ($matchingModule.topLevelElements.name -notcontains 'name') { - $templateContent += " name: '`${uniqueString(deployment().name$($locationParameterExists ? ', location' : ''))}-$($resourceTypeSingular)-$($childResourceTypeSingular)-`${index}'" - } else { - $existingParam = $matchingModule.topLevelElements | Where-Object { $_.name -eq 'name' } - $templateContent += $existingParam.content - } + if ($matchingModule.topLevelElements.name -notcontains 'name') { + $templateContent += " name: '`${uniqueString(deployment().name$($locationParameterExists ? ', location' : ''))}-$($resourceTypeSingular)-$($childResourceType)'" + } else { + $existingParam = $matchingModule.topLevelElements | Where-Object { $_.name -eq 'name' } + $templateContent += $existingParam.content + } - $templateContent += ' params: {' - $templateContent += @() + $templateContent += ' params: {' + $templateContent += @() - $alreadyAddedParams = @() + $alreadyAddedParams = @() - # All param names of parents - foreach ($parentResourceType in $parentResourceTypes) { - $parentParamName = ((Get-ResourceTypeSingularName -ResourceType $parentResourceType) -split '/')[-1] - $templateContent += ' {0}Name: {0}Name' -f $parentParamName - $alreadyAddedParams += $parentParamName - } - # Itself - $selfParamName = ((Get-ResourceTypeSingularName -ResourceType ($FullResourceType -split '/')[-1]) -split '/')[-1] - $templateContent += ' {0}Name: name' -f $selfParamName - $alreadyAddedParams += $selfParamName + # All param names of parents + foreach ($parentResourceType in $parentResourceTypes) { + $parentParamName = ((Get-ResourceTypeSingularName -ResourceType $parentResourceType) -split '/')[-1] + $templateContent += ' {0}Name: {0}Name' -f $parentParamName + $alreadyAddedParams += $parentParamName + } + # Itself + $selfParamName = ((Get-ResourceTypeSingularName -ResourceType ($FullResourceType -split '/')[-1]) -split '/')[-1] + $templateContent += ' {0}Name: name' -f $selfParamName + $alreadyAddedParams += $selfParamName + + # Any proxy default if any + if ($hasProxyParent) { + $proxyDefaultValue = ($dataBlock.metadata.urlPath -split '\/')[-3] + $proxyParamName = Get-ResourceTypeSingularName -ResourceType ($proxyParentName -split '/')[-1] + $templateContent += " {0}Name: '{1}'" -f $proxyParamName, $proxyDefaultValue + $alreadyAddedParams += $proxyParamName + } - # Any proxy default if any - if ($hasProxyParent) { - $proxyDefaultValue = ($dataBlock.metadata.urlPath -split '\/')[-3] - $proxyParamName = Get-ResourceTypeSingularName -ResourceType ($proxyParentName -split '/')[-1] - $templateContent += " {0}Name: '{1}'" -f $proxyParamName, $proxyDefaultValue - $alreadyAddedParams += $proxyParamName - } + # Add primary child parameters + $allParam = $dataBlock.data.parameters + $dataBlock.data.additionalParameters + foreach ($parameter in (($allParam | Where-Object { $_.Level -in @(0, 1) -and $_.name -ne 'properties' -and ([String]::IsNullOrEmpty($_.Parent) -or $_.Parent -eq 'properties') }) | Sort-Object -Property 'Name')) { + $wouldBeParameter = Get-FormattedModuleParameter -ParameterData $parameter | Where-Object { $_ -like 'param *' } | ForEach-Object { $_ -replace 'param ', '' } + $wouldBeParamElem = $wouldBeParameter -split ' = ' + $parameter.name = ($wouldBeParamElem -split ' ')[0] + + if ($matchingModule.nestedElements.name -notcontains $parameter.name) { + $existingParam = $matchingModule.nestedElements | Where-Object { $_.name -eq $parameter.name } + if ($alreadyAddedParams -notcontains $existingParam.name) { + $templateContent += $existingParam.content + } + continue + } + + if ($wouldBeParamElem.count -gt 1) { + # With default - # Add primary child parameters - $allParam = $dataBlock.data.parameters + $dataBlock.data.additionalParameters - foreach ($parameter in (($allParam | Where-Object { $_.Level -in @(0, 1) -and $_.name -ne 'properties' -and ([String]::IsNullOrEmpty($_.Parent) -or $_.Parent -eq 'properties') }) | Sort-Object -Property 'Name')) { - $wouldBeParameter = Get-FormattedModuleParameter -ParameterData $parameter | Where-Object { $_ -like 'param *' } | ForEach-Object { $_ -replace 'param ', '' } - $wouldBeParamElem = $wouldBeParameter -split ' = ' - $parameter.name = ($wouldBeParamElem -split ' ')[0] - - if ($matchingModule.nestedElements.name -notcontains $parameter.name) { - $existingParam = $matchingModule.nestedElements | Where-Object { $_.name -eq $parameter.name } - if ($alreadyAddedParams -notcontains $existingParam.name) { - $templateContent += $existingParam.content + if ($parameter.name -eq 'lock') { + # Special handling as we pass the parameter down to the child + $templateContent += " $($parameter.name): contains($($childResourceType), 'lock') ? $($childResourceType).lock : lock" + $alreadyAddedParams += $parameter.name + continue + } + + $wouldBeParamValue = $wouldBeParamElem[1] + + # Special case, location function - should reference a location parameter instead + if ($wouldBeParamValue -like '*().location') { + $wouldBeParamValue = 'location' + } + + $templateContent += " $($parameter.name): contains($($childResourceType), '$($parameter.name)') ? $($childResourceType).$($parameter.name) : $($wouldBeParamValue)" + $alreadyAddedParams += $parameter.name + } else { + # No default + $templateContent += " $($parameter.name): $($childResourceType).$($parameter.name)" + $alreadyAddedParams += $parameter.name } - continue } - if ($wouldBeParamElem.count -gt 1) { - # With default + $templateContent += @( + # Special handling as we pass the variable down to the child + ' enableDefaultTelemetry: enableReferencedModulesTelemetry' + ' }' + '}' + '' + ) + } else { - if ($parameter.name -eq 'lock') { - # Special handling as we pass the parameter down to the child - $templateContent += " $($parameter.name): contains($($childResourceTypeSingular), 'lock') ? $($childResourceTypeSingular).lock : lock" - $alreadyAddedParams += $parameter.name + $childResourceTypeSingular = Get-ResourceTypeSingularName -ResourceType $childResourceType + + $templateContent += @( + "module $moduleName '$modulePath' = [for ($($childResourceTypeSingular), index) in $($childResourceType): {" + ) + + if ($matchingModule.topLevelElements.name -notcontains 'name') { + $templateContent += " name: '`${uniqueString(deployment().name$($locationParameterExists ? ', location' : ''))}-$($resourceTypeSingular)-$($childResourceTypeSingular)-`${index}'" + } else { + $existingParam = $matchingModule.topLevelElements | Where-Object { $_.name -eq 'name' } + $templateContent += $existingParam.content + } + + $templateContent += ' params: {' + $templateContent += @() + + $alreadyAddedParams = @() + + # All param names of parents + foreach ($parentResourceType in $parentResourceTypes) { + $parentParamName = ((Get-ResourceTypeSingularName -ResourceType $parentResourceType) -split '/')[-1] + $templateContent += ' {0}Name: {0}Name' -f $parentParamName + $alreadyAddedParams += $parentParamName + } + # Itself + $selfParamName = ((Get-ResourceTypeSingularName -ResourceType ($FullResourceType -split '/')[-1]) -split '/')[-1] + $templateContent += ' {0}Name: name' -f $selfParamName + $alreadyAddedParams += $selfParamName + + # Any proxy default if any + if ($hasProxyParent) { + $proxyDefaultValue = ($dataBlock.metadata.urlPath -split '\/')[-3] + $proxyParamName = Get-ResourceTypeSingularName -ResourceType ($proxyParentName -split '/')[-1] + $templateContent += " {0}Name: '{1}'" -f $proxyParamName, $proxyDefaultValue + $alreadyAddedParams += $proxyParamName + } + + # Add primary child parameters + $allParam = $dataBlock.data.parameters + $dataBlock.data.additionalParameters + foreach ($parameter in (($allParam | Where-Object { $_.Level -in @(0, 1) -and $_.name -ne 'properties' -and ([String]::IsNullOrEmpty($_.Parent) -or $_.Parent -eq 'properties') }) | Sort-Object -Property 'Name')) { + $wouldBeParameter = Get-FormattedModuleParameter -ParameterData $parameter | Where-Object { $_ -like 'param *' } | ForEach-Object { $_ -replace 'param ', '' } + $wouldBeParamElem = $wouldBeParameter -split ' = ' + $parameter.name = ($wouldBeParamElem -split ' ')[0] + + if ($matchingModule.nestedElements.name -notcontains $parameter.name) { + $existingParam = $matchingModule.nestedElements | Where-Object { $_.name -eq $parameter.name } + if ($alreadyAddedParams -notcontains $existingParam.name) { + $templateContent += $existingParam.content + } continue } - $wouldBeParamValue = $wouldBeParamElem[1] + if ($wouldBeParamElem.count -gt 1) { + # With default - # Special case, location function - should reference a location parameter instead - if ($wouldBeParamValue -like '*().location') { - $wouldBeParamValue = 'location' - } + if ($parameter.name -eq 'lock') { + # Special handling as we pass the parameter down to the child + $templateContent += " $($parameter.name): contains($($childResourceTypeSingular), 'lock') ? $($childResourceTypeSingular).lock : lock" + $alreadyAddedParams += $parameter.name + continue + } - $templateContent += " $($parameter.name): contains($($childResourceTypeSingular), '$($parameter.name)') ? $($childResourceTypeSingular).$($parameter.name) : $($wouldBeParamValue)" - $alreadyAddedParams += $parameter.name - } else { - # No default - $templateContent += " $($parameter.name): $($childResourceTypeSingular).$($parameter.name)" - $alreadyAddedParams += $parameter.name + $wouldBeParamValue = $wouldBeParamElem[1] + + # Special case, location function - should reference a location parameter instead + if ($wouldBeParamValue -like '*().location') { + $wouldBeParamValue = 'location' + } + + $templateContent += " $($parameter.name): contains($($childResourceTypeSingular), '$($parameter.name)') ? $($childResourceTypeSingular).$($parameter.name) : $($wouldBeParamValue)" + $alreadyAddedParams += $parameter.name + } else { + # No default + $templateContent += " $($parameter.name): $($childResourceTypeSingular).$($parameter.name)" + $alreadyAddedParams += $parameter.name + } } - } - $templateContent += @( - # Special handling as we pass the variable down to the child - ' enableDefaultTelemetry: enableReferencedModulesTelemetry' - ' }' - '}]' - '' - ) + $templateContent += @( + # Special handling as we pass the variable down to the child + ' enableDefaultTelemetry: enableReferencedModulesTelemetry' + ' }' + '}]' + '' + ) + } } # TODO : Add other module references @@ -514,68 +602,19 @@ function Set-ModuleTemplate { $templateContent += '' } - $defaultOutputs = @( - @{ - name = 'name' - type = 'string' - content = @( - "@description('The name of the $resourceTypeSingular.')" - "output name string = $resourceTypeSingular.name" - ) - }, - @{ - name = 'resourceId' - type = 'string' - content = @( - "@description('The resource ID of the $resourceTypeSingular.')" - "output resourceId string = $resourceTypeSingular.id" - ) - } - ) - - if ($targetScope -eq 'resourceGroup') { - $defaultOutputs += @{ - name = 'resourceGroupName' - type = 'string' - content = @( - "@description('The name of the resource group the $resourceTypeSingular was created in.')" - 'output resourceGroupName string = resourceGroup().name' - ) - } - } - - # If the main resource has a location property, an output should be returned too - if ($ModuleData.parametersToAdd.name -contains 'location' -and $ModuleData.parametersToAdd['location'].defaultValue -ne 'global') { - $defaultOutputs += @{ - name = 'location' - type = 'string' - content = @( - "@description('The location the resource was deployed into.')" - '{0}.location' -f $resourceTypeSingular - ) - } + $outputsInputObject = @{ + FullResourceType = $FullResourceType + UrlPath = $UrlPath + ModuleData = $ModuleData } - - # Extra outputs - $outputsToAdd = -not $existingTemplateContent ? @() : $existingTemplateContent.outputs - foreach ($default in $defaultOutputs) { - if ($outputsToAdd.name -notcontains $default.name) { - $outputsToAdd += $default - } + if ($ExistingTemplateContent.Count -gt 0) { + $outputsInputObject['ExistingTemplateContent'] = $ExistingTemplateContent } + $templateContent += Get-ModuleOutputContent @outputsInputObject - # Output header comment - $templateContent += @( - '// =========== //' - '// Outputs //' - '// =========== //' - '' - ) - - foreach ($output in $outputsToAdd) { - $templateContent += $output.content - $templateContent += '' - } + ############################ + ## Update template file ## + ############################ # Update file # ----------- diff --git a/utilities/tools/REST2CARML/private/specs/Resolve-ModuleData.ps1 b/utilities/tools/REST2CARML/private/specs/Resolve-ModuleData.ps1 index 146ae7f5f2..9c335c0351 100644 --- a/utilities/tools/REST2CARML/private/specs/Resolve-ModuleData.ps1 +++ b/utilities/tools/REST2CARML/private/specs/Resolve-ModuleData.ps1 @@ -36,8 +36,9 @@ function Resolve-ModuleData { # Output object $templateData = [System.Collections.ArrayList]@() - # Collect data - # ------------ + ##################################### + ## Collect primary module data ## + ##################################### $specificationData = Get-Content -Path $JSONFilePath -Raw | ConvertFrom-Json -AsHashtable # Get PUT parameters @@ -116,5 +117,10 @@ function Resolve-ModuleData { } Set-LockModuleData @lockInputObject + # Check if there can be mutliple instances of the current Resource Type. + # For example, this is 'true' for Resource Type 'Microsoft.Storage/storageAccounts/blobServices/containers', and 'false' for Resource Type 'Microsoft.Storage/storageAccounts/blobServices' + $listUrlPath = (Split-Path $UrlPath -Parent) -replace '\\', '/' + $moduleData['isSingleton'] = $specificationData.paths[$listUrlPath].get.Keys -notcontains 'x-ms-pageable' + return $moduleData } From b95cbe05c3928b2e95ee53da84c9ab7202a7c2d0 Mon Sep 17 00:00:00 2001 From: MrMCake Date: Sat, 5 Nov 2022 20:54:48 +0100 Subject: [PATCH 21/30] Refactored a lot of logic into dedicated functions --- .../module/Get-LinkedChildModuleList.ps1 | 47 ++ .../module/Get-TemplateChildModuleContent.ps1 | 235 ++++++++ ...tent.ps1 => Get-TemplateOutputContent.ps1} | 30 +- .../module/Get-TemplateParametersContent.ps1 | 148 +++++ .../module/Get-TemplateResourcesContent.ps1 | 205 +++++++ .../module/Get-TemplateVariablesContent.ps1 | 70 +++ .../private/module/Set-ModuleTemplate.ps1 | 521 ++---------------- 7 files changed, 760 insertions(+), 496 deletions(-) create mode 100644 utilities/tools/REST2CARML/private/module/Get-LinkedChildModuleList.ps1 create mode 100644 utilities/tools/REST2CARML/private/module/Get-TemplateChildModuleContent.ps1 rename utilities/tools/REST2CARML/private/module/{Set-ModuleOutputContent.ps1 => Get-TemplateOutputContent.ps1} (81%) create mode 100644 utilities/tools/REST2CARML/private/module/Get-TemplateParametersContent.ps1 create mode 100644 utilities/tools/REST2CARML/private/module/Get-TemplateResourcesContent.ps1 create mode 100644 utilities/tools/REST2CARML/private/module/Get-TemplateVariablesContent.ps1 diff --git a/utilities/tools/REST2CARML/private/module/Get-LinkedChildModuleList.ps1 b/utilities/tools/REST2CARML/private/module/Get-LinkedChildModuleList.ps1 new file mode 100644 index 0000000000..c53a51af28 --- /dev/null +++ b/utilities/tools/REST2CARML/private/module/Get-LinkedChildModuleList.ps1 @@ -0,0 +1,47 @@ +function Get-LinkedChildModuleList { + + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [string] $FullResourceType, + + [Parameter(Mandatory = $true)] + [array] $FullModuleData + ) + + begin { + Write-Debug ('{0} entered' -f $MyInvocation.MyCommand) + } + + process { + # Collect child-resource information + $linkedChildren = $fullmoduleData | Where-Object { + # Is nested + $_.identifier -like "$FullResourceType/*" -and + # Is direct child + (($_.identifier -split '/').Count -eq (($FullResourceType -split '/').Count + 1) + ) + } + ## Add indirect child (via proxy resource) (i.e. it's a nested-nested resources who's parent has no individual specification/JSONFilePath). + # TODO: Is that always true? What if the data is specified in one file? + $indirectChildren = $FullModuleData | Where-Object { + # Is nested + $_.identifier -like "$FullResourceType/*" -and + # Is indirect child + (($_.identifier -split '/').Count -eq (($FullResourceType -split '/').Count + 2)) + } | Where-Object { + # If the child's parent's parentUrlPath is empty, this parent has no PUT rest command which indicates it cannot be created independently + [String]::IsNullOrEmpty($_.metadata.parentUrlPath) + } + + if ($indirectChildren) { + $linkedChildren += $indirectChildren + } + + return $linkedChildren + } + + end { + Write-Debug ('{0} exited' -f $MyInvocation.MyCommand) + } +} diff --git a/utilities/tools/REST2CARML/private/module/Get-TemplateChildModuleContent.ps1 b/utilities/tools/REST2CARML/private/module/Get-TemplateChildModuleContent.ps1 new file mode 100644 index 0000000000..bd2efb77b8 --- /dev/null +++ b/utilities/tools/REST2CARML/private/module/Get-TemplateChildModuleContent.ps1 @@ -0,0 +1,235 @@ +function Get-TemplateChildModuleContent { + + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [string] $FullResourceType, + + [Parameter(Mandatory = $true)] + [string] $ResourceType, + + [Parameter(Mandatory = $false)] + [string] $ResourceTypeSingular = ((Get-ResourceTypeSingularName -ResourceType $ResourceType) -split '/')[-1], + + [Parameter(Mandatory = $false)] + [array] $LinkedChildren = @(), + + [Parameter(Mandatory = $true)] + [array] $ModuleData, + + [Parameter(Mandatory = $true)] + [string] $LocationParameterExists, + + [Parameter(Mandatory = $false)] + [array] $ExistingTemplateContent = @(), + + [Parameter(Mandatory = $false)] + [array] $ParentResourceTypes = @() + ) + + begin { + Write-Debug ('{0} entered' -f $MyInvocation.MyCommand) + } + + process { + + ##################################### + ## Add child-module references ## + ##################################### + $templateContent = @() + + foreach ($dataBlock in $linkedChildren) { + $childResourceType = ($dataBlock.identifier -split '/')[-1] + + $hasProxyParent = [String]::IsNullOrEmpty($dataBlock.metadata.parentUrlPath) + if ($hasProxyParent) { + $proxyParentName = Split-Path (Split-Path $dataBlock.identifier -Parent) -Leaf + } + + $moduleName = '{0}{1}_{2}' -f ($hasProxyParent ? "$($proxyParentName)_" : ''), $resourceTypeSingular, $childResourceType + $modulePath = '{0}{1}/deploy.bicep' -f ($hasProxyParent ? "$proxyParentName/" : ''), $childResourceType + + $matchingModule = $ExistingTemplateContent.modules | Where-Object { $_.name -eq $moduleName -and $_.path -eq $modulePath } + + # Differentiate 'singular' children (like 'blobservices') vs. 'multiple' chilren (like 'containers') + if ($ModuleData.isSingleton) { + $templateContent += @( + "module $moduleName '$modulePath' = {" + ) + + if ($matchingModule.topLevelElements.name -notcontains 'name') { + $templateContent += " name: '`${uniqueString(deployment().name$($LocationParameterExists ? ', location' : ''))}-$($resourceTypeSingular)-$($childResourceType)'" + } else { + $existingParam = $matchingModule.topLevelElements | Where-Object { $_.name -eq 'name' } + $templateContent += $existingParam.content + } + + $templateContent += ' params: {' + $templateContent += @() + + $alreadyAddedParams = @() + + # All param names of parents + foreach ($parentResourceType in $parentResourceTypes) { + $parentParamName = ((Get-ResourceTypeSingularName -ResourceType $parentResourceType) -split '/')[-1] + $templateContent += ' {0}Name: {0}Name' -f $parentParamName + $alreadyAddedParams += $parentParamName + } + # Itself + $selfParamName = ((Get-ResourceTypeSingularName -ResourceType ($FullResourceType -split '/')[-1]) -split '/')[-1] + $templateContent += ' {0}Name: name' -f $selfParamName + $alreadyAddedParams += $selfParamName + + # Any proxy default if any + if ($hasProxyParent) { + $proxyDefaultValue = ($dataBlock.metadata.urlPath -split '\/')[-3] + $proxyParamName = Get-ResourceTypeSingularName -ResourceType ($proxyParentName -split '/')[-1] + $templateContent += " {0}Name: '{1}'" -f $proxyParamName, $proxyDefaultValue + $alreadyAddedParams += $proxyParamName + } + + # Add primary child parameters + $allParam = $dataBlock.data.parameters + $dataBlock.data.additionalParameters + foreach ($parameter in (($allParam | Where-Object { $_.Level -in @(0, 1) -and $_.name -ne 'properties' -and ([String]::IsNullOrEmpty($_.Parent) -or $_.Parent -eq 'properties') }) | Sort-Object -Property 'Name')) { + $wouldBeParameter = Get-FormattedModuleParameter -ParameterData $parameter | Where-Object { $_ -like 'param *' } | ForEach-Object { $_ -replace 'param ', '' } + $wouldBeParamElem = $wouldBeParameter -split ' = ' + $parameter.name = ($wouldBeParamElem -split ' ')[0] + + if ($matchingModule.nestedElements.name -notcontains $parameter.name) { + $existingParam = $matchingModule.nestedElements | Where-Object { $_.name -eq $parameter.name } + if ($alreadyAddedParams -notcontains $existingParam.name) { + $templateContent += $existingParam.content + } + continue + } + + if ($wouldBeParamElem.count -gt 1) { + # With default + + if ($parameter.name -eq 'lock') { + # Special handling as we pass the parameter down to the child + $templateContent += " $($parameter.name): contains($($childResourceType), 'lock') ? $($childResourceType).lock : lock" + $alreadyAddedParams += $parameter.name + continue + } + + $wouldBeParamValue = $wouldBeParamElem[1] + + # Special case, location function - should reference a location parameter instead + if ($wouldBeParamValue -like '*().location') { + $wouldBeParamValue = 'location' + } + + $templateContent += " $($parameter.name): contains($($childResourceType), '$($parameter.name)') ? $($childResourceType).$($parameter.name) : $($wouldBeParamValue)" + $alreadyAddedParams += $parameter.name + } else { + # No default + $templateContent += " $($parameter.name): $($childResourceType).$($parameter.name)" + $alreadyAddedParams += $parameter.name + } + } + + $templateContent += @( + # Special handling as we pass the variable down to the child + ' enableDefaultTelemetry: enableReferencedModulesTelemetry' + ' }' + '}' + '' + ) + } else { + + $childResourceTypeSingular = Get-ResourceTypeSingularName -ResourceType $childResourceType + + $templateContent += @( + "module $moduleName '$modulePath' = [for ($($childResourceTypeSingular), index) in $($childResourceType): {" + ) + + if ($matchingModule.topLevelElements.name -notcontains 'name') { + $templateContent += " name: '`${uniqueString(deployment().name$($LocationParameterExists ? ', location' : ''))}-$($resourceTypeSingular)-$($childResourceTypeSingular)-`${index}'" + } else { + $existingParam = $matchingModule.topLevelElements | Where-Object { $_.name -eq 'name' } + $templateContent += $existingParam.content + } + + $templateContent += ' params: {' + $templateContent += @() + + $alreadyAddedParams = @() + + # All param names of parents + foreach ($parentResourceType in $parentResourceTypes) { + $parentParamName = ((Get-ResourceTypeSingularName -ResourceType $parentResourceType) -split '/')[-1] + $templateContent += ' {0}Name: {0}Name' -f $parentParamName + $alreadyAddedParams += $parentParamName + } + # Itself + $selfParamName = ((Get-ResourceTypeSingularName -ResourceType ($FullResourceType -split '/')[-1]) -split '/')[-1] + $templateContent += ' {0}Name: name' -f $selfParamName + $alreadyAddedParams += $selfParamName + + # Any proxy default if any + if ($hasProxyParent) { + $proxyDefaultValue = ($dataBlock.metadata.urlPath -split '\/')[-3] + $proxyParamName = Get-ResourceTypeSingularName -ResourceType ($proxyParentName -split '/')[-1] + $templateContent += " {0}Name: '{1}'" -f $proxyParamName, $proxyDefaultValue + $alreadyAddedParams += $proxyParamName + } + + # Add primary child parameters + $allParam = $dataBlock.data.parameters + $dataBlock.data.additionalParameters + foreach ($parameter in (($allParam | Where-Object { $_.Level -in @(0, 1) -and $_.name -ne 'properties' -and ([String]::IsNullOrEmpty($_.Parent) -or $_.Parent -eq 'properties') }) | Sort-Object -Property 'Name')) { + $wouldBeParameter = Get-FormattedModuleParameter -ParameterData $parameter | Where-Object { $_ -like 'param *' } | ForEach-Object { $_ -replace 'param ', '' } + $wouldBeParamElem = $wouldBeParameter -split ' = ' + $parameter.name = ($wouldBeParamElem -split ' ')[0] + + if ($matchingModule.nestedElements.name -notcontains $parameter.name) { + $existingParam = $matchingModule.nestedElements | Where-Object { $_.name -eq $parameter.name } + if ($alreadyAddedParams -notcontains $existingParam.name) { + $templateContent += $existingParam.content + } + continue + } + + if ($wouldBeParamElem.count -gt 1) { + # With default + + if ($parameter.name -eq 'lock') { + # Special handling as we pass the parameter down to the child + $templateContent += " $($parameter.name): contains($($childResourceTypeSingular), 'lock') ? $($childResourceTypeSingular).lock : lock" + $alreadyAddedParams += $parameter.name + continue + } + + $wouldBeParamValue = $wouldBeParamElem[1] + + # Special case, location function - should reference a location parameter instead + if ($wouldBeParamValue -like '*().location') { + $wouldBeParamValue = 'location' + } + + $templateContent += " $($parameter.name): contains($($childResourceTypeSingular), '$($parameter.name)') ? $($childResourceTypeSingular).$($parameter.name) : $($wouldBeParamValue)" + $alreadyAddedParams += $parameter.name + } else { + # No default + $templateContent += " $($parameter.name): $($childResourceTypeSingular).$($parameter.name)" + $alreadyAddedParams += $parameter.name + } + } + + $templateContent += @( + # Special handling as we pass the variable down to the child + ' enableDefaultTelemetry: enableReferencedModulesTelemetry' + ' }' + '}]' + '' + ) + } + } + + return $templateContent + } + + end { + Write-Debug ('{0} exited' -f $MyInvocation.MyCommand) + } +} diff --git a/utilities/tools/REST2CARML/private/module/Set-ModuleOutputContent.ps1 b/utilities/tools/REST2CARML/private/module/Get-TemplateOutputContent.ps1 similarity index 81% rename from utilities/tools/REST2CARML/private/module/Set-ModuleOutputContent.ps1 rename to utilities/tools/REST2CARML/private/module/Get-TemplateOutputContent.ps1 index b2e69954ca..3c7af901de 100644 --- a/utilities/tools/REST2CARML/private/module/Set-ModuleOutputContent.ps1 +++ b/utilities/tools/REST2CARML/private/module/Get-TemplateOutputContent.ps1 @@ -1,13 +1,15 @@ -function Get-ModuleOutputContent { +function Get-TemplateOutputContent { [CmdletBinding()] param ( - [Parameter()] [Parameter(Mandatory = $true)] - [string] $FullResourceType, + [string] $ResourceType, + + [Parameter(Mandatory = $false)] + [string] $ResourceTypeSingular = ((Get-ResourceTypeSingularName -ResourceType $ResourceType) -split '/')[-1], [Parameter(Mandatory = $true)] - [string] $UrlPath, + [string] $TargetScope, [Parameter(Mandatory = $true)] [array] $ModuleData, @@ -21,22 +23,9 @@ } process { - ##################### ## Collect Data # ##################### - - $providerNamespace = ($FullResourceType -split '/')[0] - $resourceType = $FullResourceType -replace "$providerNamespace/", '' - - # Get the singular version of the current resource type for proper naming - $resourceTypeSingular = ((Get-ResourceTypeSingularName -ResourceType $resourceType) -split '/')[-1] - - $targetScope = Get-TargetScope -UrlPath $UrlPath - - #################### - ## Set Outputs # - #################### $defaultOutputs = @( @{ name = 'name' @@ -87,7 +76,10 @@ } } - # Output header comment + ######################## + ## Create Content ## + ######################## + $templateContent = @( '// =========== //' '// Outputs //' @@ -100,7 +92,7 @@ $templateContent += '' } - + return $templateContent } end { diff --git a/utilities/tools/REST2CARML/private/module/Get-TemplateParametersContent.ps1 b/utilities/tools/REST2CARML/private/module/Get-TemplateParametersContent.ps1 new file mode 100644 index 0000000000..da0a85cfd4 --- /dev/null +++ b/utilities/tools/REST2CARML/private/module/Get-TemplateParametersContent.ps1 @@ -0,0 +1,148 @@ +function Get-TemplateParametersContent { + + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [string] $FullResourceType, + + [Parameter(Mandatory = $true)] + [array] $ModuleData, + + [Parameter(Mandatory = $true)] + [array] $FullModuleData, + + [Parameter(Mandatory = $false)] + [array] $ParentResourceTypes = @(), + + [Parameter(Mandatory = $false)] + [array] $ExistingTemplateContent = @(), + + [Parameter(Mandatory = $false)] + [array] $LinkedChildren = @() + ) + + begin { + Write-Debug ('{0} entered' -f $MyInvocation.MyCommand) + } + + process { + ##################### + ## Collect Data # + ##################### + + # Handle parent proxy, if any + $hasAProxyParent = $FullModuleData.identifier -notContains ((Split-Path $FullResourceType -Parent) -replace '\\', '/') + $parentProxyName = $hasAProxyParent ? ($UrlPath -split '\/')[-3] : '' + $proxyParentType = Split-Path (Split-Path $FullResourceType -Parent) -Leaf + + + + # Collect parameters to create + # ---------------------------- + $parametersToAdd = @() + + # Add parent parameters + foreach ($parentResourceType in ($parentResourceTypes | Sort-Object)) { + $thisParentIsProxy = $hasAProxyParent -and $parentResourceType -eq $proxyParentType + + $parentParamData = @{ + level = 0 + name = '{0}Name' -f (Get-ResourceTypeSingularName -ResourceType $parentResourceType) + type = 'string' + description = '{0}. The name of the parent {1}. Required if the template is used in a standalone deployment.' -f ($thisParentIsProxy ? 'Optional' : 'Conditional'), $parentResourceType + required = $false + } + + if ($thisParentIsProxy) { + # Handle proxy parents (i.e., empty containers with only a default value name) + $parentParamData['default'] = $parentProxyName + } + + $parametersToAdd += $parentParamData + } + + # Add primary (service) parameters (i.e. top-level and those in the properties) + $parametersToAdd += @() + ($ModuleData.parameters | Where-Object { $_.Level -in @(0, 1) -and $_.name -ne 'properties' -and ([String]::IsNullOrEmpty($_.Parent) -or $_.Parent -eq 'properties') }) + + # Add additional (extension) parameters + $parametersToAdd += $ModuleData.additionalParameters + + # Add child module references + foreach ($dataBlock in ($linkedChildren | Sort-Object -Property 'identifier')) { + $childResourceType = ($dataBlock.identifier -split '/')[-1] + $parametersToAdd += @{ + level = 0 + name = $childResourceType + type = 'array' + default = @() + description = "The $childResourceType to create as part of the $resourceTypeSingular." + required = $false + } + } + + # Add telemetry parameter + $parametersToAdd += @{ + level = 0 + name = 'enableDefaultTelemetry' + type = 'boolean' + default = $true + description = 'Enable telemetry via the Customer Usage Attribution ID (GUID).' + required = $false + } + + + ######################## + ## Create Content ## + ######################## + + $templateContent = @( + '// ============== //' + '// Parameters //' + '// ============== //' + '' + ) + + # Note: If there already is a template and a given parameter was already specified, we use the existing declaration instead of generating a new one + # as it may have custom logic / default values, etc. + + # First the required + foreach ($parameter in ($parametersToAdd | Where-Object { $_.required } | Sort-Object -Property 'Name')) { + if ($existingTemplateContent.parameters.name -notcontains $parameter.name) { + $templateContent += Get-FormattedModuleParameter -ParameterData $parameter + } else { + $templateContent += ($existingTemplateContent.parameters | Where-Object { $_.name -eq $parameter.name }).content + $templateContent += '' + } + } + # Then the conditional + foreach ($parameter in ($parametersToAdd | Where-Object { -not $_.required -and $_.description -like 'Conditional. *' } | Sort-Object -Property 'Name')) { + if ($existingTemplateContent.parameters.name -notcontains $parameter.name) { + $templateContent += Get-FormattedModuleParameter -ParameterData $parameter + } else { + $templateContent += ($existingTemplateContent.parameters | Where-Object { $_.name -eq $parameter.name }).content + $templateContent += '' + } + } + # Then the rest + foreach ($parameter in ($parametersToAdd | Where-Object { -not $_.required -and $_.description -notlike 'Conditional. *' } | Sort-Object -Property 'Name')) { + if ($existingTemplateContent.parameters.name -notcontains $parameter.name) { + $templateContent += Get-FormattedModuleParameter -ParameterData $parameter + } else { + $templateContent += ($existingTemplateContent.parameters | Where-Object { $_.name -eq $parameter.name }).content + $templateContent += '' + } + } + + # Add additional parameters to only exist in a pre-existing template at the end + foreach ($extraParameter in ($existingTemplateContent.parameters | Where-Object { $parametersToAdd.name -notcontains $_.name })) { + $templateContent += $extraParameter.content + $templateContent += '' + } + + return $templateContent + } + + end { + Write-Debug ('{0} exited' -f $MyInvocation.MyCommand) + } +} diff --git a/utilities/tools/REST2CARML/private/module/Get-TemplateResourcesContent.ps1 b/utilities/tools/REST2CARML/private/module/Get-TemplateResourcesContent.ps1 new file mode 100644 index 0000000000..b65dbfa5b9 --- /dev/null +++ b/utilities/tools/REST2CARML/private/module/Get-TemplateResourcesContent.ps1 @@ -0,0 +1,205 @@ +function Get-TemplateResourcesContent { + + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [string] $FullResourceType, + + [Parameter(Mandatory = $true)] + [string] $ResourceType, + + [Parameter(Mandatory = $false)] + [string] $ResourceTypeSingular = ((Get-ResourceTypeSingularName -ResourceType $ResourceType) -split '/')[-1], + + [Parameter(Mandatory = $true)] + [array] $ModuleData, + + [Parameter(Mandatory = $true)] + [array] $FullModuleData, + + [Parameter(Mandatory = $false)] + [array] $ParentResourceTypes = @(), + + [Parameter(Mandatory = $false)] + [array] $ExistingTemplateContent = @(), + + [Parameter(Mandatory = $false)] + [array] $LinkedChildren = @() + ) + + begin { + Write-Debug ('{0} entered' -f $MyInvocation.MyCommand) + } + + process { + ##################### + ## Collect Data # + ##################### + + # Collect all parent references for 'exiting' resource references + $fullParentResourceStack = Get-ParentResourceTypeList -ResourceType $FullResourceType + + $locationParameterExists = ($templateContent | Where-Object { $_ -like 'param location *' }).Count -gt 0 + + $matchingExistingResource = $existingTemplateContent.resources | Where-Object { + $_.resourceType -eq $FullResourceType -and $_.resourceName -eq $resourceTypeSingular + } + + ######################## + ## Create Content ## + ######################## + + $templateContent = @( + '// =============== //' + '// Deployments //' + '// =============== //' + '' + ) + + # Add telemetry resource + # ---------------------- + $telemetryTemplate = Get-Content -Path (Join-Path $Script:src 'telemetry.bicep') + if (-not $locationParameterExists) { + # Remove the location from the deployment name if the template has no such parameter + $telemetryTemplate = $telemetryTemplate -replace ', location', '' + } + $templateContent += $telemetryTemplate + $templateContent += '' + + # Add 'existing' parents (if any) + # ------------------------------- + $existingResourceIndent = 0 + $orderedParentResourceTypes = $fullParentResourceStack | Where-Object { $_ -notlike $FullResourceType } | Sort-Object + foreach ($parentResourceType in $orderedParentResourceTypes) { + $singularParent = ((Get-ResourceTypeSingularName -ResourceType $parentResourceType) -split '/')[-1] + $levedParentResourceType = ($parentResourceType -ne (@() + $orderedParentResourceTypes)[0]) ? (Split-Path $parentResourceType -Leaf) : $parentResourceType + $parentJSONPath = ($FullModuleData | Where-Object { $_.identifier -eq $parentResourceType }).Metadata.JSONFilePath + + if ([String]::IsNullOrEmpty($parentJSONPath)) { + # Case: A child who's parent resource does not exist (i.e., is a proxy). In this case we use the current API paths as a fallback + # Example: 'Microsoft.AVS/privateClouds/workloadNetworks' is not actually existing as a parent for 'Microsoft.AVS/privateClouds/workloadNetworks/dhcpConfigurations' + $parentJSONPath = $JSONFilePath + } + + $parentResourceAPI = Split-Path (Split-Path $parentJSONPath -Parent) -Leaf + $templateContent += @( + "$(' ' * $existingResourceIndent)resource $($singularParent) '$($levedParentResourceType)@$($parentResourceAPI)' existing = {", + "$(' ' * $existingResourceIndent) name: $($singularParent)Name" + ) + if ($parentResourceType -ne (@() + $orderedParentResourceTypes)[-1]) { + # Only add an empty line if there is more content to add + $templateContent += '' + } + $existingResourceIndent += 4 + } + # Add closing brakets + foreach ($parentResourceType in ($fullParentResourceStack | Where-Object { $_ -notlike $FullResourceType } | Sort-Object)) { + $existingResourceIndent -= 4 + $templateContent += "$(' ' * $existingResourceIndent)}" + } + $templateContent += '' + + # Add primary resource + # -------------------- + # Deployment resource declaration line + $serviceAPIVersion = Split-Path (Split-Path $JSONFilePath -Parent) -Leaf + $templateContent += "resource $resourceTypeSingular '$FullResourceType@$serviceAPIVersion' = {" + + if (($FullResourceType -split '/').Count -ne 2) { + # In case of children, we set the 'parent' to the next parent + $templateContent += (' parent: {0}' -f (($parentResourceTypes | ForEach-Object { Get-ResourceTypeSingularName -ResourceType $_ }) -join '::')) + } + + foreach ($parameter in ($ModuleData.parameters | Where-Object { $_.level -eq 0 -and $_.name -ne 'properties' } | Sort-Object -Property 'name')) { + if ($matchingExistingResource.topLevelElements.name -notcontains $parameter.name) { + $templateContent += ' {0}: {0}' -f $parameter.name + } else { + $existingProperty = $matchingExistingResource.topLevelElements | Where-Object { $_.name -eq $parameter.name } + $templateContent += $existingProperty.content + } + } + + $templateContent += ' properties: {' + foreach ($parameter in ($ModuleData.parameters | Where-Object { $_.level -eq 1 -and $_.Parent -eq 'properties' } | Sort-Object -Property 'name')) { + if ($matchingExistingResource.nestedElements.name -notcontains $parameter.name) { + $templateContent += ' {0}: {0}' -f $parameter.name + } else { + $existingProperty = $matchingExistingResource.nestedElements | Where-Object { $_.name -eq $parameter.name } + $templateContent += $existingProperty.content + } + } + + $templateContent += @( + ' }' + '}' + '' + ) + + # If a template already exists, add 'extra' resources that are not yet part of the template content + # ------------------------------------------------------------------------------------------------- + $preExistingExtraResources = $existingTemplateContent.resources | Where-Object { + $_.resourceName -notIn ($ModuleData.resources.name + 'defaultTelemetry' + $resourceTypeSingular) + } + foreach ($resource in $preExistingExtraResources) { + $templateContent += $resource.content + $templateContent += '' + } + + # Add additional resources such as extensions (like DiagnosticSettigs) + # -------------------------------------------------------------------- + # Other collected resources + foreach ($additionalResource in $ModuleData.resources) { + if ($existingTemplateContent.resources.resourceName -notcontains $additionalResource.name) { + $templateContent += $additionalResource.content + } else { + $existingResource = $existingTemplateContent.resources | Where-Object { $_.resourceName -eq $additionalResource.name } + $templateContent += $existingResource.content + $templateContent += '' + } + } + + # Add child-module references + # --------------------------- + $childrenInputObject = @{ + FullResourceType = $FullResourceType + ResourceType = $ResourceType + ResourceTypeSingular = $ResourceTypeSingular + ModuleData = $ModuleData + LocationParameterExists = $LocationParameterExists + } + if ($LinkedChildren.Count -gt 0) { + $childrenInputObject['LinkedChildren'] = $LinkedChildren + } + if ($ExistingTemplateContent.Count -gt 0) { + $childrenInputObject['ExistingTemplateContent'] = $ExistingTemplateContent + } + if ($ParentResourceTypes.Count -gt 0) { + $childrenInputObject['ParentResourceTypes'] = $ParentResourceTypes + } + $templateContent += Get-TemplateChildModuleContent @childrenInputObject + + # TODO : Add other module references + # ---------------------------------- + foreach ($additionalResource in $ModuleData.modules) { + if ($existingTemplateContent.modules.name -notcontains $additionalResource.name) { + $templateContent += $additionalResource.content + } else { + $existingResource = $existingTemplateContent.modules | Where-Object { $_.name -eq $additionalResource.name } + $templateContent += $existingResource.content + $templateContent += '' + } + } + + # TODO: Extra extra modules + # $preExistingExtraModules = $existingTemplateContent.modules | Where-Object { $_.name -notIn $ModuleData.modules.name } + # foreach ($preExistingMdoule in $preExistingExtraModules) { + # # Beware: The pre-existing content also contains e.g. 'linkedChildren' we add as part of the template generation + # } + + return $templateContent + } + + end { + Write-Debug ('{0} exited' -f $MyInvocation.MyCommand) + } +} diff --git a/utilities/tools/REST2CARML/private/module/Get-TemplateVariablesContent.ps1 b/utilities/tools/REST2CARML/private/module/Get-TemplateVariablesContent.ps1 new file mode 100644 index 0000000000..0b892d9e46 --- /dev/null +++ b/utilities/tools/REST2CARML/private/module/Get-TemplateVariablesContent.ps1 @@ -0,0 +1,70 @@ +function Get-TemplateVariablesContent { + + [CmdletBinding()] + param ( + [Parameter(Mandatory = $true)] + [array] $ModuleData, + + [Parameter(Mandatory = $false)] + [array] $ExistingTemplateContent = @() + ) + + begin { + Write-Debug ('{0} entered' -f $MyInvocation.MyCommand) + } + + process { + + ######################## + ## Create Content ## + ######################## + + $templateContent = @( + '// ============= //' + '// Variables //' + '// ============= //' + '' + ) + + foreach ($variable in $ModuleData.variables) { + if ($existingTemplateContent.variables.name -notcontains $variable.name) { + $templateContent += $variable.content + } else { + $matchingExistingVar = $existingTemplateContent.variables | Where-Object { $_.name -eq $variable.name } + $templateContent += $matchingExistingVar.content + } + $templateContent += '' + } + + # Add telemetry variable + if ($linkedChildren.Count -gt 0) { + if ($existingTemplateContent.variables.name -notcontains 'enableReferencedModulesTelemetry') { + $templateContent += @( + 'var enableReferencedModulesTelemetry = false' + '' + ) + } else { + $matchingExistingVar = $existingTemplateContent.variables | Where-Object { $_.name -eq 'enableReferencedModulesTelemetry' } + $templateContent += $matchingExistingVar.content + } + $templateContent += '' + } + + # Add additional parameters to only exist in a pre-existing template at the end + foreach ($extraVariable in ($existingTemplateContent.variables | Where-Object { $ModuleData.variables.name -notcontains $_.name -and $_.name -ne 'enableReferencedModulesTelemetry' })) { + $templateContent += $extraVariable.content + $templateContent += '' + } + + # Only add the section if any content was added + if ($templateContent.count -eq 4) { + return @() + } else { + return $templateContent + } + } + + end { + Write-Debug ('{0} exited' -f $MyInvocation.MyCommand) + } +} diff --git a/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 b/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 index b57d4a03e4..52f33276ec 100644 --- a/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 +++ b/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 @@ -63,28 +63,7 @@ function Set-ModuleTemplate { $existingTemplateContent = Resolve-ExistingTemplateContent -TemplateFilePath $templateFilePath # Collect child-resource information - $linkedChildren = $fullmoduleData | Where-Object { - # Is nested - $_.identifier -like "$FullResourceType/*" -and - # Is direct child - (($_.identifier -split '/').Count -eq (($FullResourceType -split '/').Count + 1) - ) - } - ## Add indirect child (via proxy resource) (i.e. it's a nested-nested resources who's parent has no individual specification/JSONFilePath). - # TODO: Is that always true? What if the data is specified in one file? - $indirectChildren = $FullModuleData | Where-Object { - # Is nested - $_.identifier -like "$FullResourceType/*" -and - # Is indirect child - (($_.identifier -split '/').Count -eq (($FullResourceType -split '/').Count + 2)) - } | Where-Object { - # If the child's parent's parentUrlPath is empty, this parent has no PUT rest command which indicates it cannot be created independently - [String]::IsNullOrEmpty($_.metadata.parentUrlPath) - } - - if ($indirectChildren) { - $linkedChildren += $indirectChildren - } + $linkedChildren = Get-LinkedChildModuleList -FullModuleData $FullModuleData -FullResourceType $FullResourceType # Collect parent resources to use for parent type references $typeElem = $FullResourceType -split '/' @@ -94,22 +73,13 @@ function Set-ModuleTemplate { $parentResourceTypes = @() } - # Collect all parent references for 'exiting' resource references - $fullParentResourceStack = Get-ParentResourceTypeList -ResourceType $FullResourceType - # Get the singular version of the current resource type for proper naming $resourceTypeSingular = ((Get-ResourceTypeSingularName -ResourceType $resourceType) -split '/')[-1] - - # Handle parent proxy, if any - $hasAProxyParent = $FullModuleData.identifier -notContains ((Split-Path $FullResourceType -Parent) -replace '\\', '/') - $parentProxyName = $hasAProxyParent ? ($UrlPath -split '\/')[-3] : '' - $proxyParentType = Split-Path (Split-Path $FullResourceType -Parent) -Leaf #endregion - ################## - ## PARAMETERS ## - ################## - #region parameters + ############# + ## SCOPE ## + ############# $targetScope = Get-TargetScope -UrlPath $UrlPath $templateContent = ($targetScope -ne 'resourceGroup') ? @( @@ -117,105 +87,27 @@ function Set-ModuleTemplate { '' ) : @() - $templateContent += @( - '// ============== //' - '// Parameters //' - '// ============== //' - '' - ) - - # Collect parameters to create - # ---------------------------- - $parametersToAdd = @() - - # Add parent parameters - foreach ($parentResourceType in ($parentResourceTypes | Sort-Object)) { - $thisParentIsProxy = $hasAProxyParent -and $parentResourceType -eq $proxyParentType - - $parentParamData = @{ - level = 0 - name = '{0}Name' -f (Get-ResourceTypeSingularName -ResourceType $parentResourceType) - type = 'string' - description = '{0}. The name of the parent {1}. Required if the template is used in a standalone deployment.' -f ($thisParentIsProxy ? 'Optional' : 'Conditional'), $parentResourceType - required = $false - } - - if ($thisParentIsProxy) { - # Handle proxy parents (i.e., empty containers with only a default value name) - $parentParamData['default'] = $parentProxyName - } - - $parametersToAdd += $parentParamData - } - - # Add primary (service) parameters (i.e. top-level and those in the properties) - $parametersToAdd += @() + ($ModuleData.parameters | Where-Object { $_.Level -in @(0, 1) -and $_.name -ne 'properties' -and ([String]::IsNullOrEmpty($_.Parent) -or $_.Parent -eq 'properties') }) - - - # Add additional (extension) parameters - $parametersToAdd += $ModuleData.additionalParameters - - # Add child module references - foreach ($dataBlock in ($linkedChildren | Sort-Object -Property 'identifier')) { - $childResourceType = ($dataBlock.identifier -split '/')[-1] - $parametersToAdd += @{ - level = 0 - name = $childResourceType - type = 'array' - default = @() - description = "The $childResourceType to create as part of the $resourceTypeSingular." - required = $false - } - } + ################## + ## PARAMETERS ## + ################## + #region parameters - # Add telemetry parameter - $parametersToAdd += @{ - level = 0 - name = 'enableDefaultTelemetry' - type = 'boolean' - default = $true - description = 'Enable telemetry via the Customer Usage Attribution ID (GUID).' - required = $false + $parametersInputObject = @{ + ModuleData = $ModuleData + FullModuleData = $FullModuleData + FullResourceType = $FullResourceType } - - # Create collected parameters - # --------------------------- - # Note: If there already is a template and a given parameter was already specified, we use the existing declaration instead of generating a new one - # as it may have custom logic / default values, etc. - - # First the required - foreach ($parameter in ($parametersToAdd | Where-Object { $_.required } | Sort-Object -Property 'Name')) { - if ($existingTemplateContent.parameters.name -notcontains $parameter.name) { - $templateContent += Get-FormattedModuleParameter -ParameterData $parameter - } else { - $templateContent += ($existingTemplateContent.parameters | Where-Object { $_.name -eq $parameter.name }).content - $templateContent += '' - } + if ($ExistingTemplateContent.Count -gt 0) { + $parametersInputObject['ExistingTemplateContent'] = $ExistingTemplateContent } - # Then the conditional - foreach ($parameter in ($parametersToAdd | Where-Object { -not $_.required -and $_.description -like 'Conditional. *' } | Sort-Object -Property 'Name')) { - if ($existingTemplateContent.parameters.name -notcontains $parameter.name) { - $templateContent += Get-FormattedModuleParameter -ParameterData $parameter - } else { - $templateContent += ($existingTemplateContent.parameters | Where-Object { $_.name -eq $parameter.name }).content - $templateContent += '' - } + if ($ParentResourceTypes.Count -gt 0) { + $parametersInputObject['ParentResourceTypes'] = $ParentResourceTypes } - # Then the rest - foreach ($parameter in ($parametersToAdd | Where-Object { -not $_.required -and $_.description -notlike 'Conditional. *' } | Sort-Object -Property 'Name')) { - if ($existingTemplateContent.parameters.name -notcontains $parameter.name) { - $templateContent += Get-FormattedModuleParameter -ParameterData $parameter - } else { - $templateContent += ($existingTemplateContent.parameters | Where-Object { $_.name -eq $parameter.name }).content - $templateContent += '' - } + if ($LinkedChildren.Count -gt 0) { + $parametersInputObject['LinkedChildren'] = $LinkedChildren } + $templateContent += Get-TemplateParametersContent @parametersInputObject - # Add additional parameters to only exist in a pre-existing template at the end - foreach ($extraParameter in ($existingTemplateContent.parameters | Where-Object { $parametersToAdd.name -notcontains $_.name })) { - $templateContent += $extraParameter.content - $templateContent += '' - } #endregion ################# @@ -227,35 +119,13 @@ function Set-ModuleTemplate { $templateContent += '' } - foreach ($variable in $ModuleData.variables) { - if ($existingTemplateContent.variables.name -notcontains $variable.name) { - $templateContent += $variable.content - } else { - $matchingExistingVar = $existingTemplateContent.variables | Where-Object { $_.name -eq $variable.name } - $templateContent += $matchingExistingVar.content - } - $templateContent += '' - } - - # Add telemetry variable - if ($linkedChildren.Count -gt 0) { - if ($existingTemplateContent.variables.name -notcontains 'enableReferencedModulesTelemetry') { - $templateContent += @( - 'var enableReferencedModulesTelemetry = false' - '' - ) - } else { - $matchingExistingVar = $existingTemplateContent.variables | Where-Object { $_.name -eq 'enableReferencedModulesTelemetry' } - $templateContent += $matchingExistingVar.content - } - $templateContent += '' + $variablesInputObject = @{ + ModuleData = $ModuleData } - - # Add additional parameters to only exist in a pre-existing template at the end - foreach ($extraVariable in ($existingTemplateContent.variables | Where-Object { $ModuleData.variables.name -notcontains $_.name -and $_.name -ne 'enableReferencedModulesTelemetry' })) { - $templateContent += $extraVariable.content - $templateContent += '' + if ($ExistingTemplateContent.Count -gt 0) { + $variablesInputObject['ExistingTemplateContent'] = $ExistingTemplateContent } + $templateContent += Get-TemplateVariablesContent @variablesInputObject #endregion ################### @@ -263,339 +133,34 @@ function Set-ModuleTemplate { ################### #region resources & modules - $locationParameterExists = ($templateContent | Where-Object { $_ -like 'param location *' }).Count -gt 0 - - $matchingExistingResource = $existingTemplateContent.resources | Where-Object { - $_.resourceType -eq $FullResourceType -and $_.resourceName -eq $resourceTypeSingular - } - # Add a space in between the new section and the previous one in case no space exists if (-not [String]::IsNullOrEmpty($templateContent[-1])) { $templateContent += '' } - $templateContent += @( - '// =============== //' - '// Deployments //' - '// =============== //' - '' - ) - - # Add telemetry resource - # ---------------------- - $telemetryTemplate = Get-Content -Path (Join-Path $Script:src 'telemetry.bicep') - if (-not $locationParameterExists) { - # Remove the location from the deployment name if the template has no such parameter - $telemetryTemplate = $telemetryTemplate -replace ', location', '' - } - $templateContent += $telemetryTemplate - $templateContent += '' - - # Add 'existing' parents (if any) - # ------------------------------- - $existingResourceIndent = 0 - $orderedParentResourceTypes = $fullParentResourceStack | Where-Object { $_ -notlike $FullResourceType } | Sort-Object - foreach ($parentResourceType in $orderedParentResourceTypes) { - $singularParent = ((Get-ResourceTypeSingularName -ResourceType $parentResourceType) -split '/')[-1] - $levedParentResourceType = ($parentResourceType -ne (@() + $orderedParentResourceTypes)[0]) ? (Split-Path $parentResourceType -Leaf) : $parentResourceType - $parentJSONPath = ($FullModuleData | Where-Object { $_.identifier -eq $parentResourceType }).Metadata.JSONFilePath - - if ([String]::IsNullOrEmpty($parentJSONPath)) { - # Case: A child who's parent resource does not exist (i.e., is a proxy). In this case we use the current API paths as a fallback - # Example: 'Microsoft.AVS/privateClouds/workloadNetworks' is not actually existing as a parent for 'Microsoft.AVS/privateClouds/workloadNetworks/dhcpConfigurations' - $parentJSONPath = $JSONFilePath - } - - $parentResourceAPI = Split-Path (Split-Path $parentJSONPath -Parent) -Leaf - $templateContent += @( - "$(' ' * $existingResourceIndent)resource $($singularParent) '$($levedParentResourceType)@$($parentResourceAPI)' existing = {", - "$(' ' * $existingResourceIndent) name: $($singularParent)Name" - ) - if ($parentResourceType -ne (@() + $orderedParentResourceTypes)[-1]) { - # Only add an empty line if there is more content to add - $templateContent += '' - } - $existingResourceIndent += 4 - } - # Add closing brakets - foreach ($parentResourceType in ($fullParentResourceStack | Where-Object { $_ -notlike $FullResourceType } | Sort-Object)) { - $existingResourceIndent -= 4 - $templateContent += "$(' ' * $existingResourceIndent)}" - } - $templateContent += '' - - # Add primary resource - # -------------------- - # Deployment resource declaration line - $serviceAPIVersion = Split-Path (Split-Path $JSONFilePath -Parent) -Leaf - $templateContent += "resource $resourceTypeSingular '$FullResourceType@$serviceAPIVersion' = {" - - if (($FullResourceType -split '/').Count -ne 2) { - # In case of children, we set the 'parent' to the next parent - $templateContent += (' parent: {0}' -f (($parentResourceTypes | ForEach-Object { Get-ResourceTypeSingularName -ResourceType $_ }) -join '::')) - } - - foreach ($parameter in ($ModuleData.parameters | Where-Object { $_.level -eq 0 -and $_.name -ne 'properties' } | Sort-Object -Property 'name')) { - if ($matchingExistingResource.topLevelElements.name -notcontains $parameter.name) { - $templateContent += ' {0}: {0}' -f $parameter.name - } else { - $existingProperty = $matchingExistingResource.topLevelElements | Where-Object { $_.name -eq $parameter.name } - $templateContent += $existingProperty.content - } - } - - $templateContent += ' properties: {' - foreach ($parameter in ($ModuleData.parameters | Where-Object { $_.level -eq 1 -and $_.Parent -eq 'properties' } | Sort-Object -Property 'name')) { - if ($matchingExistingResource.nestedElements.name -notcontains $parameter.name) { - $templateContent += ' {0}: {0}' -f $parameter.name - } else { - $existingProperty = $matchingExistingResource.nestedElements | Where-Object { $_.name -eq $parameter.name } - $templateContent += $existingProperty.content - } + $resourcesInputObject = @{ + FullResourceType = $FullResourceType + ResourceType = $ResourceType + ResourceTypeSingular = $ResourceTypeSingular + ModuleData = $ModuleData + FullModuleData = $FullModuleData } - - $templateContent += @( - ' }' - '}' - '' - ) - - # If a template already exists, add 'extra' resources that are not yet part of the template content - # ------------------------------------------------------------------------------------------------- - $preExistingExtraResources = $existingTemplateContent.resources | Where-Object { - $_.resourceName -notIn ($ModuleData.resources.name + 'defaultTelemetry' + $resourceTypeSingular) - } - foreach ($resource in $preExistingExtraResources) { - $templateContent += $resource.content - $templateContent += '' + if ($ExistingTemplateContent.Count -gt 0) { + $resourcesInputObject['ExistingTemplateContent'] = $ExistingTemplateContent } - - # Add additional resources such as extensions (like DiagnosticSettigs) - # -------------------------------------------------------------------- - # Other collected resources - foreach ($additionalResource in $ModuleData.resources) { - if ($existingTemplateContent.resources.resourceName -notcontains $additionalResource.name) { - $templateContent += $additionalResource.content - } else { - $existingResource = $existingTemplateContent.resources | Where-Object { $_.resourceName -eq $additionalResource.name } - $templateContent += $existingResource.content - $templateContent += '' - } + if ($ParentResourceTypes.Count -gt 0) { + $resourcesInputObject['ParentResourceTypes'] = $ParentResourceTypes } - - # Add child-module references - # --------------------------- - foreach ($dataBlock in $linkedChildren) { - $childResourceType = ($dataBlock.identifier -split '/')[-1] - - $hasProxyParent = [String]::IsNullOrEmpty($dataBlock.metadata.parentUrlPath) - if ($hasProxyParent) { - $proxyParentName = Split-Path (Split-Path $dataBlock.identifier -Parent) -Leaf - } - - $moduleName = '{0}{1}_{2}' -f ($hasProxyParent ? "$($proxyParentName)_" : ''), $resourceTypeSingular, $childResourceType - $modulePath = '{0}{1}/deploy.bicep' -f ($hasProxyParent ? "$proxyParentName/" : ''), $childResourceType - - $matchingModule = $existingTemplateContent.modules | Where-Object { $_.name -eq $moduleName -and $_.path -eq $modulePath } - - # Differentiate 'singular' children (like 'blobservices') vs. 'multiple' chilren (like 'containers') - if ($ModuleData.isSingleton) { - $templateContent += @( - "module $moduleName '$modulePath' = {" - ) - - if ($matchingModule.topLevelElements.name -notcontains 'name') { - $templateContent += " name: '`${uniqueString(deployment().name$($locationParameterExists ? ', location' : ''))}-$($resourceTypeSingular)-$($childResourceType)'" - } else { - $existingParam = $matchingModule.topLevelElements | Where-Object { $_.name -eq 'name' } - $templateContent += $existingParam.content - } - - $templateContent += ' params: {' - $templateContent += @() - - $alreadyAddedParams = @() - - # All param names of parents - foreach ($parentResourceType in $parentResourceTypes) { - $parentParamName = ((Get-ResourceTypeSingularName -ResourceType $parentResourceType) -split '/')[-1] - $templateContent += ' {0}Name: {0}Name' -f $parentParamName - $alreadyAddedParams += $parentParamName - } - # Itself - $selfParamName = ((Get-ResourceTypeSingularName -ResourceType ($FullResourceType -split '/')[-1]) -split '/')[-1] - $templateContent += ' {0}Name: name' -f $selfParamName - $alreadyAddedParams += $selfParamName - - # Any proxy default if any - if ($hasProxyParent) { - $proxyDefaultValue = ($dataBlock.metadata.urlPath -split '\/')[-3] - $proxyParamName = Get-ResourceTypeSingularName -ResourceType ($proxyParentName -split '/')[-1] - $templateContent += " {0}Name: '{1}'" -f $proxyParamName, $proxyDefaultValue - $alreadyAddedParams += $proxyParamName - } - - # Add primary child parameters - $allParam = $dataBlock.data.parameters + $dataBlock.data.additionalParameters - foreach ($parameter in (($allParam | Where-Object { $_.Level -in @(0, 1) -and $_.name -ne 'properties' -and ([String]::IsNullOrEmpty($_.Parent) -or $_.Parent -eq 'properties') }) | Sort-Object -Property 'Name')) { - $wouldBeParameter = Get-FormattedModuleParameter -ParameterData $parameter | Where-Object { $_ -like 'param *' } | ForEach-Object { $_ -replace 'param ', '' } - $wouldBeParamElem = $wouldBeParameter -split ' = ' - $parameter.name = ($wouldBeParamElem -split ' ')[0] - - if ($matchingModule.nestedElements.name -notcontains $parameter.name) { - $existingParam = $matchingModule.nestedElements | Where-Object { $_.name -eq $parameter.name } - if ($alreadyAddedParams -notcontains $existingParam.name) { - $templateContent += $existingParam.content - } - continue - } - - if ($wouldBeParamElem.count -gt 1) { - # With default - - if ($parameter.name -eq 'lock') { - # Special handling as we pass the parameter down to the child - $templateContent += " $($parameter.name): contains($($childResourceType), 'lock') ? $($childResourceType).lock : lock" - $alreadyAddedParams += $parameter.name - continue - } - - $wouldBeParamValue = $wouldBeParamElem[1] - - # Special case, location function - should reference a location parameter instead - if ($wouldBeParamValue -like '*().location') { - $wouldBeParamValue = 'location' - } - - $templateContent += " $($parameter.name): contains($($childResourceType), '$($parameter.name)') ? $($childResourceType).$($parameter.name) : $($wouldBeParamValue)" - $alreadyAddedParams += $parameter.name - } else { - # No default - $templateContent += " $($parameter.name): $($childResourceType).$($parameter.name)" - $alreadyAddedParams += $parameter.name - } - } - - $templateContent += @( - # Special handling as we pass the variable down to the child - ' enableDefaultTelemetry: enableReferencedModulesTelemetry' - ' }' - '}' - '' - ) - } else { - - $childResourceTypeSingular = Get-ResourceTypeSingularName -ResourceType $childResourceType - - $templateContent += @( - "module $moduleName '$modulePath' = [for ($($childResourceTypeSingular), index) in $($childResourceType): {" - ) - - if ($matchingModule.topLevelElements.name -notcontains 'name') { - $templateContent += " name: '`${uniqueString(deployment().name$($locationParameterExists ? ', location' : ''))}-$($resourceTypeSingular)-$($childResourceTypeSingular)-`${index}'" - } else { - $existingParam = $matchingModule.topLevelElements | Where-Object { $_.name -eq 'name' } - $templateContent += $existingParam.content - } - - $templateContent += ' params: {' - $templateContent += @() - - $alreadyAddedParams = @() - - # All param names of parents - foreach ($parentResourceType in $parentResourceTypes) { - $parentParamName = ((Get-ResourceTypeSingularName -ResourceType $parentResourceType) -split '/')[-1] - $templateContent += ' {0}Name: {0}Name' -f $parentParamName - $alreadyAddedParams += $parentParamName - } - # Itself - $selfParamName = ((Get-ResourceTypeSingularName -ResourceType ($FullResourceType -split '/')[-1]) -split '/')[-1] - $templateContent += ' {0}Name: name' -f $selfParamName - $alreadyAddedParams += $selfParamName - - # Any proxy default if any - if ($hasProxyParent) { - $proxyDefaultValue = ($dataBlock.metadata.urlPath -split '\/')[-3] - $proxyParamName = Get-ResourceTypeSingularName -ResourceType ($proxyParentName -split '/')[-1] - $templateContent += " {0}Name: '{1}'" -f $proxyParamName, $proxyDefaultValue - $alreadyAddedParams += $proxyParamName - } - - # Add primary child parameters - $allParam = $dataBlock.data.parameters + $dataBlock.data.additionalParameters - foreach ($parameter in (($allParam | Where-Object { $_.Level -in @(0, 1) -and $_.name -ne 'properties' -and ([String]::IsNullOrEmpty($_.Parent) -or $_.Parent -eq 'properties') }) | Sort-Object -Property 'Name')) { - $wouldBeParameter = Get-FormattedModuleParameter -ParameterData $parameter | Where-Object { $_ -like 'param *' } | ForEach-Object { $_ -replace 'param ', '' } - $wouldBeParamElem = $wouldBeParameter -split ' = ' - $parameter.name = ($wouldBeParamElem -split ' ')[0] - - if ($matchingModule.nestedElements.name -notcontains $parameter.name) { - $existingParam = $matchingModule.nestedElements | Where-Object { $_.name -eq $parameter.name } - if ($alreadyAddedParams -notcontains $existingParam.name) { - $templateContent += $existingParam.content - } - continue - } - - if ($wouldBeParamElem.count -gt 1) { - # With default - - if ($parameter.name -eq 'lock') { - # Special handling as we pass the parameter down to the child - $templateContent += " $($parameter.name): contains($($childResourceTypeSingular), 'lock') ? $($childResourceTypeSingular).lock : lock" - $alreadyAddedParams += $parameter.name - continue - } - - $wouldBeParamValue = $wouldBeParamElem[1] - - # Special case, location function - should reference a location parameter instead - if ($wouldBeParamValue -like '*().location') { - $wouldBeParamValue = 'location' - } - - $templateContent += " $($parameter.name): contains($($childResourceTypeSingular), '$($parameter.name)') ? $($childResourceTypeSingular).$($parameter.name) : $($wouldBeParamValue)" - $alreadyAddedParams += $parameter.name - } else { - # No default - $templateContent += " $($parameter.name): $($childResourceTypeSingular).$($parameter.name)" - $alreadyAddedParams += $parameter.name - } - } - - $templateContent += @( - # Special handling as we pass the variable down to the child - ' enableDefaultTelemetry: enableReferencedModulesTelemetry' - ' }' - '}]' - '' - ) - } + if ($LinkedChildren.Count -gt 0) { + $resourcesInputObject['LinkedChildren'] = $LinkedChildren } - - # TODO : Add other module references - # ---------------------------------- - foreach ($additionalResource in $ModuleData.modules) { - if ($existingTemplateContent.modules.name -notcontains $additionalResource.name) { - $templateContent += $additionalResource.content - } else { - $existingResource = $existingTemplateContent.modules | Where-Object { $_.name -eq $additionalResource.name } - $templateContent += $existingResource.content - $templateContent += '' - } - } - - # TODO: Extra extra modules - # $preExistingExtraModules = $existingTemplateContent.modules | Where-Object { $_.name -notIn $ModuleData.modules.name } - # foreach ($preExistingMdoule in $preExistingExtraModules) { - # # Beware: The pre-existing content also contains e.g. 'linkedChildren' we add as part of the template generation - # } - + $templateContent += Get-TemplateResourcesContent @resourcesInputObject #endregion ####################################### ## Create template outputs section ## ####################################### + #region outputs # Add a space in between the new section and the previous one in case no space exists if (-not [String]::IsNullOrEmpty($templateContent[-1])) { @@ -603,14 +168,16 @@ function Set-ModuleTemplate { } $outputsInputObject = @{ - FullResourceType = $FullResourceType - UrlPath = $UrlPath - ModuleData = $ModuleData + ResourceType = $ResourceType + ResourceTypeSingular = $ResourceTypeSingular + TargetScope = $TargetScope + ModuleData = $ModuleData } if ($ExistingTemplateContent.Count -gt 0) { $outputsInputObject['ExistingTemplateContent'] = $ExistingTemplateContent } - $templateContent += Get-ModuleOutputContent @outputsInputObject + $templateContent += Get-TemplateOutputContent @outputsInputObject + #endregion ############################ ## Update template file ## From a416f55d50efb79315755386e4bacfbcb2e55dce Mon Sep 17 00:00:00 2001 From: MrMCake Date: Sat, 5 Nov 2022 20:57:26 +0100 Subject: [PATCH 22/30] Re-generated module --- .../modulePipelines/ms.avs.privateclouds.yml | 40 ++ .github/workflows/ms.avs.privateclouds.yml | 145 +++++++ .../privateClouds/.test/common/deploy.bicep | 0 .../privateClouds/.test/min/deploy.bicep | 0 .../privateClouds/addons/deploy.bicep | 62 +++ .../privateClouds/addons/version.json | 4 + .../privateClouds/authorizations/deploy.bicep | 52 +++ .../privateClouds/authorizations/readme.md | 54 +++ .../privateClouds/authorizations/version.json | 4 + .../privateClouds/cloudLinks/deploy.bicep | 56 +++ .../privateClouds/cloudLinks/readme.md | 55 +++ .../privateClouds/cloudLinks/version.json | 4 + .../clusters/datastores/deploy.bicep | 67 ++++ .../clusters/datastores/readme.md | 57 +++ .../clusters/datastores/version.json | 4 + .../privateClouds/clusters/deploy.bicep | 95 +++++ .../clusters/placementPolicies/deploy.bicep | 103 +++++ .../clusters/placementPolicies/version.json | 4 + .../privateClouds/clusters/version.json | 4 + .../Microsoft.AVS/privateClouds/deploy.bicep | 372 ++++++++++++++++++ .../globalReachConnections/deploy.bicep | 64 +++ .../globalReachConnections/readme.md | 57 +++ .../globalReachConnections/version.json | 4 + .../hcxEnterpriseSites/deploy.bicep | 52 +++ .../hcxEnterpriseSites/readme.md | 54 +++ .../hcxEnterpriseSites/version.json | 4 + .../scriptExecutions/deploy.bicep | 84 ++++ .../privateClouds/scriptExecutions/readme.md | 62 +++ .../scriptExecutions/version.json | 4 + .../Microsoft.AVS/privateClouds/version.json | 4 + .../dhcpConfigurations/deploy.bicep | 75 ++++ .../dhcpConfigurations/version.json | 4 + .../workloadNetworks/dnsServices/deploy.bicep | 90 +++++ .../workloadNetworks/dnsServices/version.json | 4 + .../workloadNetworks/dnsZones/deploy.bicep | 83 ++++ .../workloadNetworks/dnsZones/version.json | 4 + .../portMirroringProfiles/deploy.bicep | 84 ++++ .../portMirroringProfiles/version.json | 4 + .../workloadNetworks/publicIPs/deploy.bicep | 67 ++++ .../workloadNetworks/publicIPs/version.json | 4 + .../workloadNetworks/segments/deploy.bicep | 75 ++++ .../workloadNetworks/segments/version.json | 4 + .../workloadNetworks/vmGroups/deploy.bicep | 71 ++++ .../workloadNetworks/vmGroups/version.json | 4 + 44 files changed, 2144 insertions(+) create mode 100644 .azuredevops/modulePipelines/ms.avs.privateclouds.yml create mode 100644 .github/workflows/ms.avs.privateclouds.yml create mode 100644 modules/Microsoft.AVS/privateClouds/.test/common/deploy.bicep create mode 100644 modules/Microsoft.AVS/privateClouds/.test/min/deploy.bicep create mode 100644 modules/Microsoft.AVS/privateClouds/addons/deploy.bicep create mode 100644 modules/Microsoft.AVS/privateClouds/addons/version.json create mode 100644 modules/Microsoft.AVS/privateClouds/authorizations/deploy.bicep create mode 100644 modules/Microsoft.AVS/privateClouds/authorizations/readme.md create mode 100644 modules/Microsoft.AVS/privateClouds/authorizations/version.json create mode 100644 modules/Microsoft.AVS/privateClouds/cloudLinks/deploy.bicep create mode 100644 modules/Microsoft.AVS/privateClouds/cloudLinks/readme.md create mode 100644 modules/Microsoft.AVS/privateClouds/cloudLinks/version.json create mode 100644 modules/Microsoft.AVS/privateClouds/clusters/datastores/deploy.bicep create mode 100644 modules/Microsoft.AVS/privateClouds/clusters/datastores/readme.md create mode 100644 modules/Microsoft.AVS/privateClouds/clusters/datastores/version.json create mode 100644 modules/Microsoft.AVS/privateClouds/clusters/deploy.bicep create mode 100644 modules/Microsoft.AVS/privateClouds/clusters/placementPolicies/deploy.bicep create mode 100644 modules/Microsoft.AVS/privateClouds/clusters/placementPolicies/version.json create mode 100644 modules/Microsoft.AVS/privateClouds/clusters/version.json create mode 100644 modules/Microsoft.AVS/privateClouds/deploy.bicep create mode 100644 modules/Microsoft.AVS/privateClouds/globalReachConnections/deploy.bicep create mode 100644 modules/Microsoft.AVS/privateClouds/globalReachConnections/readme.md create mode 100644 modules/Microsoft.AVS/privateClouds/globalReachConnections/version.json create mode 100644 modules/Microsoft.AVS/privateClouds/hcxEnterpriseSites/deploy.bicep create mode 100644 modules/Microsoft.AVS/privateClouds/hcxEnterpriseSites/readme.md create mode 100644 modules/Microsoft.AVS/privateClouds/hcxEnterpriseSites/version.json create mode 100644 modules/Microsoft.AVS/privateClouds/scriptExecutions/deploy.bicep create mode 100644 modules/Microsoft.AVS/privateClouds/scriptExecutions/readme.md create mode 100644 modules/Microsoft.AVS/privateClouds/scriptExecutions/version.json create mode 100644 modules/Microsoft.AVS/privateClouds/version.json create mode 100644 modules/Microsoft.AVS/privateClouds/workloadNetworks/dhcpConfigurations/deploy.bicep create mode 100644 modules/Microsoft.AVS/privateClouds/workloadNetworks/dhcpConfigurations/version.json create mode 100644 modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsServices/deploy.bicep create mode 100644 modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsServices/version.json create mode 100644 modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsZones/deploy.bicep create mode 100644 modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsZones/version.json create mode 100644 modules/Microsoft.AVS/privateClouds/workloadNetworks/portMirroringProfiles/deploy.bicep create mode 100644 modules/Microsoft.AVS/privateClouds/workloadNetworks/portMirroringProfiles/version.json create mode 100644 modules/Microsoft.AVS/privateClouds/workloadNetworks/publicIPs/deploy.bicep create mode 100644 modules/Microsoft.AVS/privateClouds/workloadNetworks/publicIPs/version.json create mode 100644 modules/Microsoft.AVS/privateClouds/workloadNetworks/segments/deploy.bicep create mode 100644 modules/Microsoft.AVS/privateClouds/workloadNetworks/segments/version.json create mode 100644 modules/Microsoft.AVS/privateClouds/workloadNetworks/vmGroups/deploy.bicep create mode 100644 modules/Microsoft.AVS/privateClouds/workloadNetworks/vmGroups/version.json diff --git a/.azuredevops/modulePipelines/ms.avs.privateclouds.yml b/.azuredevops/modulePipelines/ms.avs.privateclouds.yml new file mode 100644 index 0000000000..4f3d86e218 --- /dev/null +++ b/.azuredevops/modulePipelines/ms.avs.privateclouds.yml @@ -0,0 +1,40 @@ +name: 'AVS - PrivateClouds' + +parameters: + - name: removeDeployment + displayName: Remove deployed module + type: boolean + default: true + - name: prerelease + displayName: Publish prerelease module + type: boolean + default: false + +pr: none + +trigger: + batch: true + branches: + include: + - main + paths: + include: + - '/.azuredevops/modulePipelines/ms.avs.privateclouds.yml' + - '/.azuredevops/pipelineTemplates/*.yml' + - '/modules/Microsoft.AVS/privateClouds/*' + - '/utilities/pipelines/*' + exclude: + - '/utilities/pipelines/dependencies/*' + - '/**/*.md' + +variables: + - template: '../../settings.yml' + - group: 'PLATFORM_VARIABLES' + - name: modulePath + value: '/modules/Microsoft.AVS/privateClouds' + +stages: + - template: /.azuredevops/pipelineTemplates/stages.module.yml + parameters: + removeDeployment: '${{ parameters.removeDeployment }}' + prerelease: '${{ parameters.prerelease }}' \ No newline at end of file diff --git a/.github/workflows/ms.avs.privateclouds.yml b/.github/workflows/ms.avs.privateclouds.yml new file mode 100644 index 0000000000..0a5e19acbd --- /dev/null +++ b/.github/workflows/ms.avs.privateclouds.yml @@ -0,0 +1,145 @@ +name: 'AVS: PrivateClouds' + +on: + workflow_dispatch: + inputs: + removeDeployment: + type: boolean + description: 'Remove deployed module' + required: false + default: true + prerelease: + type: boolean + description: 'Publish prerelease module' + required: false + default: false + push: + branches: + - main + paths: + - '.github/actions/templates/**' + - '.github/workflows/ms.avs.privateclouds.yml' + - 'modules/Microsoft.AVS/privateClouds/**' + - 'utilities/pipelines/**' + - '!utilities/pipelines/dependencies/**' + - '!*/**/readme.md' + +env: + variablesPath: 'settings.yml' + modulePath: 'modules/Microsoft.AVS/privateClouds' + workflowPath: '.github/workflows/ms.avs.privateclouds.yml' + AZURE_CREDENTIALS: ${{ secrets.AZURE_CREDENTIALS }} + ARM_SUBSCRIPTION_ID: '${{ secrets.ARM_SUBSCRIPTION_ID }}' + ARM_MGMTGROUP_ID: '${{ secrets.ARM_MGMTGROUP_ID }}' + ARM_TENANT_ID: '${{ secrets.ARM_TENANT_ID }}' + TOKEN_NAMEPREFIX: '${{ secrets.TOKEN_NAMEPREFIX }}' + +jobs: + ########################### + # Initialize pipeline # + ########################### + job_initialize_pipeline: + runs-on: ubuntu-20.04 + name: 'Initialize pipeline' + steps: + - name: 'Checkout' + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: 'Set input parameters to output variables' + id: get-workflow-param + uses: ./.github/actions/templates/getWorkflowInput + with: + workflowPath: '${{ env.workflowPath}}' + - name: 'Get parameter file paths' + id: get-module-test-file-paths + uses: ./.github/actions/templates/getModuleTestFiles + with: + modulePath: '${{ env.modulePath }}' + outputs: + removeDeployment: ${{ steps.get-workflow-param.outputs.removeDeployment }} + moduleTestFilePaths: ${{ steps.get-module-test-file-paths.outputs.moduleTestFilePaths }} + + ######################### + # Static validation # + ######################### + job_module_pester_validation: + runs-on: ubuntu-20.04 + name: 'Static validation' + steps: + - name: 'Checkout' + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Set environment variables + uses: ./.github/actions/templates/setEnvironmentVariables + with: + variablesPath: ${{ env.variablesPath }} + - name: 'Run tests' + uses: ./.github/actions/templates/validateModulePester + with: + modulePath: '${{ env.modulePath }}' + moduleTestFilePath: '${{ env.moduleTestFilePath }}' + + ############################# + # Deployment validation # + ############################# + job_module_deploy_validation: + runs-on: ubuntu-20.04 + name: 'Deployment validation' + needs: + - job_initialize_pipeline + - job_module_pester_validation + strategy: + fail-fast: false + matrix: + moduleTestFilePaths: ${{ fromJSON(needs.job_initialize_pipeline.outputs.moduleTestFilePaths) }} + steps: + - name: 'Checkout' + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Set environment variables + uses: ./.github/actions/templates/setEnvironmentVariables + with: + variablesPath: ${{ env.variablesPath }} + - name: 'Using test file [${{ matrix.moduleTestFilePaths }}]' + uses: ./.github/actions/templates/validateModuleDeployment + with: + templateFilePath: '${{ env.modulePath }}/${{ matrix.moduleTestFilePaths }}' + location: '${{ env.location }}' + resourceGroupName: '${{ env.resourceGroupName }}' + subscriptionId: '${{ secrets.ARM_SUBSCRIPTION_ID }}' + managementGroupId: '${{ secrets.ARM_MGMTGROUP_ID }}' + removeDeployment: '${{ needs.job_initialize_pipeline.outputs.removeDeployment }}' + + ################## + # Publishing # + ################## + job_publish_module: + name: 'Publishing' + if: github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master' || github.event.inputs.prerelease == 'true' + runs-on: ubuntu-20.04 + needs: + - job_module_deploy_validation + steps: + - name: 'Checkout' + uses: actions/checkout@v2 + with: + fetch-depth: 0 + - name: Set environment variables + uses: ./.github/actions/templates/setEnvironmentVariables + with: + variablesPath: ${{ env.variablesPath }} + - name: 'Publishing' + uses: ./.github/actions/templates/publishModule + with: + templateFilePath: '${{ env.modulePath }}/deploy.bicep' + templateSpecsRGName: '${{ env.templateSpecsRGName }}' + templateSpecsRGLocation: '${{ env.templateSpecsRGLocation }}' + templateSpecsDescription: '${{ env.templateSpecsDescription }}' + templateSpecsDoPublish: '${{ env.templateSpecsDoPublish }}' + bicepRegistryName: '${{ env.bicepRegistryName }}' + bicepRegistryRGName: '${{ env.bicepRegistryRGName }}' + bicepRegistryRgLocation: '${{ env.bicepRegistryRgLocation }}' + bicepRegistryDoPublish: '${{ env.bicepRegistryDoPublish }}' \ No newline at end of file diff --git a/modules/Microsoft.AVS/privateClouds/.test/common/deploy.bicep b/modules/Microsoft.AVS/privateClouds/.test/common/deploy.bicep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/Microsoft.AVS/privateClouds/.test/min/deploy.bicep b/modules/Microsoft.AVS/privateClouds/.test/min/deploy.bicep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/modules/Microsoft.AVS/privateClouds/addons/deploy.bicep b/modules/Microsoft.AVS/privateClouds/addons/deploy.bicep new file mode 100644 index 0000000000..597f3dca3b --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/addons/deploy.bicep @@ -0,0 +1,62 @@ +// ============== // +// Parameters // +// ============== // + +@description('Required. Name of the addon for the private cloud') +param name string + +@description('Conditional. The name of the parent privateClouds. Required if the template is used in a standalone deployment.') +param privateCloudName string + +@description('Optional. The type of private cloud addon') +@allowed([ + 'SRM' + 'VR' + 'HCX' + 'Arc' +]) +param addonType string = '' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +// =============== // +// Deployments // +// =============== // + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { + name: privateCloudName +} + +resource addon 'Microsoft.AVS/privateClouds/addons@2022-05-01' = { + parent: privateCloud + name: name + properties: { + addonType: addonType + } +} + +// =========== // +// Outputs // +// =========== // + +@description('The name of the addon.') +output name string = addon.name + +@description('The resource ID of the addon.') +output resourceId string = addon.id + +@description('The name of the resource group the addon was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.AVS/privateClouds/addons/version.json b/modules/Microsoft.AVS/privateClouds/addons/version.json new file mode 100644 index 0000000000..41f66cc990 --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/addons/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/modules/Microsoft.AVS/privateClouds/authorizations/deploy.bicep b/modules/Microsoft.AVS/privateClouds/authorizations/deploy.bicep new file mode 100644 index 0000000000..508635ef94 --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/authorizations/deploy.bicep @@ -0,0 +1,52 @@ +// ============== // +// Parameters // +// ============== // + +@description('Required. Name of the ExpressRoute Circuit Authorization in the private cloud') +param name string + +@description('Conditional. The name of the parent privateClouds. Required if the template is used in a standalone deployment.') +param privateCloudName string + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +// =============== // +// Deployments // +// =============== // + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { + name: privateCloudName +} + +resource authorization 'Microsoft.AVS/privateClouds/authorizations@2022-05-01' = { + parent: privateCloud + name: name + properties: { + } +} + +// =========== // +// Outputs // +// =========== // + +@description('The name of the authorization.') +output name string = authorization.name + +@description('The resource ID of the authorization.') +output resourceId string = authorization.id + +@description('The name of the resource group the authorization was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.AVS/privateClouds/authorizations/readme.md b/modules/Microsoft.AVS/privateClouds/authorizations/readme.md new file mode 100644 index 0000000000..89ab5af150 --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/authorizations/readme.md @@ -0,0 +1,54 @@ +# AVS PrivateClouds Authorizations `[Microsoft.AVS/privateClouds/authorizations]` + +This module deploys AVS PrivateClouds Authorizations. +// TODO: Replace Resource and fill in description + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.AVS/privateClouds/authorizations` | [2022-05-01](https://docs.microsoft.com/en-us/azure/templates/Microsoft.AVS/privateClouds/authorizations) | + +## Parameters + +**Required parameters** + +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the ExpressRoute Circuit Authorization in the private cloud | + +**Conditional parameters** + +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `privateCloudName` | string | The name of the parent privateClouds. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | + + +### Parameter Usage: `` + +// TODO: Fill in Parameter usage + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the authorization. | +| `resourceGroupName` | string | The name of the resource group the authorization was created in. | +| `resourceId` | string | The resource ID of the authorization. | + +## Cross-referenced modules + +_None_ diff --git a/modules/Microsoft.AVS/privateClouds/authorizations/version.json b/modules/Microsoft.AVS/privateClouds/authorizations/version.json new file mode 100644 index 0000000000..41f66cc990 --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/authorizations/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/modules/Microsoft.AVS/privateClouds/cloudLinks/deploy.bicep b/modules/Microsoft.AVS/privateClouds/cloudLinks/deploy.bicep new file mode 100644 index 0000000000..8948ad6f16 --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/cloudLinks/deploy.bicep @@ -0,0 +1,56 @@ +// ============== // +// Parameters // +// ============== // + +@description('Required. Name of the cloud link resource') +param name string + +@description('Conditional. The name of the parent privateClouds. Required if the template is used in a standalone deployment.') +param privateCloudName string + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Identifier of the other private cloud participating in the link.') +param linkedCloud string = '' + +// =============== // +// Deployments // +// =============== // + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { + name: privateCloudName +} + +resource cloudLink 'Microsoft.AVS/privateClouds/cloudLinks@2022-05-01' = { + parent: privateCloud + name: name + properties: { + linkedCloud: linkedCloud + } +} + +// =========== // +// Outputs // +// =========== // + +@description('The name of the cloudLink.') +output name string = cloudLink.name + +@description('The resource ID of the cloudLink.') +output resourceId string = cloudLink.id + +@description('The name of the resource group the cloudLink was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.AVS/privateClouds/cloudLinks/readme.md b/modules/Microsoft.AVS/privateClouds/cloudLinks/readme.md new file mode 100644 index 0000000000..163ef46d6e --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/cloudLinks/readme.md @@ -0,0 +1,55 @@ +# AVS PrivateClouds CloudLinks `[Microsoft.AVS/privateClouds/cloudLinks]` + +This module deploys AVS PrivateClouds CloudLinks. +// TODO: Replace Resource and fill in description + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.AVS/privateClouds/cloudLinks` | [2022-05-01](https://docs.microsoft.com/en-us/azure/templates/Microsoft.AVS/privateClouds/cloudLinks) | + +## Parameters + +**Required parameters** + +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the cloud link resource | + +**Conditional parameters** + +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `privateCloudName` | string | The name of the parent privateClouds. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `linkedCloud` | string | `''` | Identifier of the other private cloud participating in the link. | + + +### Parameter Usage: `` + +// TODO: Fill in Parameter usage + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the cloudLink. | +| `resourceGroupName` | string | The name of the resource group the cloudLink was created in. | +| `resourceId` | string | The resource ID of the cloudLink. | + +## Cross-referenced modules + +_None_ diff --git a/modules/Microsoft.AVS/privateClouds/cloudLinks/version.json b/modules/Microsoft.AVS/privateClouds/cloudLinks/version.json new file mode 100644 index 0000000000..41f66cc990 --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/cloudLinks/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/modules/Microsoft.AVS/privateClouds/clusters/datastores/deploy.bicep b/modules/Microsoft.AVS/privateClouds/clusters/datastores/deploy.bicep new file mode 100644 index 0000000000..85bcc45cd9 --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/clusters/datastores/deploy.bicep @@ -0,0 +1,67 @@ +// ============== // +// Parameters // +// ============== // + +@description('Required. Name of the datastore in the private cloud cluster') +param name string + +@description('Conditional. The name of the parent clusters. Required if the template is used in a standalone deployment.') +param clusterName string + +@description('Conditional. The name of the parent privateClouds. Required if the template is used in a standalone deployment.') +param privateCloudName string + +@description('Optional. An iSCSI volume from Microsoft.StoragePool provider') +param diskPoolVolume object = {} + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. An Azure NetApp Files volume from Microsoft.NetApp provider') +param netAppVolume object = {} + +// =============== // +// Deployments // +// =============== // + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { + name: privateCloudName + + resource cluster 'clusters@2022-05-01' existing = { + name: clusterName + } +} + +resource datastore 'Microsoft.AVS/privateClouds/clusters/datastores@2022-05-01' = { + parent: privateCloud::cluster + name: name + properties: { + diskPoolVolume: diskPoolVolume + netAppVolume: netAppVolume + } +} + +// =========== // +// Outputs // +// =========== // + +@description('The name of the datastore.') +output name string = datastore.name + +@description('The resource ID of the datastore.') +output resourceId string = datastore.id + +@description('The name of the resource group the datastore was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.AVS/privateClouds/clusters/datastores/readme.md b/modules/Microsoft.AVS/privateClouds/clusters/datastores/readme.md new file mode 100644 index 0000000000..dcecf01a6c --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/clusters/datastores/readme.md @@ -0,0 +1,57 @@ +# AVS PrivateClouds Clusters Datastores `[Microsoft.AVS/privateClouds/clusters/datastores]` + +This module deploys AVS PrivateClouds Clusters Datastores. +// TODO: Replace Resource and fill in description + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.AVS/privateClouds/clusters/datastores` | [2022-05-01](https://docs.microsoft.com/en-us/azure/templates/Microsoft.AVS/privateClouds/clusters/datastores) | + +## Parameters + +**Required parameters** + +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the datastore in the private cloud cluster | + +**Conditional parameters** + +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `clusterName` | string | The name of the parent clusters. Required if the template is used in a standalone deployment. | +| `privateCloudName` | string | The name of the parent privateClouds. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `diskPoolVolume` | object | `{object}` | An iSCSI volume from Microsoft.StoragePool provider | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `netAppVolume` | object | `{object}` | An Azure NetApp Files volume from Microsoft.NetApp provider | + + +### Parameter Usage: `` + +// TODO: Fill in Parameter usage + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the datastore. | +| `resourceGroupName` | string | The name of the resource group the datastore was created in. | +| `resourceId` | string | The resource ID of the datastore. | + +## Cross-referenced modules + +_None_ diff --git a/modules/Microsoft.AVS/privateClouds/clusters/datastores/version.json b/modules/Microsoft.AVS/privateClouds/clusters/datastores/version.json new file mode 100644 index 0000000000..41f66cc990 --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/clusters/datastores/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/modules/Microsoft.AVS/privateClouds/clusters/deploy.bicep b/modules/Microsoft.AVS/privateClouds/clusters/deploy.bicep new file mode 100644 index 0000000000..8166f21125 --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/clusters/deploy.bicep @@ -0,0 +1,95 @@ +// ============== // +// Parameters // +// ============== // + +@description('Required. Name of the cluster in the private cloud') +param name string + +@description('Required. The resource model definition representing SKU') +param sku object + +@description('Conditional. The name of the parent privateClouds. Required if the template is used in a standalone deployment.') +param privateCloudName string + +@description('Optional. The cluster size') +param clusterSize int = + +@description('Optional. The datastores to create as part of the cluster.') +param datastores array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The hosts') +param hosts array = [] + +@description('Optional. The placementPolicies to create as part of the cluster.') +param placementPolicies array = [] + +// ============= // +// Variables // +// ============= // + +var enableReferencedModulesTelemetry = false + + +// =============== // +// Deployments // +// =============== // + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { + name: privateCloudName +} + +resource cluster 'Microsoft.AVS/privateClouds/clusters@2022-05-01' = { + parent: privateCloud + name: name + sku: sku + properties: { + clusterSize: clusterSize + hosts: hosts + } +} + +module cluster_datastores 'datastores/deploy.bicep' = [for (datastore, index) in datastores: { + name: '${uniqueString(deployment().name, location)}-cluster-datastore-${index}' + params: { + privateCloudName: privateCloudName + clusterName: name + enableDefaultTelemetry: enableReferencedModulesTelemetry + } +}] + +module cluster_placementPolicies 'placementPolicies/deploy.bicep' = [for (placementPolicy, index) in placementPolicies: { + name: '${uniqueString(deployment().name, location)}-cluster-placementPolicy-${index}' + params: { + privateCloudName: privateCloudName + clusterName: name + enableDefaultTelemetry: enableReferencedModulesTelemetry + } +}] + +// =========== // +// Outputs // +// =========== // + +@description('The name of the cluster.') +output name string = cluster.name + +@description('The resource ID of the cluster.') +output resourceId string = cluster.id + +@description('The name of the resource group the cluster was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.AVS/privateClouds/clusters/placementPolicies/deploy.bicep b/modules/Microsoft.AVS/privateClouds/clusters/placementPolicies/deploy.bicep new file mode 100644 index 0000000000..bb78b7de40 --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/clusters/placementPolicies/deploy.bicep @@ -0,0 +1,103 @@ +// ============== // +// Parameters // +// ============== // + +@description('Required. Name of the VMware vSphere Distributed Resource Scheduler (DRS) placement policy') +param name string + +@description('Conditional. The name of the parent clusters. Required if the template is used in a standalone deployment.') +param clusterName string + +@description('Conditional. The name of the parent privateClouds. Required if the template is used in a standalone deployment.') +param privateCloudName string + +@description('Optional. VM-Host placement policy affinity strength (should/must)') +@allowed([ + 'Should' + 'Must' +]) +param affinityStrength string = '' + +@description('Optional. Placement policy hosts opt-in Azure Hybrid Benefit type') +@allowed([ + 'SqlHost' + 'None' +]) +param azureHybridBenefitType string = '' + +@description('Optional. Display name of the placement policy') +param displayName string = '' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Host members list') +param hostMembers array = [] + +@description('Optional. Whether the placement policy is enabled or disabled') +@allowed([ + 'Enabled' + 'Disabled' +]) +param state string = '' + +@description('Optional. placement policy type') +@allowed([ + 'VmVm' + 'VmHost' +]) +param type string = '' + +@description('Optional. Virtual machine members list') +param vmMembers array = [] + +// =============== // +// Deployments // +// =============== // + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { + name: privateCloudName + + resource cluster 'clusters@2022-05-01' existing = { + name: clusterName + } +} + +resource placementPolicy 'Microsoft.AVS/privateClouds/clusters/placementPolicies@2022-05-01' = { + parent: privateCloud::cluster + name: name + properties: { + affinityStrength: affinityStrength + azureHybridBenefitType: azureHybridBenefitType + displayName: displayName + hostMembers: hostMembers + state: state + type: type + vmMembers: vmMembers + } +} + +// =========== // +// Outputs // +// =========== // + +@description('The name of the placementPolicy.') +output name string = placementPolicy.name + +@description('The resource ID of the placementPolicy.') +output resourceId string = placementPolicy.id + +@description('The name of the resource group the placementPolicy was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.AVS/privateClouds/clusters/placementPolicies/version.json b/modules/Microsoft.AVS/privateClouds/clusters/placementPolicies/version.json new file mode 100644 index 0000000000..41f66cc990 --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/clusters/placementPolicies/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/modules/Microsoft.AVS/privateClouds/clusters/version.json b/modules/Microsoft.AVS/privateClouds/clusters/version.json new file mode 100644 index 0000000000..41f66cc990 --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/clusters/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/modules/Microsoft.AVS/privateClouds/deploy.bicep b/modules/Microsoft.AVS/privateClouds/deploy.bicep new file mode 100644 index 0000000000..624e35ac0e --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/deploy.bicep @@ -0,0 +1,372 @@ +// ============== // +// Parameters // +// ============== // + +@description('Required. Name of the private cloud') +param name string + +@description('Required. The resource model definition representing SKU') +param sku object + +@description('Optional. The addons to create as part of the privateCloud.') +param addons array = [] + +@description('Optional. The authorizations to create as part of the privateCloud.') +param authorizations array = [] + +@description('Optional. The properties describing private cloud availability zone distribution') +param availability object = {} + +@description('Optional. An ExpressRoute Circuit') +param circuit object = {} + +@description('Optional. The cloudLinks to create as part of the privateCloud.') +param cloudLinks array = [] + +@description('Optional. The clusters to create as part of the privateCloud.') +param clusters array = [] + +@description('Optional. The dhcpConfigurations to create as part of the privateCloud.') +param dhcpConfigurations array = [] + +@description('Optional. Resource ID of the diagnostic event hub authorization rule for the Event Hubs namespace in which the event hub should be created or streamed to.') +param diagnosticEventHubAuthorizationRuleId string = '' + +@description('Optional. Name of the diagnostic event hub within the namespace to which logs are streamed. Without this, an event hub is created for each log category. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub.') +param diagnosticEventHubName string = '' + +@description('Optional. The name of logs that will be streamed.') +@allowed([ + 'CapacityLatest' + 'DiskUsedPercentage' + 'EffectiveCpuAverage' + 'EffectiveMemAverage' + 'OverheadAverage' + 'TotalMbAverage' + 'UsageAverage' + 'UsedLatest' +]) +param diagnosticLogCategoriesToEnable array = [ + 'CapacityLatest' + 'DiskUsedPercentage' + 'EffectiveCpuAverage' + 'EffectiveMemAverage' + 'OverheadAverage' + 'TotalMbAverage' + 'UsageAverage' + 'UsedLatest' +] + +@description('Optional. Specifies the number of days that logs will be kept for; a value of 0 will retain data indefinitely.') +param diagnosticLogsRetentionInDays int = 365 + +@description('Optional. The name of metrics that will be streamed.') +@allowed([ + 'AllMetrics' +]) +param diagnosticMetricsToEnable array = [ + 'AllMetrics' +] + +@description('Optional. The name of the diagnostic setting, if deployed.') +param diagnosticSettingsName string = '${name}-diagnosticSettings' + +@description('Optional. Resource ID of the diagnostic storage account. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub.') +param diagnosticStorageAccountId string = '' + +@description('Optional. Resource ID of the diagnostic log analytics workspace. For security reasons, it is recommended to set diagnostic settings to send data to either storage account, log analytics workspace or event hub.') +param diagnosticWorkspaceId string = '' + +@description('Optional. The dnsServices to create as part of the privateCloud.') +param dnsServices array = [] + +@description('Optional. The dnsZones to create as part of the privateCloud.') +param dnsZones array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The properties of customer managed encryption key') +param encryption object = {} + +@description('Optional. The globalReachConnections to create as part of the privateCloud.') +param globalReachConnections array = [] + +@description('Optional. The hcxEnterpriseSites to create as part of the privateCloud.') +param hcxEnterpriseSites array = [] + +@description('Optional. Identity for the virtual machine.') +param identity object = {} + +@description('Optional. vCenter Single Sign On Identity Sources') +param identitySources array = [] + +@description('Optional. Connectivity to internet is enabled or disabled') +@allowed([ + 'Enabled' + 'Disabled' +]) +param internet string = 'Disabled' + +@description('Optional. Location for all Resources.') +param location string = resourceGroup().location + +@description('Optional. Specify the type of lock.') +@allowed([ + '' + 'CanNotDelete' + 'ReadOnly' +]) +param lock string = '' + +@description('Optional. The properties of a management cluster') +param managementCluster object = {} + +@description('Optional. The block of addresses should be unique across VNet in your subscription as well as on-premise. Make sure the CIDR format is conformed to (A.B.C.D/X) where A,B,C,D are between 0 and 255, and X is between 0 and 22') +param networkBlock string = '' + +@description('Optional. Optionally, set the NSX-T Manager password when the private cloud is created') +@secure() +param nsxtPassword string = '' + +@description('Optional. The portMirroringProfiles to create as part of the privateCloud.') +param portMirroringProfiles array = [] + +@description('Optional. The publicIPs to create as part of the privateCloud.') +param publicIPs array = [] + +@description('Optional. The scriptExecutions to create as part of the privateCloud.') +param scriptExecutions array = [] + +@description('Optional. An ExpressRoute Circuit') +param secondaryCircuit object = {} + +@description('Optional. The segments to create as part of the privateCloud.') +param segments array = [] + +@description('Optional. Resource tags') +param tags object = {} + +@description('Optional. Optionally, set the vCenter admin password when the private cloud is created') +@secure() +param vcenterPassword string = '' + +@description('Optional. The vmGroups to create as part of the privateCloud.') +param vmGroups array = [] + +// ============= // +// Variables // +// ============= // + +var diagnosticsMetrics = [for metric in diagnosticMetricsToEnable: { + category: metric + timeGrain: null + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { + category: category + enabled: true + retentionPolicy: { + enabled: true + days: diagnosticLogsRetentionInDays + } +}] + +var enableReferencedModulesTelemetry = false + + +// =============== // +// Deployments // +// =============== // + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + + +resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' = { + identity: identity + location: location + name: name + sku: sku + tags: tags + properties: { + availability: availability + circuit: circuit + encryption: encryption + identitySources: identitySources + internet: internet + managementCluster: managementCluster + networkBlock: networkBlock + nsxtPassword: nsxtPassword + secondaryCircuit: secondaryCircuit + vcenterPassword: vcenterPassword + } +} + +resource privateCloud_diagnosticSettings 'Microsoft.Insights/diagnosticsettings@2021-05-01-preview' = if ((!empty(diagnosticStorageAccountId)) || (!empty(diagnosticWorkspaceId)) || (!empty(diagnosticEventHubAuthorizationRuleId)) || (!empty(diagnosticEventHubName))) { + name: diagnosticSettingsName + properties: { + storageAccountId: !empty(diagnosticStorageAccountId) ? diagnosticStorageAccountId : null + workspaceId: !empty(diagnosticWorkspaceId) ? diagnosticWorkspaceId : null + eventHubAuthorizationRuleId: !empty(diagnosticEventHubAuthorizationRuleId) ? diagnosticEventHubAuthorizationRuleId : null + eventHubName: !empty(diagnosticEventHubName) ? diagnosticEventHubName : null + metrics: diagnosticsMetrics + logs: diagnosticsLogs + } + scope: privateCloud +} + +resource privateCloud_lock 'Microsoft.Authorization/locks@2017-04-01' = if (!empty(lock)) { + name: '${privateCloud.name}-${lock}-lock' + properties: { + level: any(lock) + notes: lock == 'CanNotDelete' ? 'Cannot delete resource or child resources.' : 'Cannot modify the resource or child resources.' + } + scope: privateCloud +} + +module privateCloud_cloudLinks 'cloudLinks/deploy.bicep' = [for (cloudLink, index) in cloudLinks: { + name: '${uniqueString(deployment().name, location)}-privateCloud-cloudLink-${index}' + params: { + privateCloudName: name + enableDefaultTelemetry: enableReferencedModulesTelemetry + } +}] + +module privateCloud_hcxEnterpriseSites 'hcxEnterpriseSites/deploy.bicep' = [for (hcxEnterpriseSite, index) in hcxEnterpriseSites: { + name: '${uniqueString(deployment().name, location)}-privateCloud-hcxEnterpriseSite-${index}' + params: { + privateCloudName: name + enableDefaultTelemetry: enableReferencedModulesTelemetry + } +}] + +module privateCloud_authorizations 'authorizations/deploy.bicep' = [for (authorization, index) in authorizations: { + name: '${uniqueString(deployment().name, location)}-privateCloud-authorization-${index}' + params: { + privateCloudName: name + enableDefaultTelemetry: enableReferencedModulesTelemetry + } +}] + +module privateCloud_scriptExecutions 'scriptExecutions/deploy.bicep' = [for (scriptExecution, index) in scriptExecutions: { + name: '${uniqueString(deployment().name, location)}-privateCloud-scriptExecution-${index}' + params: { + privateCloudName: name + enableDefaultTelemetry: enableReferencedModulesTelemetry + } +}] + +module privateCloud_globalReachConnections 'globalReachConnections/deploy.bicep' = [for (globalReachConnection, index) in globalReachConnections: { + name: '${uniqueString(deployment().name, location)}-privateCloud-globalReachConnection-${index}' + params: { + privateCloudName: name + enableDefaultTelemetry: enableReferencedModulesTelemetry + } +}] + +module privateCloud_addons 'addons/deploy.bicep' = [for (addon, index) in addons: { + name: '${uniqueString(deployment().name, location)}-privateCloud-addon-${index}' + params: { + privateCloudName: name + enableDefaultTelemetry: enableReferencedModulesTelemetry + } +}] + +module privateCloud_clusters 'clusters/deploy.bicep' = [for (cluster, index) in clusters: { + name: '${uniqueString(deployment().name, location)}-privateCloud-cluster-${index}' + params: { + privateCloudName: name + enableDefaultTelemetry: enableReferencedModulesTelemetry + } +}] + +module workloadNetworks_privateCloud_dhcpConfigurations 'workloadNetworks/dhcpConfigurations/deploy.bicep' = [for (dhcpConfiguration, index) in dhcpConfigurations: { + name: '${uniqueString(deployment().name, location)}-privateCloud-dhcpConfiguration-${index}' + params: { + privateCloudName: name + workloadNetworkName: 'default' + enableDefaultTelemetry: enableReferencedModulesTelemetry + } +}] + +module workloadNetworks_privateCloud_portMirroringProfiles 'workloadNetworks/portMirroringProfiles/deploy.bicep' = [for (portMirroringProfile, index) in portMirroringProfiles: { + name: '${uniqueString(deployment().name, location)}-privateCloud-portMirroringProfile-${index}' + params: { + privateCloudName: name + workloadNetworkName: 'default' + enableDefaultTelemetry: enableReferencedModulesTelemetry + } +}] + +module workloadNetworks_privateCloud_dnsZones 'workloadNetworks/dnsZones/deploy.bicep' = [for (dnsZone, index) in dnsZones: { + name: '${uniqueString(deployment().name, location)}-privateCloud-dnsZone-${index}' + params: { + privateCloudName: name + workloadNetworkName: 'default' + enableDefaultTelemetry: enableReferencedModulesTelemetry + } +}] + +module workloadNetworks_privateCloud_publicIPs 'workloadNetworks/publicIPs/deploy.bicep' = [for (publicIP, index) in publicIPs: { + name: '${uniqueString(deployment().name, location)}-privateCloud-publicIP-${index}' + params: { + privateCloudName: name + workloadNetworkName: 'default' + enableDefaultTelemetry: enableReferencedModulesTelemetry + } +}] + +module workloadNetworks_privateCloud_dnsServices 'workloadNetworks/dnsServices/deploy.bicep' = [for (dnsService, index) in dnsServices: { + name: '${uniqueString(deployment().name, location)}-privateCloud-dnsService-${index}' + params: { + privateCloudName: name + workloadNetworkName: 'default' + enableDefaultTelemetry: enableReferencedModulesTelemetry + } +}] + +module workloadNetworks_privateCloud_vmGroups 'workloadNetworks/vmGroups/deploy.bicep' = [for (vmGroup, index) in vmGroups: { + name: '${uniqueString(deployment().name, location)}-privateCloud-vmGroup-${index}' + params: { + privateCloudName: name + workloadNetworkName: 'default' + enableDefaultTelemetry: enableReferencedModulesTelemetry + } +}] + +module workloadNetworks_privateCloud_segments 'workloadNetworks/segments/deploy.bicep' = [for (segment, index) in segments: { + name: '${uniqueString(deployment().name, location)}-privateCloud-segment-${index}' + params: { + privateCloudName: name + workloadNetworkName: 'default' + enableDefaultTelemetry: enableReferencedModulesTelemetry + } +}] + +// =========== // +// Outputs // +// =========== // + +@description('The name of the privateCloud.') +output name string = privateCloud.name + +@description('The resource ID of the privateCloud.') +output resourceId string = privateCloud.id + +@description('The name of the resource group the privateCloud was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.AVS/privateClouds/globalReachConnections/deploy.bicep b/modules/Microsoft.AVS/privateClouds/globalReachConnections/deploy.bicep new file mode 100644 index 0000000000..bd98d9ca91 --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/globalReachConnections/deploy.bicep @@ -0,0 +1,64 @@ +// ============== // +// Parameters // +// ============== // + +@description('Required. Name of the global reach connection in the private cloud') +param name string + +@description('Conditional. The name of the parent privateClouds. Required if the template is used in a standalone deployment.') +param privateCloudName string + +@description('Optional. Authorization key from the peer express route used for the global reach connection') +param authorizationKey string = '' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. The ID of the Private Cloud\'s ExpressRoute Circuit that is participating in the global reach connection') +param expressRouteId string = '' + +@description('Optional. Identifier of the ExpressRoute Circuit to peer with in the global reach connection') +param peerExpressRouteCircuit string = '' + +// =============== // +// Deployments // +// =============== // + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { + name: privateCloudName +} + +resource globalReachConnection 'Microsoft.AVS/privateClouds/globalReachConnections@2022-05-01' = { + parent: privateCloud + name: name + properties: { + authorizationKey: authorizationKey + expressRouteId: expressRouteId + peerExpressRouteCircuit: peerExpressRouteCircuit + } +} + +// =========== // +// Outputs // +// =========== // + +@description('The name of the globalReachConnection.') +output name string = globalReachConnection.name + +@description('The resource ID of the globalReachConnection.') +output resourceId string = globalReachConnection.id + +@description('The name of the resource group the globalReachConnection was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.AVS/privateClouds/globalReachConnections/readme.md b/modules/Microsoft.AVS/privateClouds/globalReachConnections/readme.md new file mode 100644 index 0000000000..3da1c7294f --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/globalReachConnections/readme.md @@ -0,0 +1,57 @@ +# AVS PrivateClouds GlobalReachConnections `[Microsoft.AVS/privateClouds/globalReachConnections]` + +This module deploys AVS PrivateClouds GlobalReachConnections. +// TODO: Replace Resource and fill in description + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.AVS/privateClouds/globalReachConnections` | [2022-05-01](https://docs.microsoft.com/en-us/azure/templates/Microsoft.AVS/privateClouds/globalReachConnections) | + +## Parameters + +**Required parameters** + +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the global reach connection in the private cloud | + +**Conditional parameters** + +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `privateCloudName` | string | The name of the parent privateClouds. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `authorizationKey` | string | `''` | Authorization key from the peer express route used for the global reach connection | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `expressRouteId` | string | `''` | The ID of the Private Cloud's ExpressRoute Circuit that is participating in the global reach connection | +| `peerExpressRouteCircuit` | string | `''` | Identifier of the ExpressRoute Circuit to peer with in the global reach connection | + + +### Parameter Usage: `` + +// TODO: Fill in Parameter usage + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the globalReachConnection. | +| `resourceGroupName` | string | The name of the resource group the globalReachConnection was created in. | +| `resourceId` | string | The resource ID of the globalReachConnection. | + +## Cross-referenced modules + +_None_ diff --git a/modules/Microsoft.AVS/privateClouds/globalReachConnections/version.json b/modules/Microsoft.AVS/privateClouds/globalReachConnections/version.json new file mode 100644 index 0000000000..41f66cc990 --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/globalReachConnections/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/modules/Microsoft.AVS/privateClouds/hcxEnterpriseSites/deploy.bicep b/modules/Microsoft.AVS/privateClouds/hcxEnterpriseSites/deploy.bicep new file mode 100644 index 0000000000..f7206b8c05 --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/hcxEnterpriseSites/deploy.bicep @@ -0,0 +1,52 @@ +// ============== // +// Parameters // +// ============== // + +@description('Required. Name of the HCX Enterprise Site in the private cloud') +param name string + +@description('Conditional. The name of the parent privateClouds. Required if the template is used in a standalone deployment.') +param privateCloudName string + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +// =============== // +// Deployments // +// =============== // + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { + name: privateCloudName +} + +resource hcxEnterpriseSite 'Microsoft.AVS/privateClouds/hcxEnterpriseSites@2022-05-01' = { + parent: privateCloud + name: name + properties: { + } +} + +// =========== // +// Outputs // +// =========== // + +@description('The name of the hcxEnterpriseSite.') +output name string = hcxEnterpriseSite.name + +@description('The resource ID of the hcxEnterpriseSite.') +output resourceId string = hcxEnterpriseSite.id + +@description('The name of the resource group the hcxEnterpriseSite was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.AVS/privateClouds/hcxEnterpriseSites/readme.md b/modules/Microsoft.AVS/privateClouds/hcxEnterpriseSites/readme.md new file mode 100644 index 0000000000..7a0a111fdf --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/hcxEnterpriseSites/readme.md @@ -0,0 +1,54 @@ +# AVS PrivateClouds HcxEnterpriseSites `[Microsoft.AVS/privateClouds/hcxEnterpriseSites]` + +This module deploys AVS PrivateClouds HcxEnterpriseSites. +// TODO: Replace Resource and fill in description + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.AVS/privateClouds/hcxEnterpriseSites` | [2022-05-01](https://docs.microsoft.com/en-us/azure/templates/Microsoft.AVS/privateClouds/hcxEnterpriseSites) | + +## Parameters + +**Required parameters** + +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the HCX Enterprise Site in the private cloud | + +**Conditional parameters** + +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `privateCloudName` | string | The name of the parent privateClouds. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | + + +### Parameter Usage: `` + +// TODO: Fill in Parameter usage + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the hcxEnterpriseSite. | +| `resourceGroupName` | string | The name of the resource group the hcxEnterpriseSite was created in. | +| `resourceId` | string | The resource ID of the hcxEnterpriseSite. | + +## Cross-referenced modules + +_None_ diff --git a/modules/Microsoft.AVS/privateClouds/hcxEnterpriseSites/version.json b/modules/Microsoft.AVS/privateClouds/hcxEnterpriseSites/version.json new file mode 100644 index 0000000000..41f66cc990 --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/hcxEnterpriseSites/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/modules/Microsoft.AVS/privateClouds/scriptExecutions/deploy.bicep b/modules/Microsoft.AVS/privateClouds/scriptExecutions/deploy.bicep new file mode 100644 index 0000000000..5422b3033b --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/scriptExecutions/deploy.bicep @@ -0,0 +1,84 @@ +// ============== // +// Parameters // +// ============== // + +@description('Required. Name of the user-invoked script execution resource') +param name string + +@description('Conditional. The name of the parent privateClouds. Required if the template is used in a standalone deployment.') +param privateCloudName string + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Error message if the script was able to run, but if the script itself had errors or powershell threw an exception') +param failureReason string = '' + +@description('Optional. Parameters that will be hidden/not visible to ARM, such as passwords and credentials') +param hiddenParameters array = [] + +@description('Optional. User-defined dictionary.') +param namedOutputs object = {} + +@description('Optional. Standard output stream from the powershell execution') +param output array = [] + +@description('Optional. Parameters the script will accept') +param parameters array = [] + +@description('Optional. Time to live for the resource. If not provided, will be available for 60 days') +param retention string = '' + +@description('Optional. A reference to the script cmdlet resource if user is running a AVS script') +param scriptCmdletId string = '' + +@description('Optional. Time limit for execution') +param timeout string = '' + +// =============== // +// Deployments // +// =============== // + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { + name: privateCloudName +} + +resource scriptExecution 'Microsoft.AVS/privateClouds/scriptExecutions@2022-05-01' = { + parent: privateCloud + name: name + properties: { + failureReason: failureReason + hiddenParameters: hiddenParameters + namedOutputs: namedOutputs + output: output + parameters: parameters + retention: retention + scriptCmdletId: scriptCmdletId + timeout: timeout + } +} + +// =========== // +// Outputs // +// =========== // + +@description('The name of the scriptExecution.') +output name string = scriptExecution.name + +@description('The resource ID of the scriptExecution.') +output resourceId string = scriptExecution.id + +@description('The name of the resource group the scriptExecution was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.AVS/privateClouds/scriptExecutions/readme.md b/modules/Microsoft.AVS/privateClouds/scriptExecutions/readme.md new file mode 100644 index 0000000000..50ea7501f0 --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/scriptExecutions/readme.md @@ -0,0 +1,62 @@ +# AVS PrivateClouds ScriptExecutions `[Microsoft.AVS/privateClouds/scriptExecutions]` + +This module deploys AVS PrivateClouds ScriptExecutions. +// TODO: Replace Resource and fill in description + +## Navigation + +- [Resource Types](#Resource-Types) +- [Parameters](#Parameters) +- [Outputs](#Outputs) +- [Cross-referenced modules](#Cross-referenced-modules) + +## Resource Types + +| Resource Type | API Version | +| :-- | :-- | +| `Microsoft.AVS/privateClouds/scriptExecutions` | [2022-05-01](https://docs.microsoft.com/en-us/azure/templates/Microsoft.AVS/privateClouds/scriptExecutions) | + +## Parameters + +**Required parameters** + +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | Name of the user-invoked script execution resource | + +**Conditional parameters** + +| Parameter Name | Type | Description | +| :-- | :-- | :-- | +| `privateCloudName` | string | The name of the parent privateClouds. Required if the template is used in a standalone deployment. | + +**Optional parameters** + +| Parameter Name | Type | Default Value | Description | +| :-- | :-- | :-- | :-- | +| `enableDefaultTelemetry` | bool | `True` | Enable telemetry via the Customer Usage Attribution ID (GUID). | +| `failureReason` | string | `''` | Error message if the script was able to run, but if the script itself had errors or powershell threw an exception | +| `hiddenParameters` | array | `[]` | Parameters that will be hidden/not visible to ARM, such as passwords and credentials | +| `namedOutputs` | object | `{object}` | User-defined dictionary. | +| `output` | array | `[]` | Standard output stream from the powershell execution | +| `parameters` | array | `[]` | Parameters the script will accept | +| `retention` | string | `''` | Time to live for the resource. If not provided, will be available for 60 days | +| `scriptCmdletId` | string | `''` | A reference to the script cmdlet resource if user is running a AVS script | +| `timeout` | string | `''` | Time limit for execution | + + +### Parameter Usage: `` + +// TODO: Fill in Parameter usage + +## Outputs + +| Output Name | Type | Description | +| :-- | :-- | :-- | +| `name` | string | The name of the scriptExecution. | +| `resourceGroupName` | string | The name of the resource group the scriptExecution was created in. | +| `resourceId` | string | The resource ID of the scriptExecution. | + +## Cross-referenced modules + +_None_ diff --git a/modules/Microsoft.AVS/privateClouds/scriptExecutions/version.json b/modules/Microsoft.AVS/privateClouds/scriptExecutions/version.json new file mode 100644 index 0000000000..41f66cc990 --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/scriptExecutions/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/modules/Microsoft.AVS/privateClouds/version.json b/modules/Microsoft.AVS/privateClouds/version.json new file mode 100644 index 0000000000..41f66cc990 --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dhcpConfigurations/deploy.bicep b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dhcpConfigurations/deploy.bicep new file mode 100644 index 0000000000..39ec347746 --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dhcpConfigurations/deploy.bicep @@ -0,0 +1,75 @@ +// ============== // +// Parameters // +// ============== // + +@description('Required. NSX DHCP identifier. Generally the same as the DHCP display name') +param name string + +@description('Conditional. The name of the parent privateClouds. Required if the template is used in a standalone deployment.') +param privateCloudName string + +@description('Optional. Type of DHCP: SERVER or RELAY.') +@allowed([ + 'SERVER' + 'RELAY' +]) +param dhcpType string = '' + +@description('Optional. Display name of the DHCP entity.') +param displayName string = '' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. NSX revision number.') +param revision int = + +@description('Optional. The name of the parent workloadNetworks. Required if the template is used in a standalone deployment.') +param workloadNetworkName string = 'default' + +// =============== // +// Deployments // +// =============== // + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { + name: privateCloudName + + resource workloadNetwork 'workloadNetworks@2022-05-01' existing = { + name: workloadNetworkName + } +} + +resource dhcpConfiguration 'Microsoft.AVS/privateClouds/workloadNetworks/dhcpConfigurations@2022-05-01' = { + parent: privateCloud::workloadNetwork + name: name + properties: { + dhcpType: dhcpType + displayName: displayName + revision: revision + } +} + +// =========== // +// Outputs // +// =========== // + +@description('The name of the dhcpConfiguration.') +output name string = dhcpConfiguration.name + +@description('The resource ID of the dhcpConfiguration.') +output resourceId string = dhcpConfiguration.id + +@description('The name of the resource group the dhcpConfiguration was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dhcpConfigurations/version.json b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dhcpConfigurations/version.json new file mode 100644 index 0000000000..41f66cc990 --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dhcpConfigurations/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsServices/deploy.bicep b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsServices/deploy.bicep new file mode 100644 index 0000000000..1364785293 --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsServices/deploy.bicep @@ -0,0 +1,90 @@ +// ============== // +// Parameters // +// ============== // + +@description('Required. NSX DNS Service identifier. Generally the same as the DNS Service\'s display name') +param name string + +@description('Conditional. The name of the parent privateClouds. Required if the template is used in a standalone deployment.') +param privateCloudName string + +@description('Optional. Default DNS zone of the DNS Service.') +param defaultDnsZone string = '' + +@description('Optional. Display name of the DNS Service.') +param displayName string = '' + +@description('Optional. DNS service IP of the DNS Service.') +param dnsServiceIp string = '' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. FQDN zones of the DNS Service.') +param fqdnZones array = [] + +@description('Optional. DNS Service log level.') +@allowed([ + 'DEBUG' + 'INFO' + 'WARNING' + 'ERROR' + 'FATAL' +]) +param logLevel string = '' + +@description('Optional. NSX revision number.') +param revision int = + +@description('Optional. The name of the parent workloadNetworks. Required if the template is used in a standalone deployment.') +param workloadNetworkName string = 'default' + +// =============== // +// Deployments // +// =============== // + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { + name: privateCloudName + + resource workloadNetwork 'workloadNetworks@2022-05-01' existing = { + name: workloadNetworkName + } +} + +resource dnsService 'Microsoft.AVS/privateClouds/workloadNetworks/dnsServices@2022-05-01' = { + parent: privateCloud::workloadNetwork + name: name + properties: { + defaultDnsZone: defaultDnsZone + displayName: displayName + dnsServiceIp: dnsServiceIp + fqdnZones: fqdnZones + logLevel: logLevel + revision: revision + } +} + +// =========== // +// Outputs // +// =========== // + +@description('The name of the dnsService.') +output name string = dnsService.name + +@description('The resource ID of the dnsService.') +output resourceId string = dnsService.id + +@description('The name of the resource group the dnsService was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsServices/version.json b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsServices/version.json new file mode 100644 index 0000000000..41f66cc990 --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsServices/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsZones/deploy.bicep b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsZones/deploy.bicep new file mode 100644 index 0000000000..6e610bb3e9 --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsZones/deploy.bicep @@ -0,0 +1,83 @@ +// ============== // +// Parameters // +// ============== // + +@description('Required. NSX DNS Zone identifier. Generally the same as the DNS Zone\'s display name') +param name string + +@description('Conditional. The name of the parent privateClouds. Required if the template is used in a standalone deployment.') +param privateCloudName string + +@description('Optional. Display name of the DNS Zone.') +param displayName string = '' + +@description('Optional. DNS Server IP array of the DNS Zone.') +param dnsServerIps array = [] + +@description('Optional. Number of DNS Services using the DNS zone.') +param dnsServices int = + +@description('Optional. Domain names of the DNS Zone.') +param domain array = [] + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. NSX revision number.') +param revision int = + +@description('Optional. Source IP of the DNS Zone.') +param sourceIp string = '' + +@description('Optional. The name of the parent workloadNetworks. Required if the template is used in a standalone deployment.') +param workloadNetworkName string = 'default' + +// =============== // +// Deployments // +// =============== // + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { + name: privateCloudName + + resource workloadNetwork 'workloadNetworks@2022-05-01' existing = { + name: workloadNetworkName + } +} + +resource dnsZone 'Microsoft.AVS/privateClouds/workloadNetworks/dnsZones@2022-05-01' = { + parent: privateCloud::workloadNetwork + name: name + properties: { + displayName: displayName + dnsServerIps: dnsServerIps + dnsServices: dnsServices + domain: domain + revision: revision + sourceIp: sourceIp + } +} + +// =========== // +// Outputs // +// =========== // + +@description('The name of the dnsZone.') +output name string = dnsZone.name + +@description('The resource ID of the dnsZone.') +output resourceId string = dnsZone.id + +@description('The name of the resource group the dnsZone was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsZones/version.json b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsZones/version.json new file mode 100644 index 0000000000..41f66cc990 --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/workloadNetworks/dnsZones/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/portMirroringProfiles/deploy.bicep b/modules/Microsoft.AVS/privateClouds/workloadNetworks/portMirroringProfiles/deploy.bicep new file mode 100644 index 0000000000..5eb37963af --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/workloadNetworks/portMirroringProfiles/deploy.bicep @@ -0,0 +1,84 @@ +// ============== // +// Parameters // +// ============== // + +@description('Required. NSX Port Mirroring identifier. Generally the same as the Port Mirroring display name') +param name string + +@description('Conditional. The name of the parent privateClouds. Required if the template is used in a standalone deployment.') +param privateCloudName string + +@description('Optional. Destination VM Group.') +param destination string = '' + +@description('Optional. Direction of port mirroring profile.') +@allowed([ + 'INGRESS' + 'EGRESS' + 'BIDIRECTIONAL' +]) +param direction string = '' + +@description('Optional. Display name of the port mirroring profile.') +param displayName string = '' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. NSX revision number.') +param revision int = + +@description('Optional. Source VM Group.') +param source string = '' + +@description('Optional. The name of the parent workloadNetworks. Required if the template is used in a standalone deployment.') +param workloadNetworkName string = 'default' + +// =============== // +// Deployments // +// =============== // + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { + name: privateCloudName + + resource workloadNetwork 'workloadNetworks@2022-05-01' existing = { + name: workloadNetworkName + } +} + +resource portMirroringProfile 'Microsoft.AVS/privateClouds/workloadNetworks/portMirroringProfiles@2022-05-01' = { + parent: privateCloud::workloadNetwork + name: name + properties: { + destination: destination + direction: direction + displayName: displayName + revision: revision + source: source + } +} + +// =========== // +// Outputs // +// =========== // + +@description('The name of the portMirroringProfile.') +output name string = portMirroringProfile.name + +@description('The resource ID of the portMirroringProfile.') +output resourceId string = portMirroringProfile.id + +@description('The name of the resource group the portMirroringProfile was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/portMirroringProfiles/version.json b/modules/Microsoft.AVS/privateClouds/workloadNetworks/portMirroringProfiles/version.json new file mode 100644 index 0000000000..41f66cc990 --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/workloadNetworks/portMirroringProfiles/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/publicIPs/deploy.bicep b/modules/Microsoft.AVS/privateClouds/workloadNetworks/publicIPs/deploy.bicep new file mode 100644 index 0000000000..f424a34ab5 --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/workloadNetworks/publicIPs/deploy.bicep @@ -0,0 +1,67 @@ +// ============== // +// Parameters // +// ============== // + +@description('Required. NSX Public IP Block identifier. Generally the same as the Public IP Block\'s display name') +param name string + +@description('Conditional. The name of the parent privateClouds. Required if the template is used in a standalone deployment.') +param privateCloudName string + +@description('Optional. Display name of the Public IP Block.') +param displayName string = '' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Number of Public IPs requested.') +param numberOfPublicIPs int = + +@description('Optional. The name of the parent workloadNetworks. Required if the template is used in a standalone deployment.') +param workloadNetworkName string = 'default' + +// =============== // +// Deployments // +// =============== // + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { + name: privateCloudName + + resource workloadNetwork 'workloadNetworks@2022-05-01' existing = { + name: workloadNetworkName + } +} + +resource publicIP 'Microsoft.AVS/privateClouds/workloadNetworks/publicIPs@2022-05-01' = { + parent: privateCloud::workloadNetwork + name: name + properties: { + displayName: displayName + numberOfPublicIPs: numberOfPublicIPs + } +} + +// =========== // +// Outputs // +// =========== // + +@description('The name of the publicIP.') +output name string = publicIP.name + +@description('The resource ID of the publicIP.') +output resourceId string = publicIP.id + +@description('The name of the resource group the publicIP was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/publicIPs/version.json b/modules/Microsoft.AVS/privateClouds/workloadNetworks/publicIPs/version.json new file mode 100644 index 0000000000..41f66cc990 --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/workloadNetworks/publicIPs/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/segments/deploy.bicep b/modules/Microsoft.AVS/privateClouds/workloadNetworks/segments/deploy.bicep new file mode 100644 index 0000000000..ed80042d91 --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/workloadNetworks/segments/deploy.bicep @@ -0,0 +1,75 @@ +// ============== // +// Parameters // +// ============== // + +@description('Required. NSX Segment identifier. Generally the same as the Segment\'s display name') +param name string + +@description('Conditional. The name of the parent privateClouds. Required if the template is used in a standalone deployment.') +param privateCloudName string + +@description('Optional. Gateway which to connect segment to.') +param connectedGateway string = '' + +@description('Optional. Display name of the segment.') +param displayName string = '' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. NSX revision number.') +param revision int = + +@description('Optional. Subnet configuration for segment') +param subnet object = {} + +@description('Optional. The name of the parent workloadNetworks. Required if the template is used in a standalone deployment.') +param workloadNetworkName string = 'default' + +// =============== // +// Deployments // +// =============== // + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { + name: privateCloudName + + resource workloadNetwork 'workloadNetworks@2022-05-01' existing = { + name: workloadNetworkName + } +} + +resource segment 'Microsoft.AVS/privateClouds/workloadNetworks/segments@2022-05-01' = { + parent: privateCloud::workloadNetwork + name: name + properties: { + connectedGateway: connectedGateway + displayName: displayName + revision: revision + subnet: subnet + } +} + +// =========== // +// Outputs // +// =========== // + +@description('The name of the segment.') +output name string = segment.name + +@description('The resource ID of the segment.') +output resourceId string = segment.id + +@description('The name of the resource group the segment was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/segments/version.json b/modules/Microsoft.AVS/privateClouds/workloadNetworks/segments/version.json new file mode 100644 index 0000000000..41f66cc990 --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/workloadNetworks/segments/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/vmGroups/deploy.bicep b/modules/Microsoft.AVS/privateClouds/workloadNetworks/vmGroups/deploy.bicep new file mode 100644 index 0000000000..7efe5c6a16 --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/workloadNetworks/vmGroups/deploy.bicep @@ -0,0 +1,71 @@ +// ============== // +// Parameters // +// ============== // + +@description('Required. NSX VM Group identifier. Generally the same as the VM Group\'s display name') +param name string + +@description('Conditional. The name of the parent privateClouds. Required if the template is used in a standalone deployment.') +param privateCloudName string + +@description('Optional. Display name of the VM group.') +param displayName string = '' + +@description('Optional. Enable telemetry via the Customer Usage Attribution ID (GUID).') +param enableDefaultTelemetry bool = true + +@description('Optional. Virtual machine members of this group.') +param members array = [] + +@description('Optional. NSX revision number.') +param revision int = + +@description('Optional. The name of the parent workloadNetworks. Required if the template is used in a standalone deployment.') +param workloadNetworkName string = 'default' + +// =============== // +// Deployments // +// =============== // + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-47ed15a6-730a-4827-bcb4-0fd963ffbd82-${uniqueString(deployment().name)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} + +resource privateCloud 'Microsoft.AVS/privateClouds@2022-05-01' existing = { + name: privateCloudName + + resource workloadNetwork 'workloadNetworks@2022-05-01' existing = { + name: workloadNetworkName + } +} + +resource vmGroup 'Microsoft.AVS/privateClouds/workloadNetworks/vmGroups@2022-05-01' = { + parent: privateCloud::workloadNetwork + name: name + properties: { + displayName: displayName + members: members + revision: revision + } +} + +// =========== // +// Outputs // +// =========== // + +@description('The name of the vmGroup.') +output name string = vmGroup.name + +@description('The resource ID of the vmGroup.') +output resourceId string = vmGroup.id + +@description('The name of the resource group the vmGroup was created in.') +output resourceGroupName string = resourceGroup().name diff --git a/modules/Microsoft.AVS/privateClouds/workloadNetworks/vmGroups/version.json b/modules/Microsoft.AVS/privateClouds/workloadNetworks/vmGroups/version.json new file mode 100644 index 0000000000..41f66cc990 --- /dev/null +++ b/modules/Microsoft.AVS/privateClouds/workloadNetworks/vmGroups/version.json @@ -0,0 +1,4 @@ +{ + "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", + "version": "0.1" +} From d2280d807fabc079c1c91b3caffc7a741be6474f Mon Sep 17 00:00:00 2001 From: MrMCake Date: Sun, 6 Nov 2022 09:48:37 +0100 Subject: [PATCH 23/30] Improved idempotency --- .../modulePipelines/ms.avs.privateclouds.yml | 2 +- .github/workflows/ms.avs.privateclouds.yml | 2 +- .../privateClouds/clusters/deploy.bicep | 1 - modules/Microsoft.AVS/privateClouds/deploy.bicep | 1 - .../private/module/Get-TemplateResourcesContent.ps1 | 12 ++++++++---- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/.azuredevops/modulePipelines/ms.avs.privateclouds.yml b/.azuredevops/modulePipelines/ms.avs.privateclouds.yml index 4f3d86e218..9e3bec03f2 100644 --- a/.azuredevops/modulePipelines/ms.avs.privateclouds.yml +++ b/.azuredevops/modulePipelines/ms.avs.privateclouds.yml @@ -37,4 +37,4 @@ stages: - template: /.azuredevops/pipelineTemplates/stages.module.yml parameters: removeDeployment: '${{ parameters.removeDeployment }}' - prerelease: '${{ parameters.prerelease }}' \ No newline at end of file + prerelease: '${{ parameters.prerelease }}' diff --git a/.github/workflows/ms.avs.privateclouds.yml b/.github/workflows/ms.avs.privateclouds.yml index 0a5e19acbd..15e86296b0 100644 --- a/.github/workflows/ms.avs.privateclouds.yml +++ b/.github/workflows/ms.avs.privateclouds.yml @@ -142,4 +142,4 @@ jobs: bicepRegistryName: '${{ env.bicepRegistryName }}' bicepRegistryRGName: '${{ env.bicepRegistryRGName }}' bicepRegistryRgLocation: '${{ env.bicepRegistryRgLocation }}' - bicepRegistryDoPublish: '${{ env.bicepRegistryDoPublish }}' \ No newline at end of file + bicepRegistryDoPublish: '${{ env.bicepRegistryDoPublish }}' diff --git a/modules/Microsoft.AVS/privateClouds/clusters/deploy.bicep b/modules/Microsoft.AVS/privateClouds/clusters/deploy.bicep index 8166f21125..1df6ee7abb 100644 --- a/modules/Microsoft.AVS/privateClouds/clusters/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/clusters/deploy.bicep @@ -32,7 +32,6 @@ param placementPolicies array = [] var enableReferencedModulesTelemetry = false - // =============== // // Deployments // // =============== // diff --git a/modules/Microsoft.AVS/privateClouds/deploy.bicep b/modules/Microsoft.AVS/privateClouds/deploy.bicep index 624e35ac0e..086ea63e34 100644 --- a/modules/Microsoft.AVS/privateClouds/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/deploy.bicep @@ -179,7 +179,6 @@ var diagnosticsLogs = [for category in diagnosticLogCategoriesToEnable: { var enableReferencedModulesTelemetry = false - // =============== // // Deployments // // =============== // diff --git a/utilities/tools/REST2CARML/private/module/Get-TemplateResourcesContent.ps1 b/utilities/tools/REST2CARML/private/module/Get-TemplateResourcesContent.ps1 index b65dbfa5b9..843ee2ca23 100644 --- a/utilities/tools/REST2CARML/private/module/Get-TemplateResourcesContent.ps1 +++ b/utilities/tools/REST2CARML/private/module/Get-TemplateResourcesContent.ps1 @@ -42,7 +42,7 @@ $locationParameterExists = ($templateContent | Where-Object { $_ -like 'param location *' }).Count -gt 0 $matchingExistingResource = $existingTemplateContent.resources | Where-Object { - $_.resourceType -eq $FullResourceType -and $_.resourceName -eq $resourceTypeSingular + $_.type -eq $FullResourceType -and $_.name -eq $resourceTypeSingular } ######################## @@ -137,8 +137,12 @@ # If a template already exists, add 'extra' resources that are not yet part of the template content # ------------------------------------------------------------------------------------------------- + # Excluded are + # - Anything we generate anew as a resource + # - Telemetry (as it's regenerated above anyways) + # - Existing parent resources (as they are regenerated above anyways) $preExistingExtraResources = $existingTemplateContent.resources | Where-Object { - $_.resourceName -notIn ($ModuleData.resources.name + 'defaultTelemetry' + $resourceTypeSingular) + $_.name -notIn $ModuleData.resources.name + @('defaultTelemetry') + @($resourceTypeSingular) -and $_.content[0] -notlike '* existing = {' } foreach ($resource in $preExistingExtraResources) { $templateContent += $resource.content @@ -149,10 +153,10 @@ # -------------------------------------------------------------------- # Other collected resources foreach ($additionalResource in $ModuleData.resources) { - if ($existingTemplateContent.resources.resourceName -notcontains $additionalResource.name) { + if ($existingTemplateContent.resources.name -notcontains $additionalResource.name) { $templateContent += $additionalResource.content } else { - $existingResource = $existingTemplateContent.resources | Where-Object { $_.resourceName -eq $additionalResource.name } + $existingResource = $existingTemplateContent.resources | Where-Object { $_.name -eq $additionalResource.name } $templateContent += $existingResource.content $templateContent += '' } From 25c98807bbbf668fb77bf57a364c714076211811 Mon Sep 17 00:00:00 2001 From: MrMCake Date: Sun, 6 Nov 2022 10:55:12 +0100 Subject: [PATCH 24/30] Added docs --- .../module/Get-TemplateVariablesContent.ps1 | 51 ++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/utilities/tools/REST2CARML/private/module/Get-TemplateVariablesContent.ps1 b/utilities/tools/REST2CARML/private/module/Get-TemplateVariablesContent.ps1 index 0b892d9e46..475ac394e3 100644 --- a/utilities/tools/REST2CARML/private/module/Get-TemplateVariablesContent.ps1 +++ b/utilities/tools/REST2CARML/private/module/Get-TemplateVariablesContent.ps1 @@ -1,4 +1,53 @@ -function Get-TemplateVariablesContent { +<# +.SYNOPSIS +Get the formatted content for the template's 'variables' section + +.DESCRIPTION +Get the formatted content for the template's 'variables' section. 'Existing' template content taxes precedence over new variables. + +.PARAMETER ModuleData +Mandatory. The module data to fetch the data for this section from & then format it propertly for the template. + +Expects an array with objects like: +Name Value +---- ----- +parameters {name, identity, type, properties…} +outputs {} +additionalFiles {} +modules {} +variables {diagnosticsMetrics, diagnosticsLogs} +resources {privateCloud_diagnosticSettings, privateCloud_lock} +isSingleton False +additionalParameters {diagnosticLogsRetentionInDays, diagnosticStorageAccountId, diagnosticWorkspaceId, diagnosticEventHubAuthorizationRuleId…} + +.PARAMETER ExistingTemplateContent +Optional. The prepared content of an existing template, if any. + +Expects an array with objects like: + +Name Value +---- ----- +modules {privateCloud_cloudLinks, privateCloud_hcxEnterpriseSites, privateCloud_authorizations, privateCloud_scriptExecutions…} +variables {diagnosticsMetrics, diagnosticsLogs, enableReferencedModulesTelemetry} +parameters {name, sku, addons, authorizations…} +outputs {name, resourceId, resourceGroupName} +resources {defaultTelemetry, privateCloud, privateCloud_diagnosticSettings, privateCloud_lock} + +.EXAMPLE +Get-TemplateVariablesContent -ModuleData @(@{ variables = @(@{ name = 'abc'; content = @( var abc = (...)) }; (...))}, (...)) -ExistingTemplateContent @(@{ variables = @(@{ name = 'abc'; content = @( var abc = (...))}, (...))}, (...)) + +Generate the variables content for the above example containing at least the 'abc' variable. Would result in an output like + +```Bicep +// ============= // +// Variables // +// ============= // + +var abc = (...) +(...) +``` +#> +function Get-TemplateVariablesContent { [CmdletBinding()] param ( From d1c991b1a75f57a4ee485a0ddd6c09d7cc36043d Mon Sep 17 00:00:00 2001 From: MrMCake Date: Sun, 6 Nov 2022 11:21:42 +0100 Subject: [PATCH 25/30] Updated docs --- ...ps1 => Get-TemplateDeploymentsContent.ps1} | 99 ++++++++++++++++++- .../module/Get-TemplateVariablesContent.ps1 | 2 +- .../private/module/Set-ModuleTemplate.ps1 | 2 +- 3 files changed, 100 insertions(+), 3 deletions(-) rename utilities/tools/REST2CARML/private/module/{Get-TemplateResourcesContent.ps1 => Get-TemplateDeploymentsContent.ps1} (65%) diff --git a/utilities/tools/REST2CARML/private/module/Get-TemplateResourcesContent.ps1 b/utilities/tools/REST2CARML/private/module/Get-TemplateDeploymentsContent.ps1 similarity index 65% rename from utilities/tools/REST2CARML/private/module/Get-TemplateResourcesContent.ps1 rename to utilities/tools/REST2CARML/private/module/Get-TemplateDeploymentsContent.ps1 index 843ee2ca23..eb3be80867 100644 --- a/utilities/tools/REST2CARML/private/module/Get-TemplateResourcesContent.ps1 +++ b/utilities/tools/REST2CARML/private/module/Get-TemplateDeploymentsContent.ps1 @@ -1,4 +1,101 @@ -function Get-TemplateResourcesContent { +<# +.SYNOPSIS +Get the formatted content for the template's 'deployments' section + +.DESCRIPTION +Get the formatted content for the template's 'deployments' section. For the primary resource, template content of any pre-existing template takes precedence over new content. + +.PARAMETER FullResourceType +Mandatory. The complete ResourceType identifier to update the template for (e.g., 'Microsoft.Storage/storageAccounts'). + +.PARAMETER ResourceType +Mandatory. The resource type without the provider namespace (e.g., 'storageAccounts') + +.PARAMETER ResourceTypeSingular +Optional. The 'singular' version of the resource type. For example 'container' instead of 'containers'. + +.PARAMETER ModuleData +Mandatory. The module data to fetch the data for this section from & then format it propertly for the template. + +Expects an array with objects like: +Name Value +---- ----- +parameters {name, identity, type, properties…} +outputs {} +additionalFiles {} +modules {} +variables {diagnosticsMetrics, diagnosticsLogs} +resources {privateCloud_diagnosticSettings, privateCloud_lock} +isSingleton False +additionalParameters {diagnosticLogsRetentionInDays, diagnosticStorageAccountId, diagnosticWorkspaceId, diagnosticEventHubAuthorizationRuleId…} + +.PARAMETER FullModuleData +Mandatory. The full stack of module data of all modules included in the original invocation. May be used for parent-child references. + +Expects an array with objects like: + +Name Value +---- ----- +identifier Microsoft.AVS/privateClouds/workloadNetworks/dhcpConfigurations +data {parameters, outputs, additionalFiles, modules…} +metadata {urlPath, jsonFilePath, parentUrlPath} +identifier Microsoft.AVS/privateClouds/cloudLinks +data {parameters, outputs, additionalFiles, modules…} +metadata {urlPath, jsonFilePath, parentUrlPath} +identifier Microsoft.AVS/privateClouds/workloadNetworks/portMirroringProfiles +data {parameters, outputs, additionalFiles, modules…} +metadata {urlPath, jsonFilePath, parentUrlPath} + +.PARAMETER ParentResourceTypes +Optional. The name of any parent resource type. (e.g., @('privateClouds', 'clusters') + +.PARAMETER ExistingTemplateContent +Optional. The prepared content of an existing template, if any. + +Expects an array with objects like: + +Name Value +---- ----- +modules {privateCloud_cloudLinks, privateCloud_hcxEnterpriseSites, privateCloud_authorizations, privateCloud_scriptExecutions…} +variables {diagnosticsMetrics, diagnosticsLogs, enableReferencedModulesTelemetry} +parameters {name, sku, addons, authorizations…} +outputs {name, resourceId, resourceGroupName} +resources {defaultTelemetry, privateCloud, privateCloud_diagnosticSettings, privateCloud_lock} + + +.PARAMETER LinkedChildren +Optional. Information about any child-module of the current resource type. Used to generate proper module references. + +Expects an array with objects like: + +Name Value +---- ----- +identifier Microsoft.AVS/privateClouds/cloudLinks +data {parameters, outputs, additionalFiles, modules…} +metadata {urlPath, jsonFilePath, parentUrlPath} +identifier Microsoft.AVS/privateClouds/hcxEnterpriseSites +data {parameters, outputs, additionalFiles, modules…} +metadata {urlPath, jsonFilePath, parentUrlPath} +identifier Microsoft.AVS/privateClouds/authorizations +data {parameters, outputs, additionalFiles, modules…} +metadata {urlPath, jsonFilePath, parentUrlPath} + +.EXAMPLE +$contentInputObject = @{ + FullResourceType = 'Microsoft.AVS/privateClouds/clusters/datastores' + ResourceType = 'privateClouds/clusters/datastores' + ResourceTypeSingular = 'datastore' + ModuleData = @(@{...}, (...)) + FullModuleData = @(@{...}, (...)) + ParentResourceTypes = @('privateClouds', 'clusters') + ExistingTemplateContent = @(@{...}, (...)) + LinkedChildren = @(@{...}, (...)) +} +Get-TemplateDeploymentsContent @contentInputObject + +Get the formatted template content for resource type 'Microsoft.AVS/privateClouds/clusters/datastores' based on the given data - including an existing template's data +#> +function Get-TemplateDeploymentsContent { [CmdletBinding()] param ( diff --git a/utilities/tools/REST2CARML/private/module/Get-TemplateVariablesContent.ps1 b/utilities/tools/REST2CARML/private/module/Get-TemplateVariablesContent.ps1 index 475ac394e3..0e78b2d04a 100644 --- a/utilities/tools/REST2CARML/private/module/Get-TemplateVariablesContent.ps1 +++ b/utilities/tools/REST2CARML/private/module/Get-TemplateVariablesContent.ps1 @@ -3,7 +3,7 @@ Get the formatted content for the template's 'variables' section .DESCRIPTION -Get the formatted content for the template's 'variables' section. 'Existing' template content taxes precedence over new variables. +Get the formatted content for the template's 'variables' section. Template content of any pre-existing template takes precedence over new content. .PARAMETER ModuleData Mandatory. The module data to fetch the data for this section from & then format it propertly for the template. diff --git a/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 b/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 index 52f33276ec..517e1f8d0e 100644 --- a/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 +++ b/utilities/tools/REST2CARML/private/module/Set-ModuleTemplate.ps1 @@ -154,7 +154,7 @@ function Set-ModuleTemplate { if ($LinkedChildren.Count -gt 0) { $resourcesInputObject['LinkedChildren'] = $LinkedChildren } - $templateContent += Get-TemplateResourcesContent @resourcesInputObject + $templateContent += Get-TemplateDeploymentsContent @resourcesInputObject #endregion ####################################### From 19b0e8d37e3210e33016d77ee739d08a0ec64b10 Mon Sep 17 00:00:00 2001 From: MrMCake Date: Sun, 6 Nov 2022 11:26:41 +0100 Subject: [PATCH 26/30] Update to latest --- .../module/Get-TemplateDeploymentsContent.ps1 | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/utilities/tools/REST2CARML/private/module/Get-TemplateDeploymentsContent.ps1 b/utilities/tools/REST2CARML/private/module/Get-TemplateDeploymentsContent.ps1 index eb3be80867..05ab61cf0b 100644 --- a/utilities/tools/REST2CARML/private/module/Get-TemplateDeploymentsContent.ps1 +++ b/utilities/tools/REST2CARML/private/module/Get-TemplateDeploymentsContent.ps1 @@ -93,7 +93,26 @@ $contentInputObject = @{ } Get-TemplateDeploymentsContent @contentInputObject -Get the formatted template content for resource type 'Microsoft.AVS/privateClouds/clusters/datastores' based on the given data - including an existing template's data +Get the formatted template content for resource type 'Microsoft.AVS/privateClouds/clusters/datastores' based on the given data - including an existing template's data. The output looks something like: + +```bicep +// =============== // +// Deployments // +// =============== // + +resource defaultTelemetry 'Microsoft.Resources/deployments@2021-04-01' = if (enableDefaultTelemetry) { + name: 'pid-11111111-1111-1111-1111-111111111111-${uniqueString(deployment().name, location)}' + properties: { + mode: 'Incremental' + template: { + '$schema': 'https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#' + contentVersion: '1.0.0.0' + resources: [] + } + } +} +(...) +``` #> function Get-TemplateDeploymentsContent { From fda806df32d93671579e5bd39d494a3d271b6449 Mon Sep 17 00:00:00 2001 From: MrMCake Date: Sun, 6 Nov 2022 12:02:00 +0100 Subject: [PATCH 27/30] Updated docs + updated module gen --- .../privateClouds/clusters/deploy.bicep | 11 ++ .../Microsoft.AVS/privateClouds/deploy.bicep | 59 ++++++++ .../module/Get-TemplateChildModuleContent.ps1 | 126 +++++++++++++++--- 3 files changed, 177 insertions(+), 19 deletions(-) diff --git a/modules/Microsoft.AVS/privateClouds/clusters/deploy.bicep b/modules/Microsoft.AVS/privateClouds/clusters/deploy.bicep index 1df6ee7abb..2a8e49ddf8 100644 --- a/modules/Microsoft.AVS/privateClouds/clusters/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/clusters/deploy.bicep @@ -67,6 +67,9 @@ module cluster_datastores 'datastores/deploy.bicep' = [for (datastore, index) in params: { privateCloudName: privateCloudName clusterName: name + diskPoolVolume: contains(datastore, 'diskPoolVolume') ? datastore.diskPoolVolume : {} + name: datastore.name + netAppVolume: contains(datastore, 'netAppVolume') ? datastore.netAppVolume : {} enableDefaultTelemetry: enableReferencedModulesTelemetry } }] @@ -76,6 +79,14 @@ module cluster_placementPolicies 'placementPolicies/deploy.bicep' = [for (placem params: { privateCloudName: privateCloudName clusterName: name + affinityStrength: contains(placementPolicy, 'affinityStrength') ? placementPolicy.affinityStrength : '' + azureHybridBenefitType: contains(placementPolicy, 'azureHybridBenefitType') ? placementPolicy.azureHybridBenefitType : '' + displayName: contains(placementPolicy, 'displayName') ? placementPolicy.displayName : '' + hostMembers: contains(placementPolicy, 'hostMembers') ? placementPolicy.hostMembers : [] + name: placementPolicy.name + state: contains(placementPolicy, 'state') ? placementPolicy.state : '' + type: contains(placementPolicy, 'type') ? placementPolicy.type : '' + vmMembers: contains(placementPolicy, 'vmMembers') ? placementPolicy.vmMembers : [] enableDefaultTelemetry: enableReferencedModulesTelemetry } }] diff --git a/modules/Microsoft.AVS/privateClouds/deploy.bicep b/modules/Microsoft.AVS/privateClouds/deploy.bicep index 086ea63e34..20cce2c3c3 100644 --- a/modules/Microsoft.AVS/privateClouds/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/deploy.bicep @@ -242,6 +242,8 @@ module privateCloud_cloudLinks 'cloudLinks/deploy.bicep' = [for (cloudLink, inde name: '${uniqueString(deployment().name, location)}-privateCloud-cloudLink-${index}' params: { privateCloudName: name + linkedCloud: contains(cloudLink, 'linkedCloud') ? cloudLink.linkedCloud : '' + name: cloudLink.name enableDefaultTelemetry: enableReferencedModulesTelemetry } }] @@ -250,6 +252,7 @@ module privateCloud_hcxEnterpriseSites 'hcxEnterpriseSites/deploy.bicep' = [for name: '${uniqueString(deployment().name, location)}-privateCloud-hcxEnterpriseSite-${index}' params: { privateCloudName: name + name: hcxEnterpriseSite.name enableDefaultTelemetry: enableReferencedModulesTelemetry } }] @@ -258,6 +261,7 @@ module privateCloud_authorizations 'authorizations/deploy.bicep' = [for (authori name: '${uniqueString(deployment().name, location)}-privateCloud-authorization-${index}' params: { privateCloudName: name + name: authorization.name enableDefaultTelemetry: enableReferencedModulesTelemetry } }] @@ -266,6 +270,15 @@ module privateCloud_scriptExecutions 'scriptExecutions/deploy.bicep' = [for (scr name: '${uniqueString(deployment().name, location)}-privateCloud-scriptExecution-${index}' params: { privateCloudName: name + failureReason: contains(scriptExecution, 'failureReason') ? scriptExecution.failureReason : '' + hiddenParameters: contains(scriptExecution, 'hiddenParameters') ? scriptExecution.hiddenParameters : [] + name: scriptExecution.name + namedOutputs: contains(scriptExecution, 'namedOutputs') ? scriptExecution.namedOutputs : {} + output: contains(scriptExecution, 'output') ? scriptExecution.output : [] + parameters: contains(scriptExecution, 'parameters') ? scriptExecution.parameters : [] + retention: contains(scriptExecution, 'retention') ? scriptExecution.retention : '' + scriptCmdletId: contains(scriptExecution, 'scriptCmdletId') ? scriptExecution.scriptCmdletId : '' + timeout: contains(scriptExecution, 'timeout') ? scriptExecution.timeout : '' enableDefaultTelemetry: enableReferencedModulesTelemetry } }] @@ -274,6 +287,10 @@ module privateCloud_globalReachConnections 'globalReachConnections/deploy.bicep' name: '${uniqueString(deployment().name, location)}-privateCloud-globalReachConnection-${index}' params: { privateCloudName: name + authorizationKey: contains(globalReachConnection, 'authorizationKey') ? globalReachConnection.authorizationKey : '' + expressRouteId: contains(globalReachConnection, 'expressRouteId') ? globalReachConnection.expressRouteId : '' + name: globalReachConnection.name + peerExpressRouteCircuit: contains(globalReachConnection, 'peerExpressRouteCircuit') ? globalReachConnection.peerExpressRouteCircuit : '' enableDefaultTelemetry: enableReferencedModulesTelemetry } }] @@ -282,6 +299,8 @@ module privateCloud_addons 'addons/deploy.bicep' = [for (addon, index) in addons name: '${uniqueString(deployment().name, location)}-privateCloud-addon-${index}' params: { privateCloudName: name + addonType: contains(addon, 'addonType') ? addon.addonType : '' + name: addon.name enableDefaultTelemetry: enableReferencedModulesTelemetry } }] @@ -290,6 +309,10 @@ module privateCloud_clusters 'clusters/deploy.bicep' = [for (cluster, index) in name: '${uniqueString(deployment().name, location)}-privateCloud-cluster-${index}' params: { privateCloudName: name + clusterSize: contains(cluster, 'clusterSize') ? cluster.clusterSize : + hosts: contains(cluster, 'hosts') ? cluster.hosts : [] + name: cluster.name + sku: cluster.sku enableDefaultTelemetry: enableReferencedModulesTelemetry } }] @@ -299,6 +322,10 @@ module workloadNetworks_privateCloud_dhcpConfigurations 'workloadNetworks/dhcpCo params: { privateCloudName: name workloadNetworkName: 'default' + dhcpType: contains(dhcpConfiguration, 'dhcpType') ? dhcpConfiguration.dhcpType : '' + displayName: contains(dhcpConfiguration, 'displayName') ? dhcpConfiguration.displayName : '' + name: dhcpConfiguration.name + revision: contains(dhcpConfiguration, 'revision') ? dhcpConfiguration.revision : enableDefaultTelemetry: enableReferencedModulesTelemetry } }] @@ -308,6 +335,12 @@ module workloadNetworks_privateCloud_portMirroringProfiles 'workloadNetworks/por params: { privateCloudName: name workloadNetworkName: 'default' + destination: contains(portMirroringProfile, 'destination') ? portMirroringProfile.destination : '' + direction: contains(portMirroringProfile, 'direction') ? portMirroringProfile.direction : '' + displayName: contains(portMirroringProfile, 'displayName') ? portMirroringProfile.displayName : '' + name: portMirroringProfile.name + revision: contains(portMirroringProfile, 'revision') ? portMirroringProfile.revision : + source: contains(portMirroringProfile, 'source') ? portMirroringProfile.source : '' enableDefaultTelemetry: enableReferencedModulesTelemetry } }] @@ -317,6 +350,13 @@ module workloadNetworks_privateCloud_dnsZones 'workloadNetworks/dnsZones/deploy. params: { privateCloudName: name workloadNetworkName: 'default' + displayName: contains(dnsZone, 'displayName') ? dnsZone.displayName : '' + dnsServerIps: contains(dnsZone, 'dnsServerIps') ? dnsZone.dnsServerIps : [] + dnsServices: contains(dnsZone, 'dnsServices') ? dnsZone.dnsServices : + domain: contains(dnsZone, 'domain') ? dnsZone.domain : [] + name: dnsZone.name + revision: contains(dnsZone, 'revision') ? dnsZone.revision : + sourceIp: contains(dnsZone, 'sourceIp') ? dnsZone.sourceIp : '' enableDefaultTelemetry: enableReferencedModulesTelemetry } }] @@ -326,6 +366,9 @@ module workloadNetworks_privateCloud_publicIPs 'workloadNetworks/publicIPs/deplo params: { privateCloudName: name workloadNetworkName: 'default' + displayName: contains(publicIP, 'displayName') ? publicIP.displayName : '' + name: publicIP.name + numberOfPublicIPs: contains(publicIP, 'numberOfPublicIPs') ? publicIP.numberOfPublicIPs : enableDefaultTelemetry: enableReferencedModulesTelemetry } }] @@ -335,6 +378,13 @@ module workloadNetworks_privateCloud_dnsServices 'workloadNetworks/dnsServices/d params: { privateCloudName: name workloadNetworkName: 'default' + defaultDnsZone: contains(dnsService, 'defaultDnsZone') ? dnsService.defaultDnsZone : '' + displayName: contains(dnsService, 'displayName') ? dnsService.displayName : '' + dnsServiceIp: contains(dnsService, 'dnsServiceIp') ? dnsService.dnsServiceIp : '' + fqdnZones: contains(dnsService, 'fqdnZones') ? dnsService.fqdnZones : [] + logLevel: contains(dnsService, 'logLevel') ? dnsService.logLevel : '' + name: dnsService.name + revision: contains(dnsService, 'revision') ? dnsService.revision : enableDefaultTelemetry: enableReferencedModulesTelemetry } }] @@ -344,6 +394,10 @@ module workloadNetworks_privateCloud_vmGroups 'workloadNetworks/vmGroups/deploy. params: { privateCloudName: name workloadNetworkName: 'default' + displayName: contains(vmGroup, 'displayName') ? vmGroup.displayName : '' + members: contains(vmGroup, 'members') ? vmGroup.members : [] + name: vmGroup.name + revision: contains(vmGroup, 'revision') ? vmGroup.revision : enableDefaultTelemetry: enableReferencedModulesTelemetry } }] @@ -353,6 +407,11 @@ module workloadNetworks_privateCloud_segments 'workloadNetworks/segments/deploy. params: { privateCloudName: name workloadNetworkName: 'default' + connectedGateway: contains(segment, 'connectedGateway') ? segment.connectedGateway : '' + displayName: contains(segment, 'displayName') ? segment.displayName : '' + name: segment.name + revision: contains(segment, 'revision') ? segment.revision : + subnet: contains(segment, 'subnet') ? segment.subnet : {} enableDefaultTelemetry: enableReferencedModulesTelemetry } }] diff --git a/utilities/tools/REST2CARML/private/module/Get-TemplateChildModuleContent.ps1 b/utilities/tools/REST2CARML/private/module/Get-TemplateChildModuleContent.ps1 index bd2efb77b8..d3f791deb7 100644 --- a/utilities/tools/REST2CARML/private/module/Get-TemplateChildModuleContent.ps1 +++ b/utilities/tools/REST2CARML/private/module/Get-TemplateChildModuleContent.ps1 @@ -1,4 +1,91 @@ -function Get-TemplateChildModuleContent { +<# +.SYNOPSIS +Generate the child-module's template content based on the given module data. + +.DESCRIPTION +Generate the child-module's template content based on the given module data. + +.PARAMETER FullResourceType +Mandatory. The complete ResourceType identifier to update the template for (e.g., 'Microsoft.Storage/storageAccounts'). + +.PARAMETER ResourceType +Mandatory. The resource type without the provider namespace (e.g., 'storageAccounts') + +.PARAMETER ResourceTypeSingular +Optional. The 'singular' version of the resource type. For example 'container' instead of 'containers'. + +.PARAMETER ModuleData +Mandatory. The module data to fetch the data for this section from & then format it propertly for the template. + +Expects an array with objects like: +Name Value +---- ----- +parameters {name, identity, type, properties…} +outputs {} +additionalFiles {} +modules {} +variables {diagnosticsMetrics, diagnosticsLogs} +resources {privateCloud_diagnosticSettings, privateCloud_lock} +isSingleton False +additionalParameters {diagnosticLogsRetentionInDays, diagnosticStorageAccountId, diagnosticWorkspaceId, diagnosticEventHubAuthorizationRuleId…} + +.PARAMETER LinkedChildren +Optional. Information about any child-module of the current resource type. Used to generate proper module references. + +Expects an array with objects like: + +Name Value +---- ----- +identifier Microsoft.AVS/privateClouds/cloudLinks +data {parameters, outputs, additionalFiles, modules…} +metadata {urlPath, jsonFilePath, parentUrlPath} +identifier Microsoft.AVS/privateClouds/hcxEnterpriseSites +data {parameters, outputs, additionalFiles, modules…} +metadata {urlPath, jsonFilePath, parentUrlPath} +identifier Microsoft.AVS/privateClouds/authorizations +data {parameters, outputs, additionalFiles, modules…} +metadata {urlPath, jsonFilePath, parentUrlPath} + +.PARAMETER LocationParameterExists +Mandatory. An indicator whether the template will contain a 'location' parameter. Only then we can reference it in e.g., deployment names. + +.PARAMETER ExistingTemplateContent +Optional. The prepared content of an existing template, if any. + +Expects an array with objects like: + +Name Value +---- ----- +modules {privateCloud_cloudLinks, privateCloud_hcxEnterpriseSites, privateCloud_authorizations, privateCloud_scriptExecutions…} +variables {diagnosticsMetrics, diagnosticsLogs, enableReferencedModulesTelemetry} +parameters {name, sku, addons, authorizations…} +outputs {name, resourceId, resourceGroupName} +resources {defaultTelemetry, privateCloud, privateCloud_diagnosticSettings, privateCloud_lock} + +.PARAMETER ParentResourceTypes +Optional. The name of any parent resource type. (e.g., @('privateClouds', 'clusters') + +.EXAMPLE +$contentInputObject = @{ + FullResourceType = 'Microsoft.AVS/privateClouds/clusters/datastores' + ResourceType = 'privateClouds/clusters/datastores' + ResourceTypeSingular = 'datastore' + LinkedChildren = @(@{...}, (...)) + ModuleData = @(@{...}, (...)) + LocationParameterExists = $true + ExistingTemplateContent = @(@{...}, (...)) + ParentResourceTypes = @('privateClouds', 'clusters') +} +Get-TemplateChildModuleContent @contentInputObject + +Get the formatted template content for resource type 'Microsoft.AVS/privateClouds/clusters/datastores' based on the given data - including an existing template's data. The output looks something like: + +```bicep + +(...) +``` +#> +function Get-TemplateChildModuleContent { [CmdletBinding()] param ( @@ -18,7 +105,7 @@ [array] $ModuleData, [Parameter(Mandatory = $true)] - [string] $LocationParameterExists, + [bool] $LocationParameterExists, [Parameter(Mandatory = $false)] [array] $ExistingTemplateContent = @(), @@ -49,7 +136,7 @@ $moduleName = '{0}{1}_{2}' -f ($hasProxyParent ? "$($proxyParentName)_" : ''), $resourceTypeSingular, $childResourceType $modulePath = '{0}{1}/deploy.bicep' -f ($hasProxyParent ? "$proxyParentName/" : ''), $childResourceType - $matchingModule = $ExistingTemplateContent.modules | Where-Object { $_.name -eq $moduleName -and $_.path -eq $modulePath } + $existingModuleData = $ExistingTemplateContent.modules | Where-Object { $_.name -eq $moduleName -and $_.path -eq $modulePath } # Differentiate 'singular' children (like 'blobservices') vs. 'multiple' chilren (like 'containers') if ($ModuleData.isSingleton) { @@ -57,10 +144,10 @@ "module $moduleName '$modulePath' = {" ) - if ($matchingModule.topLevelElements.name -notcontains 'name') { + if ($existingModuleData.topLevelElements.name -notcontains 'name') { $templateContent += " name: '`${uniqueString(deployment().name$($LocationParameterExists ? ', location' : ''))}-$($resourceTypeSingular)-$($childResourceType)'" } else { - $existingParam = $matchingModule.topLevelElements | Where-Object { $_.name -eq 'name' } + $existingParam = $existingModuleData.topLevelElements | Where-Object { $_.name -eq 'name' } $templateContent += $existingParam.content } @@ -95,8 +182,8 @@ $wouldBeParamElem = $wouldBeParameter -split ' = ' $parameter.name = ($wouldBeParamElem -split ' ')[0] - if ($matchingModule.nestedElements.name -notcontains $parameter.name) { - $existingParam = $matchingModule.nestedElements | Where-Object { $_.name -eq $parameter.name } + if ($existingModuleData.nestedElements.name -notcontains $parameter.name) { + $existingParam = $existingModuleData.nestedElements | Where-Object { $_.name -eq $parameter.name } if ($alreadyAddedParams -notcontains $existingParam.name) { $templateContent += $existingParam.content } @@ -144,10 +231,10 @@ "module $moduleName '$modulePath' = [for ($($childResourceTypeSingular), index) in $($childResourceType): {" ) - if ($matchingModule.topLevelElements.name -notcontains 'name') { + if ($existingModuleData.topLevelElements.name -notcontains 'name') { $templateContent += " name: '`${uniqueString(deployment().name$($LocationParameterExists ? ', location' : ''))}-$($resourceTypeSingular)-$($childResourceTypeSingular)-`${index}'" } else { - $existingParam = $matchingModule.topLevelElements | Where-Object { $_.name -eq 'name' } + $existingParam = $existingModuleData.topLevelElements | Where-Object { $_.name -eq 'name' } $templateContent += $existingParam.content } @@ -180,10 +267,11 @@ foreach ($parameter in (($allParam | Where-Object { $_.Level -in @(0, 1) -and $_.name -ne 'properties' -and ([String]::IsNullOrEmpty($_.Parent) -or $_.Parent -eq 'properties') }) | Sort-Object -Property 'Name')) { $wouldBeParameter = Get-FormattedModuleParameter -ParameterData $parameter | Where-Object { $_ -like 'param *' } | ForEach-Object { $_ -replace 'param ', '' } $wouldBeParamElem = $wouldBeParameter -split ' = ' - $parameter.name = ($wouldBeParamElem -split ' ')[0] + $parameterName = ($wouldBeParamElem -split ' ')[0] - if ($matchingModule.nestedElements.name -notcontains $parameter.name) { - $existingParam = $matchingModule.nestedElements | Where-Object { $_.name -eq $parameter.name } + # If the existing content already specifies the parameter, let's use that one instead of generating a new + if ($existingModuleData.nestedElements.name -contains $parameterName) { + $existingParam = $existingModuleData.nestedElements | Where-Object { $_.name -eq $parameterName } if ($alreadyAddedParams -notcontains $existingParam.name) { $templateContent += $existingParam.content } @@ -193,10 +281,10 @@ if ($wouldBeParamElem.count -gt 1) { # With default - if ($parameter.name -eq 'lock') { + if ($parameterName -eq 'lock') { # Special handling as we pass the parameter down to the child - $templateContent += " $($parameter.name): contains($($childResourceTypeSingular), 'lock') ? $($childResourceTypeSingular).lock : lock" - $alreadyAddedParams += $parameter.name + $templateContent += " $($parameterName): contains($($childResourceTypeSingular), 'lock') ? $($childResourceTypeSingular).lock : lock" + $alreadyAddedParams += $parameterName continue } @@ -207,12 +295,12 @@ $wouldBeParamValue = 'location' } - $templateContent += " $($parameter.name): contains($($childResourceTypeSingular), '$($parameter.name)') ? $($childResourceTypeSingular).$($parameter.name) : $($wouldBeParamValue)" - $alreadyAddedParams += $parameter.name + $templateContent += " $($parameterName): contains($($childResourceTypeSingular), '$($parameterName)') ? $($childResourceTypeSingular).$($parameterName) : $($wouldBeParamValue)" + $alreadyAddedParams += $parameterName } else { # No default - $templateContent += " $($parameter.name): $($childResourceTypeSingular).$($parameter.name)" - $alreadyAddedParams += $parameter.name + $templateContent += " $($parameterName): $($childResourceTypeSingular).$($parameterName)" + $alreadyAddedParams += $parameterName } } From 3c3cd9e208637f353b36a628a85b8dd014e70c50 Mon Sep 17 00:00:00 2001 From: MrMCake Date: Sun, 6 Nov 2022 12:13:57 +0100 Subject: [PATCH 28/30] Updated docs --- .../module/Get-TemplateOutputContent.ps1 | 74 +++++++++++- .../module/Get-TemplateParametersContent.ps1 | 108 +++++++++++++++++- 2 files changed, 178 insertions(+), 4 deletions(-) diff --git a/utilities/tools/REST2CARML/private/module/Get-TemplateOutputContent.ps1 b/utilities/tools/REST2CARML/private/module/Get-TemplateOutputContent.ps1 index 3c7af901de..0957fe2774 100644 --- a/utilities/tools/REST2CARML/private/module/Get-TemplateOutputContent.ps1 +++ b/utilities/tools/REST2CARML/private/module/Get-TemplateOutputContent.ps1 @@ -1,4 +1,76 @@ -function Get-TemplateOutputContent { +<# +.SYNOPSIS +Get the formatted content for the template's 'outputs' section + +.DESCRIPTION +Get the formatted content for the template's 'outputs' section. For the primary resource, template content of any pre-existing template takes precedence over new content. + +.PARAMETER ResourceType +Mandatory. The resource type without the provider namespace (e.g., 'storageAccounts') + +.PARAMETER ResourceTypeSingular +Optional. The 'singular' version of the resource type. For example 'container' instead of 'containers'. + +.PARAMETER TargetScope +Mandatory. The scope of the target template (e.g., 'resourceGroup', 'subscription', etc.) + +.PARAMETER ModuleData +Mandatory. The module data to fetch the data for this section from & then format it propertly for the template. + +Expects an array with objects like: +Name Value +---- ----- +parameters {name, identity, type, properties…} +outputs {} +additionalFiles {} +modules {} +variables {diagnosticsMetrics, diagnosticsLogs} +resources {privateCloud_diagnosticSettings, privateCloud_lock} +isSingleton False +additionalParameters {diagnosticLogsRetentionInDays, diagnosticStorageAccountId, diagnosticWorkspaceId, diagnosticEventHubAuthorizationRuleId…} + +.PARAMETER ExistingTemplateContent +Optional. The prepared content of an existing template, if any. + +Expects an array with objects like: + +Name Value +---- ----- +modules {privateCloud_cloudLinks, privateCloud_hcxEnterpriseSites, privateCloud_authorizations, privateCloud_scriptExecutions…} +variables {diagnosticsMetrics, diagnosticsLogs, enableReferencedModulesTelemetry} +parameters {name, sku, addons, authorizations…} +outputs {name, resourceId, resourceGroupName} +resources {defaultTelemetry, privateCloud, privateCloud_diagnosticSettings, privateCloud_lock} + +.EXAMPLE +$contentInputObject = @{ + ResourceType = 'privateClouds/clusters/datastores' + ResourceTypeSingular = 'datastore' + TargetScope = 'resourceGroup' + ModuleData = @(@{...}, (...)) + ExistingTemplateContent = @(@{...}, (...)) +} +Get-TemplateOutputContent @contentInputObject + +Get the formatted template content for resource type 'Microsoft.AVS/privateClouds/clusters/datastores' based on the given data - including an existing template's data. The output looks something like: + +```bicep +// =========== // +// Outputs // +// =========== // + +@description('The name of the datastore.') +output name string = datastore.name + +@description('The resource ID of the datastore.') +output resourceId string = datastore.id + +@description('The name of the resource group the datastore was created in.') +output resourceGroupName string = resourceGroup().name +(...) +``` +#> +function Get-TemplateOutputContent { [CmdletBinding()] param ( diff --git a/utilities/tools/REST2CARML/private/module/Get-TemplateParametersContent.ps1 b/utilities/tools/REST2CARML/private/module/Get-TemplateParametersContent.ps1 index da0a85cfd4..df795e1038 100644 --- a/utilities/tools/REST2CARML/private/module/Get-TemplateParametersContent.ps1 +++ b/utilities/tools/REST2CARML/private/module/Get-TemplateParametersContent.ps1 @@ -1,4 +1,108 @@ -function Get-TemplateParametersContent { +<# +.SYNOPSIS +Get the formatted content for the template's 'parameters' section + +.DESCRIPTION +Get the formatted content for the template's 'parameters' section. Template content of any pre-existing template takes precedence over new content. + +.PARAMETER FullResourceType +Mandatory. The complete ResourceType identifier to update the template for (e.g., 'Microsoft.Storage/storageAccounts'). + +.PARAMETER ModuleData +Mandatory. The module data to fetch the data for this section from & then format it propertly for the template. + +Expects an array with objects like: +Name Value +---- ----- +parameters {name, identity, type, properties…} +outputs {} +additionalFiles {} +modules {} +variables {diagnosticsMetrics, diagnosticsLogs} +resources {privateCloud_diagnosticSettings, privateCloud_lock} +isSingleton False +additionalParameters {diagnosticLogsRetentionInDays, diagnosticStorageAccountId, diagnosticWorkspaceId, diagnosticEventHubAuthorizationRuleId…} + +.PARAMETER FullModuleData +Mandatory. The full stack of module data of all modules included in the original invocation. May be used for parent-child references. + +Expects an array with objects like: + +Name Value +---- ----- +identifier Microsoft.AVS/privateClouds/workloadNetworks/dhcpConfigurations +data {parameters, outputs, additionalFiles, modules…} +metadata {urlPath, jsonFilePath, parentUrlPath} +identifier Microsoft.AVS/privateClouds/cloudLinks +data {parameters, outputs, additionalFiles, modules…} +metadata {urlPath, jsonFilePath, parentUrlPath} +identifier Microsoft.AVS/privateClouds/workloadNetworks/portMirroringProfiles +data {parameters, outputs, additionalFiles, modules…} +metadata {urlPath, jsonFilePath, parentUrlPath} + +.PARAMETER ParentResourceTypes +Optional. The name of any parent resource type. (e.g., @('privateClouds', 'clusters') + +.PARAMETER ExistingTemplateContent +Optional. The prepared content of an existing template, if any. + +Expects an array with objects like: + +Name Value +---- ----- +modules {privateCloud_cloudLinks, privateCloud_hcxEnterpriseSites, privateCloud_authorizations, privateCloud_scriptExecutions…} +variables {diagnosticsMetrics, diagnosticsLogs, enableReferencedModulesTelemetry} +parameters {name, sku, addons, authorizations…} +outputs {name, resourceId, resourceGroupName} +resources {defaultTelemetry, privateCloud, privateCloud_diagnosticSettings, privateCloud_lock} + +.PARAMETER LinkedChildren +Optional. Information about any child-module of the current resource type. Used to generate proper module references. + +Expects an array with objects like: + +Name Value +---- ----- +identifier Microsoft.AVS/privateClouds/cloudLinks +data {parameters, outputs, additionalFiles, modules…} +metadata {urlPath, jsonFilePath, parentUrlPath} +identifier Microsoft.AVS/privateClouds/hcxEnterpriseSites +data {parameters, outputs, additionalFiles, modules…} +metadata {urlPath, jsonFilePath, parentUrlPath} +identifier Microsoft.AVS/privateClouds/authorizations +data {parameters, outputs, additionalFiles, modules…} +metadata {urlPath, jsonFilePath, parentUrlPath} + +.EXAMPLE +$contentInputObject = @{ + FullResourceType = 'Microsoft.AVS/privateClouds/clusters/datastores' + ModuleData = @(@{...}, (...)) + FullModuleData = @(@{...}, (...)) + ParentResourceTypes = @('privateClouds', 'clusters') + ExistingTemplateContent = @(@{...}, (...)) + LinkedChildren = @(@{...}, (...)) +} +Get-TemplateParametersContent @contentInputObject + +Get the formatted template content for resource type 'Microsoft.AVS/privateClouds/clusters/datastores' based on the given data - including an existing template's data. The output looks something like: + +```bicep +// ============== // +// Parameters // +// ============== // + +@description('Required. Name of the private cloud') +param name string + +@description('Required. The resource model definition representing SKU') +param sku object + +@description('Optional. The addons to create as part of the privateCloud.') +param addons array = [] +(...) +``` +#> +function Get-TemplateParametersContent { [CmdletBinding()] param ( @@ -35,8 +139,6 @@ $parentProxyName = $hasAProxyParent ? ($UrlPath -split '\/')[-3] : '' $proxyParentType = Split-Path (Split-Path $FullResourceType -Parent) -Leaf - - # Collect parameters to create # ---------------------------- $parametersToAdd = @() From a0474eee7d2f0cac6277c7f88815bcaa0da9b86c Mon Sep 17 00:00:00 2001 From: MrMCake Date: Sun, 6 Nov 2022 12:16:13 +0100 Subject: [PATCH 29/30] Update to latest --- .../private/module/Get-TemplateDeploymentsContent.ps1 | 1 - .../REST2CARML/private/module/Get-TemplateVariablesContent.ps1 | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/utilities/tools/REST2CARML/private/module/Get-TemplateDeploymentsContent.ps1 b/utilities/tools/REST2CARML/private/module/Get-TemplateDeploymentsContent.ps1 index 05ab61cf0b..0c1c386782 100644 --- a/utilities/tools/REST2CARML/private/module/Get-TemplateDeploymentsContent.ps1 +++ b/utilities/tools/REST2CARML/private/module/Get-TemplateDeploymentsContent.ps1 @@ -62,7 +62,6 @@ parameters {name, sku, addons, authorizations…} outputs {name, resourceId, resourceGroupName} resources {defaultTelemetry, privateCloud, privateCloud_diagnosticSettings, privateCloud_lock} - .PARAMETER LinkedChildren Optional. Information about any child-module of the current resource type. Used to generate proper module references. diff --git a/utilities/tools/REST2CARML/private/module/Get-TemplateVariablesContent.ps1 b/utilities/tools/REST2CARML/private/module/Get-TemplateVariablesContent.ps1 index 0e78b2d04a..3a9d9b7790 100644 --- a/utilities/tools/REST2CARML/private/module/Get-TemplateVariablesContent.ps1 +++ b/utilities/tools/REST2CARML/private/module/Get-TemplateVariablesContent.ps1 @@ -38,7 +38,7 @@ Get-TemplateVariablesContent -ModuleData @(@{ variables = @(@{ name = 'abc'; con Generate the variables content for the above example containing at least the 'abc' variable. Would result in an output like -```Bicep +```bicep // ============= // // Variables // // ============= // From 18cbfb74cab4724a8588dc8d859cc51e6a5e216b Mon Sep 17 00:00:00 2001 From: MrMCake Date: Sun, 6 Nov 2022 13:09:12 +0100 Subject: [PATCH 30/30] Update to latest --- .../privateClouds/clusters/deploy.bicep | 4 +- .../Microsoft.AVS/privateClouds/deploy.bicep | 124 +++++++++--------- .../module/Get-TemplateChildModuleContent.ps1 | 2 +- .../module/Get-TemplateDeploymentsContent.ps1 | 16 ++- .../module/Get-TemplateVariablesContent.ps1 | 1 - 5 files changed, 74 insertions(+), 73 deletions(-) diff --git a/modules/Microsoft.AVS/privateClouds/clusters/deploy.bicep b/modules/Microsoft.AVS/privateClouds/clusters/deploy.bicep index 2a8e49ddf8..f400449f8c 100644 --- a/modules/Microsoft.AVS/privateClouds/clusters/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/clusters/deploy.bicep @@ -63,7 +63,7 @@ resource cluster 'Microsoft.AVS/privateClouds/clusters@2022-05-01' = { } module cluster_datastores 'datastores/deploy.bicep' = [for (datastore, index) in datastores: { - name: '${uniqueString(deployment().name, location)}-cluster-datastore-${index}' + name: '${uniqueString(deployment().name)}-cluster-datastore-${index}' params: { privateCloudName: privateCloudName clusterName: name @@ -75,7 +75,7 @@ module cluster_datastores 'datastores/deploy.bicep' = [for (datastore, index) in }] module cluster_placementPolicies 'placementPolicies/deploy.bicep' = [for (placementPolicy, index) in placementPolicies: { - name: '${uniqueString(deployment().name, location)}-cluster-placementPolicy-${index}' + name: '${uniqueString(deployment().name)}-cluster-placementPolicy-${index}' params: { privateCloudName: privateCloudName clusterName: name diff --git a/modules/Microsoft.AVS/privateClouds/deploy.bicep b/modules/Microsoft.AVS/privateClouds/deploy.bicep index 20cce2c3c3..05be0abfd2 100644 --- a/modules/Microsoft.AVS/privateClouds/deploy.bicep +++ b/modules/Microsoft.AVS/privateClouds/deploy.bicep @@ -238,47 +238,43 @@ resource privateCloud_lock 'Microsoft.Authorization/locks@2017-04-01' = if (!emp scope: privateCloud } -module privateCloud_cloudLinks 'cloudLinks/deploy.bicep' = [for (cloudLink, index) in cloudLinks: { - name: '${uniqueString(deployment().name, location)}-privateCloud-cloudLink-${index}' +module privateCloud_addons 'addons/deploy.bicep' = [for (addon, index) in addons: { + name: '${uniqueString(deployment().name, location)}-privateCloud-addon-${index}' params: { privateCloudName: name - linkedCloud: contains(cloudLink, 'linkedCloud') ? cloudLink.linkedCloud : '' - name: cloudLink.name + addonType: contains(addon, 'addonType') ? addon.addonType : '' + name: addon.name enableDefaultTelemetry: enableReferencedModulesTelemetry } }] -module privateCloud_hcxEnterpriseSites 'hcxEnterpriseSites/deploy.bicep' = [for (hcxEnterpriseSite, index) in hcxEnterpriseSites: { - name: '${uniqueString(deployment().name, location)}-privateCloud-hcxEnterpriseSite-${index}' +module privateCloud_authorizations 'authorizations/deploy.bicep' = [for (authorization, index) in authorizations: { + name: '${uniqueString(deployment().name, location)}-privateCloud-authorization-${index}' params: { privateCloudName: name - name: hcxEnterpriseSite.name + name: authorization.name enableDefaultTelemetry: enableReferencedModulesTelemetry } }] -module privateCloud_authorizations 'authorizations/deploy.bicep' = [for (authorization, index) in authorizations: { - name: '${uniqueString(deployment().name, location)}-privateCloud-authorization-${index}' +module privateCloud_cloudLinks 'cloudLinks/deploy.bicep' = [for (cloudLink, index) in cloudLinks: { + name: '${uniqueString(deployment().name, location)}-privateCloud-cloudLink-${index}' params: { privateCloudName: name - name: authorization.name + linkedCloud: contains(cloudLink, 'linkedCloud') ? cloudLink.linkedCloud : '' + name: cloudLink.name enableDefaultTelemetry: enableReferencedModulesTelemetry } }] -module privateCloud_scriptExecutions 'scriptExecutions/deploy.bicep' = [for (scriptExecution, index) in scriptExecutions: { - name: '${uniqueString(deployment().name, location)}-privateCloud-scriptExecution-${index}' +module privateCloud_clusters 'clusters/deploy.bicep' = [for (cluster, index) in clusters: { + name: '${uniqueString(deployment().name, location)}-privateCloud-cluster-${index}' params: { privateCloudName: name - failureReason: contains(scriptExecution, 'failureReason') ? scriptExecution.failureReason : '' - hiddenParameters: contains(scriptExecution, 'hiddenParameters') ? scriptExecution.hiddenParameters : [] - name: scriptExecution.name - namedOutputs: contains(scriptExecution, 'namedOutputs') ? scriptExecution.namedOutputs : {} - output: contains(scriptExecution, 'output') ? scriptExecution.output : [] - parameters: contains(scriptExecution, 'parameters') ? scriptExecution.parameters : [] - retention: contains(scriptExecution, 'retention') ? scriptExecution.retention : '' - scriptCmdletId: contains(scriptExecution, 'scriptCmdletId') ? scriptExecution.scriptCmdletId : '' - timeout: contains(scriptExecution, 'timeout') ? scriptExecution.timeout : '' + clusterSize: contains(cluster, 'clusterSize') ? cluster.clusterSize : + hosts: contains(cluster, 'hosts') ? cluster.hosts : [] + name: cluster.name + sku: cluster.sku enableDefaultTelemetry: enableReferencedModulesTelemetry } }] @@ -295,24 +291,28 @@ module privateCloud_globalReachConnections 'globalReachConnections/deploy.bicep' } }] -module privateCloud_addons 'addons/deploy.bicep' = [for (addon, index) in addons: { - name: '${uniqueString(deployment().name, location)}-privateCloud-addon-${index}' +module privateCloud_hcxEnterpriseSites 'hcxEnterpriseSites/deploy.bicep' = [for (hcxEnterpriseSite, index) in hcxEnterpriseSites: { + name: '${uniqueString(deployment().name, location)}-privateCloud-hcxEnterpriseSite-${index}' params: { privateCloudName: name - addonType: contains(addon, 'addonType') ? addon.addonType : '' - name: addon.name + name: hcxEnterpriseSite.name enableDefaultTelemetry: enableReferencedModulesTelemetry } }] -module privateCloud_clusters 'clusters/deploy.bicep' = [for (cluster, index) in clusters: { - name: '${uniqueString(deployment().name, location)}-privateCloud-cluster-${index}' +module privateCloud_scriptExecutions 'scriptExecutions/deploy.bicep' = [for (scriptExecution, index) in scriptExecutions: { + name: '${uniqueString(deployment().name, location)}-privateCloud-scriptExecution-${index}' params: { privateCloudName: name - clusterSize: contains(cluster, 'clusterSize') ? cluster.clusterSize : - hosts: contains(cluster, 'hosts') ? cluster.hosts : [] - name: cluster.name - sku: cluster.sku + failureReason: contains(scriptExecution, 'failureReason') ? scriptExecution.failureReason : '' + hiddenParameters: contains(scriptExecution, 'hiddenParameters') ? scriptExecution.hiddenParameters : [] + name: scriptExecution.name + namedOutputs: contains(scriptExecution, 'namedOutputs') ? scriptExecution.namedOutputs : {} + output: contains(scriptExecution, 'output') ? scriptExecution.output : [] + parameters: contains(scriptExecution, 'parameters') ? scriptExecution.parameters : [] + retention: contains(scriptExecution, 'retention') ? scriptExecution.retention : '' + scriptCmdletId: contains(scriptExecution, 'scriptCmdletId') ? scriptExecution.scriptCmdletId : '' + timeout: contains(scriptExecution, 'timeout') ? scriptExecution.timeout : '' enableDefaultTelemetry: enableReferencedModulesTelemetry } }] @@ -330,17 +330,18 @@ module workloadNetworks_privateCloud_dhcpConfigurations 'workloadNetworks/dhcpCo } }] -module workloadNetworks_privateCloud_portMirroringProfiles 'workloadNetworks/portMirroringProfiles/deploy.bicep' = [for (portMirroringProfile, index) in portMirroringProfiles: { - name: '${uniqueString(deployment().name, location)}-privateCloud-portMirroringProfile-${index}' +module workloadNetworks_privateCloud_dnsServices 'workloadNetworks/dnsServices/deploy.bicep' = [for (dnsService, index) in dnsServices: { + name: '${uniqueString(deployment().name, location)}-privateCloud-dnsService-${index}' params: { privateCloudName: name workloadNetworkName: 'default' - destination: contains(portMirroringProfile, 'destination') ? portMirroringProfile.destination : '' - direction: contains(portMirroringProfile, 'direction') ? portMirroringProfile.direction : '' - displayName: contains(portMirroringProfile, 'displayName') ? portMirroringProfile.displayName : '' - name: portMirroringProfile.name - revision: contains(portMirroringProfile, 'revision') ? portMirroringProfile.revision : - source: contains(portMirroringProfile, 'source') ? portMirroringProfile.source : '' + defaultDnsZone: contains(dnsService, 'defaultDnsZone') ? dnsService.defaultDnsZone : '' + displayName: contains(dnsService, 'displayName') ? dnsService.displayName : '' + dnsServiceIp: contains(dnsService, 'dnsServiceIp') ? dnsService.dnsServiceIp : '' + fqdnZones: contains(dnsService, 'fqdnZones') ? dnsService.fqdnZones : [] + logLevel: contains(dnsService, 'logLevel') ? dnsService.logLevel : '' + name: dnsService.name + revision: contains(dnsService, 'revision') ? dnsService.revision : enableDefaultTelemetry: enableReferencedModulesTelemetry } }] @@ -361,6 +362,21 @@ module workloadNetworks_privateCloud_dnsZones 'workloadNetworks/dnsZones/deploy. } }] +module workloadNetworks_privateCloud_portMirroringProfiles 'workloadNetworks/portMirroringProfiles/deploy.bicep' = [for (portMirroringProfile, index) in portMirroringProfiles: { + name: '${uniqueString(deployment().name, location)}-privateCloud-portMirroringProfile-${index}' + params: { + privateCloudName: name + workloadNetworkName: 'default' + destination: contains(portMirroringProfile, 'destination') ? portMirroringProfile.destination : '' + direction: contains(portMirroringProfile, 'direction') ? portMirroringProfile.direction : '' + displayName: contains(portMirroringProfile, 'displayName') ? portMirroringProfile.displayName : '' + name: portMirroringProfile.name + revision: contains(portMirroringProfile, 'revision') ? portMirroringProfile.revision : + source: contains(portMirroringProfile, 'source') ? portMirroringProfile.source : '' + enableDefaultTelemetry: enableReferencedModulesTelemetry + } +}] + module workloadNetworks_privateCloud_publicIPs 'workloadNetworks/publicIPs/deploy.bicep' = [for (publicIP, index) in publicIPs: { name: '${uniqueString(deployment().name, location)}-privateCloud-publicIP-${index}' params: { @@ -373,18 +389,16 @@ module workloadNetworks_privateCloud_publicIPs 'workloadNetworks/publicIPs/deplo } }] -module workloadNetworks_privateCloud_dnsServices 'workloadNetworks/dnsServices/deploy.bicep' = [for (dnsService, index) in dnsServices: { - name: '${uniqueString(deployment().name, location)}-privateCloud-dnsService-${index}' +module workloadNetworks_privateCloud_segments 'workloadNetworks/segments/deploy.bicep' = [for (segment, index) in segments: { + name: '${uniqueString(deployment().name, location)}-privateCloud-segment-${index}' params: { privateCloudName: name workloadNetworkName: 'default' - defaultDnsZone: contains(dnsService, 'defaultDnsZone') ? dnsService.defaultDnsZone : '' - displayName: contains(dnsService, 'displayName') ? dnsService.displayName : '' - dnsServiceIp: contains(dnsService, 'dnsServiceIp') ? dnsService.dnsServiceIp : '' - fqdnZones: contains(dnsService, 'fqdnZones') ? dnsService.fqdnZones : [] - logLevel: contains(dnsService, 'logLevel') ? dnsService.logLevel : '' - name: dnsService.name - revision: contains(dnsService, 'revision') ? dnsService.revision : + connectedGateway: contains(segment, 'connectedGateway') ? segment.connectedGateway : '' + displayName: contains(segment, 'displayName') ? segment.displayName : '' + name: segment.name + revision: contains(segment, 'revision') ? segment.revision : + subnet: contains(segment, 'subnet') ? segment.subnet : {} enableDefaultTelemetry: enableReferencedModulesTelemetry } }] @@ -402,20 +416,6 @@ module workloadNetworks_privateCloud_vmGroups 'workloadNetworks/vmGroups/deploy. } }] -module workloadNetworks_privateCloud_segments 'workloadNetworks/segments/deploy.bicep' = [for (segment, index) in segments: { - name: '${uniqueString(deployment().name, location)}-privateCloud-segment-${index}' - params: { - privateCloudName: name - workloadNetworkName: 'default' - connectedGateway: contains(segment, 'connectedGateway') ? segment.connectedGateway : '' - displayName: contains(segment, 'displayName') ? segment.displayName : '' - name: segment.name - revision: contains(segment, 'revision') ? segment.revision : - subnet: contains(segment, 'subnet') ? segment.subnet : {} - enableDefaultTelemetry: enableReferencedModulesTelemetry - } -}] - // =========== // // Outputs // // =========== // diff --git a/utilities/tools/REST2CARML/private/module/Get-TemplateChildModuleContent.ps1 b/utilities/tools/REST2CARML/private/module/Get-TemplateChildModuleContent.ps1 index d3f791deb7..23d5c82c06 100644 --- a/utilities/tools/REST2CARML/private/module/Get-TemplateChildModuleContent.ps1 +++ b/utilities/tools/REST2CARML/private/module/Get-TemplateChildModuleContent.ps1 @@ -125,7 +125,7 @@ function Get-TemplateChildModuleContent { ##################################### $templateContent = @() - foreach ($dataBlock in $linkedChildren) { + foreach ($dataBlock in ($linkedChildren | Sort-Object -Property 'identifier')) { $childResourceType = ($dataBlock.identifier -split '/')[-1] $hasProxyParent = [String]::IsNullOrEmpty($dataBlock.metadata.parentUrlPath) diff --git a/utilities/tools/REST2CARML/private/module/Get-TemplateDeploymentsContent.ps1 b/utilities/tools/REST2CARML/private/module/Get-TemplateDeploymentsContent.ps1 index 0c1c386782..12a843ee56 100644 --- a/utilities/tools/REST2CARML/private/module/Get-TemplateDeploymentsContent.ps1 +++ b/utilities/tools/REST2CARML/private/module/Get-TemplateDeploymentsContent.ps1 @@ -256,18 +256,20 @@ function Get-TemplateDeploymentsContent { # - Anything we generate anew as a resource # - Telemetry (as it's regenerated above anyways) # - Existing parent resources (as they are regenerated above anyways) - $preExistingExtraResources = $existingTemplateContent.resources | Where-Object { - $_.name -notIn $ModuleData.resources.name + @('defaultTelemetry') + @($resourceTypeSingular) -and $_.content[0] -notlike '* existing = {' - } - foreach ($resource in $preExistingExtraResources) { - $templateContent += $resource.content - $templateContent += '' + if ($existingTemplateContent.resources.count -gt 0) { + $preExistingExtraResources = $existingTemplateContent.resources | Where-Object { + $_.name -notIn $ModuleData.resources.name + @('defaultTelemetry') + @($resourceTypeSingular) -and $_.content[0] -notlike '* existing = {' + } + foreach ($resource in $preExistingExtraResources) { + $templateContent += $resource.content + $templateContent += '' + } } # Add additional resources such as extensions (like DiagnosticSettigs) # -------------------------------------------------------------------- # Other collected resources - foreach ($additionalResource in $ModuleData.resources) { + foreach ($additionalResource in ($ModuleData.resources | Sort-Object 'name')) { if ($existingTemplateContent.resources.name -notcontains $additionalResource.name) { $templateContent += $additionalResource.content } else { diff --git a/utilities/tools/REST2CARML/private/module/Get-TemplateVariablesContent.ps1 b/utilities/tools/REST2CARML/private/module/Get-TemplateVariablesContent.ps1 index 3a9d9b7790..6df2aec519 100644 --- a/utilities/tools/REST2CARML/private/module/Get-TemplateVariablesContent.ps1 +++ b/utilities/tools/REST2CARML/private/module/Get-TemplateVariablesContent.ps1 @@ -90,7 +90,6 @@ function Get-TemplateVariablesContent { if ($existingTemplateContent.variables.name -notcontains 'enableReferencedModulesTelemetry') { $templateContent += @( 'var enableReferencedModulesTelemetry = false' - '' ) } else { $matchingExistingVar = $existingTemplateContent.variables | Where-Object { $_.name -eq 'enableReferencedModulesTelemetry' }