You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

119 lines
6.7 KiB

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