0
votes

Trying to apply tags that are set at the resource GROUP level to any resources within the resource group (all resources).

Found a script online and modified it minimally.

It should make sure the tag NAME and tag VALUE are both set based on the resource group (example: if the resource group has tag name "ABCD" and tag value "1234", and a resource underneath the resource group has tag "ABCD" and tag value "4567", then it should overwrite that value with "1234") There is one tag that should be set on all resources. The name we know, but the value we don't.

I've noticed it takes a LONG time to run. A resource group with 10 resources in it might take 1-2 minutes for the script to run against

Any ideas or suggestions?

#List all Resources within the Subscription
$Resources = Get-AzureRmResource

#For each Resource apply the Tag of the Resource Group
Foreach ($resource in $Resources)
{
$Rgname = $resource.Resourcegroupname

$resourceid = $resource.resourceId
$RGTags = (Get-AzureRmResourceGroup -Name $Rgname).Tags

$resourcetags = $resource.Tags

If ($resourcetags -eq $null)
    {
        Write-Output "---------------------------------------------"
        Write-Output "Applying the following Tags to $($resourceid)" $RGTags
        Write-Output "---------------------------------------------"
        $Settag = Set-AzureRmResource -ResourceId $resourceid -Tag $RGTagS -Force

    }
Else
    {
        $RGTagFinal = @{}
        $RGTagFinal = $RGTags                  
                Foreach ($resourcetag in $resourcetags.GetEnumerator())
                {

                If ($RGTags.Keys -inotcontains $resourcetag.Key)
                    {                        
                            Write-Output "------------------------------------------------"
                            Write-Output "Keydoesn't exist in RG Tags adding to Hash Table" $resourcetag
                            Write-Output "------------------------------------------------"
                            $RGTagFinal.Add($resourcetag.Key,$resourcetag.Value)
                    }    

                }
        Write-Output "---------------------------------------------"
        Write-Output "Applying the following Tags to $($resourceid)" $RGTagFinal
        Write-Output "---------------------------------------------"
        $Settag = Set-AzureRmResource -ResourceId $resourceid -Tag $RGTagFinal -Force
    }   
}

A few things the script should do too, which i'm not sure this script does.

  1. If the resource already has 15 tags, it will not overwrite a tag with the resource group level tag; it will just skip it
  2. Rather than copying ALL tags from the resource group to the resource, there's only one tag. Could we put logic in where if the resource group has a tag of "ABCDEFG" for instance, it will copy it over? Any other tags it won't?
  3. Perhaps to speed it up, is it possible to just CHECK if the tag name and value on the resource level matches the tag on the resource group level, and not to overwrite it if it already matches. I suspect it's the write that is taking time, and just reading the tags isn't.
1
do you do this for a specific group, or just scanning all resources (multiple groups)? - Mike Twc
What if the number of tags exceeds 15 during the addition process? Seems there is a limit of 15 tags. - Joy Wang-MSFT
If I understand things correctly, you are looking for a solution that can pulls a specific tag from the resource group, updates that tag across all child ressources, if they don't have 15 tags already. Correct? - Mötz
@JoyWang please note the first item in my list - if it has 15 tags it should just skip it. - S. Space
@MikeTwc The idea is to run this across all resource groups (and thus all resources within them) for all subscriptions. - S. Space

1 Answers

0
votes

This one should bring you very close to what you are looking for

$tagName = "ABCD"
$tagFallbackValue = "123"

$subscriptionId = "ewn3k4l4jh32jæ42æ3lj4æl12j4"

Connect-AzureRmAccount

$sub = Get-AzureRmSubscription -SubscriptionId $subscriptionId

Set-AzureRmContext -SubscriptionObject $sub

$resGroups = Get-AzureRmResourceGroup

