Danger, Will Robinson or how to bulk delete Azure resource groups

Suppose you’re a an accomplished DevOps cloud architect. You build 100% of your Azure infrastructure via code. That means you’re in the enviable position of being able to blow away all traces of an environment and recreate it at will. And you probably want or need to do this regularly, for example when resetting development environments at build or release time.

This post is about making removing entire Azure environments a little faster and more convenient.

Unfortunately, there are no batch capabilities in the Azure portal that would let you easily select a bunch of resource groups and remove them (and all the contained resources).

And, unlike AWS, Azure isn’t eventually consistent when using PowerShell. That means you wait for each Remove-AzureResourceGroup cmdlet to complete. So, it can take a very long time time to remove one-by-one in PowerShell an environment consisting of many resource groups.

The simple PowerShell script below, shown as a function, uses tags to find and remove a number of resource groups. For each resource group, it uses Start-Job so that resource group deletion happens in parallel.

But Danger, Will Robinson!  The script is indiscriminate: it blows away everything in the resource group and all resource groups containing a specific tag.

The script won’t work unless you were smart enough to tag each resource group with an “Environment” tag. That’s best practice anyway.

As always, the elegance of the PowerShell pipeline reduces the work needed to, essentially, just three lines of code.

I hope you find this useful, and Microsoft, if you are listening, how about adding AsJob to more AzureRM PowerShell cmdlets?

<#
    .SYNOPSIS
        Deletes all Azure resource groups with a specific tag value for a tag key "Environment"
    
    .DESCRIPTION
        Starts PowerShell background jobs to remove an environement by tags. USE WITH CAUTION.
    Also, a destructive, kinda ass-backwards way to see if everything was tagged when created. When this completes, any resources remaining in the environment were NOT properly tagged.
    
    .PARAMETER -env 
        Given a _existing_ tag in the resource group of form: $tags = @{"Environment" = "MyTestEnvironment"}, -env is $tags.Item("Environment")
    
    .EXAMPLE
    PS C:\> . .\FunctionRemoveEnvironment.ps1
    PS C:\> Remove-Environment -env "MyTestEnvironment"
    
    .NOTES
        Alex Neihaus 2018-01-05
        (c) 2018 Air11 Technology LLC -- licensed under the Apache OpenSource 2.0 license, https://opensource.org/licenses/Apache-2.0
        Licensed under the Apache License, Version 2.0 (the "License");
        you may not use this file except in compliance with the License.
        You may obtain a copy of the License at
        http://www.apache.org/licenses/LICENSE-2.0
 
        Unless required by applicable law or agreed to in writing, software
        distributed under the License is distributed on an "AS IS" BASIS,
        WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
        See the License for the specific language governing permissions and
        limitations under the License.
 
        Author's blog: https://www.yobyot.com
#>
function Remove-Environment ([string]$env)
# Parameter is the value of a tag named "Environment" existing in all Azure resource groups which should be deleted e.g. "FinanceDev01" or "ClaimsStage03", etc.
{
    # Finding RGs by tag assumes that an "Environment" tag was added at creation time
    Find-AzureRmResourceGroup -tag @{ "Environment" = $env } | ForEach-Object -Process {
        $rgname = $_.Name;
        Start-Job -ScriptBlock { Remove-AzureRmResourceGroup -Name $args[0] -Force } -ArgumentList $rgname;
        Start-Sleep 30 # Azure gets very upset if you slam too much work at it and randomly decides not to accept the request
    }
    Get-Job | Wait-Job | Receive-Job
}

 


Posted

in

, , ,

by

Comments

4 responses to “Danger, Will Robinson or how to bulk delete Azure resource groups”

  1. Dwain Avatar
    Dwain

    I tried using this and downloaded the latest module. Had to change the syntax to to get-Azure

    function Remove-Environment ([string]$val)

    Parameter is the value of a tag named “Environment” existing in all Azure resource groups which should be deleted e.g. “FinanceDev01” or “ClaimsStage03”, etc.

    {
    # Finding RGs by tag assumes that an “Environment” tag was added at creation time
    Get-AzureRmResourceGroup -tag @{ “Client” = $val } | ForEach-Object -Process {
    $rgname = $_.Name;
    Start-Job -ScriptBlock { Remove-AzureRmResourceGroup -Name $args[0] -Force } -ArgumentList $rgname;
    Start-Sleep 30 # Azure gets very upset if you slam too much work at it and randomly decides not to accept the request
    }
    Get-Job | Wait-Job | Receive-Job
    }

    I got this error

    Cannot validate argument on parameter ‘Name’. The argument is null or empty. Provide an argument
    that is not null or empty, and then try the command again.
    + CategoryInfo : InvalidData: (:) [Remove-AzureRmResourceGroup], ParameterBindingValida
    tionException
    + FullyQualifiedErrorId : ParameterArgumentValidationError,Microsoft.Azure.Commands.Resources.Re
    moveAzureResourceGroupCmdlet
    + PSComputerName : localhost

    Still learning so any help would be good

    1. Alex Neihaus Avatar
      Alex Neihaus

      If I read your changes correctly, you simply changed the name of the variable used as the value for the resource group’s key in the hashtable passed to Get-AzureRmResourceGroup. That’s fine; the name of that variable is arbitrary. It does need to contain the actual value associated with the tag. For example, if the tag is named “Client”, $val will need to contain a value, like “MyFavoriteClient” or whatever you put into the tag.

      Your error is clear: $args is empty, probably because you aren’t retrieving the RG tags. That means whatever you as passing to the cmdlet is either invalid or returning nothing. Try running Get-AzureRmResourceGroup from the console with your values as strings. You have to get that working in order to pass the returned value to Remove-AzureRmResourceGroup.

      Good luck.

  2. Ana Avatar
    Ana

    Thanks for post, but I faced an issue: Find-AzureRmResourceGroup is not recognized as a name of cmdlet. 

    1. Alex Neihaus Avatar
      Alex Neihaus

      I am guessing you are new to PowerShell. Install the Azure cmdlets with Install-Module AzureRm.

Leave a Reply

Your email address will not be published. Required fields are marked *