Delete play-resources from Azure using runbooks daniele levis pelusi Pp9qkEV xPk unsplash scaled

Delete play-resources from Azure using runbooks

Learning a new cloud can be frighting: do I configure this right? And, when I click here, don’t I end up with a huge bill at the end of the month?

In general, these fears can be solved quite easily: when you follow along with a training, the trainer will tell you when something might cost you a lot of money. Some common sense is also required. When you start a virtual machine to play around with all the options that are there, you don’t need a virtual machine with 416 cores (even when they are available). In general I use the B1s (1 CPU, 1 GB memory, $6.40 per month) for Linux machines and the B2s (2 CPUs, 4 GB memory, $25.61 per month) for Windows systems. Most resources will be billed per hour, per minute or even per second – so when you stop all resources at the end of the day your bill will be reasonable.

Most of you will know the trick of creating a new resource group for tests and then remove that resource group at the end of the day. You have to keep in mind to actually do so and also be careful not to remove other resource groups that should stay. In my environment, I have a (test) DNS domain that I use to explore f.e. custom domains in Azure Active Directory. The resource group that this DNS domain is running in should not be removed at the end of the day.

To make the removal process more easy, I always test in the same resource group. It is called HelloWorld. At the end of the day, I remove all resources from this specific resource group, but I keep the resource group itself. This will not cost any money. And when I learned about runbooks, I thought “why wouldn’t I schedule this every evening, just in case I forget to remove the resources manually”? You can follow along in your own account when you wish to.

Automation Account

First, create an empty resource group called HelloWorld. Then go to the top of the portal and search for Automation Account. Create a new automation account in a resource group other than “HelloWorld”, call it f.e. Automation. Create a new Azure Run As account, this is the account that the playbook will use to execute the tasks. Please note the information box that warns that you might want to restrict the permissions of this account: it will be contributor on subscription level by default.

Delete play-resources from Azure using runbooks 1 Create automation account

When you created the account, click on the left menu under “Shared Resources” on “Modules”. We will go and use Powershell. The disadvantage of runbooks that use Powershell is that they still use the old version of the Azure modules in Powershell. So we will have to add some modules to use the new version. For our solution, we need two modules: Az.Accounts to be able to connect to the Azure environment and Az.Resources to get information about resources in the HelloWorld resource group and to remove them.

To add these modules, click in the top menu on “Browse gallery”:

Delete play-resources from Azure using runbooks 2 Browse gallery

In the search bar, search for Az.Accounts. Click on Az.Accounts, then on Import. You will see a warning that importing a module may take several minutes. Click on Ok. You will see that the import of Az.Accounts from the portal is very fast, two seconds at the most.

Delete play-resources from Azure using runbooks 3 Import Az.Accounts

Now try to add Az.Resources in the same way. At first, you might see the following message:

Delete play-resources from Azure using runbooks 4 Dependency error

The confirmation that the Az.Accounts module was imported came too fast, Azure was still adding it in the background. When you try again after a minute or so you will see that it is now possible to import Az.Resources as well.

Runbook

Now go back to the Automation Modules page and in the left menu, under Process Automation, click on Runbooks. Add a new runbook by clicking on “Create a runbook” in the top menu. Name it “RemoveHelloWorldResources”, then click on Create.

Now you can copy the Powershell from below and paste it into this screen.

# Runbook RemoveHelloWorldResources
# =================================

# Constants
# =========

$AzureRunAsAccountName = "AzureRunAsConnection"
$resourceGroupName     = "HelloWorld"

# Connect-AzEnvironment
# ---------------------

function Connect-AzEnvironment {
    param(
        $AzureRunAsAccountName
    )

    Write-Output "TRACE: Connecting..."

    try
    {
        # Get the connection "AzureRunAsConnection "
        $sPConnection=Get-AutomationConnection -Name $AzureRunAsAccountName
        Connect-AzAccount `
            -ServicePrincipal `
            -Tenant $sPConnection.TenantId `
            -ApplicationId $sPConnection.ApplicationId `
            -CertificateThumbprint $sPConnection.CertificateThumbprint
    }
    catch {
        if (!$sPConnection)
        {
            $ErrorMsg = "$AzureRunAsAccountName not found."
            throw $ErrorMsg
        } else{
            Write-Error -Message $_.Exception
            throw $_.Exception
        }
    }
}

#  ====
#  Main
#  ====

Write-Output "TRACE: Start runbook RemoveHelloWorldResources"

Connect-AzEnvironment -AzureRunAsAccountName $AzureRunAsAccountName

