Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Ported deployment removal from CARML #1773

Merged
merged 152 commits into from
Apr 29, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
152 commits
Select commit Hold shift + click to select a range
20ac8b7
Added skeleton
AlexanderSehr Nov 7, 2023
4939b4d
Implemented first new tests
AlexanderSehr Nov 7, 2023
4e1d86f
Changed to warning
AlexanderSehr Nov 8, 2023
94fff0b
Expanded test verbosity & added additional tets
AlexanderSehr Nov 8, 2023
c18ce6b
Finalized further tests
AlexanderSehr Nov 8, 2023
a343694
Update to latest
AlexanderSehr Nov 8, 2023
3a6f0a2
Update to latest
AlexanderSehr Nov 8, 2023
4ab6a5b
Added module name + small fix
AlexanderSehr Nov 8, 2023
9bb64bd
Fixed kvlt
AlexanderSehr Nov 8, 2023
68e2bd2
Small caching fix
AlexanderSehr Nov 8, 2023
1a013c2
Small fix and enabled passthru of warnings to GH
AlexanderSehr Nov 8, 2023
1c2fc8a
More updates
AlexanderSehr Nov 8, 2023
d9c6dd5
Update to latest
AlexanderSehr Nov 8, 2023
dd0c343
Updated test names
AlexanderSehr Nov 8, 2023
2ebd458
JSON rollback
AlexanderSehr Nov 8, 2023
f6caf7e
Updated regex
AlexanderSehr Nov 8, 2023
f56f66a
Removed assertion
AlexanderSehr Nov 8, 2023
282b640
Update to latest
AlexanderSehr Nov 8, 2023
c025f52
Update avm/utilities/pipelines/staticValidation/compliance/module.tes…
AlexanderSehr Nov 9, 2023
405901a
Update avm/utilities/pipelines/staticValidation/compliance/module.tes…
AlexanderSehr Nov 9, 2023
904c82f
Merge branch 'main' into users/alsehr/testFileCompliance
AlexanderSehr Nov 9, 2023
ef24d1f
Rollback of unrelated changes
AlexanderSehr Nov 9, 2023
9393aa1
Merge branch 'Azure:main' into main
AlexanderSehr Nov 9, 2023
cb39086
Merge branch 'Azure:main' into main
AlexanderSehr Nov 9, 2023
89eac40
Merge branch 'Azure:main' into main
AlexanderSehr Nov 10, 2023
712a673
Merge branch 'Azure:main' into main
AlexanderSehr Nov 13, 2023
55e095f
Resolved conflict
AlexanderSehr Nov 14, 2023
3121335
Update to latest
AlexanderSehr Nov 14, 2023
e9d736c
Merge branch 'Azure:main' into main
AlexanderSehr Nov 15, 2023
abfa1b9
Merge branch 'Azure:main' into main
AlexanderSehr Nov 15, 2023
c6707f6
Merge branch 'Azure:main' into main
AlexanderSehr Nov 16, 2023
246f9ba
Merge branch 'Azure:main' into main
AlexanderSehr Nov 16, 2023
6e9729d
Merge branch 'Azure:main' into main
AlexanderSehr Nov 16, 2023
26ea9f6
Merge branch 'Azure:main' into main
AlexanderSehr Nov 17, 2023
c2d183b
Merge branch 'Azure:main' into main
AlexanderSehr Nov 18, 2023
0c6650e
Merge branch 'Azure:main' into main
AlexanderSehr Nov 19, 2023
65094a5
Merge branch 'Azure:main' into main
AlexanderSehr Nov 21, 2023
968cd9a
Merge branch 'Azure:main' into main
AlexanderSehr Nov 21, 2023
3c9589b
Merge branch 'Azure:main' into main
AlexanderSehr Nov 24, 2023
eb34ddf
Merge branch 'Azure:main' into main
AlexanderSehr Nov 25, 2023
3d4f5c6
Added pipeline to main for testing
AlexanderSehr Nov 26, 2023
70154f3
Merge branch 'Azure:main' into main
AlexanderSehr Nov 27, 2023
18bd2ad
Merge branch 'Azure:main' into main
AlexanderSehr Nov 27, 2023
940b34f
Merge branch 'Azure:main' into main
AlexanderSehr Nov 28, 2023
fbb840f
Merge branch 'Azure:main' into main
AlexanderSehr Nov 29, 2023
381e366
Merge branch 'Azure:main' into main
AlexanderSehr Nov 29, 2023
06bcda3
Merge branch 'Azure:main' into main
AlexanderSehr Dec 1, 2023
0858beb
Merge branch 'Azure:main' into main
AlexanderSehr Dec 1, 2023
72b5fbb
Merge branch 'Azure:main' into main
AlexanderSehr Dec 1, 2023
917a761
TEst disable pipe
AlexanderSehr Dec 4, 2023
1b89452
Merge branch 'Azure:main' into main
AlexanderSehr Dec 4, 2023
feb981e
Update to latest
AlexanderSehr Dec 4, 2023
dda85a8
Merge branch 'Azure:main' into main
AlexanderSehr Dec 4, 2023
0373f46
Merge branch 'Azure:main' into main
AlexanderSehr Dec 6, 2023
80247e4
Merge branch 'Azure:main' into main
AlexanderSehr Dec 9, 2023
2b5a791
Merge branch 'Azure:main' into main
AlexanderSehr Dec 10, 2023
f1bab34
Merge branch 'Azure:main' into main
AlexanderSehr Dec 19, 2023
ef12ee5
Merge branch 'Azure:main' into main
AlexanderSehr Dec 21, 2023
ec1722c
Merge branch 'Azure:main' into main
AlexanderSehr Dec 21, 2023
f4136ec
Added SA workflow
AlexanderSehr Dec 22, 2023
e55e732
Added workflow
AlexanderSehr Jan 1, 2024
5c6aa5e
Update to latest
AlexanderSehr Jan 1, 2024
086c1a8
Merge branch 'Azure:main' into main
AlexanderSehr Jan 2, 2024
a9821fb
Merge branch 'Azure:main' into main
AlexanderSehr Jan 3, 2024
62b326f
Merge branch 'Azure:main' into main
AlexanderSehr Jan 3, 2024
c159269
Merge branch 'Azure:main' into main
AlexanderSehr Jan 4, 2024
6e1f59a
Merge branch 'Azure:main' into main
AlexanderSehr Jan 5, 2024
fb7befc
Merge branch 'Azure:main' into main
AlexanderSehr Jan 5, 2024
cb72681
Merge branch 'Azure:main' into main
AlexanderSehr Jan 8, 2024
f3befb7
Merge branch 'Azure:main' into main
AlexanderSehr Jan 10, 2024
f938cd8
Merge branch 'Azure:main' into main
AlexanderSehr Jan 12, 2024
d0924b6
Merge branch 'Azure:main' into main
AlexanderSehr Jan 14, 2024
315522f
Merge branch 'Azure:main' into main
AlexanderSehr Jan 17, 2024
4012fdd
Update to latest
AlexanderSehr Jan 18, 2024
b18ab70
Merge branch 'Azure:main' into main
AlexanderSehr Jan 20, 2024
686dc83
Merge branch 'Azure:main' into main
AlexanderSehr Jan 22, 2024
3f225f9
Removed outdated metadata
AlexanderSehr Jan 23, 2024
f2bd197
Update to latest
AlexanderSehr Jan 23, 2024
4cd0a6f
Merge branch 'Azure:main' into main
AlexanderSehr Jan 26, 2024
01f3a38
Merged latest main
AlexanderSehr Jan 26, 2024
18c794a
Merge branch 'Azure:main' into users/alsehr/testCleanup
AlexanderSehr Jan 26, 2024
732a605
Merge branch 'main' into users/alsehr/testCleanup
AlexanderSehr Jan 29, 2024
c0105fe
Merge branch 'Azure:main' into main
AlexanderSehr Jan 29, 2024
c7d09f2
Merge branch 'main' into users/alsehr/testCleanup
AlexanderSehr Jan 29, 2024
bea9408
Merge branch 'users/alsehr/testCleanup' of https://github.com/Alexand…
AlexanderSehr Jan 29, 2024
9d063ce
Refereshed docs
AlexanderSehr Jan 29, 2024
db61282
Merge branch 'main' into users/alsehr/testCleanup
AlexanderSehr Jan 29, 2024
4ec79f8
Merge branch 'Azure:main' into main
AlexanderSehr Jan 29, 2024
c26b307
Merge branches 'users/alsehr/testCleanup' and 'main' of https://githu…
AlexanderSehr Jan 29, 2024
e3759a8
Merge branch 'Azure:main' into main
AlexanderSehr Feb 2, 2024
86869a1
Merge branch 'main' of https://github.com/AlexanderSehr/bicep-registr…
AlexanderSehr Feb 2, 2024
f8da6b9
Merge branch 'Azure:main' into main
AlexanderSehr Feb 4, 2024
ece4faa
Merge branch 'main' of https://github.com/AlexanderSehr/bicep-registr…
AlexanderSehr Feb 4, 2024
8884290
Merge branch 'Azure:main' into main
AlexanderSehr Feb 9, 2024
6ed614f
Merge branch 'Azure:main' into main
AlexanderSehr Feb 10, 2024
e307d2a
Merge branch 'Azure:main' into main
AlexanderSehr Feb 11, 2024
96589bb
Merge branch 'Azure:main' into main
AlexanderSehr Feb 12, 2024
75ade55
Merge branch 'Azure:main' into main
AlexanderSehr Feb 13, 2024
56e7afb
Merge branch 'Azure:main' into main
AlexanderSehr Feb 21, 2024
f89b946
Merge branch 'Azure:main' into main
AlexanderSehr Feb 21, 2024
c861111
Merge branch 'Azure:main' into main
AlexanderSehr Feb 22, 2024
9511716
Merge branch 'Azure:main' into main
AlexanderSehr Feb 26, 2024
f28816d
Merge branch 'Azure:main' into main
AlexanderSehr Feb 27, 2024
79b4e78
Merge branch 'Azure:main' into main
AlexanderSehr Mar 5, 2024
31a3f76
Merge branch 'Azure:main' into main
AlexanderSehr Mar 7, 2024
e6975de
Merge branch 'Azure:main' into main
AlexanderSehr Mar 9, 2024
005581f
Update to latest
AlexanderSehr Mar 9, 2024
15a7ed5
Update to latest
AlexanderSehr Mar 9, 2024
922fd79
Update to latest
AlexanderSehr Mar 9, 2024
d861c45
Update to latest
AlexanderSehr Mar 9, 2024
a4d71e7
Merge branch 'main' into users/alsehr/e2eTestCheck
AlexanderSehr Mar 10, 2024
033baab
Merge branch 'Azure:main' into main
AlexanderSehr Mar 11, 2024
c46abd0
Merge branch 'main' of https://github.com/AlexanderSehr/bicep-registr…
AlexanderSehr Mar 11, 2024
5b35a3f
Merge branch 'Azure:main' into main
AlexanderSehr Mar 13, 2024
0012def
Merge branch 'Azure:main' into main
AlexanderSehr Mar 17, 2024
13f0450
Merge branch 'Azure:main' into main
AlexanderSehr Mar 21, 2024
4dcee53
Merge branch 'Azure:main' into main
AlexanderSehr Mar 23, 2024
88e2bea
Merge branch 'Azure:main' into main
AlexanderSehr Mar 25, 2024
776bed8
Retired / refactored workflows
AlexanderSehr Mar 25, 2024
0ab044d
Merge branch 'Azure:main' into main
AlexanderSehr Mar 26, 2024
d4c3794
Merge branch 'Azure:main' into main
AlexanderSehr Mar 26, 2024
e51366b
Merge branch 'Azure:main' into main
AlexanderSehr Mar 31, 2024
06ad8d7
Merge branch 'main' into users/workflowRetire
AlexanderSehr Mar 31, 2024
aaf0d22
Merge branch 'main' into users/workflowRetire
AlexanderSehr Mar 31, 2024
a4c516d
Applied suggestion
AlexanderSehr Mar 31, 2024
16899f2
Removed scripts
AlexanderSehr Mar 31, 2024
29f60ed
Merge branch 'Azure:main' into main
AlexanderSehr Apr 1, 2024
74783f1
Merge branch 'main' into users/workflowRetire
AlexanderSehr Apr 2, 2024
7888d41
Merge branch 'Azure:main' into main
AlexanderSehr Apr 3, 2024
666a545
Merge branch 'Azure:main' into main
AlexanderSehr Apr 3, 2024
a7aea77
Merge branch 'Azure:main' into main
AlexanderSehr Apr 8, 2024
5c05401
Merge branch 'Azure:main' into main
AlexanderSehr Apr 8, 2024
2ba34a4
Merge branch 'Azure:main' into main
AlexanderSehr Apr 10, 2024
f61b688
Updated encr
AlexanderSehr Apr 12, 2024
5032da5
Merge branch 'Azure:main' into main
AlexanderSehr Apr 12, 2024
ba3e41d
Merge branch 'main' of https://github.com/AlexanderSehr/bicep-registr…
AlexanderSehr Apr 12, 2024
1c658d3
Merge branch 'Azure:main' into main
AlexanderSehr Apr 15, 2024
2192861
Merge branch 'main' of https://github.com/AlexanderSehr/bicep-registr…
AlexanderSehr Apr 15, 2024
10339d4
Merged latest main
AlexanderSehr Apr 15, 2024
825468e
Merge branch 'users/workflowRetire' of https://github.com/AlexanderSe…
AlexanderSehr Apr 15, 2024
7ab22c1
Merge branch 'Azure:main' into main
AlexanderSehr Apr 17, 2024
98b4bbc
Merge branches 'users/workflowRetire' and 'main' of https://github.co…
AlexanderSehr Apr 18, 2024
391dec3
Merge branch 'Azure:main' into main
AlexanderSehr Apr 20, 2024
cd4d559
Update to latest
AlexanderSehr Apr 20, 2024
7ae8786
Undid changes that should be in branch in main
AlexanderSehr Apr 20, 2024
86ed73b
Merge branch 'Azure:main' into main
AlexanderSehr Apr 27, 2024
42f7fe9
Merge branch 'Azure:main' into main
AlexanderSehr Apr 29, 2024
d20afeb
Added workflow
AlexanderSehr Apr 29, 2024
157adb5
Merge pull request #4 from AlexanderSehr/users/alsehr/deploymentRemoval
AlexanderSehr Apr 29, 2024
2157079
Update to latest
AlexanderSehr Apr 29, 2024
e64d2f2
Merge branch 'main' into users/alsehr/deploymentRemoval
AlexanderSehr Apr 29, 2024
2bd3129
Small fix
AlexanderSehr Apr 29, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 126 additions & 0 deletions .github/workflows/platform.deployment.history.cleanup.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
name: ".Platform - Clean up deployment history"

