How to Find Empty Azure Resource Groups

Resource Groups form the backbone of many companies compliance policies, they’re often the target of tagging policies and annual reviews, which means that for each Resource Group you’re often increasing the amount of maintenance overhead.

That’s fine if the Resource Group contains something of value, but what if you’re wasting effort on Resource Group that no longer need to be maintained?

One option would be to simply click through each Resource Group one by one to identify any that may be empty, which could be a valid tactic if you’re only dealing with a couple, but nay more than that and we’ll likely want to turn to PowerShell.

I’ll show a very simple method to gather a list of all Resource Groups that are empty so that we can remove them.

The Script

The script below will provide a CSV export showing all Resource Groups which are empty, along with any Tags that you want to retrieve as part of the report. It does this by roughly following the process below –

  1. Connect to Azure
  2. Switch to each Subscription, if the Subscription is in the list then search it, otherwise skip.
  3. Retrieve all Resource Groups in the Subscription.
  4. Retrieve all Resources in each Resource Group.
  5. If there are none then create a basic PowerShell object containing the name and any requested Tags.
  6. Append the object to a CSV file.
  7. Once all Resource Groups are processed, open the CSV for review.

$tenantId = '################'
# Set the name of Subscriptions to scan, leave empty to scan all Subscriptions
$subscriptionsToScan = @("Development", "Production", "Etc")
$tagsToRetrieve = @("Owner", "Creator", "Function") # Provide a list of Tags to retrieve from Resource Groups

# Configure export details
$exportLocation = 'C:\temp'
$exportFilePrefix = 'emptyResourceGroups'
$date = Get-Date
$exportPath = "$exportLocation\$exportFilePrefix-$($date.Year)$($date.Month)$($date.Day)$($date.Millisecond).csv"

# Connect to Azure
Connect-AzAccount -TenantId $tenantId -Subscription $subscriptionsToScan[0]

# Get all Subscription details
$subscriptions = Get-AzSubscription

# Loop through each subscription, skipping subscriptions as required
foreach($subscription in $subscriptions) {
    # Skip the Subscription if needed
    if($null -ne $subscriptionsToScan -and $subscriptionsToScan.length -ne 0 -and !($subscriptionsToScan.Contains($subscription.Name))) {
        Write-Host "Skipped $($subscription.Name) Subscription due to filter"
        continue
    }

    Select-AzSubscription -subscriptionId $subscription.Id | Out-Null
    Write-Host "Processing $($subscription.Name) Subscription"

    # Get all RGs in the Subscription
    $resourceGroups = Get-AzResourceGroup
    foreach($resourceGroup in $resourceGroups) {
        $resources = Get-AzResource -ResourceGroupName $resourceGroup.ResourceGroupName

        # if there is a RG with 0 resources then create an object for it and append to the CSV
        if($resources.Count -eq 0) {
            $exportData = [PSCustomObject]@{
                Name = $resourceGroup.ResourceGroupName
                Subscription = $subscription.Name
                Url = "https://portal.azure.com/#@$($tenantId)/resource/subscriptions/$($subscription.Id)/resourceGroups/$($resourceGroup.ResourceGroupName)/overview"
            }

            # Add any configured Tags, ensuring that Tag exists and if not creating an empty value
            foreach($tag in $tagsToRetrieve) {
                if ($resourceGroup.Tags -and $resourceGroup.Tags.ContainsKey($tag)) {
                    $exportData | Add-Member -Name $tag -Type NoteProperty -Value $resourceGroup.Tags[$tag]
                } else {
                    $exportData | Add-Member -Name $tag -Type NoteProperty -Value ""
                }
            }
            
            $exportData | Export-CSV $exportPath -NoClobber -NoTypeInformation -Append
        }
    }
}

Write-Host "Script Completed"
Invoke-Item $exportPath

Leave a comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Design a site like this with WordPress.com
Get started