@@ -0,0 +1,120 @@
# Requires -Version 3.0
Param (
[string ] [Parameter (Mandatory = $true )] $ResourceGroupLocation ,
[string ] $ResourceGroupName = ' AzureResourceGroup29' ,
[switch ] $UploadArtifacts ,
[string ] $StorageAccountName ,
[string ] $StorageContainerName = $ResourceGroupName.ToLowerInvariant () + ' -stageartifacts' ,
[string ] $TemplateFile = ' WebSite.json' ,
[string ] $TemplateParametersFile = ' WebSite.parameters.json' ,
[string ] $ArtifactStagingDirectory = ' .' ,
[string ] $DSCSourceFolder = ' DSC' ,
[switch ] $ValidateOnly
)
try {
[Microsoft.Azure.Common.Authentication.AzureSession ]::ClientFactory.AddUserAgent(" VSAzureTools-$UI $ ( $host.name ) " .replace(' ' , ' _' ), ' 3.0.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
$TemplateFile = [System.IO.Path ]::GetFullPath([System.IO.Path ]::Combine($PSScriptRoot , $TemplateFile ))
$TemplateParametersFile = [System.IO.Path ]::GetFullPath([System.IO.Path ]::Combine($PSScriptRoot , $TemplateParametersFile ))
if ($UploadArtifacts ) {
# 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 - Expand $ArtifactsLocationName - ErrorAction Ignore | Select - Expand ' value' - ErrorAction Ignore
$OptionalParameters [$ArtifactsLocationSasTokenName ] = $JsonParameters | Select - Expand $ArtifactsLocationSasTokenName - ErrorAction Ignore | Select - 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-AzureRmVMDscConfiguration $DSCSourceFilePath - OutputArchivePath $DSCArchiveFilePath - Force - Verbose
}
}
# Create a storage account name if none was provided
if ($StorageAccountName -eq ' ' ) {
$StorageAccountName = ' stage' + ((Get-AzureRmContext ).Subscription.SubscriptionId).Replace(' -' , ' ' ).substring(0 , 19 )
}
$StorageAccount = (Get-AzureRmStorageAccount | Where-Object {$_.StorageAccountName -eq $StorageAccountName })
# Create the storage account if it doesn't already exist
if ($StorageAccount -eq $null ) {
$StorageResourceGroupName = ' ARM_Deploy_Staging'
New-AzureRmResourceGroup - Location " $ResourceGroupLocation " - Name $StorageResourceGroupName - Force
$StorageAccount = New-AzureRmStorageAccount - StorageAccountName $StorageAccountName - Type ' Standard_LRS' - ResourceGroupName $StorageResourceGroupName - Location " $ResourceGroupLocation "
}
# Generate the value for artifacts location if it is not provided in the parameter file
if ($OptionalParameters [$ArtifactsLocationName ] -eq $null ) {
$OptionalParameters [$ArtifactsLocationName ] = $StorageAccount.Context.BlobEndPoint + $StorageContainerName
}
# Copy files from the local storage staging location to the storage account container
New-AzureStorageContainer - Name $StorageContainerName - Context $StorageAccount.Context - ErrorAction SilentlyContinue * > & 1
$ArtifactFilePaths = Get-ChildItem $ArtifactStagingDirectory - Recurse - File | ForEach-Object - Process {$_.FullName }
foreach ($SourcePath in $ArtifactFilePaths ) {
Set-AzureStorageBlobContent - File $SourcePath - Blob $SourcePath.Substring ($ArtifactStagingDirectory.length + 1 ) `
- Container $StorageContainerName - Context $StorageAccount.Context - Force
}
# 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 ] = ConvertTo-SecureString - AsPlainText - Force `
(New-AzureStorageContainerSASToken - Container $StorageContainerName - Context $StorageAccount.Context - Permission r - ExpiryTime (Get-Date ).AddHours(4 ))
}
}
# Create the resource group only when it doesn't already exist
if ((Get-AzureRmResourceGroup - Name $ResourceGroupName - Location $ResourceGroupLocation - Verbose - ErrorAction SilentlyContinue) -eq $null ) {
New-AzureRmResourceGroup - Name $ResourceGroupName - Location $ResourceGroupLocation - Verbose - Force - ErrorAction Stop
}
if ($ValidateOnly ) {
$ErrorMessages = Format-ValidationOutput (Test-AzureRmResourceGroupDeployment - ResourceGroupName $ResourceGroupName `
- TemplateFile $TemplateFile `
- TemplateParameterFile $TemplateParametersFile `
@OptionalParameters )
if ($ErrorMessages ) {
Write-Output ' ' , ' Validation returned the following errors:' , @ ($ErrorMessages ), ' ' , ' Template is invalid.'
}
else {
Write-Output ' ' , ' Template is valid.'
}
}
else {
New-AzureRmResourceGroupDeployment - Name ((Get-ChildItem $TemplateFile ).BaseName + ' -' + ((Get-Date ).ToUniversalTime()).ToString(' MMdd-HHmm' )) `
- ResourceGroupName $ResourceGroupName `
- TemplateFile $TemplateFile `
- TemplateParameterFile $TemplateParametersFile `
@OptionalParameters `
- Force - Verbose `
- ErrorVariable ErrorMessages
if ($ErrorMessages ) {
Write-Output ' ' , ' Template deployment returned the following errors:' , @ (@ ($ErrorMessages ) | ForEach-Object { $_.Exception.Message.TrimEnd (" `r`n " ) })
}
}