Azure Garbage Collection (auto-delete Your Unused Resources)

As I described in a previous post on ephemeral workloads, I separate experiments into their own resource groups and like to automate all provisioning to make sure they’re repeatable and delete-able.
I saw this tweet from Jeff Hollan the other day and it gave me the foundation to create a garbage collector for my experiments using Powershell Azure Functions. This makes a good example of Azure management automation using Functions.
When I create a quick demo or repro I preface my resource groups with "deleteme" - but sometimes forget to clean them up. Just wrote a quick PowerShell @AzureFunctions that does it automatically for me every night! Took about 10 minutes and 10 lines 🎉 pic.twitter.com/WtJDwgQjcm
— Jeff Hollan (@jeffhollan) May 26, 2019
The concept is great! Since I’m already using a purpose tag to identify transient workload I want to piggy-back on that. I also want to be able to keep resource groups longer than just one day. My garbage collector needs to:
- Automatically assign a
purpose1 if it’s missing. - For resource groups with a tag
purposeset toexperiment, add an expiry date automatically, two weeks from now - Delete groups with an
expirytag once it’s in the past - Send me notification to make sure things aren’t marked for deletion erroneously.
To do so I’m using a combination of Powershell Azure Functions to tag and remove the resources, and LogicApp to send notifications. The solution (including a provisioning script that can be ran to deploy everything to your own subscription) is on GitHub.
FunctionApp

The function app contains three functions:
AddPurposeruns every hour and adds apurposetag if none is set.AddExpiryDateruns every hour and adds anexpirytag in 2 weeks if none is set.CleanupExpiredruns once a day at UTC+8 (PT), and deletes all resource groups whereexpiryis in the past.
All functions send a message to a queue when they do something.
Those functions are relatively simple. Let’s look at CleanupExpired for example:
Select the subscription and query expired resource groups:
param($Timer)
$date=Get-Date
Write-Host "Garbage collection triggered at $date"
Select-AzSubscription -Subscription $env:SUBSCRIPTION
$expiredResources = Get-AzResourceGroup | Where-Object { $_.Tags.expiry -and [DateTime] $_.Tags.expiry -lt $date }
Iterate through resource groups and delete them:
Foreach ($resourceGroup in $expiredResources) {
Write-Host "Collecting $($resourceGroup.ResourceGroupName)"
Remove-AzResourceGroup -Name $resourceGroup.ResourceGroupName -Force
Send a message to the queue (using a queue binding):
$evt = [ordered]@{
type="groupCollected"
group=$resourceGroup.ResourceGroupName
date=$date
}
$jsonEvent = $evt | ConvertTo-Json -Depth 10
Push-OutputBinding -Name "eventsQueue" -Value $jsonEvent
}
Write-Host "Done collecting"
LogicApp
The logic app uses the queue connector to retrieve messages to be sent:

Based on the type, a different message is assembled, then it uses the O365 connector to send an email.

Code
All the code is here.
Notes
-
Purpose being: experiment, production, development, etc. ↩