ManageTagsOnVM.ps1

<#PSScriptInfo
 
.VERSION 1.0.0.1
 
.GUID 02d9d53f-b0e8-4b9f-aafa-27a55792373b
 
.AUTHOR AlexG
 
.COMPANYNAME
 
.COPYRIGHT
 
.TAGS Azure Automation Tags
 
.LICENSEURI
 
.PROJECTURI
 
.ICONURI
 
.EXTERNALMODULEDEPENDENCIES
 
.REQUIREDSCRIPTS
 
.EXTERNALSCRIPTDEPENDENCIES
 
.RELEASENOTES
 
 
#>


<#
 
.DESCRIPTION
 This is a Powershell script to help manage TAGS on Azure Virtual Machine Resource
 While it is very easy to add and change tags using console, it is not so easy to delete a specific tag
 from a resource. The console also limits the number of resources you can update to 100. so if you need
 to change tags on more than 100 VMs, then you'll need to rinse and repeat as often as neccessary
 
 This script will allow you to add, replace or remove a specific tag from any VM that matches a search criteria
 using parameters -ManageThisTag or ManageThisTag and ManageThisTagValue.
 
 This script is part of a set of ManageTagsOn scripts. Please look for
 ManageTagsOnDisk
 ManageTagsOnNetworkCard
 ManageTagsOnPublicIP
 ManageTagsOnNetworkSecurityGroup
 ManageTagsOnAvailabilitySet
 ManageTagsOnRouteTable
 ManageTagsOnAutomationRunbooks
 
#>


<# \
.SYNOPSIS
    Add, Remove or Replace tags on Virtual Machine Resources in Azure
 
.DESCRIPTION
    This is a Powershell script to help manage TAGS on Azure Virtual Machine Resource
    While it is very easy to add and change tags using console, it is not so easy to delete a specific tag
    from a resource. The console also limits the number of resources you can update to 100. so if you need
    to change tags on more than 100 VMs, then you'll need to rinse and repeat as often as neccessary
 
    This script will allow you to add, replace or remove a specific tag from any VM that matches a search criteria
    using parameters -ManageThisTag or ManageThisTag and ManageThisTagValue.
 
.PARAMETER ManageThisTag
    The name of the TAG to be use as a search criteria. Filters only those VMs where this tag exists.
 
.PARAMETER ManageThisTagValue
    The value of the TAG specified by ManageThisTag. This further filters only those VMs where this tag exists and it value matches ManageThisTagValue.
 
.PARAMETER FromGroup
    The name of the Resource Group to limit search scope. Filters only those VMs in the specific Resource Group.
 
.PARAMETER addtag
    the addtag switch works together with NewTagKey and NewTagValue parameters. This will make the script add a new tag NewTagKey with value of NewTagValue
    to the VMs that match the search criteria
 
.PARAMETER replacetag
    The replacetag parameter will tell the script to delete the specified tag, no matter of its value is
    and replace it with a new tag NewTagKey with value of NewTagValue
 
.PARAMETER replacetagvalue
    The replacetagvalue parameter will tell the script to delete the specified tag, only if its value matches ManageThisTagValue
    and replace it with a new tag NewTagKey with value of NewTagValue
 
.PARAMETER removetag
    The replacetag parameter will tell the script to delete the specified tag, no matter of its value is
 
.PARAMETER removetagvalue
    The replacetagvalue parameter will tell the script to delete the specified tag, only if its value matches ManageThisTagValue
 
.PARAMETER WhatIf
    Safe run of the script without any changes to preview changes that would be made.
 
 
.EXAMPLE
    ManageTagsOnVM.ps1 -ManageThisTag "Environment" -removetag -FromGroup "test-vm-servers"
 
    ManageTagsOnVM.ps1 -ManageThisTag "Environment" -ManageThisTagValue "Development" -replacetagvalue -NewTagKey "Environment" -NewTagValue "Test"
 
.NOTES
    AUTHOR: Alexander Goldberg
    LASTEDIT: Feb 12, 2020
#>


param(
    [string]$ManageThisTag,
    [string]$ManageThisTagValue,
    [string]$NewTagKey,
    [string]$NewTagValue,
    [string]$FromGroup,
    [switch]$addtag,
    [switch]$replacetag,
    [switch]$replacetagvalue,
    [switch]$removetag,
    [switch]$removetagvalue,
    [switch]$WhatIf

)