on:
workflow_dispatch:
inputs:
handleSubscriptionScope:
type: boolean
description: "Include Subscription deployments"
required: false
default: true # Note: This requires your service principal to have permissions on the subscription scope.
handleManagementGroupScope:
type: boolean
description: "Include Management Group deployments"
required: false
default: true # Note: This requires your service principal to have permissions on the management group scope.
maxDeploymentRetentionInDays:
type: string
description: "The number of days to keep deployments with status [failed]" # 'Running' are always excluded
required: false
default: "14"
schedule:
- cron: "0 0 * * *"

env:
workflowPath: ".github/workflows/platform.deployment.history.cleanup.yml"

jobs:
###########################
# Initialize pipeline #
###########################
job_initialize_pipeline:
runs-on: ubuntu-latest
name: "Initialize pipeline"
steps:
- name: "Checkout"
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: "Set input parameters to output variables"
id: get-workflow-param
uses: ./.github/actions/templates/avm-getWorkflowInput
with:
workflowPath: "${{ env.workflowPath}}"
outputs:
workflowInput: ${{ steps.get-workflow-param.outputs.workflowInput }}

###############
# Removal #
###############
job_cleanup_subscription_deployments:
runs-on: ubuntu-20.04
name: "Remove Subscription deployments"
needs:
- job_initialize_pipeline
if: ${{ (fromJson(needs.job_initialize_pipeline.outputs.workflowInput)).handleSubscriptionScope == 'true' }}
steps:
- name: "Checkout"
uses: actions/checkout@v3
with:
fetch-depth: 0

