I 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.
Leave a Reply