foreach ($resGroup in $resGroups) {
    #Some ResourceGroups might not have tags defined at all.
    if($null -eq $resGroup.Tags) {
        $Tag = @{}
        $null = $Tag.Add($tagName, $tagFallbackValue)

        Set-AzureRmResourceGroup -Tag $Tag -Id $resGroup.ResourceId
    }#Some ResourceGroups might have tags but missing ours.
    elseif ($resGroup.Tags.ContainsKey($tagName) -eq $false) {
        $Tag = $resGroup.Tags
        $null = $Tag.Add($tagName, $tagFallbackValue)

        Set-AzureRmResourceGroup -Tag $Tag -Id $resGroup.ResourceId
    }#We need to test those that have our tag, if they have the desired tag value
    else {
        if($resGroup.Tags.$tagName -ne $tagFallbackValue) {
            $Tag = $resGroup.Tags
            $Tag.$tagName = $tagFallbackValue

            Set-AzureRmResourceGroup -Tag $Tag -Id $resGroup.ResourceId
        }
    }

    $tagValue = $resGroup.Tags.$tagName
    $resGroupName = $resGroup.ResourceGroupName

    #Some resources might already have our tag, find them and test if they have the correct value
    $resHasTag = Get-AzureRmResource -ResourceGroupName $resGroupName | Where-Object {$null -ne $_.tags -and $_.Tags.ContainsKey($tagName) -eq $true}
    foreach ($res in $resHasTag) {
        if($res.Tags.$tagName -ne $tagValue) {
            $Tag = $res.Tags
            $Tag.$tagName = $tagValue

            Set-AzureRmResource -ResourceId $res.ResourceId -Tag $Tag -Force
        }
    }

    #Some resources might not have tags defined at all.
    $resNoTags = Get-AzureRmResource -ResourceGroupName $resGroupName | Where-Object {$null -eq $_.tags -or $_.tags.Count -lt 1}
    foreach ($res in $resNoTags) {
        $Tag = @{}
        $null = $Tag.Add($tagName, $tagValue)
        Set-AzureRmResource -ResourceId $res.ResourceId -Tag $Tag -Force
    }

    #We need to find all resources that is missing our tag and have less than 15 tags
    $resOtherTags = Get-AzureRmResource -ResourceGroupName $resGroupName | Where-Object {$null -ne $_.tags -and $_.tags.Count -lt 15 -and $_.Tags.ContainsKey($tagName) -eq $false}
    foreach ($res in $resOtherTags) {
        $Tag = $res.Tags
        $null = $Tag.Add($tagName, $tagValue)

        Set-AzureRmResource -ResourceId $res.ResourceId -Tag $Tag -Force
    }
}

Updated version matching the new requirements

$tagName = "COSTCODE"

Connect-AzureRmAccount

$subscriptions = Get-AzureRmSubscription

foreach ($sub in $subscriptions) {
    Set-AzureRmContext -SubscriptionObject $sub

    $resGroups = Get-AzureRmResourceGroup

    foreach ($resGroup in $resGroups) {
        #Some ResourceGroups might not have tags defined at all, we skip those.
        if ($null -eq $resGroup.Tags) { continue }

        #Some ResourceGroups might have tags but missing ours, we skip those.
        elseif ($resGroup.Tags.ContainsKey($tagName) -eq $false) { continue }
        #We need to test those that have our tag, if they have the desired tag value

        $tagValue = $resGroup.Tags.$tagName
        $resGroupName = $resGroup.ResourceGroupName

        #Some resources might already have our tag, find them and test if they have the correct value
        $resHasTag = Get-AzureRmResource -ResourceGroupName $resGroupName | Where-Object {$null -ne $_.tags -and $_.Tags.ContainsKey($tagName) -eq $true}
        foreach ($res in $resHasTag) {
            if ($res.Tags.$tagName -ne $tagValue) {
                $Tag = $res.Tags
                $Tag.$tagName = $tagValue

                Set-AzureRmResource -ResourceId $res.ResourceId -Tag $Tag -Force
            }
        }

        #Some resources might not have tags defined at all.
        $resNoTags = Get-AzureRmResource -ResourceGroupName $resGroupName | Where-Object {$null -eq $_.tags -or $_.tags.Count -lt 1}
        foreach ($res in $resNoTags) {
            $Tag = @{}
            $null = $Tag.Add($tagName, $tagValue)
            Set-AzureRmResource -ResourceId $res.ResourceId -Tag $Tag -Force
        }

        #We need to find all resources that is missing our tag and have less than 15 tags
        $resOtherTags = Get-AzureRmResource -ResourceGroupName $resGroupName | Where-Object {$null -ne $_.tags -and $_.tags.Count -lt 15 -and $_.Tags.ContainsKey($tagName) -eq $false}
        foreach ($res in $resOtherTags) {
            $Tag = $res.Tags
            $null = $Tag.Add($tagName, $tagValue)

            Set-AzureRmResource -ResourceId $res.ResourceId -Tag $Tag -Force
        }
    }
}