Skip to content

Commit

Permalink
Merge pull request Azure#5923 from bmoore-msft/newscript
Browse files Browse the repository at this point in the history
Added new Az cmdlet version of scripts
  • Loading branch information
bmoore-msft authored Mar 27, 2019
2 parents 838186a + 748acf5 commit 7938202
Show file tree
Hide file tree
Showing 2 changed files with 264 additions and 0 deletions.
204 changes: 204 additions & 0 deletions Deploy-AzTemplate.ps1
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") })
}
}
60 changes: 60 additions & 0 deletions SideLoad-CreateUIDefinition - Copy.ps1
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 $_
}

0 comments on commit 7938202

Please sign in to comment.