Write-Output "TRACE: Get a list of resources to remove..."
$resourcesToBeRemoved = (Get-AzResource -ResourceGroupName $resourceGroupName)
$numberOfResourcesToBeRemoved = ($resourcesToBeRemoved | Measure-Object).Count

Write-Output "TRACE: Number of resources to be removed = $numberOfResourcesToBeRemoved"

while ($numberOfResourcesToBeRemoved -gt 0)
{
    Foreach ($resource in $resourcesToBeRemoved) {
        Write-Output "TRACE: $($resource.Name) will be removed..."
        Remove-AzResource -ResourceId $resource.ResourceId -Force
    }

    # Wait a few seconds for the last action to complete. When this isn't done, some parts
    # of Azure might still see the (already deleted) objects

    Start-Sleep -seconds 10

    Write-Output "TRACE: Get a new list of resources to remove..."
    $previousNumberOfResourcesToBeRemoved = $numberOfResourcesToBeRemoved
    $resourcesToBeRemoved = (Get-AzResource -ResourceGroupName $resourceGroupName)
    $numberOfResourcesToBeRemoved = ($resourcesToBeRemoved | Measure-Object).Count

    if ($numberOfResourcesToBeRemoved -eq $previousNumberOfResourcesToBeRemoved) {
        Write-Error "ERROR: Resources cannot be removed. Current list:"
        ($resourcesToBeRemoved).Name
        $ErrorMsg = "ERROR: There are remaining resources in resourcegroup $resourceGroupName."
        throw $ErrorMsg
    }
    Write-Output "TRACE: New number of resources to be removed = $numberOfResourcesToBeRemoved"
}

In the top menu, click on “Test Pane”. In this pane, click “Start” to test the runbook. As expected, there are no resources that can be removed.

Delete play-resources from Azure using runbooks 5 no resources to be removed

Test with a Virtual Machine

Now, let’s test the runbook when a Virtual Machine is deployed. Create a new Virtual Machine in the resource group Hello World. Call it vm1, use an Ubuntu virtual machine, with size B1s. Use password as authentication type, you might want to use azureuser as user-id and enter “BlogAzure2021# as the password. In the Disks submenu, use Standard HDD as disk type (we will not log on to the machine anyway). Under Management disable the Boot diagnostics. Use the defaults for all other fields. Then click Review + Create and Create.

When the VM is deployed, go back to the Automation account, go to the runbook RemoveHelloWorldResources and click on Test pane again. Click on Start. You will see something like this:

Delete play-resources from Azure using runbooks 6 Remove VM from HelloWorldRG

You can see the dependency error: it is impossible to remove a disk when the VM is still running, so in the first while loop six of the seven resources are removed. The second time the VM is already gone and then the disk can be removed without any problems. When you look in the HelloWorld resource group, this resource group is empty. This looks fine, so in the Edit PowerShell Runbook screen, click on Publish and then press Ok.

Delete play-resources from Azure using runbooks 7 Publish

Automation

You can now go to the runbook and press Start every time you want to clean up the HelloWorld resource group. But this isn’t too useful, because going to the HelloWorld resource group and delete all resources from there is just as quick. The real advantage of using Runbooks is that you can automate them. In our case, by scheduling this runbook to run every night at 10PM.

Delete play-resources from Azure using runbooks 8 Runbook

Go to the runbook “RemoveHelloWorldResources” and click on “Link to schedule”. Click under Link a schedule to your runbook and add a schedule. Name it “RemoveHelloWorldResourcesSchedule” and enter the data. Let it run recurring, every day without expiration.

Delete play-resources from Azure using runbooks 9 Schedule

I also added a schedule that runs once, at 10:00 AM (which is 30 minutes from the moment I am configuring this). You can find the schedules in the left menu of the runbook:

Delete play-resources from Azure using runbooks 10 Schedules

You can test the schedule (again) by creating a new virtual machine in the HelloWorld resource group. The results can be seen in the Jobs menu (under Resources).

Pricing of automation

You might have noticed the nice blue box “Learn more about Automation pricing” when you created the automation account:

Delete play-resources from Azure using runbooks 99 pricingpng

Unfortunately, this is just an information box and it doesn’t include a link to a website. When you search for it on the internet, you will find this website [1]: in West Europe you currently get the first 500 minutes for free and pay $0.002 per extra minute.

Links

[1] Pricing of automation: https://azure.microsoft.com/en-us/pricing/details/automation/

Photo by Daniele Levis Pelusi on Unsplash

One Response

  1. Frederique Retsema July 13, 2022

Leave a Reply

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