AWS logo

Recently I had the need to tag all our EC2 instances based on the platform, as I wanted to create resource groups based on the actual underlying platform used for the EC2 instances.

Much to my surprise the AWS console did not offer any tools to do this, and as such I instantly knew that it was time for some PowerShell magic. Amazon has really done a great job of creating PowerShell modules for their services, and you can pretty much do anything the console does and then some.

To do this we use the Get-EC2Instance and New-Ec2Tag cmdlets to do this job for us, where we apply a filter to Get-EC2Instance to get all Windows instances. The code for this is as follows:

$tag = New-Object Amazon.EC2.Model.Tag
$tag.Key = "OS"
$tag.Value = "Windows"

$filter = @(New-Object Amazon.EC2.Model.Filter -Property @{Name = "platform"; Values = "windows" })

$instances = (Get-EC2Instance -Filter $filter).Instances

$instances | ForEach-Object {
    $instanceId = $_.InstanceID
    Write-Output "Processing instance $instanceId"

    try {
        New-EC2Tag -Resource $instanceId -Tag $tag
    }
    catch {
        throw
    }
}

Here we first create a tag pair using Amazon.EC2.Model.Tag object, and then we create the filter object using Amazon.EC2.Model.Filter object type. One interesting thing I noticed when researching this was that all the filter properties and values seemed to require lowercase, as using @{Name = “Platform”; Values = “Windows” } returned an empty result. This is in contrast to how the filters operate when you are on the EC2 instance overview page in the AWS Console.

Another thing I noticed when trying to filter out the Linux instances, was that using @{Name = “platform; Values = “linux” } returned an empty result. I then proceeded to run (Get-EC2Instance).Instances without any filters, and examined its output using Format-Table -AutoSize and noticed that the platform field for all my Linux instances came up empty. Time to adjust the code, which ended up being:

$tag = New-Object Amazon.EC2.Model.Tag
$tag.Key = "OS"
$tag.Value = "Linux"

$instances = (Get-EC2Instance).Instances

$instances | ForEach-Object {
    if ($_.Platform -like '') {
        $instanceId = $_.InstanceID
        Write-Output "Processing instance $instanceId"

        try {
            New-EC2Tag -Resource $instanceId -Tag $tag
        }
        catch {
            throw
        }
    }
}

Using Get-EC2Instances is your friend whenever you need to perform operations on a selection of instances, and if you are like me filtering on tags (and you are using tags right?), then filtering on tags is dead simple. Said you had a tag called Department that you wanted to filter on the value IT, then the filter you would use would end up being $filter = @(New-Object Amazon.EC2.Model.Filter -Property @{Name = “tag:Department”; Values = “IT” }).

Good luck tagging your EC2 instances :)

By Jostein Elvaker Haande

"A free society is a society where it is safe to be unpopular" - Adlai Stevenson

Leave a Reply

Your email address will not be published. Required fields are marked *