- name: Set environment
uses: ./.github/actions/templates/avm-setEnvironment

- name: Azure Login
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
enable-AzPSSession: true

- name: Remove deployments
uses: azure/powershell@v1
with:
inlineScript: |
# Load used functions
. (Join-Path $env:GITHUB_WORKSPACE 'avm' 'utilities' 'pipelines' 'platform' 'deploymentRemoval' 'Clear-SubscriptionDeploymentHistory.ps1')

$functionInput = @{
SubscriptionId = '${{ secrets.ARM_SUBSCRIPTION_ID }}'
maxDeploymentRetentionInDays = '${{ (fromJson(needs.job_initialize_pipeline.outputs.workflowInput)).maxDeploymentRetentionInDays }}'
}

Write-Verbose "Invoke task with" -Verbose
Write-Verbose ($functionInput | ConvertTo-Json | Out-String) -Verbose

Clear-SubscriptionDeploymentHistory @functionInput
azPSVersion: "latest"

job_cleanup_managementGroup_deployments:
runs-on: ubuntu-20.04
name: "Remove Management Group deployments"
needs:
- job_initialize_pipeline
if: ${{ (fromJson(needs.job_initialize_pipeline.outputs.workflowInput)).handleManagementGroupScope == 'true' }}
steps:
- name: "Checkout"
uses: actions/checkout@v3
with:
fetch-depth: 0

