Filtering resources by tag in AWS PowerShell

If you’ve worked with AWS PowerShell for any length of time, you’re probably well used to filtering resources based on attributes. For instance, grabbing any Autoscaling groups with a name that matches a given filter, like this.

Get-ASAutoScalingGroup | ? { $_.AutoScalingGroupName -like "production-*" }

Easy, isn’t it? Just uses the Where-Object cmdlet, with the filter parameter set to a simple -like match

And that’s about as far as many people go with Where-Object. Simple, first level matching. However when you’re dealing with AWS tags, you’ve got to do a bit more work. Tags are not exposed as first-level properties on your object. Instead, the Tags[] object is a first-level property, and the tags themselves are objects, with Key and Value properties. So you have to have a filter in your filter so you can filter while you filter.

With EC2, you can use the -Filter parameter on Get-EC2Instance, but Get-ASAutoScalingGroup doesn’t have this parameter. So you have to get smarter with Where-Object.

Luckily, the filter you pass into Where-Object is in fact a script block. You can do as much work as you like in there. It’s much more versatile than a simple string match. Let’s look, for example, at filtering AutoScaling Groups based on a tag named “Sleepytime” with value of “Yes”. I’ve expanded the properties a bit and added some formatting, to make it easier to read:

Get-ASAutoScalingGroup | Where-Object -FilterScript {
    $_.Tags | Where-Object {
        $_.Key -eq "Sleepytime" -and $_.Value -eq "Yes" 
    }
}

Or, as I’d have it in my own script

Get-ASAutoScalingGroup | ? { $_.Tags | ? { $_.Key -eq "Sleepytime" -and $_.Value -eq "Yes" }}

Taking this to its logical extent, you could take a huge object structure and zoom right in to a property many branches deep into the object tree, with a relatively readable filter structure. If you’ve read a big XML or JSON document into memory, for instance, this will allow you to filter by attributes buried far into the tree.

Of course, if your objects are extremely complex, there may be better, faster ways to query them, but in the case of AWS tags, this is a quick, simple and effective way of getting it done.

One reply

  1. Chris Fowles says:

    One I like is:
    $Instances = @{}
    (Get-EC2Instance).Instances.ForEach({$Instances.Add($_.Tags.Where({$_.Key -eq ‘Name’}).Value, $_)})

    Lets you do stuff like:
    $Instances.’PROD-APP01′.PrivateDnsName

Leave a Reply

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