1+ # Requires -Version 3.0
2+ # Requires -Module AzureRM .Resources
3+ # Requires -Module Azure .Storage
4+
5+ Param (
6+ [string ] [Parameter (Mandatory = $true )] $ResourceGroupLocation ,
7+ [string ] $ResourceGroupName = ' eShopOnAzure.Deploy' ,
8+ [switch ] $UploadArtifacts ,
9+ [string ] $StorageAccountName ,
10+ [string ] $StorageContainerName = $ResourceGroupName.ToLowerInvariant () + ' -stageartifacts' ,
11+ [string ] $TemplateFile = ' azuredeploy.json' ,
12+ [string ] $TemplateParametersFile = ' azuredeploy.parameters.json' ,
13+ [string ] $ArtifactStagingDirectory = ' .' ,
14+ [string ] $DSCSourceFolder = ' DSC' ,
15+ [switch ] $ValidateOnly
16+ )
17+
18+ try {
19+ [Microsoft.Azure.Common.Authentication.AzureSession ]::ClientFactory.AddUserAgent(" VSAzureTools-$UI $ ( $host.name ) " .replace(' ' , ' _' ), ' 3.0.0' )
20+ } catch { }
21+
22+ $ErrorActionPreference = ' Stop'
23+ Set-StrictMode - Version 3
24+
25+ function Format-ValidationOutput {
26+ param ($ValidationOutput , [int ] $Depth = 0 )
27+ Set-StrictMode - Off
28+ return @ ($ValidationOutput | Where-Object { $_ -ne $null } | ForEach-Object { @ (' ' * $Depth + ' : ' + $_.Message ) + @ (Format-ValidationOutput @ ($_.Details ) ($Depth + 1 )) })
29+ }
30+
31+ $OptionalParameters = New-Object - TypeName Hashtable
32+ $TemplateFile = [System.IO.Path ]::GetFullPath([System.IO.Path ]::Combine($PSScriptRoot , $TemplateFile ))
33+ $TemplateParametersFile = [System.IO.Path ]::GetFullPath([System.IO.Path ]::Combine($PSScriptRoot , $TemplateParametersFile ))
34+
35+ if ($UploadArtifacts ) {
36+ # Convert relative paths to absolute paths if needed
37+ $ArtifactStagingDirectory = [System.IO.Path ]::GetFullPath([System.IO.Path ]::Combine($PSScriptRoot , $ArtifactStagingDirectory ))
38+ $DSCSourceFolder = [System.IO.Path ]::GetFullPath([System.IO.Path ]::Combine($PSScriptRoot , $DSCSourceFolder ))
39+
40+ # Parse the parameter file and update the values of artifacts location and artifacts location SAS token if they are present
41+ $JsonParameters = Get-Content $TemplateParametersFile - Raw | ConvertFrom-Json
42+ if (($JsonParameters | Get-Member - Type NoteProperty ' parameters' ) -ne $null ) {
43+ $JsonParameters = $JsonParameters.parameters
44+ }
45+ $ArtifactsLocationName = ' _artifactsLocation'
46+ $ArtifactsLocationSasTokenName = ' _artifactsLocationSasToken'
47+ $OptionalParameters [$ArtifactsLocationName ] = $JsonParameters | Select - Expand $ArtifactsLocationName - ErrorAction Ignore | Select - Expand ' value' - ErrorAction Ignore
48+ $OptionalParameters [$ArtifactsLocationSasTokenName ] = $JsonParameters | Select - Expand $ArtifactsLocationSasTokenName - ErrorAction Ignore | Select - Expand ' value' - ErrorAction Ignore
49+
50+ # Create DSC configuration archive
51+ if (Test-Path $DSCSourceFolder ) {
52+ $DSCSourceFilePaths = @ (Get-ChildItem $DSCSourceFolder - File - Filter ' *.ps1' | ForEach-Object - Process {$_.FullName })
53+ foreach ($DSCSourceFilePath in $DSCSourceFilePaths ) {
54+ $DSCArchiveFilePath = $DSCSourceFilePath.Substring (0 , $DSCSourceFilePath.Length - 4 ) + ' .zip'
55+ Publish-AzureRmVMDscConfiguration $DSCSourceFilePath - OutputArchivePath $DSCArchiveFilePath - Force - Verbose
56+ }
57+ }
58+
59+ # Create a storage account name if none was provided
60+ if ($StorageAccountName -eq ' ' ) {
61+ $StorageAccountName = ' stage' + ((Get-AzureRmContext ).Subscription.SubscriptionId).Replace(' -' , ' ' ).substring(0 , 19 )
62+ }
63+
64+ $StorageAccount = (Get-AzureRmStorageAccount | Where-Object {$_.StorageAccountName -eq $StorageAccountName })
65+
66+ # Create the storage account if it doesn't already exist
67+ if ($StorageAccount -eq $null ) {
68+ $StorageResourceGroupName = ' ARM_Deploy_Staging'
69+ New-AzureRmResourceGroup - Location " $ResourceGroupLocation " - Name $StorageResourceGroupName - Force
70+ $StorageAccount = New-AzureRmStorageAccount - StorageAccountName $StorageAccountName - Type ' Standard_LRS' - ResourceGroupName $StorageResourceGroupName - Location " $ResourceGroupLocation "
71+ }
72+
73+ # Generate the value for artifacts location if it is not provided in the parameter file
74+ if ($OptionalParameters [$ArtifactsLocationName ] -eq $null ) {
75+ $OptionalParameters [$ArtifactsLocationName ] = $StorageAccount.Context.BlobEndPoint + $StorageContainerName
76+ }
77+
78+ # Copy files from the local storage staging location to the storage account container
79+ New-AzureStorageContainer - Name $StorageContainerName - Context $StorageAccount.Context - ErrorAction SilentlyContinue * > & 1
80+
81+ $ArtifactFilePaths = Get-ChildItem $ArtifactStagingDirectory - Recurse - File | ForEach-Object - Process {$_.FullName }
82+ foreach ($SourcePath in $ArtifactFilePaths ) {
83+ Set-AzureStorageBlobContent - File $SourcePath - Blob $SourcePath.Substring ($ArtifactStagingDirectory.length + 1 ) `
84+ - Container $StorageContainerName - Context $StorageAccount.Context - Force
85+ }
86+
87+ # Generate a 4 hour SAS token for the artifacts location if one was not provided in the parameters file
88+ if ($OptionalParameters [$ArtifactsLocationSasTokenName ] -eq $null ) {
89+ $OptionalParameters [$ArtifactsLocationSasTokenName ] = ConvertTo-SecureString - AsPlainText - Force `
90+ (New-AzureStorageContainerSASToken - Container $StorageContainerName - Context $StorageAccount.Context - Permission r - ExpiryTime (Get-Date ).AddHours(4 ))
91+ }
92+ }
93+
94+ # Create or update the resource group using the specified template file and template parameters file
95+ New-AzureRmResourceGroup - Name $ResourceGroupName - Location $ResourceGroupLocation - Verbose - Force
96+
97+ if ($ValidateOnly ) {
98+ $ErrorMessages = Format-ValidationOutput (Test-AzureRmResourceGroupDeployment - ResourceGroupName $ResourceGroupName `
99+ - TemplateFile $TemplateFile `
100+ - TemplateParameterFile $TemplateParametersFile `
101+ @OptionalParameters )
102+ if ($ErrorMessages ) {
103+ Write-Output ' ' , ' Validation returned the following errors:' , @ ($ErrorMessages ), ' ' , ' Template is invalid.'
104+ }
105+ else {
106+ Write-Output ' ' , ' Template is valid.'
107+ }
108+ }
109+ else {
110+ New-AzureRmResourceGroupDeployment - Name ((Get-ChildItem $TemplateFile ).BaseName + ' -' + ((Get-Date ).ToUniversalTime()).ToString(' MMdd-HHmm' )) `
111+ - ResourceGroupName $ResourceGroupName `
112+ - TemplateFile $TemplateFile `
113+ - TemplateParameterFile $TemplateParametersFile `
114+ @OptionalParameters `
115+ - Force - Verbose `
116+ - ErrorVariable ErrorMessages
117+ if ($ErrorMessages ) {
118+ Write-Output ' ' , ' Template deployment returned the following errors:' , @ (@ ($ErrorMessages ) | ForEach-Object { $_.Exception.Message.TrimEnd (" `r`n " ) })
119+ }
120+ }
0 commit comments