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:


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 });
});

Source

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();
		})
	});		

Source


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]

Example Code


Resources