1
votes

I'm interested in querying an Azure subscription to provide a Tagging report which indicates the VM Name, Azure Region, and the Tags and Tag Value for each VM.

My current script provides me with the all the data with the exception of the Tag Value for each respective Tag. My output is displaying a result as if a Tag doesn't exist.

Does anyone have any advice on my script? Thanks!

param( [Parameter(Mandatory = $true)] [String] $subscriptionName )

Select-AzSubscription -Subscription $subscriptionName

$allTags = Get-AzTag

$allVMs = Get-AzVM

$vmInformation = @() foreach ($vm in $allVMs) {

$vmInformationObject = New-Object PSObject

$vmName = $vm.Name
$vmRegion = $vm.Location
$vmInformationObject | Add-Member -MemberType NoteProperty -Name "VM_Name" -Value $vmName
$vmInformationObject | Add-Member -MemberType NoteProperty -Name "VM_Region" -Value $vmRegion

$vm_tags = $vm.tags
foreach ($tag in $allTags) {
    $IfTagExists = $false
    foreach ($vmtag in $vm_tags) {
        if ($tag.name -like $vmtag.keys) {
            $IfTagExists = $true
            $vmInformationObject | Add-Member -MemberType NoteProperty -Name $tag.Name -Value $vmtag.$($tag.Name)
            break
        }
    }
    if ($IfTagExists -eq $false) {
        $vmInformationObject | Add-Member -MemberType NoteProperty -Name $tag.Name -Value "--"
    }
}
$vmInformation += $vmInformationObject }

$vmInformation | Export-Csv "path.csv" -NoTypeInformation -Force

2
$tag.name -like $vmtag.keys should use a different operator --> $tag.name -in $vmtag.keys as an example. You are comparing a single value to a list of values. You, therefore, need an operator that compares items in a list.AdminOfThings
Thanks for your help and the advice. I amended the code and that resulted in Tag Values being populated in my output. Much appreciated!ks2933

2 Answers

0
votes

The issue here is the comparison statement $tag.name -like $vmtag.keys. Since the left-hand side value is a scalar and the right-hand side value is a collection or list, you need to use a containment comparison operator. The easiest options are -in or -contains.

# Option 1
# Use -in when singular item is on the LHS and collection is on RHS
if ($tag.name -in $vmtag.keys) {
            $IfTagExists = $true
            $vmInformationObject | Add-Member -MemberType NoteProperty -Name $tag.Name -Value $vmtag.$($tag.Name)
            break
}

# Option 2
# Use -contains when singular item is on the RHS and collection is on LHS
if ($vmtag.keys -contains $tag.name) {
            $IfTagExists = $true
            $vmInformationObject | Add-Member -MemberType NoteProperty -Name $tag.Name -Value $vmtag.$($tag.Name)
            break
}
0
votes

I am bit late to the party and I would like to mention that if you try to export the results to a CSV file you will have issues. According to Microsoft Export-CSV organizes the file based on the properties of the first object that you submit. If the remaining objects do not have one of the specified properties, the property value of that object is null, as represented by two consecutive commas. If the remaining objects have additional properties, those property values are not included in the file.

https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.utility/export-csv?view=powershell-7.1

Your script will also run slower because you are using the variable $allTags = Get-AzTag instead of filtering only the common tags across all the VMs as you can see in the variable $AllVMsTagKeys in the script below which will do everything that you want and in quicker and cleaner way and will also export the results to a CSV file on your desktop:

$VMs = Get-AzVM -Status
$AllVMsTagKeys = $VMs.Tags.Keys | Sort-Object -Unique

  foreach ( $VM in $VMs ) {

    $Output = [PSCustomObject]@{
      VMName = $VM.Name
      VMRegion = $VM.Location
      ResourceGroup = $VM.ResourceGroupName
      PowerState = $VM.PowerState
    }    

    foreach ( $VMTagKey in $AllVMsTagKeys ) {

      Add-Member -InputObject $Output -Force -NotePropertyName $VMTagKey -NotePropertyValue $VM.Tags[$VMTagKey]

    }

    $Output
    $Output | Export-Csv -NoTypeInformation -Append -Path $env:USERPROFILE\Desktop\VMsWithTags.csv

  }