Trying out AWS.Tools in Docker

If you’re a frequent user of the AWS Powershell tools, you’ve probably had this experience: you go to run a couple commands against your AWS environment. You do it all the time, so you know to type

Get-EC2Instance -InstanceId i-1111111111

But out of force of habit you type

Get-Ec2inst

And hit the tab key. Now you’re sitting and waiting for several minutes while Powershell loads all of the AWS modules for IAM, ECS, Cloudfront, S3, etc, etc, etc, even though you only want to interact with EC2. A few minutes later it’s done, and you start typing again

Get-EC2Instance -ins

And without thinking you hit the tab key again, and wait for another few minutes while Powershell loads parameter completion.

Well, AWS recently released AWS.Tools for Powershell. It’s a modularized version of the AWS Powershell tools that promises better load times because you can pick and choose the modules for AWS services that you want. Like most of you, I’m hesitant to try anything new fangled on my main laptop right away. Your boss probably likes hearing, “I can’t help with that issue right now, I broke my management environment” as much as mine does.

So I figured I’d try installing the tools in a docker container first. My current windows 10 version is 1803, so I’ll be using

mcr.microsoft.com/windows/servercore:1803

(Yes, I know server nano is smaller. Yes, I know you can run AWS.Tools on linux with .NET Core. I use a windows laptop, so I’d like to see AWS.Tools running in as close to my laptop as I can get)

docker run -it -v "$($home)/.aws:c:\users\containeradministrator\.aws" mcr.microsoft.com/windows/servercore:1803  powershell

The -v is to map my AWS credentials into the container to use after I install AWS.Tools

Next, following the install instructions here I run

Install-Module -Name AWS.Tools.Installer

I had to accept a new NuGet provider when prompted

NuGet provider is required to continue
PowerShellGet requires NuGet provider version '2.8.5.201' or newer to interact with NuGet-based repositories. The NuGet provider must be available in 'C:\Program
Files\PackageManagement\ProviderAssemblies' or 'C:\Users\ContainerAdministrator\AppData\Local\PackageManagement\ProviderAssemblies'. You can also install the NuGet provider by running
'Install-PackageProvider -Name NuGet -MinimumVersion 2.8.5.201 -Force'. Do you want PowerShellGet to install and import the NuGet provider now?
[Y] Yes [N] No [S] Suspend [?] Help (default is "Y"): Y

And then accept that AWS is technically an untrusted repository

Untrusted repository
You are installing the modules from an untrusted repository. If you trust this repository, change its InstallationPolicy value by running the Set-PSRepository cmdlet. Are you sure you want to
install the modules from 'PSGallery'?
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is "N"): Y

Easy enough! Next I tried to use the build in installer function that handles dependencies for you. I’ll start with just the EC2 module for simplicity

Install-AWSToolsModule AWS.Tools.EC2

This command sat for quite a while for me, but when it was done I couldn’t import or use the modle

PS C:\> get-ec2instance
get-ec2instance : The term 'get-ec2instance' is not recognized

I haven’t taken the time to troubleshoot this, but it seems like the documentation promises to install to $env:ProgramFiles\Powershell\Modules when the container has $env:ProgramFiles\WindowsPowershell\modules 

At any rate, let’s try just grabbing the modules ourselves instead of letting AWS abstract it away.

I ran these commands to grab the common module (used by all the AWS.Tools modules) and the EC2 module directly

install-module AWS.Tools.Common
install-module AWS.Tools.EC2

Which seems to work great, and I can now interact with AWS like I’d expect

PS C:\> Get-EC2Instance -InstanceId i-**********
GroupNames    : {}
Groups : {}
Instances : {******}
OwnerId : *********
RequesterId : 987******
ReservationId : r-***********

Now that I’ve got it working, I removed all of the modules from my session with

Remove-module AWS*

So I can compare importing the module versions to the monolithic tools on my laptop. I’ll use this command in both environments to see how long it takes to load the modules, and query EC2 for the results:

$start = get-date;$result = Get-EC2Instance -InstanceId i-********;$end = get-date;write-host "$($end - $start)";

Loading the EC2 module result was 00:00:01.5066032, so under 2 seconds! The next run was much faster, with all of the module already loaded

PS C:\> $start = get-date;$result = Get-EC2Instance -InstanceId i-**********;$end = get-date;write-host "$($end - $start)";
00:00:00.8229332

Under a second! Let’s try that with the old AWSPowershellTools back on my laptop (which loads all of the AWS powershell modules when you call any command)

PS C:\Users\bolson> $start = get-date;$result = Get-EC2Instance -InstanceId i-***********;$end = get-date
;write-host "$($end - $start)";
00:00:08.1064289

Over 8 seconds! It’s not a huge price to pay, but I’ll take a second load time over 8 any day.

Finally, I used this blog post to submit a new issue: https://github.com/aws/aws-tools-for-powershell/issues/118. I haven’t had time to debug what could be wrong, hoping someone else can pick up the torch.