Raku CLI AWS – Postvent

It was great fun writing my two contributions to the Raku Advent calendar:

  1. Day 11: Santa CL::AWS with a short raku procedural wrapper on AWS CLI
  2. Day 16: Santa CL::AWS (part 2) with a raku OO refactoring

These posts presented my work in progress, in advent calendar style of course, on a new raku module: CLI::AWS::EC2-Simple. The module is now available at the raku zef repository via raku.land with github repo here. This post completes the CL::AWS trilogy with a demo of it in action and how the OO model from last time is now wrapped as a command.

Show Me

First, here’s the new module in action:

By the way, I chose to base the script name as “raws” in homage to the great, but different, perl5 cpan module paws. Paws is an autogenerated and complete perl5 interface to AWSCLI … and can easily be used from raku code like this use PAWS::EC2:from<Perl>; and indeed there’s a debate about that on the raku reddit.

But Raws is different. It is meant primarily to help me in my needs to quickly and consistently launch the same EC2 configuration as specified in a minimal yaml. A command line shorthand alternative to the AWS EC2 console launch dialog. So, Raws is an added value wrapper to AWSCLI, an abstraction with the emphasis on Simplicity and Repeatability. I have released it as a module in the vague expectation that others will have the same needs.

The sharp eyed reader will note that the command is actually raws-ec2. This is in anticipation of some other author creating a raws-s3 for example, or maybe a broader command that can be used via a bare raws –ec2 or raws –s3 and so on.

Getting Started

  • apt-get update && apt-get install aws-cli
  • aws configure [enter your config here]
  • zef install CLI::AWS::EC2-Simple
  • raws-ec2 [enter your commands here]

Command Abstract

The built-in raku MAIN() routine helps to quickly add command line features to our module including a quick abstract of the commands and arguments. Just type raws-ec2 for this:

./raws-ec2 [--id=] [--nsu] [--eip] [-y] 
             One of 'list launch setup connect state terminate nuke'
    --id=    Running InstanceId of form 'i-0785d8bd98b5f458b'
    --nsu    No setup (suppress launch from running setup)
    --eip    Allocates (if needed) and Associates Elastic IP
    -y       Silence confirmation  cmd only

Authors note: Beware – these examples can quickly ramp your AWS bill! Keep an eye in your AWS EC2 Instances console. 

Simple Consistent Pattern

Now, here’s a peek inside the default aws-ec2-launch.yaml file that comes with the module:

    image: 'ami-0f540e9f488cfa27d'
    type: 't2.micro'
        name: 'MySG'
            - inbound:
                port: 80
                cidr: ''
            - inbound:
                port: 443 
                cidr: ''

This is the heart of the system, making one easy place to setup and manage your preferences at the AWS Instance level. [Just be careful to save your changes away when reinstalling the module]

To be honest, while very powerful, I find the awscli itself quite bewildering with multiple steps to connect and setup a session (KeyPair, Security Groups, Elastic IP assignment, and so on), so I was chuffed to see just how neatly the key parameters can be boiled down and handed to raws-ec2 to do the painful bit.

Making a Raku Library Module

Here’s the raku Object Oriented code from part II… with some details folded away:

To turn this into a raku module, a couple of tweaks were needed: a header line like this:

unit module CLI::AWS::EC2-Simple:ver<0.0.2>:auth<Steve Roe (p6steve@furnival.net)>;

Also, the classes we want to expose need to be marked ‘is export’:

class Instance is export { ... }

Also I used the $*HOME global to set the home directory of the target installation. The curious may want to check out my Build.pm for how the install set up the default config files.

Making a Raku Command

I did think about folding away some of the command code, but then there is some value in seeing how it all fits together into just over 80 lines…

Star Features

The stars to raku fall in several places:

  • The build in MAIN() routine is the star of the show, showing how to annotate each argument declaration in the signature with Pod6 #= to make the abstract
  • The raku given/when “switch” makes the backbone of the code very intelligible
  • Raku slurp and spurt make IO a doddle
  • And the use of unless is pretty neat instead of if not

Functional Future

So, this delivery of a simple EC2 tool was pretty straightforward to write and will save me time by giving me a way to remember my repeatable settings and apply them consistently. Perhaps there is scope for friendly Instance tags here too…

As mentioned in part II, the Raku Functional features could help us to improve clarity and composability even more.

But that’s for another time…


PS. Please comment and feedback here (follow the Archive link) or over at reddit