Advanced Resource Graph query samples
The first step to understanding queries with Azure Resource Graph is a basic understanding of the Query Language. If you aren't already familiar with Azure Data Explorer, it's recommended to review the basics to understand how to compose requests for the resources you're looking for.
We'll walk through the following advanced queries:
- Show API version for each resource type
- Get virtual machine scale set capacity and size
- Remove columns from results
- List all tag names
- Virtual machines matched by regex
- List Azure Cosmos DB with specific write locations
- Key vaults with subscription name
- List SQL Databases and their elastic pools
- List virtual machines with their network interface and public IP
- List all extensions installed on a virtual machine
- Find storage accounts with a specific tag on the resource group
- Combine results from two queries into a single result
- Get virtual networks and subnets of network interfaces
- Summarize virtual machine by the power states extended property
If you don't have an Azure subscription, create a free account before you begin.
Language support
Azure CLI (through an extension) and Azure PowerShell (through a module) support Azure Resource Graph. Before running any of the following queries, check that your environment is ready. See Azure CLI and Azure PowerShell for steps to install and validate your shell environment of choice.
Show API version for each resource type
Resource Graph primarily uses the most recent non-preview version of a Resource Provider API to
GET
resource properties during an update. In some cases, the API version used has been overridden
to provide more current or widely used properties in the results. The following query details the
API version used for gathering properties on each resource type:
Resources
| distinct type, apiVersion
| where isnotnull(apiVersion)
| order by type asc
az graph query -q "Resources | distinct type, apiVersion | where isnotnull(apiVersion) | order by type asc"
Get virtual machine scale set capacity and size
This query looks for virtual machine scale set resources and gets various details including the
virtual machine size and the capacity of the scale set. The query uses the toint()
function to
cast the capacity to a number so that it can be sorted. Finally, the columns are renamed into custom
named properties.
Resources
| where type=~ 'microsoft.compute/virtualmachinescalesets'
| where name contains 'contoso'
| project subscriptionId, name, location, resourceGroup, Capacity = toint(sku.capacity), Tier = sku.name
| order by Capacity desc
az graph query -q "Resources | where type=~ 'microsoft.compute/virtualmachinescalesets' | where name contains 'contoso' | project subscriptionId, name, location, resourceGroup, Capacity = toint(sku.capacity), Tier = sku.name | order by Capacity desc"
Remove columns from results
The following query uses summarize
to count resources by subscription, join
to combine it with
subscription details from ResourceContainers table, then project-away
to remove some of the
columns.
Resources
| summarize resourceCount=count() by subscriptionId
| join (ResourceContainers | where type=='microsoft.resources/subscriptions' | project SubName=name, subscriptionId) on subscriptionId
| project-away subscriptionId, subscriptionId1
az graph query -q "Resources | summarize resourceCount=count() by subscriptionId | join (ResourceContainers | where type=='microsoft.resources/subscriptions' | project SubName=name, subscriptionId) on subscriptionId| project-away subscriptionId, subscriptionId1"
List all tag names
This query starts with the tag and builds a JSON object listing all unique tag names and their corresponding types.
Resources
| project tags
| summarize buildschema(tags)
az graph query -q "Resources | project tags | summarize buildschema(tags)"
Virtual machines matched by regex
This query looks for virtual machines that match a regular expression
(known as regex). The matches regex @ allows us to define the regex to match, which is ^Contoso(.*)[0-9]+$
.
That regex definition is explained as:
^
- Match must start at the beginning of the string.Contoso
- The case-sensitive string.(.*)
- A subexpression match:.
- Matches any single character (except a new line).*
- Matches previous element zero or more times.
[0-9]
- Character group match for numbers 0 through 9.+
- Matches previous element one or more times.$
- Match of the previous element must occur at the end of the string.
After matching by name, the query projects the name and orders by name ascending.
Resources
| where type =~ 'microsoft.compute/virtualmachines' and name matches regex @'^Contoso(.*)[0-9]+$'
| project name
| order by name asc
az graph query -q "Resources | where type =~ 'microsoft.compute/virtualmachines' and name matches regex @'^Contoso(.*)[0-9]+\$' | project name | order by name asc"
List Azure Cosmos DB with specific write locations
The following query limits to Azure Cosmos DB resources, uses mv-expand
to expand the property bag
for properties.writeLocations, then project specific fields and limit the results further to
properties.writeLocations.locationName values matching either 'East US' or 'West US'.
Resources
| where type =~ 'microsoft.documentdb/databaseaccounts'
| project id, name, writeLocations = (properties.writeLocations)
| mv-expand writeLocations
| project id, name, writeLocation = tostring(writeLocations.locationName)
| where writeLocation in ('East US', 'West US')
| summarize by id, name
az graph query -q "Resources | where type =~ 'microsoft.documentdb/databaseaccounts' | project id, name, writeLocations = (properties.writeLocations) | mv-expand writeLocations | project id, name, writeLocation = tostring(writeLocations.locationName) | where writeLocation in ('East US', 'West US') | summarize by id, name"
Key vaults with subscription name
The following query shows a complex use of join
with kind as leftouter. The query limits the
joined table to subscriptions resources and with project
to include only the original field
subscriptionId and the name field renamed to SubName. The field rename avoids join
adding it
as name1 since the field already exists in resources. The original table is filtered with
where
and the following project
includes columns from both tables. The query result is all key
vaults displaying type, the name of the key vault, and the name of the subscription it's in.
Resources
| join kind=leftouter (ResourceContainers | where type=='microsoft.resources/subscriptions' | project SubName=name, subscriptionId) on subscriptionId
| where type == 'microsoft.keyvault/vaults'
| project type, name, SubName
az graph query -q "Resources | join kind=leftouter (ResourceContainers | where type=='microsoft.resources/subscriptions' | project SubName=name, subscriptionId) on subscriptionId | where type == 'microsoft.keyvault/vaults' | project type, name, SubName"
List SQL Databases and their elastic pools
The following query uses leftouter join
to bring together SQL Database resources and their
related elastic pools, if they've any.
Resources
| where type =~ 'microsoft.sql/servers/databases'
| project databaseId = id, databaseName = name, elasticPoolId = tolower(tostring(properties.elasticPoolId))
| join kind=leftouter (
Resources
| where type =~ 'microsoft.sql/servers/elasticpools'
| project elasticPoolId = tolower(id), elasticPoolName = name, elasticPoolState = properties.state)
on elasticPoolId
| project-away elasticPoolId1
az graph query -q "Resources | where type =~ 'microsoft.sql/servers/databases' | project databaseId = id, databaseName = name, elasticPoolId = tolower(tostring(properties.elasticPoolId)) | join kind=leftouter ( Resources | where type =~ 'microsoft.sql/servers/elasticpools' | project elasticPoolId = tolower(id), elasticPoolName = name, elasticPoolState = properties.state) on elasticPoolId | project-away elasticPoolId1"
List virtual machines with their network interface and public IP
This query uses two leftouter join
commands to bring together virtual machines created with
the Resource Manager deployment model, their related network interfaces, and any public IP address
related to those network interfaces.
Resources
| where type =~ 'microsoft.compute/virtualmachines'
| extend nics=array_length(properties.networkProfile.networkInterfaces)
| mv-expand nic=properties.networkProfile.networkInterfaces
| where nics == 1 or nic.properties.primary =~ 'true' or isempty(nic)
| project vmId = id, vmName = name, vmSize=tostring(properties.hardwareProfile.vmSize), nicId = tostring(nic.id)
| join kind=leftouter (
Resources
| where type =~ 'microsoft.network/networkinterfaces'
| extend ipConfigsCount=array_length(properties.ipConfigurations)
| mv-expand ipconfig=properties.ipConfigurations
| where ipConfigsCount == 1 or ipconfig.properties.primary =~ 'true'
| project nicId = id, publicIpId = tostring(ipconfig.properties.publicIPAddress.id))
on nicId
| project-away nicId1
| summarize by vmId, vmName, vmSize, nicId, publicIpId
| join kind=leftouter (
Resources
| where type =~ 'microsoft.network/publicipaddresses'
| project publicIpId = id, publicIpAddress = properties.ipAddress)
on publicIpId
| project-away publicIpId1
az graph query -q "Resources | where type =~ 'microsoft.compute/virtualmachines' | extend nics=array_length(properties.networkProfile.networkInterfaces) | mv-expand nic=properties.networkProfile.networkInterfaces | where nics == 1 or nic.properties.primary =~ 'true' or isempty(nic) | project vmId = id, vmName = name, vmSize=tostring(properties.hardwareProfile.vmSize), nicId = tostring(nic.id) | join kind=leftouter ( Resources | where type =~ 'microsoft.network/networkinterfaces' | extend ipConfigsCount=array_length(properties.ipConfigurations) | mv-expand ipconfig=properties.ipConfigurations | where ipConfigsCount == 1 or ipconfig.properties.primary =~ 'true' | project nicId = id, publicIpId = tostring(ipconfig.properties.publicIPAddress.id)) on nicId | project-away nicId1 | summarize by vmId, vmName, vmSize, nicId, publicIpId | join kind=leftouter ( Resources | where type =~ 'microsoft.network/publicipaddresses' | project publicIpId = id, publicIpAddress = properties.ipAddress) on publicIpId | project-away publicIpId1"
List all extensions installed on a virtual machine
First, this query uses extend
on the virtual machines resource type to get the ID in uppercase
(toupper()
) the ID, get the operating system name and type, and get the virtual machine size.
Getting the resource ID in upper case is a good way to prepare to join to another property. Then,
the query uses join
with kind as leftouter to get virtual machine extensions by matching an
upper cased substring
of the extension ID. The portion of the ID before
"/extensions/<ExtensionName>" is the same format as the virtual machines ID, so we use this
property for the join
. summarize
is then used with make_list
on the name of the virtual
machine extension to combine the name of each extension where id, OSName, OSType, and VMSize
are the same into a single array property. Lastly, we order by
the lower cased OSName with
asc. By default, order by
is descending.
Resources
| where type == 'microsoft.compute/virtualmachines'
| extend
JoinID = toupper(id),
OSName = tostring(properties.osProfile.computerName),
OSType = tostring(properties.storageProfile.osDisk.osType),
VMSize = tostring(properties.hardwareProfile.vmSize)
| join kind=leftouter(
Resources
| where type == 'microsoft.compute/virtualmachines/extensions'
| extend
VMId = toupper(substring(id, 0, indexof(id, '/extensions'))),
ExtensionName = name
) on $left.JoinID == $right.VMId
| summarize Extensions = make_list(ExtensionName) by id, OSName, OSType, VMSize
| order by tolower(OSName) asc
az graph query -q "Resources | where type == 'microsoft.compute/virtualmachines' | extend JoinID = toupper(id), OSName = tostring(properties.osProfile.computerName), OSType = tostring(properties.storageProfile.osDisk.osType), VMSize = tostring(properties.hardwareProfile.vmSize) | join kind=leftouter( Resources | where type == 'microsoft.compute/virtualmachines/extensions' | extend VMId = toupper(substring(id, 0, indexof(id, '/extensions'))), ExtensionName = name ) on \$left.JoinID == \$right.VMId | summarize Extensions = make_list(ExtensionName) by id, OSName, OSType, VMSize | order by tolower(OSName) asc"
Find storage accounts with a specific tag on the resource group
The following query uses an inner join
to connect storage accounts with resource groups that
have a specified case-sensitive tag name and tag value.
Resources
| where type =~ 'microsoft.storage/storageaccounts'
| join kind=inner (
ResourceContainers
| where type =~ 'microsoft.resources/subscriptions/resourcegroups'
| where tags['Key1'] =~ 'Value1'
| project subscriptionId, resourceGroup)
on subscriptionId, resourceGroup
| project-away subscriptionId1, resourceGroup1
az graph query -q "Resources | where type =~ 'microsoft.storage/storageaccounts' | join kind=inner ( ResourceContainers | where type =~ 'microsoft.resources/subscriptions/resourcegroups' | where tags['Key1'] =~ 'Value1' | project subscriptionId, resourceGroup) on subscriptionId, resourceGroup | project-away subscriptionId1, resourceGroup1"
If it's necessary to look for a case insensitive tag name and tag value, use mv-expand
with the
bagexpansion parameter. This query uses more quota than the previous query, so use mv-expand
only if necessary.
Resources
| where type =~ 'microsoft.storage/storageaccounts'
| join kind=inner (
ResourceContainers
| where type =~ 'microsoft.resources/subscriptions/resourcegroups'
| mv-expand bagexpansion=array tags
| where isnotempty(tags)
| where tags[0] =~ 'key1' and tags[1] =~ 'value1'
| project subscriptionId, resourceGroup)
on subscriptionId, resourceGroup
| project-away subscriptionId1, resourceGroup1
az graph query -q "Resources | where type =~ 'microsoft.storage/storageaccounts' | join kind=inner ( ResourceContainers | where type =~ 'microsoft.resources/subscriptions/resourcegroups' | mv-expand bagexpansion=array tags | where isnotempty(tags) | where tags[0] =~ 'key1' and tags[1] =~ 'value1' | project subscriptionId, resourceGroup) on subscriptionId, resourceGroup | project-away subscriptionId1, resourceGroup1"
Combine results from two queries into a single result
The following query uses union
to get results from the ResourceContainers table and add them to
results from the Resources table.
ResourceContainers
| where type=='microsoft.resources/subscriptions/resourcegroups' | project name, type | limit 5
| union (Resources | project name, type | limit 5)
az graph query -q "ResourceContainers | where type=='microsoft.resources/subscriptions/resourcegroups' | project name, type | limit 5 | union (Resources | project name, type | limit 5)"
Get virtual networks and subnets of network interfaces
Use a regular expression parse
to get the virtual network and subnet names from the resource ID
property. While parse
enables getting data from a complex field, it's optimal to access properties
directly if they exist instead of using parse
.
Resources
| where type =~ 'microsoft.network/networkinterfaces'
| project id, ipConfigurations = properties.ipConfigurations
| mvexpand ipConfigurations
| project id, subnetId = tostring(ipConfigurations.properties.subnet.id)
| parse kind=regex subnetId with '/virtualNetworks/' virtualNetwork '/subnets/' subnet
| project id, virtualNetwork, subnet
az graph query -q "Resources | where type =~ 'microsoft.network/networkinterfaces' | project id, ipConfigurations = properties.ipConfigurations | mvexpand ipConfigurations | project id, subnetId = tostring(ipConfigurations.properties.subnet.id) | parse kind=regex subnetId with '/virtualNetworks/' virtualNetwork '/subnets/' subnet | project id, virtualNetwork, subnet"
Summarize virtual machine by the power states extended property
This query uses the extended properties on virtual machines to summarize by power states.
Resources
| where type == 'microsoft.compute/virtualmachines'
| summarize count() by tostring(properties.extended.instanceView.powerState.code)
az graph query -q "Resources | where type == 'microsoft.compute/virtualmachines' | summarize count() by tostring(properties.extended.instanceView.powerState.code)"
Next steps
- See samples of Starter queries.
- Learn more about the query language.
- Learn more about how to explore resources.