As per usual, what I thought would be a quick and easy task turned out to be a tad more complex than what I had expected.

All I needed to do was return a list of Azure resources, get the contents of the tags and stick them into a Python script. This should have been quite simple but I well and truly fell down the rabbit hole on this one!

Contents

Project Brief

  • Get a list off all resources within a subscription.
  • Only show the resources that have tags applied.
  • Show the contents of the tags.
  • Integrate the code within an existing Python 3 based application.

Python

The first thing I did was a Google search for listing resources via the Azure Python SDK. When I’ve performed similar queries before using the likes of PowerShell or the Azure CLI I’ve found that tags are often attributes of the resources.

The search led me to this Microsoft doc.

I followed it to the letter, and it worked pretty well when listing resource groups, but bombed out with the below error when trying to list the resources within each group:

'ResourceGroupsOperations' object has no attribute 'list_resources'

This is where I fell down the rabbit hole! A quick Google search of the error led me to Stack Overflow, which then suggested I had a module version issue. So this led me to PyPi to check the versions, which then led me to another Microsoft doc to inspect the class. Nightmare!

I spent the next hour or so trawling through various forums trying to get this to work. It should have been so easy!

Long story short, the below code is how I did it:

Install the same module version as the original MS doc. Note the latest version is on 8.0.1!

pip install azure-mgmt-resource==3.0.0

Replace the variables in the square brackets with your own. In my example, a Service Principal with Reader RBAC permissions was required.

from azure.common.credentials import ServicePrincipalCredentials  
from azure.mgmt.resource import ResourceManagementClient
from azure.mgmt.compute import ComputeManagementClient
from azure.mgmt.network import NetworkManagementClient

logging.basicConfig(level=logging.INFO)

credentials = ServicePrincipalCredentials(
    client_id = [client_id],
    secret = [secret],
    tenant = [tenant]
)

subscription_id = [subscription_id]

client = ResourceManagementClient(credentials, subscription_id)

for item in client.resource_groups.list():

        # below did not work as per the doc
        # for item in client.resource_groups.list_resources(GROUP_NAME):

        # working replacement
        for item in client.resources.list_by_resource_group(item.name):
            if item.tags: 
                logging.info(item.name + " " + str(item.tags))

Output:

This will do just nicely!

I was able to use the same module version as the guide - which was updated in 2019 (at the time of writing) with the module version listed as 3, yet the latest version is 8!

At some point I will come back to this and re-work the code to use the latest version.

Azure REST API

I very nearly gave up on using the Azure Python SDK. My fall back was to make an Azure REST API call.

Here’s how I went about meeting the project brief using the Azure REST APIs:

The below works on the basis that an access_token has already been generated. You pass it in as a Bearer within the header. If you would like me to create a guide on how to do this please get in touch.

GET https://management.azure.com/subscriptions/{subscriptionId}/resources?api-version=2019-10-01

Output:

As you can see, the resources are listed along with their tags. I can now parse this JSON output to only return objects where tags are present.

PowerShell

This is how I went about trying to achieve something similar using PowerShell:

Get-AzResource `
| Select-Object Name, ResourceGroupName, Tags `
| Where-Object {$_.Tags.Count -ne 0}

Output:

Azure CLI

This is how I went about trying to achieve something similar using the Azure CLI:

az resource list --query [?tags].[name,location,tags] --output table

Output:


So there we go - project completed!

Update

In the production version, I ended using the Azure REST API method within a Python script. I didn’t feel confident using the Python modules given the confusion over the documentation and version numbers.

Thanks for reading!