utilities/pipelines/resourceRemoval/helper/Get-DeploymentTargetResourceList.ps1 (183 lines of code) (raw):
#region helper
<#
.SYNOPSIS
Get all deployments that match a given deployment name in a given scope
.DESCRIPTION
Get all deployments that match a given deployment name in a given scope. Works recursively through the deployment tree.
.PARAMETER Name
Mandatory. The deployment name to search for
.PARAMETER ResourceGroupName
Optional. The name of the resource group for scope 'resourcegroup'
.PARAMETER ManagementGroupId
Optional. The ID of the management group to fetch deployments from. Relevant for management-group level deployments.
.PARAMETER Scope
Mandatory. The scope to search in
.EXAMPLE
Get-DeploymentTargetResourceListInner -Name 'keyvault-12356' -Scope 'resourcegroup'
Get all deployments that match name 'keyvault-12356' in scope 'resourcegroup'
.EXAMPLE
Get-ResourceIdsOfDeploymentInner -Name 'mgmtGroup-12356' -Scope 'managementGroup' -ManagementGroupId 'af760cf5-3c9e-4804-a59a-a51741daa350'
Get all deployments that match name 'mgmtGroup-12356' in scope 'managementGroup'
.NOTES
Works after the principal:
- Find all deployments for the given deployment name
- If any of them are not a deployments, add their target resource to the result set (as they are e.g. a resource)
- If any of them is are deployments, recursively invoke this function for them to get their contained target resources
#>
function Get-DeploymentTargetResourceListInner {
[CmdletBinding()]
param (
[Parameter(Mandatory)]
[string] $Name,
[Parameter(Mandatory = $false)]
[string] $ResourceGroupName,
[Parameter(Mandatory = $false)]
[string] $ManagementGroupId,
[Parameter(Mandatory)]
[ValidateSet(
'resourcegroup',
'subscription',
'managementgroup',
'tenant'
)]
[string] $Scope
)
$resultSet = [System.Collections.ArrayList]@()
##############################################
# Get all deployment children based on scope #
##############################################
switch ($Scope) {
'resourcegroup' {
if (Get-AzResourceGroup -Name $resourceGroupName -ErrorAction 'SilentlyContinue') {
[array]$deploymentTargets = (Get-AzResourceGroupDeploymentOperation -DeploymentName $name -ResourceGroupName $resourceGroupName).TargetResource | Where-Object { $_ -ne $null }
} else {
# In case the resource group itself was already deleted, there is no need to try and fetch deployments from it
# In case we already have any such resources in the list, we should remove them
[array]$resultSet = $resultSet | Where-Object { $_ -notmatch "/resourceGroups/$resourceGroupName/" }
}
break
}
'subscription' {
[array]$deploymentTargets = (Get-AzDeploymentOperation -DeploymentName $name).TargetResource | Where-Object { $_ -ne $null }
break
}
'managementgroup' {
[array]$deploymentTargets = (Get-AzManagementGroupDeploymentOperation -DeploymentName $name -ManagementGroupId $ManagementGroupId).TargetResource | Where-Object { $_ -ne $null }
break
}
'tenant' {
[array]$deploymentTargets = (Get-AzTenantDeploymentOperation -DeploymentName $name).TargetResource | Where-Object { $_ -ne $null }
break
}
}
###########################
# Manage nested resources #
###########################
foreach ($deployment in ($deploymentTargets | Where-Object { $_ -notmatch '/deployments/' } )) {
Write-Verbose ('Found deployed resource [{0}]' -f $deployment)
[array]$resultSet += $deployment
}
#############################
# Manage nested deployments #
#############################
foreach ($deployment in ($deploymentTargets | Where-Object { $_ -match '/deployments/' } )) {
$name = Split-Path $deployment -Leaf
if ($deployment -match '/resourceGroups/') {
# Resource Group Level Child Deployments #
##########################################
Write-Verbose ('Found [resource group] deployment [{0}]' -f $deployment)
$resourceGroupName = $deployment.split('/resourceGroups/')[1].Split('/')[0]
[array]$resultSet += Get-DeploymentTargetResourceListInner -Name $name -Scope 'resourcegroup' -ResourceGroupName $ResourceGroupName
} elseif ($deployment -match '/subscriptions/') {
# Subscription Level Child Deployments #
########################################
Write-Verbose ('Found [subscription] deployment [{0}]' -f $deployment)
[array]$resultSet += Get-DeploymentTargetResourceListInner -Name $name -Scope 'subscription'
} elseif ($deployment -match '/managementgroups/') {
# Management Group Level Child Deployments #
############################################
Write-Verbose ('Found [management group] deployment [{0}]' -f $deployment)
[array]$resultSet += Get-DeploymentTargetResourceListInner -Name $name -Scope 'managementgroup' -ManagementGroupId $ManagementGroupId
} else {
# Tenant Level Child Deployments #
##################################
Write-Verbose ('Found [tenant] deployment [{0}]' -f $deployment)
[array]$resultSet += Get-DeploymentTargetResourceListInner -Name $name -Scope 'tenant'
}
}
return $resultSet
}
#endregion
<#
.SYNOPSIS
Get all deployments that match a given deployment name in a given scope using a retry mechanic
.DESCRIPTION
Get all deployments that match a given deployment name in a given scope using a retry mechanic.
.PARAMETER ResourceGroupName
Optional. The name of the resource group for scope 'resourcegroup'
.PARAMETER ManagementGroupId
Optional. The ID of the management group to fetch deployments from. Relevant for management-group level deployments.
.PARAMETER Name
Optional. The deployment name to use for the removal
.PARAMETER Scope
Mandatory. The scope to search in
.PARAMETER SearchRetryLimit
Optional. The maximum times to retry the search for resources via their removal tag
.PARAMETER SearchRetryInterval
Optional. The time to wait in between the search for resources via their remove tags
.EXAMPLE
Get-DeploymentTargetResourceList -name 'KeyVault' -ResourceGroupName 'validation-rg' -scope 'resourcegroup'
Get all deployments that match name 'KeyVault' in scope 'resourcegroup' of resource group 'validation-rg'
.EXAMPLE
Get-ResourceIdsOfDeployment -Name 'mgmtGroup-12356' -Scope 'managementGroup' -ManagementGroupId 'af760cf5-3c9e-4804-a59a-a51741daa350'
Get all deployments that match name 'mgmtGroup-12356' in scope 'managementGroup'
#>
function Get-DeploymentTargetResourceList {
[CmdletBinding()]
param (
[Parameter(Mandatory = $false)]
[string] $ResourceGroupName,
[Parameter(Mandatory = $false)]
[string] $ManagementGroupId,
[Parameter(Mandatory = $true)]
[string] $Name,
[Parameter(Mandatory = $true)]
[ValidateSet(
'resourcegroup',
'subscription',
'managementgroup',
'tenant'
)]
[string] $Scope,
[Parameter(Mandatory = $false)]
[int] $SearchRetryLimit = 40,
[Parameter(Mandatory = $false)]
[int] $SearchRetryInterval = 60
)
$searchRetryCount = 1
do {
$innerInputObject = @{
Name = $name
Scope = $scope
ErrorAction = 'SilentlyContinue'
}
if (-not [String]::IsNullOrEmpty($resourceGroupName)) {
$innerInputObject['resourceGroupName'] = $resourceGroupName
}
if (-not [String]::IsNullOrEmpty($ManagementGroupId)) {
$innerInputObject['ManagementGroupId'] = $ManagementGroupId
}
[array]$targetResources = Get-DeploymentTargetResourceListInner @innerInputObject
if ($targetResources) {
break
}
Write-Verbose ('No deployment found by name [{0}] in scope [{1}]. Retrying in [{2}] seconds [{3}/{4}]' -f $name, $scope, $searchRetryInterval, $searchRetryCount, $searchRetryLimit) -Verbose
Start-Sleep $searchRetryInterval
$searchRetryCount++
} while ($searchRetryCount -le $searchRetryLimit)
if (-not $targetResources) {
Write-Warning "No deployment target resources found for [$name]"
return @()
}
return $targetResources
}