How to use Amazon.EC2.Model.Filter with PowerShell to identify EC2 instances

cornedbeefhashI gotta tell ya, I hate hash. Whatever that stuff is, topping it with an egg doesn’t make it any more delectable, IMO.

I am, however, slowly warming to PowerShell hash tables.

Hash tables are oddly named. They are so much simpler to think of as a simple database of keys and their associated values. This MSDN article delivers an excellent explanation of PowerShell hash tables.

I also don’t like the fact that AWS PowerShell cmdlets for managing assets do not use tags. When you are in the AWS Console, you work with names — at a logical level. But in PowerShell, you have to use unique identifiers to manage assets. I understand this, of course, since AWS cannot ensure tags are unique. But it still makes for a lot of work for PowerShell script writers.

In the console, it’s no problem to create an AMI of a running instance by using its name tag, even if a terminated instance has the same name tag. You just check the box next to the one you want, which serves to tell the console which instance to use as the source for the AMI. But doing the same thing in PowerShell means you must uniquely identify the instance programmatically.

Thus, you need a way to supply multiple attributes of an instance using Amazon.EC2.Model.Filter. In this case, we want a running instance with a specific string value in a tag called “Name”.

The solution is to create an array of hash tables, specifying enough attributes to Amazon.EC2.Model.Filter when calling Get-EC2Instance to enable the cmdlet to uniquely identify the desired instance. And there are many attributes available. Check out all the cool things you can filter using Amazon.EC2.Model.Filter.

In my case it was simple: I needed to filter on the tag “Name” and on the attribute instance-state-code.

This meant I needed to pass more than one hash table to Get-EC2Instance. Never having done this before, I assumed that creating an array of hash tables is done exactly like any other array. As we all know, assumptions in tech are usually wrong. But in this case, PowerShell is consistent, if cryptic. An array is an array. You specify it as always, even if it’s an array of hash tables.

Here’s what I came up with:

$instance = Get-EC2Instance `
   -Filter @( @{name='tag:Name'; values="Your Instance Name Tag Here"}; 
           @{name='instance-state-code'; values = 16} ) `
   | Select-Object -ExpandProperty instances #Get instance ID ignoring any terminated instances

Maybe it’s just me, but I think this code really demonstrates the usefulness of PowerShell. If code is poetry, this line is straight from e e cummings.

There are two hash tables in this statement. The first one contains the value of the tag “Name”:
@{name='tag:Name'; values="Your Instance Name Tag Here"}

The second hash table filters for running instances only:
@{name='instance-state-code'; values = 16}

Then, all you need to do to create the array is to enclose the pair of hash tables in the standard PowerShell array notation:
@( array contents here )

Don’t forget to separate the hash table array values with a semi-colon!

Try it: create two instances, give them the same “Name” tag, stop one and run this code. Piping the output of Get-EC2Instance to Select-Object with the -ExpandProperty parameter produces an object of type Amazon.EC2.Model.Instance. That object contains the InstanceID parameter we need to create an AMI.

It all takes longer to explain than to code. PowerShell-ful, eh? I might have to try hash again.


Posted

in

, ,

by

Comments

7 responses to “How to use Amazon.EC2.Model.Filter with PowerShell to identify EC2 instances”

  1. petervandivier Avatar
    petervandivier

    I’ve taken to putting each filter into it’s own variable to try keep the script a bit more readable. I just wish there were an obvious way to group filter objects together like there is for Tag->TagSpecification. I feel a bit silly writing Get-Ec2Thing -Filter $f1, $f2

    1. Alex Neihaus Avatar
      Alex Neihaus

      Peter, thanks for commenting on this post — which is now almost four years old. Its continued popularity pleases me because it tells me that many people are enjoying doing DevOps in AWS with PowerShell, something I personally think is among the best ways to interact with AWS.

      On your point about supplying multiple objects to Get-EC2Instance‘s -Filter parameter, IMHO it’s a very natural thing. If you look at the doc for the cmdlet you’ll see that the -Filter parmeter is specifically noted to be able to accept an incoming collection of objects. It feels very “pwsh-ish” to me.

      1. petervandivier Avatar
        petervandivier

        and… here I was about to get all sassy about pwsh verbosity when I hadn’t tried simply smushing $f1, $f2, … $fN all together in a simple @() collection before the function ?

        I guess it’s no surprise that I was a little brain-fried by the time I was trolling blog posts for hints – nevertheless it’s nice to know the feedback is encouraging. Thanks again for the great reference!

  2. Jeremy Avatar
    Jeremy

    Do you know of a way to make the filter value case insensitive?  I’ve figured out that an asterisk (*) works as a wildcard character – e.g. “NA*” will match “NAME” and “NAMES”, but this won’t match “Name” or “name”.

    I hoped there was some regex magic I might be missing.

    1. Alex Neihaus Avatar
      Alex Neihaus

      Hi, Jeremy.

      Thanks for the comment. No, I don’t think you can make the filter value case insensitive because the doc explicitly notes that it is case sensitive: filter documentation

  3. Panzerbjrn Avatar
    Panzerbjrn

    A bit late to the party, but thanks for this 🙂

     

    I was trying to find a way to  search exactly this way.

     

    1. Alex Neihaus Avatar
      Alex Neihaus

      Glad it helped you out!

Leave a Reply

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