Export Azure Resource Groups with Tags to csv
The main thing to understand here is how to work with hashtables as that is what the Tags property contains. The other thing we need to account for is that tags are not consistent, no matter how hard we try as administrators, this will lead to inconsistent properties in our array of PSObjects if we just add properties for the tags from each individual Resource Group. So in advance of starting any sorting of the data for the CSV file, we need a unique list of tags across all groups. Resource Groups that don't have that tag, will need the property just so we have a complete set of data for the resulting CSV file. Anyway, less talking, more code.
# Initialise output array$Output = @()# Collect all the groups from the current subscription$ResourceGroups = Get-AzResourceGroup# Obtain a unique list of tags for these groups collectively# Use Sort-Object as per - https://github.com/PowerShell/PowerShell/issues/12059$UniqueTags = $ResourceGroups.Tags.GetEnumerator().Keys | Sort-Object -Unique# Loop through the resource groupsforeach ($ResourceGroup in $ResourceGroups) { # Create a new ordered hashtable and add the normal properties first. $RGHashtable = [ordered] @{} $RGHashtable.Add("Name",$ResourceGroup.ResourceGroupName) $RGHashtable.Add("Location",$ResourceGroup.Location) $RGHashtable.Add("Id",$ResourceGroup.ResourceId) $RGHashtable.Add("ProvisioningState",$ResourceGroup.ProvisioningState) # Loop through possible tags adding the property if there is one, adding it with a hyphen as it's value if it doesn't. if ($ResourceGroup.Tags.Count -ne 0) { $UniqueTags | Foreach-Object { if ($ResourceGroup.Tags[$_]) { $RGHashtable.Add("$_ (Tag)",$ResourceGroup.Tags[$_]) } else { $RGHashtable.Add("$_ (Tag)","-") } } } else { $UniqueTags | Foreach-Object { $RGHashtable.Add("$_ (Tag)","-") } } # Update the output array, adding the ordered hashtable we have created for the ResourceGroup details. $Output += New-Object psobject -Property $RGHashtable}# Sent the final output to CSV$Output | Export-Csv -Path test.csv -NoClobber -NoTypeInformation -Encoding UTF8 -Force
I ran a test with just some basic data in a similar structure, because I'm not on my work machine currently.
$eur = "" | select ResourceGroupName,Location,Tags,ResourceId,ProvisioningState$asia = "" | select ResourceGroupName,Location,Tags,ResourceId,ProvisioningState$na = "" | select ResourceGroupName,Location,Tags,ResourceId,ProvisioningState$sa = "" | select ResourceGroupName,Location,Tags,ResourceId,ProvisioningState$eur.ResourceGroupName = "ParisDC"$eur.Location = "westeurope"$eur.ResourceId = 1$eur.ProvisioningState = "Succeeded"$tags = @{ Computer = "FRDC01" IP = "10.11.10.10" Datacenter = "West Europe" CostCode = 54321}$eur.Tags = $tags$asia.ResourceGroupName = "TokyoDC"$asia.Location = "eastasia"$asia.ResourceId = 2$asia.ProvisioningState = "Succeeded"$tags = @{ Server = "TODC01" IP = "10.12.10.10" CostCode = 98765}$asia.Tags = $tags$na.ResourceGroupName = "NewYorkDC"$na.Location = "eastus"$na.ResourceId = 3$na.ProvisioningState = "Failed"$tags = @{ Computer = "USDC01" IP = "10.10.10.10" Owner = "John Smith" CostCode = 12345}$na.Tags = $tags$sa.ResourceGroupName = "RioDC"$sa.Location = "brazilsouth"$sa.ResourceId = 4$sa.ProvisioningState = "Succeeded"$tags = @{}$sa.Tags = $tags$ResourceGroups += $sa,$na,$eur,$asia
If you want to see the sample, just copy and paste the data, and then omit the line $ResourceGroups = Get-AzResourceGroup
in the code I provided.
Resulting output:
Name Location Id ProvisioningState IP (Tag) Computer (Tag) Owner (Tag) CostCode (Tag) Datacenter (Tag) Server (Tag)---- -------- -- ----------------- -------- -------------- ----------- -------------- ---------------- ------------RioDC brazilsouth 4 Succeeded - - - - - -NewYorkDC eastus 3 Failed 10.10.10.10 USDC01 John Smith 12345 - -ParisDC westeurope 1 Succeeded 10.11.10.10 FRDC01 - 54321 West Europe -TokyoDC eastasia 2 Succeeded 10.12.10.10 - - 98765 - TODC01
I've updated your script a bit and added additional functionality.
- You can now pull tags for resource groups as well as resources
- Selecting multiple subscriptions and pulling all required information at same time
- Fixed issue when there were two similar tags like "testname" and "testname " (extra space at the end - don't even ask :P hehe). To make it more visible it's exporting tags with extra square brackets e.g (testname )
- Changed hashtable type (if I remember correctly as that was a few days ago it was to account for lower case and upper case tags).
Login-AzAccount$Subscription = Get-AzSubscription | Out-GridView -Title 'Select subscription' -OutputMode 'Multiple'# Initialise output array$Output = @()if($Subscription){ foreach ($item in $Subscription) { $item | Select-AzSubscription # Collect all the resources or resource groups (comment one of below) #$Resource = Get-AzResource $Resource = Get-AzResourceGroup # Obtain a unique list of tags for these groups collectively $UniqueTags = $Resource.Tags.GetEnumerator().Keys | Get-Unique �AsString | Sort-Object | Select-Object -Unique | Where-Object {$_ -notlike "hidden-*" } # Loop through the resource groups foreach ($ResourceGroup in $Resource) { # Create a new ordered hashtable and add the normal properties first. $RGHashtable = New-Object System.Collections.Specialized.OrderedDictionary $RGHashtable.Add("Name",$ResourceGroup.ResourceGroupName) $RGHashtable.Add("Location",$ResourceGroup.Location) $RGHashtable.Add("Id",$ResourceGroup.ResourceId) $RGHashtable.Add("ResourceType",$ResourceGroup.ResourceType) # Loop through possible tags adding the property if there is one, adding it with a hyphen as it's value if it doesn't. if ($ResourceGroup.Tags.Count -ne 0) { $UniqueTags | Foreach-Object { if ($ResourceGroup.Tags[$_]) { $RGHashtable.Add("($_) tag",$ResourceGroup.Tags[$_]) } else { $RGHashtable.Add("($_) tag","-") } } } else { $UniqueTags | Foreach-Object { $RGHashtable.Add("($_) tag","-") } } # Update the output array, adding the ordered hashtable we have created for the ResourceGroup details. $Output += New-Object psobject -Property $RGHashtable } # Sent the final output to CSV $Output | Export-Csv -Path c:\temp\1a.csv -append -NoClobber -NoTypeInformation -Encoding UTF8 -Force }}$Output | Out-GridView