if ( 1 -ne $replacetag.IsPresent + $replacetagvalue.IsPresent + $removetag.IsPresent + $removetagvalue.IsPresent + $addtag.IsPresent) {
    'Usage: ManageTagsOnVM -ManageThisTag -ManageThisTagValue [-FromGroup] { -addtag | -replacetag | -replacetagvalue | -removetag | -removetagvalue } [-WhatIf { true | false }]'
    exit 1
}


if ($FromGroup.Length -eq 0) {
    #Getting the list of all VMs in the subscription.
    $Resources = Get-AzureRmVM
}
else {
    #Getting the list of VMs based on the resource group.
    $Resources = Get-AzureRmVM -ResourceGroupName $FromGroup
}


#Details of the tag to managed are stored in the $TagToManage hashtable variable.
$TagToManage = @{Key = "$ManageThisTag"; Value = "$ManageThisTagValue" }

foreach ($Resource in $Resources) {
    Write-Output "processing: " + $Resource.Name
    # Initialize UpdateTags to false
    $UpdateTags = $false

    # Getting the list of all the tags for the current VM in the foreach loop.
    $Resourcetags = $Resource.tags

    if ($addtag) {
        if ($null -ne $ResourceTags -and $ResourceTags.ContainsKey($TagToManage.Key)) {
            Write-Output "Tag" + $TagToManage.Key + "exists in the" + $Resource.Name + "The new tag will be Added here"
            # Adding new tag to the Resource if it has the TagToManage
            $Resource.Tags.Add($NewTagKey, $NewTagValue)

            # In addition to the new tag key and value, you can also hardcode any additonal tag value key pairs here
            # I know, it's not pretty, but it works if you want to add multiple tags
            #$Resource.Tags.Add("tag name","tag value") # Adding the tag to update with new value
            #$Resource.Tags.Add("tag name","tag value") # Adding the tag to update with new value

            #set UpdateTags to true
            $UpdateTags = $true
        }
    }

    # The replacetag parameter will tell the script to delete the specified tag, no matter of its value is
    # and replace it with a new tag and value
    if ($replacetag) {
        if ($null -ne $ResourceTags -and $ResourceTags.ContainsKey($TagToManage.Key)) {
            Write-Output + "Tag" + $TagToManage.Key + "exists in the" + $Resource.Name + "and will be Replaced"
            $Resource.Tags.Remove($TagToManage.Key)
            $Resource.Tags.Add($NewTagKey, $NewTagValue)

            #set UpdateTags to true
            $UpdateTags = $true
        }
    }

    # The replacetagvalue parameter will tell the script to delete the specified tag, only if its value matches ManageThisTagValue
    # and replace it with a new tag and value
    if ($replacetagvalue) {
        if ($null -ne $ResourceTags -and $ResourceTags.ContainsKey($TagToManage.Key) -and ($ResourceTags.($TagToManage.Key) -eq $TagToManage.Value)) {
            Write-Output + "Tag" + $TagToManage.Key + "with value of" + $TagToManage.Value + "exists in the" + $Resource.Name + "and will be Replaced"
            $Resource.Tags.Remove($TagToManage.Key)
            $Resource.Tags.Add($NewTagKey, $NewTagValue)

            #set UpdateTags to true
            $UpdateTags = $true
        }
    }

    # The removetag parameter will tell the script to delete the specified tag, no matter of its value is
    if ($removetag) {
        If ($Resourcetag.Key -eq $TagToManage.Key) {
            Write-Output + "Tag" + $TagToManage.Key + "exists in the" + $Resource.Name + "and will be Removed"
            $Resource.Tags.Remove($TagToManage.Key)
            $UpdateTags = $true
        }
    }

    # The removetagvalue parameter will tell the script to delete the specified tag, only if its value matches ManageThisTagValue
    if ($removetagvalue) {
        if ($null -ne $ResourceTags -and $ResourceTags.ContainsKey($TagToManage.Key) -and ($ResourceTags.($TagToManage.Key) -eq $TagToManage.Value)) {
            Write-Output + "Tag" + $TagToManage.Key + "with value of" + $TagToManage.Value + "exists in the" + $Resource.Name + "and will be Removed"
            $Resource.Tags.Remove($TagToManage.Key)

            #set UpdateTags to true
            $UpdateTags = $true
        }
    }

    #Updating VM.
    if ($UpdateTags) {
        Write-Output + "Updating Tags on:" + $Resource.Name
        if (!$WhatIf) {
            $Resource | Set-AzureRmVM
        }
        else {
            Write-Output "--- new tags ---"
            Write-Output ($Resource.Tags | Out-String)
        }
    }
}