From 28802865f33ab532944a72a27082d75b7fe15bb3 Mon Sep 17 00:00:00 2001 From: uday31in <14359777+uday31in@users.noreply.github.com> Date: Mon, 17 Aug 2020 00:48:17 +0100 Subject: [PATCH 1/3] Adding suppot for template deployment without parameter files --- src/AzOps.psm1 | 10 +- src/private/New-AzOpsDeployment.ps1 | 183 +++++++++++++++++++++++ src/private/New-AzOpsStateDeployment.ps1 | 93 ------------ src/public/Invoke-AzOpsGitPush.ps1 | 95 +++++++++++- 4 files changed, 281 insertions(+), 100 deletions(-) create mode 100644 src/private/New-AzOpsDeployment.ps1 diff --git a/src/AzOps.psm1 b/src/AzOps.psm1 index a763cbd8..f14d00e6 100644 --- a/src/AzOps.psm1 +++ b/src/AzOps.psm1 @@ -96,6 +96,7 @@ class AzOpsScope { $resourcepath = Get-Content ($path) | ConvertFrom-Json -AsHashtable if ( + ($null -ne $resourcepath) -and ($resourcepath.Keys -contains "`$schema") -and ($resourcepath.Keys -contains "parameters") -and ($resourcepath.parameters.Keys -contains "input") @@ -229,7 +230,6 @@ class AzOpsScope { $this.subscriptionDisplayName = $this.GetSubscriptionDisplayName() $this.managementgroup = $this.GetManagementGroup() $this.managementgroupDisplayName = $this.GetManagementGroupName() - # $this.statepath = (join-path $this.FindAzOpsStatePath() -ChildPath "subscription.json") if ($global:AzOpsExportRawTemplate -eq 1) { $this.statepath = (join-path $this.GetAzOpsSubscriptionPath() -ChildPath ".AzState\Microsoft.Subscription-subscriptions_$($this.subscription).json") } @@ -529,7 +529,12 @@ function New-AzOpsScope { elseif ($PSCmdlet.ParameterSetName -eq "pathfile") { # Remove .AzState file extension if present $path = $path -replace $regex_findAzStateFileExtension, '' - if ((Test-Path $path) -and (Test-Path $path -IsValid) -and $PSCmdlet.ShouldProcess("Create new pathfile object?")) { + if ( + (Test-Path $path) -and + (Test-Path $path -IsValid) -and + (Resolve-Path $path).path.StartsWith((Resolve-Path $Global:AzOpsState).Path) -and + $PSCmdlet.ShouldProcess("Create new pathfile object?") + ) { Write-AzOpsLog -Level Verbose -Topic "New-AzOpsScope" -Message ("Creating new AzOpsScope object using path [$path]") return [AzOpsScope]::new($(Get-Item $path)) } @@ -546,5 +551,4 @@ function New-AzOpsScope { Write-AzOpsLog -Level Debug -Topic "New-AzOpsScope" -Message ("Initiating function " + $MyInvocation.MyCommand + " end") } } - Export-ModuleMember -Function * -Alias * diff --git a/src/private/New-AzOpsDeployment.ps1 b/src/private/New-AzOpsDeployment.ps1 new file mode 100644 index 00000000..d026deb0 --- /dev/null +++ b/src/private/New-AzOpsDeployment.ps1 @@ -0,0 +1,183 @@ +<# +.SYNOPSIS + This cmdlet processes AzOpsState changes and takes appropriate action by invoking ARM deployment and limited set of imperative operations required by platform that is currently not supported in ARM. +.DESCRIPTION + This cmdlet invokes ARM deployment by calling New-AzDeployment* command at appropriate scope mapped to tenant, Management Group, Subscription or resource group in AzOpsState folder. + 1) Template File Path .json + 2) Optional Parameter file that must end with .parameters.json + 3) This cmdlet will look for .json in same directory and use that template if found. + 4) If no template file is found, it will use default template\template.json for supported resource types. + +.EXAMPLE + # Invoke ARM Template Deployment + New-AzOpsDeployment -templateParameterFilePath 'C:\Git\CET-NorthStar\azops\3fc1081d-6105-4e19-b60c-1ec1252cf560\contoso\.AzState\Microsoft.Management-managementGroups_contoso.parameters.json' +.INPUTS + Filename +.OUTPUTS + None +#> +function New-AzOpsDeployment { + # The following SuppressMessageAttribute entries are used to suppress + # PSScriptAnalyzer tests against known exceptions as per: + # https://github.com/powershell/psscriptanalyzer#suppressing-rules + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidGlobalVars', 'global:AzOpsDefaultDeploymentRegion')] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidGlobalVars', 'global:AzOpsMainTemplate')] + [CmdletBinding(SupportsShouldProcess = $true)] + param ( + [Parameter(Position = 0, ParameterSetName = "template", Mandatory = $false, ValueFromPipeline = $true)] + [string]$name = "azops-template-deployment", + [Parameter(Position = 0, ParameterSetName = "template", ValueFromPipeline = $true)] + [ValidateScript( { Test-Path $_ })] + [string]$templateFilePath, + [Parameter(Position = 0, ParameterSetName = "template", Mandatory = $false, ValueFromPipeline = $true)] + [string]$templateParameterFilePath, + [Parameter(Position = 0, ParameterSetName = "template", Mandatory = $false, ValueFromPipeline = $true)] + [string]$Mode = "Incremental" + ) + begin { + Write-AzOpsLog -Level Debug -Topic "New-AzOpsDeployment" -Message ("Initiating function " + $MyInvocation.MyCommand + " begin") + } + process { + Write-AzOpsLog -Level Debug -Topic "New-AzOpsDeployment" -Message ("Initiating function " + $MyInvocation.MyCommand + " process") + + if ($templateParameterFilePath) { + $scope = New-AzOpsScope -path $templateParameterFilePath + } + else { + $scope = New-AzOpsScope -path $templateFilePath + } + if ($scope) { + #Evaluate Deployment Scope + if ($scope.resourcegroup) { + Write-AzOpsLog -Level Verbose -Topic "New-AzOpsDeployment" -Message "Attempting [Resource Group] deployment" + if ((Get-AzContext).Subscription.Id -ne $scope.subscription) { + Write-AzOpsLog -Level Verbose -Topic "New-AzOpsDeployment" -Message "Switching Subscription context from $($(Get-AzContext).Subscription.Name) to $scope.subscription " + Set-AzContext -SubscriptionId $scope.subscription + } + $parameters = @{ + 'TemplateFile' = $templateFilePath + 'SkipTemplateParameterPrompt' = $true + 'ResourceGroupName' = $scope.resourcegroup + } + # Add Parameter file if specified + if ($templateParameterFilePath) { + $parameters.Add('TemplateParameterFile', $templateParameterFilePath) + } + #Validate Template + $results = Test-AzResourceGroupDeployment @parameters + + if (-not $results) { + $parameters.Add('Name', $deploymentName) + if (-not ($PSCmdlet.ShouldProcess("Start ManagementGroup Deployment?"))) { + # Whatif Placeholder + New-AzResourceGroupDeployment @parameters -WhatIf -WhatIfResultFormat FullResourcePayloads + } + else { + New-AzResourceGroupDeployment @parameters + } + } + else { + Write-AzOpsLog -Level Error -Topic "New-AzOpsDeployment" -Message "Template Validation Failed $($results.Message)" + } + } + elseif ($scope.subscription) { + Write-AzOpsLog -Level Verbose -Topic "New-AzOpsDeployment" -Message "Attempting [Subscription] deployment in [$($global:AzOpsDefaultDeploymentRegion)]" + if ((Get-AzContext).Subscription.Id -ne $scope.subscription) { + Write-AzOpsLog -Level Verbose -Topic "New-AzOpsDeployment" -Message "Switching Subscription context from $($(Get-AzContext).Subscription.Name) to $scope.subscription " + Set-AzContext -SubscriptionId $scope.subscription + } + $parameters = @{ + 'TemplateFile' = $templateFilePath + 'location' = $global:AzOpsDefaultDeploymentRegion + 'SkipTemplateParameterPrompt' = $true + } + # Add Parameter file if specified + if ($templateParameterFilePath) { + $parameters.Add('TemplateParameterFile', $templateParameterFilePath) + } + #Validate Template + $results = Test-AzSubscriptionDeployment @parameters + + if (-not $results) { + $parameters.Add('Name', $deploymentName) + if (-not ($PSCmdlet.ShouldProcess("Start ManagementGroup Deployment?"))) { + # Whatif Placeholder + New-AzSubscriptionDeployment @parameters -WhatIf -WhatIfResultFormat FullResourcePayloads + } + else { + New-AzSubscriptionDeployment @parameters + } + } + else { + Write-AzOpsLog -Level Error -Topic "New-AzOpsDeployment" -Message "Template Validation Failed $($results.Message)" + } + } + elseif ($scope.managementGroup) { + Write-AzOpsLog -Level Verbose -Topic "New-AzOpsDeployment" -Message "Attempting [Management Group] deployment in [$($global:AzOpsDefaultDeploymentRegion)]" + $parameters = @{ + 'TemplateFile' = $templateFilePath + 'location' = $global:AzOpsDefaultDeploymentRegion + 'ManagementGroupId' = $scope.managementgroup + 'SkipTemplateParameterPrompt' = $true + } + # Add Parameter file if specified + if ($templateParameterFilePath) { + $parameters.Add('TemplateParameterFile', $templateParameterFilePath) + } + #Validate Template + $results = Test-AzManagementGroupDeployment @parameters + + if (-not $results) { + $parameters.Add('Name', $deploymentName) + if (-not ($PSCmdlet.ShouldProcess("Start ManagementGroup Deployment?"))) { + # Whatif Placeholder + New-AzManagementGroupDeployment @parameters -WhatIf + } + else { + New-AzManagementGroupDeployment @parameters + } + } + else { + Write-AzOpsLog -Level Error -Topic "New-AzOpsDeployment" -Message "Template Validation Failed $($results.Message)" + } + } + elseif ($scope.type -eq 'root' -and $scope.scope -eq '/') { + Write-AzOpsLog -Level Verbose -Topic "New-AzOpsDeployment" -Message "Attempting [Tenant Scope] deployment in [$($global:AzOpsDefaultDeploymentRegion)]" + $parameters = @{ + 'TemplateFile' = $templateFilePath + 'location' = $global:AzOpsDefaultDeploymentRegion + 'SkipTemplateParameterPrompt' = $true + } + # Add Parameter file if specified + if ($templateParameterFilePath) { + $parameters.Add('TemplateParameterFile', $templateParameterFilePath) + } + #Validate Template + $results = Test-AzTenantDeployment @parameters + + if (-not $results) { + $parameters.Add('Name', $deploymentName) + if (-not ($PSCmdlet.ShouldProcess("Start ManagementGroup Deployment?"))) { + # Whatif Placeholder + New-AzTenantDeployment @parameters -WhatIf + } + else { + New-AzTenantDeployment @parameters + } + } + else { + Write-AzOpsLog -Level Error -Topic "New-AzOpsDeployment" -Message "Template Validation Failed $($results.Message)" + } + } + else { + Write-AzOpsLog -Level Warning -Topic "New-AzOpsDeployment" -Message "Unable to determine scope type for Az deployment" + } + } + else { + Write-AzOpsLog -Level Warning -Topic "New-AzOpsDeployment" -Message "Unable to determine scope for templateFilePath: $templateFilePath and templateParameterFilePath: $templateParameterFilePath" + } + } + end { + Write-AzOpsLog -Level Debug -Topic "New-AzOpsDeployment" -Message ("Initiating function " + $MyInvocation.MyCommand + " end") + } +} \ No newline at end of file diff --git a/src/private/New-AzOpsStateDeployment.ps1 b/src/private/New-AzOpsStateDeployment.ps1 index e11061e4..d79831e2 100644 --- a/src/private/New-AzOpsStateDeployment.ps1 +++ b/src/private/New-AzOpsStateDeployment.ps1 @@ -2,10 +2,6 @@ .SYNOPSIS This cmdlet processes AzOpsState changes and takes appropriate action by invoking ARM deployment and limited set of imperative operations required by platform that is currently not supported in ARM. .DESCRIPTION - This cmdlet invokes ARM deployment by calling New-AzDeployment* command at appropriate scope mapped to tenant, Management Group, Subscription or resource group in AzOpsState folder. - 1) Filename must end with .parameters.json - 2) This cmdlet will look for .json in same directory and use that template if found. - 3) If no template file is found, it will use default template\template.json for supported resource types. This cmdlet invokes following imperative operations that are not supported in ARM. 1) Subscription Creation with Enterprise Enrollment - Subscription will be created if not found in Azure where service principle have access. Subscription will also be moved to the Management Group. @@ -25,9 +21,6 @@ "RegistrationState": "" } ] -.EXAMPLE - # Invoke ARM Template Deployment - New-AzOpsStateDeployment -filename 'C:\Git\CET-NorthStar\azops\3fc1081d-6105-4e19-b60c-1ec1252cf560\contoso\.AzState\Microsoft.Management-managementGroups_contoso.parameters.json' .EXAMPLE # Invoke Subscription Creation New-AzOpsStateDeployment -filename 'C:\Git\CET-NorthStar\azops\3fc1081d-6105-4e19-b60c-1ec1252cf560\contoso\platform\connectivity\subscription.json' @@ -124,96 +117,10 @@ function New-AzOpsStateDeployment { Register-AzOpsResourceProvider -filename $filename -scope $scope } - if ($filename -match '/*.parameters.json$') { - Write-AzOpsLog -Level Verbose -Topic "New-AzOpsStateDeployment" -Message "Template deployment" - - $MainTemplateSupportedTypes = @( - "Microsoft.Resources/resourceGroups", - "Microsoft.Authorization/policyAssignments", - "Microsoft.Authorization/policyDefinitions", - "Microsoft.Authorization/PolicySetDefinitions", - "Microsoft.Authorization/roleDefinitions", - "Microsoft.Authorization/roleAssignments", - "Microsoft.PolicyInsights/remediations", - "Microsoft.ContainerService/ManagedClusters", - "Microsoft.KeyVault/vaults", - "Microsoft.Network/virtualWans", - "Microsoft.Network/virtualHubs", - "Microsoft.Network/virtualNetworks", - "Microsoft.Network/azureFirewalls", - "/providers/Microsoft.Management/managementGroups", - "/subscriptions" - ) - - if (($scope.subscription) -and (Get-AzContext).Subscription.Id -ne $scope.subscription) { - Write-AzOpsLog -Level Verbose -Topic "New-AzOpsStateDeployment" -Message "Switching Subscription context from $($(Get-AzContext).Subscription.Name) to $scope.subscription " - Set-AzContext -SubscriptionId $scope.subscription - } - - $templatename = (Get-Item $filename).BaseName.Replace('.parameters', '.json') - $templatePath = (Join-Path (Get-Item $filename).Directory.FullName -ChildPath $templatename ) - if (Test-Path $templatePath) { - $templatePath = (Join-Path (Get-Item $filename).Directory.FullName -ChildPath $templatename ) - } - else { - - $effectiveResourceType = '' - # Check if generic template is supporting the resource type for the deployment. - if ((Get-Member -InputObject $templateParametersJson.parameters.input.value -Name ResourceType)) { - $effectiveResourceType = $templateParametersJson.parameters.input.value.ResourceType - } - elseif ((Get-Member -InputObject $templateParametersJson.parameters.input.value -Name Type)) { - $effectiveResourceType = $templateParametersJson.parameters.input.value.Type - } - else { - $effectiveResourceType = '' - } - if ($effectiveResourceType -and ($MainTemplateSupportedTypes -Contains $effectiveResourceType)) { - $templatePath = $global:AzOpsMainTemplate - } - } - - if (Test-Path $templatePath) { - $deploymentName = (Get-Item $filename).BaseName.replace('.parameters', '').Replace(' ', '_') - - if ($deploymentName.Length -gt 64) { - $deploymentName = $deploymentName.SubString($deploymentName.IndexOf('-') + 1) - } - Write-AzOpsLog -Level Verbose -Topic "New-AzOpsStateDeployment" -Message "Template is $templatename / $templatepath and Deployment Name is $deploymentName" - if ($scope.resourcegroup) { - Write-AzOpsLog -Level Verbose -Topic "New-AzOpsStateDeployment" -Message "Starting [Resource Group] deployment in [$($global:AzOpsDefaultDeploymentRegion)]" - Test-AzResourceGroupDeployment -ResourceGroupName $scope.resourcegroup -TemplateFile $templatePath -TemplateParameterFile $filename -OutVariable templateErrors - if (-not $templateErrors -and $PSCmdlet.ShouldProcess("Start Resource Group Deployment?")) { - New-AzResourceGroupDeployment -ResourceGroupName $scope.resourcegroup -TemplateFile $templatePath -TemplateParameterFile $filename -Name $deploymentName - } - else { - Write-AzOpsLog -Level Error -Topic "New-AzOpsStateDeployment" -Message "Resource Group [$($scope.resourcegroup)] not found. Unable to initiate deployment" - } - } - elseif ($scope.subscription -and $PSCmdlet.ShouldProcess("Start Subscription Deployment?")) { - Write-AzOpsLog -Level Verbose -Topic "New-AzOpsStateDeployment" -Message "Starting [Subscription] deployment in [$($global:AzOpsDefaultDeploymentRegion)]" - New-AzSubscriptionDeployment -Location $global:AzOpsDefaultDeploymentRegion -TemplateFile $templatePath -TemplateParameterFile $filename -Name $deploymentName - } - elseif ($scope.managementgroup -and $PSCmdlet.ShouldProcess("Start Management Group Deployment?")) { - Write-AzOpsLog -Level Verbose -Topic "New-AzOpsStateDeployment" -Message "Starting [Management Group] deployment in [$($global:AzOpsDefaultDeploymentRegion)]" - New-AzManagementGroupDeployment -ManagementGroupId $scope.managementgroup -Name $deploymentName -Location $global:AzOpsDefaultDeploymentRegion -TemplateFile $templatePath -TemplateParameterFile $filename - } - elseif ($scope.type -eq 'root' -and $PSCmdlet.ShouldProcess("Start Tenant Deployment?")) { - Write-AzOpsLog -Level Verbose -Topic "New-AzOpsStateDeployment" -Message "Starting [Tenant] deployment in [$($global:AzOpsDefaultDeploymentRegion)]" - New-AzTenantDeployment -Name $deploymentName -Location $global:AzOpsDefaultDeploymentRegion -TemplateFile $templatePath -TemplateParameterFile $filename - } - } - } - else { - Write-AzOpsLog -Level Verbose -Topic "New-AzOpsStateDeployment" -Message "Template Path for $templatePath for $filename not found" - } } else { Write-AzOpsLog -Level Warning -Topic "New-AzOpsStateDeployment" -Message "Unable to determine scope type for $filename" } - } - end {} - } \ No newline at end of file diff --git a/src/public/Invoke-AzOpsGitPush.ps1 b/src/public/Invoke-AzOpsGitPush.ps1 index 24c237c8..36f9cf3b 100644 --- a/src/public/Invoke-AzOpsGitPush.ps1 +++ b/src/public/Invoke-AzOpsGitPush.ps1 @@ -249,12 +249,99 @@ function Invoke-AzOpsGitPush { New-AzOpsStateDeployment -filename $_ } + $AzOpsDeploymentList = @() $addModifySet ` - | Where-Object -FilterScript { $_ -match '/*.parameters.json$' } ` - | Sort-Object -Property $_ ` + | Where-Object -FilterScript { $_ -match ((get-item $Global:AzOpsState).Name) } ` | Foreach-Object { - Write-AzOpsLog -Level Information -Topic "Invoke-AzOpsGitPush" -Message "Invoking new state deployment - *.parameters.json for a file $_" - New-AzOpsStateDeployment -filename $_ + $scope = (New-AzOpsScope -path $_) + if ($scope) { + $templateFilePath = $null + $templateParameterFilePath = $null + $deploymentName = $null + #Find the template + if ($_.EndsWith('.parameters.json')) { + $templateParameterFilePath = (Get-Item $_).FullName + + if (Test-Path (Get-Item $_).FullName.Replace('.parameters.json', '.json')) { + Write-AzOpsLog -Level Information -Topic "pwsh" -Message "Template found $(($(Get-Item $_).FullName.Replace('.parameters.json', '.json')))" + $templateFilePath = (Get-Item $_).FullName.Replace('.parameters.json', '.json') + } + else { + Write-AzOpsLog -Level Information -Topic "pwsh" -Message "Template NOT found $(($(Get-Item $_).FullName.Replace('.parameters.json', '.json')))" + Write-AzOpsLog -Level Information -Topic "pwsh" -Message "Determining resource type $((Get-Item $global:AzOpsMainTemplate).FullName)" + # Determine Resource Type in Parameter file + $templateParameterFileHashtable = Get-Content ($_) | ConvertFrom-Json -AsHashtable + $effectiveResourceType = $null + if ( + ($null -ne $templateParameterFileHashtable) -and + ($templateParameterFileHashtable.Keys -contains "`$schema") -and + ($templateParameterFileHashtable.Keys -contains "parameters") -and + ($templateParameterFileHashtable.parameters.Keys -contains "input") + ) { + if ($templateParameterFileHashtable.parameters.input.value.Keys -contains "Type") { + # ManagementGroup and Subscription + $effectiveResourceType = $templateParameterFileHashtable.parameters.input.value.Type + } + elseif ($templateParameterFileHashtable.parameters.input.value.Keys -contains "ResourceType") { + # Resource + $effectiveResourceType = $templateParameterFileHashtable.parameters.input.value.ResourceType + } + } + # Check if generic template is supporting the resource type for the deployment. + if ($effectiveResourceType -and + ((Get-Content (Get-Item $global:AzOpsMainTemplate).FullName) | ConvertFrom-Json -AsHashtable).variables.apiVersionLookup.ContainsKey($effectiveResourceType)) { + Write-AzOpsLog -Level Information -Topic "pwsh" -Message "effectiveResourceType: $effectiveResourceType AzOpsMainTemplate supports resource type $effectiveResourceType in $((Get-Item $global:AzOpsMainTemplate).FullName)" + $templateFilePath = (Get-Item $global:AzOpsMainTemplate).FullName + } + else { + Write-AzOpsLog -Level Warning -Topic "pwsh" -Message "effectiveResourceType: $effectiveResourceType AzOpsMainTemplate does NOT supports resource type $effectiveResourceType in $((Get-Item $global:AzOpsMainTemplate).FullName). Deployment will be ignored" + } + } + } + #Find the template parameter file + elseif ($_.EndsWith('.json')) { + $templateFilePath = (Get-Item $_).FullName + if (Test-Path (Get-Item $_).FullName.Replace('.json', '.parameters.json')) { + Write-AzOpsLog -Level Information -Topic "pwsh" -Message "Template Parameter found $(($(Get-Item $_).FullName.Replace('.json', '.parameters.json')))" + $templateParameterFilePath = (Get-Item $_).FullName.Replace('.json', '.parameters.json') + } + else { + Write-AzOpsLog -Level Information -Topic "pwsh" -Message "Template Parameter NOT found $(($(Get-Item $_).FullName.Replace('.json', '.parameters.json')))" + } + } + #Deployment Name + if ($null -ne $templateParameterFilePath) { + $deploymentName = (Get-Item $templateParameterFilePath).BaseName.replace('.parameters', '').Replace(' ', '_') + if ($deploymentName.Length -gt 64) { + $deploymentName = $deploymentName.SubString($deploymentName.IndexOf('-') + 1) + } + } + elseif ($null -ne $templateFilePath) { + $deploymentName = (Get-Item $templateFilePath).BaseName.replace('.json', '').Replace(' ', '_') + if ($deploymentName.Length -gt 64) { + $deploymentName = $deploymentName.SubString($deploymentName.IndexOf('-') + 1) + } + } + #construct deployment object + $AzOpsDeploymentList += [PSCustomObject] @{ + [string] 'templateFilePath' = $templateFilePath + [string] 'templateParameterFilePath' = $templateParameterFilePath + [string] 'deploymentName' = $deploymentName + [string] 'scope' = $scope.scope + } + #New-AzOpsDeployment -templateFilePath $templateFilePath -templateParameterFilePath $templateParameterFilePath + } + else { + Write-AzOpsLog -Level Information -Topic "pwsh" -Message "$_ is not under $($Global:AzOpsState) and ignored for the deployment" + } + } + #Starting Tenant Deployment + $AzOpsDeploymentList ` + | Where-Object -FilterScript { $null -ne $_.templateFilePath } ` + | Select-Object scope, deploymentName, templateFilePath, templateParameterFilePath -Unique ` + | ForEach-Object { + New-AzOpsDeployment -templateFilePath $_.templateFilePath ` + -templateParameterFilePath ($_.templateParameterFilePath ? $_.templateParameterFilePath : $null) } } else { From 5973e4d24810799ceb8791115a0928e6a6b73387 Mon Sep 17 00:00:00 2001 From: uday31in <14359777+uday31in@users.noreply.github.com> Date: Mon, 17 Aug 2020 02:44:48 +0100 Subject: [PATCH 2/3] updating test for template deployments --- src/private/Invoke-AzOpsChange.ps1 | 175 ++++++++++++++++++++++++++++ src/private/New-AzOpsDeployment.ps1 | 2 +- src/public/Invoke-AzOpsGitPush.ps1 | 145 +---------------------- tests/AzOps.IAB.Tests.ps1 | 71 ++++------- 4 files changed, 199 insertions(+), 194 deletions(-) create mode 100644 src/private/Invoke-AzOpsChange.ps1 diff --git a/src/private/Invoke-AzOpsChange.ps1 b/src/private/Invoke-AzOpsChange.ps1 new file mode 100644 index 00000000..64eb13ba --- /dev/null +++ b/src/private/Invoke-AzOpsChange.ps1 @@ -0,0 +1,175 @@ +<# +.SYNOPSIS + This cmdlet processes AzOps changes. +.DESCRIPTION + + Invoke-AzOpsChange -changeset [filenames] +.INPUTS + Array of Filename +.OUTPUTS + None +#> +function Invoke-AzOpsChange { + + # The following SuppressMessageAttribute entries are used to surpress + # PSScriptAnalyzer tests against known exceptions as per: + # https://github.com/powershell/psscriptanalyzer#suppressing-rules + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidGlobalVars', 'global:AzOpsDefaultDeploymentRegion')] + [Diagnostics.CodeAnalysis.SuppressMessageAttribute('PSAvoidGlobalVars', 'global:AzOpsMainTemplate')] + [CmdletBinding(SupportsShouldProcess = $true)] + param( + [Parameter(Mandatory = $true, ValueFromPipeline = $true)] + [string[]]$changeSet + ) + begin {} + + process { + if ($changeSet) { + Write-AzOpsLog -Level Information -Topic "git" -Message "Deployment required" + $deleteSet = @() + $addModifySet = @() + foreach ($change in $changeSet) { + $filename = ($change -split "`t")[-1] + if (($change -split "`t" | Select-Object -first 1) -eq 'D') { + $deleteSet += $filename + } + elseif (($change -split "`t" | Select-Object -first 1) -eq 'A' -or 'M' -or 'R') { + $addModifySet += $filename + } + } + + Write-AzOpsLog -Level Information -Topic "git" -Message "Add / Modify:" + $addModifySet | ForEach-Object { + Write-AzOpsLog -Level Information -Topic "git" -Message $_ + } + + Write-AzOpsLog -Level Information -Topic "git" -Message "Delete:" + $deleteSet | ForEach-Object { + Write-AzOpsLog -Level Information -Topic "git" -Message $_ + } + + $addModifySet ` + | Where-Object -FilterScript { $_ -match '/*.subscription.json$' } ` + | Sort-Object -Property $_ ` + | ForEach-Object { + Write-AzOpsLog -Level Information -Topic "Invoke-AzOpsGitPush" -Message "Invoking new state deployment - *.subscription.json for a file $_" + New-AzOpsStateDeployment -filename $_ + } + + $addModifySet ` + | Where-Object -FilterScript { $_ -match '/*.providerfeatures.json$' } ` + | Sort-Object -Property $_ ` + | ForEach-Object { + Write-AzOpsLog -Level Information -Topic "Invoke-AzOpsGitPush" -Message "Invoking new state deployment - *.providerfeatures.json for a file $_" + New-AzOpsStateDeployment -filename $_ + } + + $addModifySet ` + | Where-Object -FilterScript { $_ -match '/*.resourceproviders.json$' } ` + | Sort-Object -Property $_ ` + | ForEach-Object { + Write-AzOpsLog -Level Information -Topic "Invoke-AzOpsGitPush" -Message "Invoking new state deployment - *.resourceproviders.json for a file $_" + New-AzOpsStateDeployment -filename $_ + } + + $AzOpsDeploymentList = @() + $addModifySet ` + | Sort-Object -Property $_ ` + | Where-Object -FilterScript { $_ -match ((get-item $Global:AzOpsState).Name) } ` + | Foreach-Object { + $scope = (New-AzOpsScope -path $_) + if ($scope) { + $templateFilePath = $null + $templateParameterFilePath = $null + $deploymentName = $null + #Find the template + if ($_.EndsWith('.parameters.json')) { + $templateParameterFilePath = (Get-Item $_).FullName + + if (Test-Path (Get-Item $_).FullName.Replace('.parameters.json', '.json')) { + Write-AzOpsLog -Level Information -Topic "pwsh" -Message "Template found $(($(Get-Item $_).FullName.Replace('.parameters.json', '.json')))" + $templateFilePath = (Get-Item $_).FullName.Replace('.parameters.json', '.json') + } + else { + Write-AzOpsLog -Level Information -Topic "pwsh" -Message "Template NOT found $(($(Get-Item $_).FullName.Replace('.parameters.json', '.json')))" + Write-AzOpsLog -Level Information -Topic "pwsh" -Message "Determining resource type $((Get-Item $global:AzOpsMainTemplate).FullName)" + # Determine Resource Type in Parameter file + $templateParameterFileHashtable = Get-Content ($_) | ConvertFrom-Json -AsHashtable + $effectiveResourceType = $null + if ( + ($null -ne $templateParameterFileHashtable) -and + ($templateParameterFileHashtable.Keys -contains "`$schema") -and + ($templateParameterFileHashtable.Keys -contains "parameters") -and + ($templateParameterFileHashtable.parameters.Keys -contains "input") + ) { + if ($templateParameterFileHashtable.parameters.input.value.Keys -contains "Type") { + # ManagementGroup and Subscription + $effectiveResourceType = $templateParameterFileHashtable.parameters.input.value.Type + } + elseif ($templateParameterFileHashtable.parameters.input.value.Keys -contains "ResourceType") { + # Resource + $effectiveResourceType = $templateParameterFileHashtable.parameters.input.value.ResourceType + } + } + # Check if generic template is supporting the resource type for the deployment. + if ($effectiveResourceType -and + ((Get-Content (Get-Item $global:AzOpsMainTemplate).FullName) | ConvertFrom-Json -AsHashtable).variables.apiVersionLookup.ContainsKey($effectiveResourceType)) { + Write-AzOpsLog -Level Information -Topic "pwsh" -Message "effectiveResourceType: $effectiveResourceType AzOpsMainTemplate supports resource type $effectiveResourceType in $((Get-Item $global:AzOpsMainTemplate).FullName)" + $templateFilePath = (Get-Item $global:AzOpsMainTemplate).FullName + } + else { + Write-AzOpsLog -Level Warning -Topic "pwsh" -Message "effectiveResourceType: $effectiveResourceType AzOpsMainTemplate does NOT supports resource type $effectiveResourceType in $((Get-Item $global:AzOpsMainTemplate).FullName). Deployment will be ignored" + } + } + } + #Find the template parameter file + elseif ($_.EndsWith('.json')) { + $templateFilePath = (Get-Item $_).FullName + if (Test-Path (Get-Item $_).FullName.Replace('.json', '.parameters.json')) { + Write-AzOpsLog -Level Information -Topic "pwsh" -Message "Template Parameter found $(($(Get-Item $_).FullName.Replace('.json', '.parameters.json')))" + $templateParameterFilePath = (Get-Item $_).FullName.Replace('.json', '.parameters.json') + } + else { + Write-AzOpsLog -Level Information -Topic "pwsh" -Message "Template Parameter NOT found $(($(Get-Item $_).FullName.Replace('.json', '.parameters.json')))" + } + } + #Deployment Name + if ($null -ne $templateParameterFilePath) { + $deploymentName = (Get-Item $templateParameterFilePath).BaseName.replace('.parameters', '').Replace(' ', '_') + if ($deploymentName.Length -gt 64) { + $deploymentName = $deploymentName.SubString($deploymentName.IndexOf('-') + 1) + } + } + elseif ($null -ne $templateFilePath) { + $deploymentName = (Get-Item $templateFilePath).BaseName.replace('.json', '').Replace(' ', '_') + if ($deploymentName.Length -gt 64) { + $deploymentName = $deploymentName.SubString($deploymentName.IndexOf('-') + 1) + } + } + #construct deployment object + $AzOpsDeploymentList += [PSCustomObject] @{ + [string] 'templateFilePath' = $templateFilePath + [string] 'templateParameterFilePath' = $templateParameterFilePath + [string] 'deploymentName' = $deploymentName + [string] 'scope' = $scope.scope + } + #New-AzOpsDeployment -templateFilePath $templateFilePath -templateParameterFilePath $templateParameterFilePath + } + else { + Write-AzOpsLog -Level Information -Topic "pwsh" -Message "$_ is not under $($Global:AzOpsState) and ignored for the deployment" + } + } + #Starting Tenant Deployment + $AzOpsDeploymentList ` + | Where-Object -FilterScript { $null -ne $_.templateFilePath } ` + | Select-Object scope, deploymentName, templateFilePath, templateParameterFilePath -Unique ` + | Sort-Object -Property templateParameterFilePath ` + | ForEach-Object { + New-AzOpsDeployment -templateFilePath $_.templateFilePath ` + -templateParameterFilePath ($_.templateParameterFilePath ? $_.templateParameterFilePath : $null) ` + -deploymentName $_.deploymentName + } + } + } + end {} +} \ No newline at end of file diff --git a/src/private/New-AzOpsDeployment.ps1 b/src/private/New-AzOpsDeployment.ps1 index d026deb0..e2591570 100644 --- a/src/private/New-AzOpsDeployment.ps1 +++ b/src/private/New-AzOpsDeployment.ps1 @@ -25,7 +25,7 @@ function New-AzOpsDeployment { [CmdletBinding(SupportsShouldProcess = $true)] param ( [Parameter(Position = 0, ParameterSetName = "template", Mandatory = $false, ValueFromPipeline = $true)] - [string]$name = "azops-template-deployment", + [string]$deploymentName = "azops-template-deployment", [Parameter(Position = 0, ParameterSetName = "template", ValueFromPipeline = $true)] [ValidateScript( { Test-Path $_ })] [string]$templateFilePath, diff --git a/src/public/Invoke-AzOpsGitPush.ps1 b/src/public/Invoke-AzOpsGitPush.ps1 index 36f9cf3b..17a893f3 100644 --- a/src/public/Invoke-AzOpsGitPush.ps1 +++ b/src/public/Invoke-AzOpsGitPush.ps1 @@ -199,150 +199,9 @@ function Invoke-AzOpsGitPush { } } } - if ($changeSet) { - Write-AzOpsLog -Level Information -Topic "git" -Message "Deployment required" - - $deleteSet = @() - $addModifySet = @() - foreach ($change in $changeSet) { - $filename = ($change -split "`t")[-1] - if (($change -split "`t" | Select-Object -first 1) -eq 'D') { - $deleteSet += $filename - } - elseif (($change -split "`t" | Select-Object -first 1) -eq 'A' -or 'M' -or 'R') { - $addModifySet += $filename - } - } - - Write-AzOpsLog -Level Information -Topic "git" -Message "Add / Modify:" - $addModifySet | ForEach-Object { - Write-AzOpsLog -Level Information -Topic "git" -Message $_ - } - - Write-AzOpsLog -Level Information -Topic "git" -Message "Delete:" - $deleteSet | ForEach-Object { - Write-AzOpsLog -Level Information -Topic "git" -Message $_ - } - - $addModifySet ` - | Where-Object -FilterScript { $_ -match '/*.subscription.json$' } ` - | Sort-Object -Property $_ ` - | ForEach-Object { - Write-AzOpsLog -Level Information -Topic "Invoke-AzOpsGitPush" -Message "Invoking new state deployment - *.subscription.json for a file $_" - New-AzOpsStateDeployment -filename $_ - } - - $addModifySet ` - | Where-Object -FilterScript { $_ -match '/*.providerfeatures.json$' } ` - | Sort-Object -Property $_ ` - | ForEach-Object { - Write-AzOpsLog -Level Information -Topic "Invoke-AzOpsGitPush" -Message "Invoking new state deployment - *.providerfeatures.json for a file $_" - New-AzOpsStateDeployment -filename $_ - } - - $addModifySet ` - | Where-Object -FilterScript { $_ -match '/*.resourceproviders.json$' } ` - | Sort-Object -Property $_ ` - | ForEach-Object { - Write-AzOpsLog -Level Information -Topic "Invoke-AzOpsGitPush" -Message "Invoking new state deployment - *.resourceproviders.json for a file $_" - New-AzOpsStateDeployment -filename $_ - } - - $AzOpsDeploymentList = @() - $addModifySet ` - | Where-Object -FilterScript { $_ -match ((get-item $Global:AzOpsState).Name) } ` - | Foreach-Object { - $scope = (New-AzOpsScope -path $_) - if ($scope) { - $templateFilePath = $null - $templateParameterFilePath = $null - $deploymentName = $null - #Find the template - if ($_.EndsWith('.parameters.json')) { - $templateParameterFilePath = (Get-Item $_).FullName - - if (Test-Path (Get-Item $_).FullName.Replace('.parameters.json', '.json')) { - Write-AzOpsLog -Level Information -Topic "pwsh" -Message "Template found $(($(Get-Item $_).FullName.Replace('.parameters.json', '.json')))" - $templateFilePath = (Get-Item $_).FullName.Replace('.parameters.json', '.json') - } - else { - Write-AzOpsLog -Level Information -Topic "pwsh" -Message "Template NOT found $(($(Get-Item $_).FullName.Replace('.parameters.json', '.json')))" - Write-AzOpsLog -Level Information -Topic "pwsh" -Message "Determining resource type $((Get-Item $global:AzOpsMainTemplate).FullName)" - # Determine Resource Type in Parameter file - $templateParameterFileHashtable = Get-Content ($_) | ConvertFrom-Json -AsHashtable - $effectiveResourceType = $null - if ( - ($null -ne $templateParameterFileHashtable) -and - ($templateParameterFileHashtable.Keys -contains "`$schema") -and - ($templateParameterFileHashtable.Keys -contains "parameters") -and - ($templateParameterFileHashtable.parameters.Keys -contains "input") - ) { - if ($templateParameterFileHashtable.parameters.input.value.Keys -contains "Type") { - # ManagementGroup and Subscription - $effectiveResourceType = $templateParameterFileHashtable.parameters.input.value.Type - } - elseif ($templateParameterFileHashtable.parameters.input.value.Keys -contains "ResourceType") { - # Resource - $effectiveResourceType = $templateParameterFileHashtable.parameters.input.value.ResourceType - } - } - # Check if generic template is supporting the resource type for the deployment. - if ($effectiveResourceType -and - ((Get-Content (Get-Item $global:AzOpsMainTemplate).FullName) | ConvertFrom-Json -AsHashtable).variables.apiVersionLookup.ContainsKey($effectiveResourceType)) { - Write-AzOpsLog -Level Information -Topic "pwsh" -Message "effectiveResourceType: $effectiveResourceType AzOpsMainTemplate supports resource type $effectiveResourceType in $((Get-Item $global:AzOpsMainTemplate).FullName)" - $templateFilePath = (Get-Item $global:AzOpsMainTemplate).FullName - } - else { - Write-AzOpsLog -Level Warning -Topic "pwsh" -Message "effectiveResourceType: $effectiveResourceType AzOpsMainTemplate does NOT supports resource type $effectiveResourceType in $((Get-Item $global:AzOpsMainTemplate).FullName). Deployment will be ignored" - } - } - } - #Find the template parameter file - elseif ($_.EndsWith('.json')) { - $templateFilePath = (Get-Item $_).FullName - if (Test-Path (Get-Item $_).FullName.Replace('.json', '.parameters.json')) { - Write-AzOpsLog -Level Information -Topic "pwsh" -Message "Template Parameter found $(($(Get-Item $_).FullName.Replace('.json', '.parameters.json')))" - $templateParameterFilePath = (Get-Item $_).FullName.Replace('.json', '.parameters.json') - } - else { - Write-AzOpsLog -Level Information -Topic "pwsh" -Message "Template Parameter NOT found $(($(Get-Item $_).FullName.Replace('.json', '.parameters.json')))" - } - } - #Deployment Name - if ($null -ne $templateParameterFilePath) { - $deploymentName = (Get-Item $templateParameterFilePath).BaseName.replace('.parameters', '').Replace(' ', '_') - if ($deploymentName.Length -gt 64) { - $deploymentName = $deploymentName.SubString($deploymentName.IndexOf('-') + 1) - } - } - elseif ($null -ne $templateFilePath) { - $deploymentName = (Get-Item $templateFilePath).BaseName.replace('.json', '').Replace(' ', '_') - if ($deploymentName.Length -gt 64) { - $deploymentName = $deploymentName.SubString($deploymentName.IndexOf('-') + 1) - } - } - #construct deployment object - $AzOpsDeploymentList += [PSCustomObject] @{ - [string] 'templateFilePath' = $templateFilePath - [string] 'templateParameterFilePath' = $templateParameterFilePath - [string] 'deploymentName' = $deploymentName - [string] 'scope' = $scope.scope - } - #New-AzOpsDeployment -templateFilePath $templateFilePath -templateParameterFilePath $templateParameterFilePath - } - else { - Write-AzOpsLog -Level Information -Topic "pwsh" -Message "$_ is not under $($Global:AzOpsState) and ignored for the deployment" - } - } - #Starting Tenant Deployment - $AzOpsDeploymentList ` - | Where-Object -FilterScript { $null -ne $_.templateFilePath } ` - | Select-Object scope, deploymentName, templateFilePath, templateParameterFilePath -Unique ` - | ForEach-Object { - New-AzOpsDeployment -templateFilePath $_.templateFilePath ` - -templateParameterFilePath ($_.templateParameterFilePath ? $_.templateParameterFilePath : $null) - } + Write-AzOpsLog -Level Information -Topic "git" -Message "Invoking AzOps Change" + Invoke-AzOpsChange -changeSet $changeSet } else { Write-AzOpsLog -Level Information -Topic "git" -Message "Deployment not required" diff --git a/tests/AzOps.IAB.Tests.ps1 b/tests/AzOps.IAB.Tests.ps1 index 2aa99c80..e1f4615b 100644 --- a/tests/AzOps.IAB.Tests.ps1 +++ b/tests/AzOps.IAB.Tests.ps1 @@ -44,16 +44,18 @@ Describe "Tenant E2E Deployment (Integration Test)" -Tag "integration", "e2e", " #region setup # Task: Initialize environment variables - $env:AZOPS_STATE = $TestDrive + $env:AZOPS_STATE = join-path $TestDrive -ChildPath 'azops' $env:AZOPS_INVALIDATE_CACHE = 1 $env:AZOPS_MAIN_TEMPLATE = ("$PSScriptRoot/../template/template.json") $env:AZOPS_STATE_CONFIG = ("$PSScriptRoot/../src/AzOpsStateConfig.json") #Use AzOpsReference published in https://github.com/Azure/Enterprise-Scale - Start-AzOpsNativeExecution { - git clone 'https://github.com/Azure/Enterprise-Scale' - } | Out-Host - $AzOpsReferenceFolder = (Join-Path $pwd -ChildPath 'Enterprise-Scale/azopsreference') + # Start-AzOpsNativeExecution { + # } | Out-Host + + git -C $TestDrive clone 'https://github.com/Azure/Enterprise-Scale' + + $AzOpsReferenceFolder = (Join-Path $TestDrive -ChildPath 'Enterprise-Scale/azopsreference') Write-AzOpsLog -Level Information -Topic "AzOps.IAB.Tests" -Message "AzOpsReferenceFolder Path is: $AzOpsReferenceFolder" $ContosoAzState = '3fc1081d-6105-4e19-b60c-1ec1252cf560 (3fc1081d-6105-4e19-b60c-1ec1252cf560)/contoso (contoso)/.AzState' Write-AzOpsLog -Level Information -Topic "AzOps.IAB.Tests" -Message "ContosoAzState Path is: $ContosoAzState" @@ -62,7 +64,7 @@ Describe "Tenant E2E Deployment (Integration Test)" -Tag "integration", "e2e", " Write-AzOpsLog -Level Information -Topic "AzOps.IAB.Tests" -Message "Removing Tailspin Management Group" if (Get-AzManagementGroup -GroupName 'Tailspin' -ErrorAction SilentlyContinue) { Write-AzOpsLog -Level Information -Topic "AzOps.IAB.Tests" -Message "Running Remove-AzOpsManagementGroup" - Remove-AzOpsManagementGroup -GroupName 'Tailspin' + #Remove-AzOpsManagementGroup -GroupName 'Tailspin' } Write-AzOpsLog -Level Information -Topic "AzOps.IAB.Tests" -Message "Tailspin Management Group hierarchy removed" #endregion @@ -71,55 +73,24 @@ Describe "Tenant E2E Deployment (Integration Test)" -Tag "integration", "e2e", " Write-AzOpsLog -Level Information -Topic "AzOps.IAB.Tests" -Message "Running Initialize-AzOpsRepository" Initialize-AzOpsRepository -SkipResourceGroup -SkipPolicy - # Task: Deployment of 10-create-managementgroup.parameters.json - Get-ChildItem -Path "$PSScriptRoot/../template/10-create-managementgroup.parameters.json" | ForEach-Object { - $tempFileName = (Join-Path -Path $TestDrive -ChildPath $_.Name) - Copy-Item -Path $_.FullName -Destination $TestDrive - $content = Get-Content -Path $tempFileName | ConvertFrom-Json -Depth 100 - $content.parameters.input.value.ParentId = ("/providers/Microsoft.Management/managementGroups/" + (Get-AzTenant).Id) - $content | ConvertTo-Json -Depth 100 | Out-File -FilePath $tempFileName + $testTemplateFiles = @( + "$PSScriptRoot/../template/10-create-managementgroup.parameters.json", + "$PSScriptRoot/../template/20-create-child-managementgroup.parameters.json", + "$PSScriptRoot/../template/30-create-policydefinition-at-managementgroup.parameters.json" + ) - Write-AzOpsLog -Level Information -Topic "AzOps.IAB.Tests" -Message "Running New-AzOpsStateDeployment for 10-create-managementgroup.parameters.json" - New-AzOpsStateDeployment -FileName $tempFileName - } + $changeSet = @() + $testTemplateFiles | ForEach-Object { + copy-item $_ -Destination $env:AZOPS_STATE -Force -Confirm:$false + $destinationFileName = (join-path $env:AZOPS_STATE -ChildPath (Split-Path $_ -Leaf)) - # Task: Deployment of 20-create-child-managementgroup.parameters.json - Get-ChildItem -Path "$PSScriptRoot/../template/20-create-child-managementgroup.parameters.json" | ForEach-Object { - $tempFileName = (Join-Path -Path $TestDrive -ChildPath $_.Name) - Copy-Item -Path $_.FullName -Destination $TestDrive - $content = Get-Content -Path $tempFileName | ConvertFrom-Json -Depth 100 + $content = Get-Content -Path $destinationFileName | ConvertFrom-Json -Depth 100 $content.parameters.input.value.ParentId = ("/providers/Microsoft.Management/managementGroups/" + (Get-AzTenant).Id) - $content | ConvertTo-Json -Depth 100 | Out-File -FilePath $tempFileName + $content | ConvertTo-Json -Depth 100 | Out-File -FilePath $destinationFileName - Write-AzOpsLog -Level Information -Topic "AzOps.IAB.Tests" -Message "Running New-AzOpsStateDeployment for 20-create-child-managementgroup.parameters.json" - New-AzOpsStateDeployment -FileName $tempFileName + $changeSet += $destinationFileName } - - # Task: Deployment of 30-create-policydefinition-at-managementgroup.parameters.json - Get-ChildItem -Path "$PSScriptRoot/../template/30-create-policydefinition-at-managementgroup.parameters.json" | ForEach-Object { - $tempFileName = (Join-Path -Path $TestDrive -ChildPath $_.Name) - Copy-Item -Path $_.FullName -Destination $TestDrive - $content = Get-Content -Path $tempFileName | ConvertFrom-Json -Depth 100 - $content.parameters.input.value.ParentId = ("/providers/Microsoft.Management/managementGroups/" + (Get-AzTenant).Id) - $content | ConvertTo-Json -Depth 100 | Out-File -FilePath $tempFileName - - Write-AzOpsLog -Level Information -Topic "AzOps.IAB.Tests" -Message "Running New-AzOpsStateDeployment for 30-create-policydefinition-at-managementgroup.parameters.json" - New-AzOpsStateDeployment -FileName $tempFileName - } - - <# State: Disabling this due to bug where Policy assignment fails for first time. - - Get-ChildItem -Path "$PSScriptRoot/../template/40-create-policyassignment-at-managementgroup.parameters.json" | ForEach-Object { - $tempFileName = (Join-Path -Path $TestDrive -ChildPath $_.Name) - Copy-Item -Path $_.FullName -Destination $TestDrive - $content = Get-Content -Path $tempFileName | ConvertFrom-Json -Depth 100 - $content.parameters.input.value.ParentId = ("/providers/Microsoft.Management/managementGroups/" + (Get-AzTenant).Id) - $content | ConvertTo-Json -Depth 100 | Out-File -FilePath $tempFileName - New-AzOpsStateDeployment -FileName $tempFileName - } - - #> - + Invoke-AzOpsChange $changeSet # Task: Re-initialize azops/ Initialize-AzOpsRepository -SkipResourceGroup -SkipPolicy } From 9310e50378fc5f5fb84ef0db2c98bc614d66ee5b Mon Sep 17 00:00:00 2001 From: uday31in <14359777+uday31in@users.noreply.github.com> Date: Thu, 20 Aug 2020 20:21:55 +0100 Subject: [PATCH 3/3] Adding prefix for deployment name --- src/private/Invoke-AzOpsChange.ps1 | 7 +------ tests/AzOps.IAB.Tests.ps1 | 6 +++--- 2 files changed, 4 insertions(+), 9 deletions(-) diff --git a/src/private/Invoke-AzOpsChange.ps1 b/src/private/Invoke-AzOpsChange.ps1 index 559cf6a7..a0150cf1 100644 --- a/src/private/Invoke-AzOpsChange.ps1 +++ b/src/private/Invoke-AzOpsChange.ps1 @@ -136,16 +136,11 @@ function Invoke-AzOpsChange { #Deployment Name if ($null -ne $templateParameterFilePath) { $deploymentName = (Get-Item $templateParameterFilePath).BaseName.replace('.parameters', '').Replace(' ', '_') - if ($deploymentName.Length -gt 64) { - $deploymentName = $deploymentName.SubString($deploymentName.IndexOf('-') + 1) - } } elseif ($null -ne $templateFilePath) { $deploymentName = (Get-Item $templateFilePath).BaseName.replace('.json', '').Replace(' ', '_') - if ($deploymentName.Length -gt 64) { - $deploymentName = $deploymentName.SubString($deploymentName.IndexOf('-') + 1) - } } + $deploymentName = 'AzOps-' + $deploymentName.SubString(0, ($deploymentName.Length -gt 58 )?58:$deploymentName.Length) #construct deployment object $AzOpsDeploymentList += [PSCustomObject] @{ [string] 'templateFilePath' = $templateFilePath diff --git a/tests/AzOps.IAB.Tests.ps1 b/tests/AzOps.IAB.Tests.ps1 index b984fcf5..81572b73 100644 --- a/tests/AzOps.IAB.Tests.ps1 +++ b/tests/AzOps.IAB.Tests.ps1 @@ -98,13 +98,13 @@ Describe "Tenant E2E Deployment (Integration Test)" -Tag "integration", "e2e", " Context "In-a-Box" { # Debug: Get-AzTenantDeployment | Sort-Object -Property Timestamp -Descending | Format-Table It "Passes ProvisioningState 10-create-managementgroup" { - (Get-AzTenantDeployment -Name "10-create-managementgroup").ProvisioningState | Should -Match "Succeeded" + (Get-AzTenantDeployment -Name "AzOps-10-create-managementgroup").ProvisioningState | Should -Match "Succeeded" } It "Passes ProvisioningState 20-create-child-managementgroup" { - (Get-AzTenantDeployment -Name "20-create-child-managementgroup").ProvisioningState | Should -Match "Succeeded" + (Get-AzTenantDeployment -Name "AzOps-20-create-child-managementgroup").ProvisioningState | Should -Match "Succeeded" } It "Passes ProvisioningState 30-create-policydefinition-at-managementgroup" { - (Get-AzTenantDeployment -Name "30-create-policydefinition-at-managementgroup").ProvisioningState | Should -Match "Succeeded" + (Get-AzTenantDeployment -Name "AzOps-30-create-policydefinition-at-managementgroup").ProvisioningState | Should -Match "Succeeded" } It "Passes Discovery of Tailspin Management Group" { (Get-ChildItem -Directory -Recurse -Path $env:AZOPS_STATE).Name | Should -Contain 'Tailspin (Tailspin)'