Search code examples
azureazure-powershellazure-cli

Azure CLI - Delete resource without deleting resource group


The goal is to delete all resources in a resourcegroup without deleting it using azure CLI.

From reading the doc, I can do this:

az resource delete -g MyResourceGroup -n MyVm

Therefore I assumed I can do the following

az resource list   --resource-group MyResourceGroup | az resource delete 

A similar command in Azure Powershell would work like the above. I am quite new to CLI, is this method possible? What is the efficient way of removing all resources in a resource group (if we have multiple types of resources)


Solution

  • If can you run Azure CLI in powershell, you could use ConvertFrom-Json to convert the JSON result to a list of objects from az resource list, then run az resource delete on each object id using a foreach loop.

    $resources = az resource list --resource-group myResourceGroup | ConvertFrom-Json
    
    foreach ($resource in $resources) {
        az resource delete --resource-group myResourceGroup --ids $resource.id --verbose
    }
    

    We could also run this entirely in the pipeline using Foreach-Object, which is close to what you are trying to do.

    az resource list --resource-group myResourceGroup 
        | ConvertFrom-Json
            | Foreach-Object {az resource delete --resource-group myResourceGroup --ids $_.id --verbose}
    

    If you don't want to use powershell at all, we can use bash to parse the JSON output ourselves using grep and awk.

    #!/bin/bash
    
    resources="$(az resource list --resource-group myResourceGroup | grep id | awk -F \" '{print $4}')"
    
    for id in $resources; do
        az resource delete --resource-group myResourceGroup --ids "$id" --verbose
    done
    

    As @Hong Ooi helpfully pointed out in the comments, the main issue with the above is that some resources depend on other resources, so order of deletion matters. One example is that you cannot delete virtual machine disks before the virtual machine is deleted.

    To get around this, we could define an ordering of resource types in which to delete resources, as shown in the example hash table below:

    $resourceOrderRemovalOrder = [ordered]@{
        "Microsoft.Compute/virtualMachines" = 0
        "Microsoft.Compute/disks" = 1
        "Microsoft.Network/networkInterfaces" = 2
        "Microsoft.Network/publicIpAddresses" = 3
        "Microsoft.Network/networkSecurityGroups" = 4
        "Microsoft.Network/virtualNetworks" = 5
    }
    

    Then sort the resources by their resource types and delete them:

    $resources = az resource list --resource-group myResourceGroup | ConvertFrom-Json
    
    $orderedResources = $resources 
        | Sort-Object @{
            Expression = {$resourceOrderRemovalOrder[$_.type]}
            Descending = $False
        }
    
    $orderedResources | ForEach-Object {
        az resource delete --resource-group myResourceGroup --ids $_.id --verbose
    }
    

    Or in one pipeline if you prefer:

    az resource list --resource-group myResourceGroup 
        | ConvertFrom-Json
            | Sort-Object @{Expression = {$resourceOrderRemovalOrder[$_.type]}; Descending = $False}
                | ForEach-Object {az resource delete --resource-group myResourceGroup --ids $_.id --verbose}