So after a year and a half, I decided to blow off the cobwebs and flex the PowerShell muscles again. Being a Windows Engineer for ‘a few years’ and writing scripts in Monad before it became PowerShell. I felt like it was time to see what PowerShell Core was like and play with AWS.

So I used the AWS guide to install [PowerShell Core 6.0][0] for OSX

brew tap caskroom/cask
brew cask install powershell
brew update
brew cask reinstall powershell

Then install the AWSPowerShell.NetCore from PowerShell Gallery and they have module documentation. I am using VSCode as my IDE and you can get information on VSCode PowerShell plugin here.

Install-Module -Name AWSPowerShell.NetCore

Another usefull guide. AWS PowerShell user-guide

Ok so now I am up and running with PSCore, whats next… lets checkout AWS and the available cmdlets.

(get-command -Module AWSPowerShell.NetCore).count

WOW 3979 commands for AWS…. lets look at available EC2 Images.

First we need to know what cmdlets are available to work with EC2 Images, we can use Get-Command and filters to find this. PowerShell cmdlet naming standard is based on a Verb/Noun structure which we can filter on using -Verb, -Noun or -Name arguments.

Get-Command -Name *Image* -Module AWSPowerShell.NetCore

CommandType Name Version S
----------- ---- ------- -
Cmdlet Copy-EC2FpgaImage A
Cmdlet Copy-EC2Image A
Cmdlet Edit-EC2FpgaImageAttribute A
Cmdlet Edit-EC2ImageAttribute A
Cmdlet Get-APSImageBuilderList A
Cmdlet Get-APSImageList A
Cmdlet Get-CBCuratedEnvironmentImageList A
Cmdlet Get-EC2FpgaImage A
Cmdlet Get-EC2FpgaImageAttribute A
Cmdlet Get-EC2Image A
Cmdlet Get-EC2ImageAttribute A
Cmdlet Get-EC2ImageByName A
Cmdlet Get-EC2ImportImageTask A
Cmdlet Get-ECRImage A
Cmdlet Get-ECRImageBatch A
Cmdlet Get-ECRImageMetadata A
Cmdlet Import-EC2Image A
Cmdlet New-APSImageBuilder A
Cmdlet New-APSImageBuilderStreamingURL A
Cmdlet New-EC2FpgaImage A
Cmdlet New-EC2Image A
Cmdlet Register-EC2Image A
Cmdlet Remove-APSImage A
Cmdlet Remove-APSImageBuilder A
Cmdlet Remove-EC2FpgaImage A
Cmdlet Remove-ECRImageBatch A
Cmdlet Reset-EC2FpgaImageAttribute A
Cmdlet Reset-EC2ImageAttribute A
Cmdlet Search-REKFacesByImage A
Cmdlet Start-APSImageBuilder A
Cmdlet Stop-APSImageBuilder A
Cmdlet Unregister-EC2Image A
Cmdlet Write-ECRImage A

Using Get-EC2Image we can pull all the EC2 images available. But we want to filter, so we need to understand the object properties returned for an image.

One of my favorite and invaluable cmdlets is Get-Member, this allows you to see properties and methods on your objects.

Get-EC2Image -Region us-east-1 | Select -first 1 | Get-Member

TypeName: Amazon.EC2.Model.Image