- name: Set environment
uses: ./.github/actions/templates/avm-setEnvironment

- name: Azure Login
uses: azure/login@v1
with:
creds: ${{ secrets.AZURE_CREDENTIALS }}
enable-AzPSSession: true

- name: Remove deployments
uses: azure/powershell@v1
with:
inlineScript: |
# Load used functions
. (Join-Path $env:GITHUB_WORKSPACE 'avm' 'utilities' 'pipelines' 'platform' 'deploymentRemoval' 'Clear-ManagementGroupDeploymentHistory.ps1')

$functionInput = @{
ManagementGroupId = '${{ secrets.ARM_MGMTGROUP_ID }}'
maxDeploymentRetentionInDays = '${{ (fromJson(needs.job_initialize_pipeline.outputs.workflowInput)).maxDeploymentRetentionInDays }}'
}

Write-Verbose "Invoke task with" -Verbose
Write-Verbose ($functionInput | ConvertTo-Json | Out-String) -Verbose

Clear-ManagementGroupDeploymentHistory @functionInput
azPSVersion: "latest"
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@

<#
.SYNOPSIS
Bulk delete all deployments on the given management group scope

.DESCRIPTION
Bulk delete all deployments on the given management group scope

.PARAMETER ManagementGroupId
Mandatory. The Resource ID of the Management Group to remove the deployments from.

