forked from Azure/azure-quickstart-templates
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request Azure#5923 from bmoore-msft/newscript
Added new Az cmdlet version of scripts
- Loading branch information
Showing
2 changed files
with
264 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,204 @@ | ||
#Requires -Version 3.0 | ||
#Requires -Module Az.Resources | ||
#Requires -Module Az.Storage | ||
|
||
Param( | ||
[string] [Parameter(Mandatory = $true)] $ArtifactStagingDirectory, | ||
[string] [Parameter(Mandatory = $true)][alias("ResourceGroupLocation")] $Location, | ||
[string] $ResourceGroupName = (Split-Path $ArtifactStagingDirectory -Leaf), | ||
[switch] $UploadArtifacts, | ||
[string] $StorageAccountName, | ||
[string] $StorageContainerName = $ResourceGroupName.ToLowerInvariant() + '-stageartifacts', | ||
[string] $TemplateFile = $ArtifactStagingDirectory + '\mainTemplate.json', | ||
[string] $TemplateParametersFile = $ArtifactStagingDirectory + '.\azuredeploy.parameters.json', | ||
[string] $DSCSourceFolder = $ArtifactStagingDirectory + '.\DSC', | ||
[switch] $ValidateOnly, | ||
[string] $DebugOptions = "None", | ||
[switch] $Dev | ||
) | ||
|
||
try { | ||
[Microsoft.Azure.Common.Authentication.AzureSession]::ClientFactory.AddUserAgent("AzQuickStarts-$UI$($host.name)".replace(" ", "_"), "1.0") | ||
} | ||
catch { } | ||
|
||
$ErrorActionPreference = 'Stop' | ||
Set-StrictMode -Version 3 | ||
|
||
function Format-ValidationOutput { | ||
param ($ValidationOutput, [int] $Depth = 0) | ||
Set-StrictMode -Off | ||
return @($ValidationOutput | Where-Object { $_ -ne $null } | ForEach-Object { @(' ' * $Depth + ': ' + $_.Message) + @(Format-ValidationOutput @($_.Details) ($Depth + 1)) }) | ||
} | ||
|
||
$OptionalParameters = New-Object -TypeName Hashtable | ||
$TemplateArgs = New-Object -TypeName Hashtable | ||
|
||
# if the template file isn't found, try the another default | ||
if (!(Test-Path $TemplateFile)) { | ||
$TemplateFile = $ArtifactStagingDirectory + '\azuredeploy.json' | ||
} | ||
|
||
#try a few different default options for param files when the -dev switch is use | ||
if ($Dev) { | ||
$TemplateParametersFile = $TemplateParametersFile.Replace('azuredeploy.parameters.json', 'azuredeploy.parameters.dev.json') | ||
if (!(Test-Path $TemplateParametersFile)) { | ||
$TemplateParametersFile = $TemplateParametersFile.Replace('azuredeploy.parameters.dev.json', 'azuredeploy.parameters.1.json') | ||
} | ||
} | ||
|
||
Write-Host "Using parameter file: $TemplateParametersFile" | ||
|
||
if (!$ValidateOnly) { | ||
$OptionalParameters.Add('DeploymentDebugLogLevel', $DebugOptions) | ||
} | ||
|
||
$TemplateFile = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($PSScriptRoot, $TemplateFile)) | ||
$TemplateParametersFile = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($PSScriptRoot, $TemplateParametersFile)) | ||
|
||
$TemplateJSON = Get-Content $TemplateFile -Raw | ConvertFrom-Json | ||
|
||
$TemplateSchema = $TemplateJson | Select-Object -expand '$schema' -ErrorAction Ignore | ||
|
||
if ($TemplateSchema -like '*subscriptionDeploymentTemplate.json*') { | ||
$deploymentScope = "Subscription" | ||
} | ||
else { | ||
$deploymentScope = "ResourceGroup" | ||
} | ||
|
||
Write-Host "Running a $deploymentScope scoped deployment..." | ||
|
||
$ArtifactsLocationParameter = $TemplateJson | Select-Object -expand 'parameters' -ErrorAction Ignore | Select-Object -Expand '_artifactsLocation' -ErrorAction Ignore | ||
|
||
#if the switch is set or the standard parameter is present in the template, upload all artifacts | ||
if ($UploadArtifacts -Or $ArtifactsLocationParameter -ne $null) { | ||
# Convert relative paths to absolute paths if needed | ||
$ArtifactStagingDirectory = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($PSScriptRoot, $ArtifactStagingDirectory)) | ||
$DSCSourceFolder = [System.IO.Path]::GetFullPath([System.IO.Path]::Combine($PSScriptRoot, $DSCSourceFolder)) | ||
|
||
# Parse the parameter file and update the values of artifacts location and artifacts location SAS token if they are present | ||
$JsonParameters = Get-Content $TemplateParametersFile -Raw | ConvertFrom-Json | ||
if (($JsonParameters | Get-Member -Type NoteProperty 'parameters') -ne $null) { | ||
$JsonParameters = $JsonParameters.parameters | ||
} | ||
$ArtifactsLocationName = '_artifactsLocation' | ||
$ArtifactsLocationSasTokenName = '_artifactsLocationSasToken' | ||
$OptionalParameters[$ArtifactsLocationName] = $JsonParameters | Select-Object -Expand $ArtifactsLocationName -ErrorAction Ignore | Select-Object -Expand 'value' -ErrorAction Ignore | ||
$OptionalParameters[$ArtifactsLocationSasTokenName] = $JsonParameters | Select-Object -Expand $ArtifactsLocationSasTokenName -ErrorAction Ignore | Select-Object -Expand 'value' -ErrorAction Ignore | ||
|
||
# Create DSC configuration archive | ||
if (Test-Path $DSCSourceFolder) { | ||
$DSCSourceFilePaths = @(Get-ChildItem $DSCSourceFolder -File -Filter '*.ps1' | ForEach-Object -Process {$_.FullName}) | ||
foreach ($DSCSourceFilePath in $DSCSourceFilePaths) { | ||
$DSCArchiveFilePath = $DSCSourceFilePath.Substring(0, $DSCSourceFilePath.Length - 4) + '.zip' | ||
Publish-AzVMDscConfiguration $DSCSourceFilePath -OutputArchivePath $DSCArchiveFilePath -Force -Verbose | ||
} | ||
} | ||
|
||
# Create a storage account name if none was provided | ||
if ($StorageAccountName -eq '') { | ||
$StorageAccountName = 'stage' + ((Get-AzContext).Subscription.Id).Replace('-', '').substring(0, 19) | ||
} | ||
|
||
$StorageAccount = (Get-AzStorageAccount | Where-Object {$_.StorageAccountName -eq $StorageAccountName}) | ||
|
||
# Create the storage account if it doesn't already exist | ||
if ($StorageAccount -eq $null) { | ||
$StorageResourceGroupName = 'ARM_Deploy_Staging' | ||
New-AzResourceGroup -Location "$Location" -Name $StorageResourceGroupName -Force | ||
$StorageAccount = New-AzStorageAccount -StorageAccountName $StorageAccountName -Type 'Standard_LRS' -ResourceGroupName $StorageResourceGroupName -Location "$Location" | ||
} | ||
|
||
$ArtifactStagingLocation = $StorageAccount.Context.BlobEndPoint + $StorageContainerName + "/" | ||
|
||
# Generate the value for artifacts location if it is not provided in the parameter file | ||
if ($OptionalParameters[$ArtifactsLocationName] -eq $null) { | ||
#if the defaultValue for _artifactsLocation is using the template location, use the defaultValue, otherwise set it to the staging location | ||
$defaultValue = $ArtifactsLocationParameter | Select-Object -Expand 'defaultValue' -ErrorAction Ignore | ||
if ($defaultValue -like '*deployment().properties.templateLink.uri*') { | ||
$OptionalParameters.Remove($ArtifactsLocationName) | ||
} | ||
else { | ||
$OptionalParameters[$ArtifactsLocationName] = $ArtifactStagingLocation | ||
} | ||
} | ||
|
||
# Copy files from the local storage staging location to the storage account container | ||
New-AzStorageContainer -Name $StorageContainerName -Context $StorageAccount.Context -ErrorAction SilentlyContinue *>&1 | ||
|
||
$ArtifactFilePaths = Get-ChildItem $ArtifactStagingDirectory -Recurse -File | ForEach-Object -Process {$_.FullName} | ||
foreach ($SourcePath in $ArtifactFilePaths) { | ||
|
||
if ($SourcePath -like "$DSCSourceFolder*" -and $SourcePath -like "*.zip" -or !($SourcePath -like "$DSCSourceFolder*")) { | ||
#When using DSC, just copy the DSC archive, not all the modules and source files | ||
Set-AzStorageBlobContent -File $SourcePath -Blob $SourcePath.Substring($ArtifactStagingDirectory.length + 1) -Container $StorageContainerName -Context $StorageAccount.Context -Force | ||
#Write-host $SourcePath | ||
} | ||
} | ||
# Generate a 4 hour SAS token for the artifacts location if one was not provided in the parameters file | ||
if ($OptionalParameters[$ArtifactsLocationSasTokenName] -eq $null) { | ||
$OptionalParameters[$ArtifactsLocationSasTokenName] = (New-AzStorageContainerSASToken -Container $StorageContainerName -Context $StorageAccount.Context -Permission r -ExpiryTime (Get-Date).AddHours(4)) | ||
} | ||
|
||
$TemplateArgs.Add('TemplateFile', $ArtifactStagingLocation + (Get-ChildItem $TemplateFile).Name + $OptionalParameters[$ArtifactsLocationSasTokenName]) | ||
|
||
$OptionalParameters[$ArtifactsLocationSasTokenName] = ConvertTo-SecureString $OptionalParameters[$ArtifactsLocationSasTokenName] -AsPlainText -Force | ||
|
||
} | ||
else { | ||
|
||
$TemplateArgs.Add('TemplateFile', $TemplateFile) | ||
|
||
} | ||
|
||
$TemplateArgs.Add('TemplateParameterFile', $TemplateParametersFile) | ||
|
||
# Create the resource group only when it doesn't already exist - and only in RG scoped deployments | ||
if ($deploymentScope -eq "ResourceGroup") { | ||
if ((Get-AzResourcegroup -Name $ResourceGroupName -Location $Location -Verbose -ErrorAction SilentlyContinue) -eq $null) { | ||
New-AzResourceGroup -Name $ResourceGroupName -Location $Location -Verbose -Force -ErrorAction Stop | ||
} | ||
} | ||
if ($ValidateOnly) { | ||
if ($deploymentScope -eq "Subscription") { | ||
#subscription scoped deployment | ||
$ErrorMessages = Format-ValidationOutput (Test-AzDeployment -Location $Location ` | ||
@TemplateArgs ` | ||
@OptionalParameters) | ||
} | ||
else { | ||
#resourceGroup deployment | ||
$ErrorMessages = Format-ValidationOutput (Test-AzResourceGroupDeployment -ResourceGroupName $ResourceGroupName ` | ||
@TemplateArgs ` | ||
@OptionalParameters) | ||
} | ||
if ($ErrorMessages) { | ||
Write-Output '', 'Validation returned the following errors:', @($ErrorMessages), '', 'Template is invalid.' | ||
} | ||
else { | ||
Write-Output '', 'Template is valid.' | ||
} | ||
} | ||
else { | ||
if ($deploymentScope -eq "Subscription") { | ||
#subscription scoped deployment | ||
New-AzDeployment -Name ((Get-ChildItem $TemplateFile).BaseName + '-' + ((Get-Date).ToUniversalTime()).ToString('MMdd-HHmm')) ` | ||
-Location $Location ` | ||
@TemplateArgs ` | ||
@OptionalParameters ` | ||
-Verbose ` | ||
-ErrorVariable ErrorMessages | ||
} | ||
else { | ||
New-AzResourceGroupDeployment -Name ((Get-ChildItem $TemplateFile).BaseName + '-' + ((Get-Date).ToUniversalTime()).ToString('MMdd-HHmm')) ` | ||
-ResourceGroupName $ResourceGroupName ` | ||
@TemplateArgs ` | ||
@OptionalParameters ` | ||
-Force -Verbose ` | ||
-ErrorVariable ErrorMessages | ||
} | ||
if ($ErrorMessages) { | ||
Write-Output '', 'Template deployment returned the following errors:', @(@($ErrorMessages) | ForEach-Object { $_.Exception.Message.TrimEnd("`r`n") }) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
#Requires -Version 3.0 | ||
#Requires -Module Az.Resources | ||
#Requires -Module Az.Storage | ||
|
||
#use this script to side-load a createUIDefinition.json file in the Azure portal | ||
|
||
[cmdletbinding()] | ||
param( | ||
[string] $ArtifactsStagingDirectory = ".", | ||
[string] $createUIDefFile='createUIDefinition.json', | ||
[string] $storageContainerName='createuidef', | ||
[string] $StorageResourceGroupLocation, # this must be specified only when the staging resource group needs to be created - first run or if the account has been deleted | ||
[switch] $Gov | ||
) | ||
|
||
try { | ||
|
||
$StorageAccountName = 'stage' + ((Get-AzContext).Subscription.Id).Replace('-', '').substring(0, 19) | ||
$StorageAccount = (Get-AzStorageAccount | Where-Object{$_.StorageAccountName -eq $StorageAccountName}) | ||
|
||
# Create the storage account if it doesn't already exist | ||
if ($StorageAccount -eq $null) { | ||
if ($StorageResourceGroupLocation -eq "") { throw "The StorageResourceGroupLocation parameter is required on first run in a subscription." } | ||
$StorageResourceGroupName = 'ARM_Deploy_Staging' | ||
New-AzResourceGroup -Location "$StorageResourceGroupLocation" -Name $StorageResourceGroupName -Force | ||
$StorageAccount = New-AzmStorageAccount -StorageAccountName $StorageAccountName -Type 'Standard_LRS' -ResourceGroupName $StorageResourceGroupName -Location "$StorageResourceGroupLocation" | ||
} | ||
|
||
New-AzureStorageContainer -Name $StorageContainerName -Context $StorageAccount.Context -ErrorAction SilentlyContinue *>&1 | ||
|
||
Set-AzureStorageBlobContent -Container $StorageContainerName -File "$ArtifactsStagingDirectory\$createUIDefFile" -Context $storageAccount.Context -Force | ||
|
||
$uidefurl = New-AzureStorageBlobSASToken -Container $StorageContainerName -Blob (Split-Path $createUIDefFile -leaf) -Context $storageAccount.Context -FullUri -Permission r | ||
$encodedurl = [uri]::EscapeDataString($uidefurl) | ||
|
||
if ($Gov) { | ||
|
||
$target=@" | ||
https://portal.azure.us/#blade/Microsoft_Azure_Compute/CreateMultiVmWizardBlade/internal_bladeCallId/anything/internal_bladeCallerParams/{"initialData":{},"providerConfig":{"createUiDefinition":"$encodedurl"}} | ||
"@ | ||
|
||
} | ||
else { | ||
|
||
$target=@" | ||
https://portal.azure.com/#blade/Microsoft_Azure_Compute/CreateMultiVmWizardBlade/internal_bladeCallId/anything/internal_bladeCallerParams/{"initialData":{},"providerConfig":{"createUiDefinition":"$encodedurl"}} | ||
"@ | ||
|
||
} | ||
|
||
Write-Host `n"File: "$uidefurl `n | ||
Write-Host "Target URL: "$target | ||
|
||
# launching the default browser doesn't work if the default is Chrome - so force edge here | ||
Start-Process "microsoft-edge:$target" | ||
|
||
} | ||
catch { | ||
throw $_ | ||
} |