Name MemberType Definition
---- ---------- ----------
BlockDeviceMapping AliasProperty BlockDeviceMapping = BlockDeviceMappings
ImageState AliasProperty ImageState = State
Tag AliasProperty Tag = Tags
Equals Method bool Equals(System.Object obj)
GetHashCode Method int GetHashCode()
GetType Method type GetType()
ToString Method string ToString()
Architecture Property Amazon.EC2.ArchitectureValues Architecture {get;set;}
BlockDeviceMappings Property System.Collections.Generic.List[Amazon.EC2.Model.BlockDeviceMapping] BlockDeviceMappings {get;set;}
CreationDate Property string CreationDate {get;set;}
Description Property string Description {get;set;}
EnaSupport Property bool EnaSupport {get;set;}
Hypervisor Property Amazon.EC2.HypervisorType Hypervisor {get;set;}
ImageId Property string ImageId {get;set;}
ImageLocation Property string ImageLocation {get;set;}
ImageOwnerAlias Property string ImageOwnerAlias {get;set;}
ImageType Property Amazon.EC2.ImageTypeValues ImageType {get;set;}
KernelId Property string KernelId {get;set;}
Name Property string Name {get;set;}
OwnerId Property string OwnerId {get;set;}
Platform Property Amazon.EC2.PlatformValues Platform {get;set;}
ProductCodes Property System.Collections.Generic.List[Amazon.EC2.Model.ProductCode] ProductCodes {get;set;}
Public Property bool Public {get;set;}
RamdiskId Property string RamdiskId {get;set;}
RootDeviceName Property string RootDeviceName {get;set;}
RootDeviceType Property Amazon.EC2.DeviceType RootDeviceType {get;set;}
SriovNetSupport Property string SriovNetSupport {get;set;}
State Property Amazon.EC2.ImageState State {get;set;}
StateReason Property Amazon.EC2.Model.StateReason StateReason {get;set;}
Tags Property System.Collections.Generic.List[Amazon.EC2.Model.Tag] Tags {get;set;}
VirtualizationType Property Amazon.EC2.VirtualizationType VirtualizationType {get;set;}

As you can see from the output above, the object returned is a Amazon.EC2.Model.Image object and all properties, methods and aliases for the object are listed.

Using that information we can construct a PowerShell script, there are a couple ways to filter data in PowerShell.

  1. -Filter{} parameter on a cmdlets itself.
  2. Where-Object{} cmdlet, allowing pipeline filtering on returned data objects.

Both of these have their place but lets look at the performance when pulling large data sets from AWS.

Where-Object{} Cmdlet

Measure-Command{Get-EC2Image -Region us-east-1 | Where-Object{$PSItem.Platform -eq "windows"} | Select-Object Name}

Days : 0
Hours : 0
Minutes : 1
Seconds : 20
Milliseconds : 327
Ticks : 803275570
TotalDays : 0.000929717094907407
TotalHours : 0.0223132102777778
TotalMinutes : 1.33879261666667
TotalSeconds : 80.327557
TotalMilliseconds : 80327.557

-Filter{} Property

$platform_values = New-Object 'collections.generic.list[string]'
$filter_platform = New-Object Amazon.EC2.Model.Filter -Property @{Name = "platform"; Values = $platform_values}
Measure-Command{Get-EC2Image -Owner amazon -Filter $filter_platform -Region us-east-1 | Select name}

Days : 0
Hours : 0
Minutes : 0
Seconds : 34
Milliseconds : 766
Ticks : 347665610
TotalDays : 0.000402390752314815
TotalHours : 0.00965737805555555
TotalMinutes : 0.579442683333333
TotalSeconds : 34.766561
TotalMilliseconds : 34766.561

So for this case using the -Filter{} parameter is much faster than filtering the returned data with Where-Object.

To perform filtering using the -Filter{} parameter you need to submit a hash for the specific attribute you want to filter on. If you want to filter on multiple attributes then you create multiple filter objects or hash tables for each filter and wrap them in an array separated by semi-colon. Check the specific cmdlets documentation for the available filters here.

Filters for Get-EC2Image here

I want to filter on both platform, root-device-type and name.

Final Script:

$platform_values = New-Object 'collections.generic.list[string]'
$rootdevicetype_values = New-Object 'collections.generic.list[string]'
$name_values = New-Object 'collections.generic.list[string]'
$filter_platform = New-Object Amazon.EC2.Model.Filter -Property @{Name = "platform";Values = $platform_values}
$filter_rootdevicetype = New-Object Amazon.EC2.Model.Filter -Property @{Name = "root-device-type";Values = $rootdevicetype_values}
$filter_name = New-Object Amazon.EC2.Model.Filter -Property @{Name = "name";Values = $name_values}
$properties = @( $filter_platform ; $filter_rootdevicetype ; $filter_name)
Get-EC2Image -Owner amazon -Filter $properties -Region us-east-1 | Select name

Here are some more useful links.

Hope it helps.

All information is provided on an AS-IS basis, with no warranties and confers no rights