AWS: Managing AWS Command Line with Jake Tasks
The AWS Command Line is awesome. The commands are descriptive, well organized and oftentimes easier to use than any of the dashboard consoles.
If you're looking or a simple NodeJS tool to help you to script and automate commands, try JakeJS.
JakeJS is a task management tool similar to Grunt or Gulp but that is inspired by Rake --that was derived from Make. Jake is fantastic for anyone coming from the Ruby on Rails community.
Jake Features
My favorite JakeJS features include:
- Prerequisites allow you to run checks before running a task.
- Namespaces help you organize your code into groups.
- Test tasks simplify testing.
- Daisy chaining allows you to run a task within other tasks.
Gettting Started
Install JakeJS
npm install jake --save-dev
Create a Jakefile.
touch Jakefile.js
Populate the Jakefile
with tasks. Example
Organizing mutiple files
You can organize your different scripts by creating file.jake
files and placing them inside of a /jakelib
folder. See example.
Examples
All of my examples below will first require you to create an AWS cli profile.
List your IAM users
var util = require('util');
//You might want to consider .env
var config = { profile: 'process.env.DOT_ENV_PROFILE' }
desc('List of Users.');
task('listUsers', { async: true }, function() {
var cmds = [ util.format('aws iam list-users --profile %s', config.profile) ];
jake.exec(cmds, { printStdout: true });
});
Zip a collection of Lambda files
This example shows you to how zip up a bunch of lambda functions.
var util = require('util');
namespace('app', function () {
desc('Archive app for upload.');
task('archive', { async: true }, function(config) {
//Itemize the files you're excluding then concatenate them
var excludes = [
//Hidden files (i.e. .gitignore, .env)
'-x .\*',
//NPM package file
'-x "package.json"',
//NPM Jakefile
'-x "Jakefile.js"',
//ReadMe notes
'-x \*.md',
//HTTP Request Simulator
'-x \*.paw',
//AWS Policy Files
'-x "aws_policies\*"',
//Jakefile tasks
'-x "jakelib\*"'
].join(" ")
var cmds = [
//Remove all node modules including -devDependencies
"rm -r node_modules",
//Only install the production-ready modules
"npm install --only=production",
//Recursively Zip everything with exception to anything within excludes
util.format('zip -r %s * %s', config.app, excludes)
];
//Set "printStdout" to "true" if you want to see the stack trace
jake.exec(cmds, { printStdout: false }, function(){
complete();
})
});
Common S3 Commands
I first create a file called /jakelib/aws.jake
. This file will be used as a pre-requisite check that I have an AWS Client profile created.
var util = require('util');
var AWS = require("aws-sdk");
var fs = require('fs');
namespace('aws', function () {
//TODO: Keep this AWS profile up-to-date.
var AWS_CREDENTIALS = {
profile: "sgm"
}
desc('Prerequisite to most jake tasks. This loads credentials in NodeJS.');
//http://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/loading-node-credentials-shared.html
task('loadCredentials', { async: true }, { breakOnError: true }, function() {
if(!AWS_CREDENTIALS.profile) fail("No awscli profile found within .env. Learn more: https://goo.gl/U2HiAs");
AWS.config.credentials = new AWS.SharedIniFileCredentials({ profile: AWS_CREDENTIALS.profile });
//console.log(AWS.config.credentials);
complete();
});
});
My second file is titled /jakelib/s3.jake
. This file will always check aws.jake
.
var util = require('util');
namespace('s3', function () {
var config = { profile: "aws_credentials_profile" }
desc('Create an S3 bucket.');
task('create', ['aws:loadCredentials'], { async: true }, function(bucket_name) {
var cmds = [ util.format('aws s3 mb %s --profile %s', bucket_name, config.profile) ];
jake.exec(cmds, { printStdout: true });
});
desc('Upload a file to an S3 bucket.');
task('upload', ['aws:loadCredentials'], { async: true }, function(bucket_name, file) {
var cmds = [ util.format('aws s3 cp /local/file/or/folder s3://%s --profile %s', bucket_name, config.profile) ];
jake.exec(cmds, { printStdout: true });
});
desc('List objects within a bucket.');
task('list', ['aws:loadCredentials'], { async: true }, function(bucket_name) {
var cmds = [ util.format('aws s3 ls s3://%s --profile %s', bucket_name, config.profile) ];
jake.exec(cmds, { printStdout: true });
});
});
Now all you need to do is run jake namespace:task[params]
.
jake s3:create[name_of_s3_bucket,awscli_profile_name]