.PARAMETER DeploymentStatusToExclude
Optional. The status to exlude from removals. Can be multiple. By default, we exclude any deployment that is in state 'running' or 'failed'.

.PARAMETER maxDeploymentRetentionInDays
Optional. The time to keep deployments with a status to exclude. In other words, if a deployment is in a status to exclude, but older than the threshold, it will be deleted.

.EXAMPLE
Clear-ManagementGroupDeploymentHistory -ManagementGroupId 'MyManagementGroupId'

Bulk remove all 'non-running' & 'non-failed' deployments from the Management Group with ID 'MyManagementGroupId'

.EXAMPLE
Clear-ManagementGroupDeploymentHistory -ManagementGroupId 'MyManagementGroupId' -DeploymentStatusToExclude @('running')

Bulk remove all 'non-running' deployments from the Management Group with ID 'MyManagementGroupId'
#>
function Clear-ManagementGroupDeploymentHistory {


[CmdletBinding(SupportsShouldProcess)]
param (
[Parameter(Mandatory = $true)]
[string] $ManagementGroupId,

[Parameter(Mandatory = $false)]
[string[]] $DeploymentStatusToExclude = @('running', 'failed'),

[Parameter(Mandatory = $false)]
[int] $maxDeploymentRetentionInDays = 14
)

# Load helper functions
. (Join-Path (Split-Path $PSScriptRoot) 'helper' 'Split-Array.ps1')

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 # Enables web reponse
$deploymentThreshold = (Get-Date).AddDays(-1 * $maxDeploymentRetentionInDays)

$getInputObject = @{
Method = 'GET'
Uri = "https://management.azure.com/providers/Microsoft.Management/managementGroups/$ManagementGroupId/providers/Microsoft.Resources/deployments/?api-version=2021-04-01"
Headers = @{
Authorization = 'Bearer {0}' -f (Get-AzAccessToken).Token
}
}
$response = Invoke-RestMethod @getInputObject

if (($response | Get-Member -MemberType 'NoteProperty').Name -notcontains 'value') {
throw ('Fetching deployments failed with error [{0}]' -f ($reponse | Out-String))
}

Write-Verbose ('Found [{0}] deployments in management group [{1}]' -f $response.value.Count, $ManagementGroupId) -Verbose

$relevantDeployments = $response.value | Where-Object {
$_.properties.provisioningState -notin $DeploymentStatusToExclude -or
([DateTime]$_.properties.timestamp) -lt $deploymentThreshold -and
$_.properties.provisioningState -ne 'running' # we should never delete 'running' deployments
}

Write-Verbose ('Filtering [{0}] deployments out as they are in state [{1}] or newer than [{2}] days ({3})' -f ($response.value.Count - $relevantDeployments.Count), ($DeploymentStatusToExclude -join '/'), $maxDeploymentRetentionInDays, $deploymentThreshold.ToString('yyyy-MM-dd')) -Verbose

if (-not $relevantDeployments) {
Write-Verbose 'No deployments found' -Verbose
return
}

$rawDeploymentChunks = Split-Array -InputArray $relevantDeployments -SplitSize 100
if ($relevantDeployments.Count -le 100) {
$relevantDeploymentChunks = , $rawDeploymentChunks
} else {
$relevantDeploymentChunks = $rawDeploymentChunks
}

Write-Verbose ('Triggering the removal of [{0}] deployments from management group [{1}]' -f $relevantDeployments.Count, $ManagementGroupId) -Verbose

foreach ($deployments in $relevantDeploymentChunks) {

$requests = $deployments | ForEach-Object {
@{ httpMethod = 'DELETE'
name = (New-Guid).Guid # Each batch request needs a unique ID
requestHeaderDetails = @{
commandName = 'HubsExtension.Microsoft.Resources/deployments.BulkDelete.execute'
}
url = '/providers/Microsoft.Management/managementGroups/{0}/providers/Microsoft.Resources/deployments/{1}?api-version=2019-08-01' -f $ManagementGroupId, $_.name
}
}

if ($requests -is [hashtable]) {
$requests = , $requests
}

$removeInputObject = @{
Method = 'POST'
Uri = 'https://management.azure.com/batch?api-version=2020-06-01'
Headers = @{
Authorization = 'Bearer {0}' -f (Get-AzAccessToken).Token
'Content-Type' = 'application/json'
}
Body = @{
requests = $requests
} | ConvertTo-Json -Depth 4
}
if ($PSCmdlet.ShouldProcess(('Removal of [{0}] deployments' -f $requests.Count), 'Request')) {
$null = Invoke-RestMethod @removeInputObject
}
}
Write-Verbose 'Script execution finished. Note that the removal can take a few minutes to propagate.' -Verbose
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@

<#
.SYNOPSIS
Bulk delete all deployments on the given subscription scope

.DESCRIPTION
Bulk delete all deployments on the given subscription scope

.PARAMETER subscriptionId
Optional. The ID of the subscription to remove the deployments from. Defaults to the current context.

.PARAMETER DeploymentStatusToExclude
Optional. The status to exlude from removals. Can be multiple. By default, we exclude any deployment that is in state 'running' or 'failed'.

.PARAMETER maxDeploymentRetentionInDays
Optional. The time to keep deployments with a status to exclude. In other words, if a deployment is in a status to exclude, but older than the threshold, it will be deleted.

.EXAMPLE
Clear-SubscriptionDeploymentHistory -subscriptionId '11111111-1111-1111-1111-111111111111'

Bulk remove all 'non-running' & 'non-failed' deployments from the subscription with ID '11111111-1111-1111-1111-111111111111'

.EXAMPLE
Clear-SubscriptionDeploymentHistory -subscriptionId '11111111-1111-1111-1111-111111111111' -DeploymentStatusToExclude @('running')

Bulk remove all 'non-running' deployments from the subscription with ID '11111111-1111-1111-1111-111111111111'
#>
function Clear-SubscriptionDeploymentHistory {


[CmdletBinding(SupportsShouldProcess)]
param (
[Parameter(Mandatory = $false)]
[string] $subscriptionId = (Get-AzContext).Subscription.Id,

[Parameter(Mandatory = $false)]
[string[]] $DeploymentStatusToExclude = @('running', 'failed'),

[Parameter(Mandatory = $false)]
[int] $maxDeploymentRetentionInDays = 14
)

# Load helper functions
. (Join-Path (Split-Path $PSScriptRoot) 'helper' 'Split-Array.ps1')

[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 # Enables web reponse
$deploymentThreshold = (Get-Date).AddDays(-1 * $maxDeploymentRetentionInDays)

# Setting context explicitely in case the principal has permissions on multiple
Write-Verbose ('Setting context to subscription [{0}]' -f $subscriptionId)
$null = Set-AzContext -Subscription $subscriptionId

$getInputObject = @{
Method = 'GET'
Uri = "https://management.azure.com/subscriptions/$subscriptionId/providers/Microsoft.Resources/deployments?api-version=2020-06-01"
Headers = @{
Authorization = 'Bearer {0}' -f (Get-AzAccessToken).Token
}
}
$response = Invoke-RestMethod @getInputObject

if (($response | Get-Member -MemberType 'NoteProperty').Name -notcontains 'value') {
throw ('Fetching deployments failed with error [{0}]' -f ($reponse | Out-String))
}

Write-Verbose ('Found [{0}] deployments in subscription [{1}]' -f $response.value.Count, $subscriptionId) -Verbose

$relevantDeployments = $response.value | Where-Object {
$_.properties.provisioningState -notin $DeploymentStatusToExclude -or
([DateTime]$_.properties.timestamp) -lt $deploymentThreshold -and
$_.properties.provisioningState -ne 'running' # we should never delete 'running' deployments
}

Write-Verbose ('Filtering [{0}] deployments out as they are in state [{1}] or newer than [{2}] days ({3})' -f ($response.value.Count - $relevantDeployments.Count), ($DeploymentStatusToExclude -join '/'), $maxDeploymentRetentionInDays, $deploymentThreshold.ToString('yyyy-MM-dd')) -Verbose

if (-not $relevantDeployments) {
Write-Verbose ('No deployments for subscription [{0}] found' -f $subscriptionId) -Verbose
return
}

$rawDeploymentChunks = Split-Array -InputArray $relevantDeployments -SplitSize 100
if ($relevantDeployments.Count -le 100) {
$relevantDeploymentChunks = , $rawDeploymentChunks
} else {
$relevantDeploymentChunks = $rawDeploymentChunks
}

Write-Verbose ('Triggering the removal of [{0}] deployments from subscription [{1}]' -f $relevantDeployments.Count, $subscriptionId) -Verbose

foreach ($deployments in $relevantDeploymentChunks) {

$requests = $deployments | ForEach-Object {
@{ httpMethod = 'DELETE'
name = (New-Guid).Guid # Each batch request needs a unique ID
requestHeaderDetails = @{
commandName = 'HubsExtension.Microsoft.Resources/deployments.BulkDelete.execute'
}
url = '/subscriptions/{0}/providers/Microsoft.Resources/deployments/{1}?api-version=2019-08-01' -f $subscriptionId, $_.name
}
}

if ($requests -is [hashtable]) {
$requests = , $requests
}

$removeInputObject = @{
Method = 'POST'
Uri = 'https://management.azure.com/batch?api-version=2020-06-01'
Headers = @{
Authorization = 'Bearer {0}' -f (Get-AzAccessToken).Token
'Content-Type' = 'application/json'
}
Body = @{
requests = $requests
} | ConvertTo-Json -Depth 4 -EnumsAsStrings
}
if ($PSCmdlet.ShouldProcess(('Removal of [{0}] deployments' -f $requests.Count), 'Request')) {
$null = Invoke-RestMethod @removeInputObject
}
}
Write-Verbose 'Script execution finished. Note that the removal can take a few minutes to propagate.' -Verbose
}
Loading