Skip to content
Browse files

created npm package for aws wrapper

  • Loading branch information...
0 parents commit 9dc908b143bfa6e87ac61e308910cdb47b6f981e @teemow teemow committed Sep 24, 2010
Showing with 434 additions and 0 deletions.
  1. +44 −0 README.md
  2. +9 −0 examples/descibe-instances.js
  3. +214 −0 lib/aws.js
  4. +19 −0 package.json
  5. +148 −0 test/aws-test.js
44 README.md
@@ -0,0 +1,44 @@
+# amazon aws wrapper
+
+Just wraps commandline calls to aws with some predefined filters for amis, instances, public and private dns data.
+
+## Install
+You have to install all the amazon tools you'd like to use (eg. ec2, elb, autoscaling tools).
+
+The environment variables for the tools have to be configured. Something like:
+
+<pre>
+EC2_HOME=/opt/ec2-api-tools
+EC2_AMITOOL_HOME=/opt/ec2-ami-tools
+AWS_AUTO_SCALING_HOME=/opt/AutoScaling
+AWS_CLOUDWATCH_HOME=/opt/CloudWatch
+AWS_ELB_HOME=/opt/ElasticLoadBalancing
+
+EC2_PRIVATE_KEY="your-aws-private-key"
+EC2_CERT="your-aws-certificate"
+EC2_ACCESS_KEY="your-aws-access-key"
+EC2_SECRET_KEY="your-aws-secret"
+AWS_CREDENTIAL_FILE=your-credential-file
+
+EC2_REGION=eu-west-1
+EC2_KEYPAIR_EU_WEST_1=your-aws-key-pair
+</pre>
+
+Then just install the module with npm.
+
+<pre>
+npm install aws
+</pre>
+
+## Example
+
+<pre>
+var aws = require('aws');
+aws.setRegion('eu-west-1');
+
+aws.init(['ec2', 'aws_elb', 'aws_auto_scaling'], function(apis) {
+ apis.ec2.describe_instances.public_dns(function(instances) {
+ sys.puts(sys.inspect(instances)); // lists all public dns of your ec2 instances
+ });
+});
+
9 examples/descibe-instances.js
@@ -0,0 +1,9 @@
+var aws = require('aws');
+aws.setRegion('eu-west-1');
+
+aws.init(['ec2', 'aws_elb', 'aws_auto_scaling'], function(apis) {
+ apis.ec2.describe_instances.public_dns(function(instances) {
+ sys.puts(sys.inspect(instances)); // lists all public dns of your ec2 instances
+ });
+});
+
214 lib/aws.js
@@ -0,0 +1,214 @@
+/**
+ * Evil wrapper for the aws command line tools
+ */
+
+var exec = require('child_process').exec,
+ spawn = require('child_process').spawn,
+ fs = require('fs')
+ sys = require('sys');
+ http = require('http');
+ events = require("events");
+
+var tools = {}, apis = [
+ 'ec2',
+ 'ec2_amitool',
+ 'aws_auto_scaling',
+ 'aws_cloudwatch',
+ 'aws_elb'
+];
+
+exports.init = function(api, callback) {
+ var apis_comparison = '|' + apis.join('|') + '|',
+ event = new events.EventEmitter(),
+ completed = {};
+
+ if (typeof api === "string") {
+ api = [api];
+ }
+
+ api.map(function(item) {
+ if (apis_comparison.indexOf('|' + item + '|') !== -1) {
+ fs.readdir(process.env[item.toUpperCase() + '_HOME'] + '/bin', function(err, files) {
+ var count = 0;
+ files.map(function(file) {
+ if (file.indexOf('-') !== -1 && file.indexOf('cmd') === -1) {
+ if (typeof tools[item] === 'undefined') {
+ tools[item] = function() {
+ var services = [];
+ for (var i in tools[item]) {
+ services.push(i);
+ }
+ return services;
+ };
+ }
+ tools[item][file.replace(/(.*?\-)/, '').replace(/\-/g, '_')] = createService(item, file);
+ }
+ event.emit('tool', item, ++count, files.length);
+ });
+ });
+ }
+ });
+
+ event.on('tool', function(name, count, length) {
+ if (count === length) {
+ completed[name] = true;
+
+ var done = true;
+ api.map(function(item) {
+ if (!completed[item]) {
+ done = false;
+ }
+ });
+
+ if (done) {
+ callback(tools);
+ }
+ }
+ });
+
+ return event;
+}
+
+exports.setRegion = function(name) {
+ region = name;
+}
+
+createService = function(api, name) {
+
+ var service = function() {
+ var args = get_args.apply(this, arguments);
+
+ args.options.push('--region ' + region);
+
+ exec(process.env[api.toUpperCase() + '_HOME'] + '/bin' + '/' + name + ' ' + args.options.join(' '), function(err, stdout, stderr) {
+ if (err !== null) {
+ console.log('exec error: ' + err);
+ } else {
+ if (typeof args.callback !== 'undefined') {
+ args.callback(stdout);
+ } else {
+ sys.puts(stdout);
+ }
+ }
+ //sys.print('stderr: ' + stderr);
+ });
+ }
+
+ service.instances = function() {
+ var args = get_args.apply(this, arguments);
+ service(args.options, function(stdout) {
+ var data = stdout.match(/\s(i\-\S*)\s/g);
+ data = data.map(function(item) {
+ return item.replace(/[\s\t]/g, '');
+ });
+ args.callback(data);
+ });
+ };
+
+ service.images = function() {
+ var args = get_args.apply(this, arguments);
+ service(args.options, function(stdout) {
+ var data = stdout.match(/\s(ami\-\S*)\s/g);
+ data = data.map(function(item) {
+ return item.replace(/[\s\t]/g, '');
+ });
+
+ args.callback(data);
+ });
+ };
+
+ service.public_dns = function() {
+ var args = get_args.apply(this, arguments);
+ service(args.options, function(stdout) {
+ var data = {};
+
+ stdout = stdout.split('\n');
+ stdout.map(function(item) {
+ if (item.indexOf('ec2') !== -1) {
+ data[item.replace(/.*\s(i\-\S*).*/g, '$1')] = item.replace(/.*(ec2\-\S*).*/g, '$1');
+ }
+ });
+
+ args.callback(data);
+ });
+ };
+
+ service.private_dns = function() {
+ var args = get_args.apply(this, arguments);
+ service(args.options, function(stdout) {
+ var data = {};
+ stdout = stdout.split('\n');
+ stdout.map(function(item) {
+ if (item.indexOf('ip\-') !== -1) {
+ data[item.replace(/.*\s(i\-\S*).*/g, '$1')] = item.replace(/.*(ip\-\S*).*/g, '$1');
+ }
+ });
+
+ args.callback(data);
+ });
+ };
+
+ if (name === 'as-describe-auto-scaling-groups') {
+ service.launch_config = function() {
+ var args = get_args.apply(this, arguments);
+ service(args.options, function(stdout) {
+ var data = {};
+ stdout = stdout.split('\n');
+ stdout = stdout[0].split(' ');
+
+ args.callback(stdout[2]);
+ });
+ }
+ }
+
+ return service;
+};
+
+exports.info = function(element, callback) {
+ // if element is empty all possible infos are listed
+
+ var ip_address = '169.254.169.254';
+ var client = http.createClient(80, ip_address);
+ var request = client.request('GET', '/latest/meta-data/' + element);
+ request.end();
+
+ request.on('response', function(response) {
+ if (response.statusCode !== 200) {
+ return callback(new Error('Couldn\'t find meta data for instance'));
+ }
+
+ response.setEncoding('utf8');
+
+ var info = '';
+ response.on('data', function(chunk) {
+ info += chunk;
+ });
+ response.on('end', function() {
+ callback(null, info);
+ });
+ });
+}
+
+function get_args(options, callback) {
+ if (typeof options === 'function') {
+ callback = options;
+ options = [];
+ }
+
+ if (typeof options === 'undefined') {
+ options = [];
+ }
+
+ if (typeof options === 'string') {
+ if (options === 'help') {
+ options = '--help';
+ }
+ options = [options];
+ }
+
+ return {
+ options: options,
+ callback: callback
+ };
+}
+
19 package.json
@@ -0,0 +1,19 @@
+{
+ "name": "aws",
+ "description": "evil wrapper for the amazon command line tools",
+ "url": "http://github.com/teemow/node-aws",
+ "keywords": ["amazon", "aws", "ec2", "cloud"],
+ "author": "Timo Derstappen <teemow@gmail.com>",
+ "repository": {
+ "type": "git",
+ "url": "http://github.com/teemow/node-aws.git"
+ },
+ "main": "./lib/aws",
+ "dependencies": {
+ "vows": ">= 0.5.1",
+ "vargs": ">= 0.1.0",
+ },
+ "engines": { "node": ">= 0.2.0" },
+ "version": "0.0.1"
+}
+
148 test/aws-test.js
@@ -0,0 +1,148 @@
+/**
+ * AWS wrapper tests
+ */
+require.paths.unshift("../lib");
+
+var sys = require("sys"),
+ assert = require("assert"),
+ vows = require("vows");
+
+vows.describe('aws').addBatch({
+ 'EC2 API': {
+ "GIVEN I have instances on EC2": {
+ topic: function() {
+ var callback = this.callback;
+ var aws = require("aws");
+ aws.setRegion('eu-west-1')
+ aws.init(['ec2'], function(api) {
+ callback(undefined, api.ec2)
+ });
+ },
+ "WHEN I describe instances": {
+ topic: function(api) {
+ var callback = this.callback;
+ api.describe_instances(function(data) {
+ callback(undefined, data)
+ });
+ },
+ "THEN the result should contain ec2 instances": function(data) {
+ var instances = data.split(/\s+/).filter(function(item) {
+ return item === "INSTANCE"
+ });
+ assert.isTrue(instances.length > 0);
+ }
+ },
+ "WHEN I describe instances and filter instances": {
+ topic: function(api) {
+ var callback = this.callback;
+ api.describe_instances.instances(function(data) {
+ callback(undefined, data)
+ });
+ },
+ "THEN the result should contain ec2 instance ids": function(data) {
+ assert.isTrue(data.length > 0);
+ data.forEach(function(item) {
+ assert.equal(item.indexOf('i-'), 0);
+ });
+ }
+ },
+ "WHEN I describe instances and filter images": {
+ topic: function(api) {
+ var callback = this.callback;
+ api.describe_instances.images(function(data) {
+ callback(undefined, data)
+ });
+ },
+ "THEN the result should contain amazon images": function(data) {
+ assert.isTrue(data.length > 0);
+ data.forEach(function(item) {
+ assert.equal(item.indexOf('ami-'), 0);
+ });
+ }
+ },
+ "WHEN I describe instances and filter public dns": {
+ topic: function(api) {
+ var callback = this.callback;
+ api.describe_instances.public_dns(function(data) {
+ callback(undefined, data)
+ });
+ },
+ "THEN the result should contain ec2 public dns addresses": function(data) {
+ var count = 0;
+ for (var i in data) {
+ count++;
+ assert.equal(i.indexOf('i-'), 0);
+ assert.equal(data[i].indexOf('ec2-'), 0);
+
+ var matches = data[i].match(/\.eu\-west\-1\.compute\.amazonaws\.com$/);
+ assert.equal(matches[0], '.eu-west-1.compute.amazonaws.com');
+ assert.equal(matches.index, data[i].length - 32);
+ }
+ assert.isTrue(count > 0);
+ }
+ },
+ "WHEN I describe instances and filter private dns": {
+ topic: function(api) {
+ var callback = this.callback;
+ api.describe_instances.private_dns(function(data) {
+ callback(undefined, data)
+ });
+ },
+ "THEN the result should contain ec2 private dns addresses": function(data) {
+ var count = 0;
+ for (var i in data) {
+ count++;
+ assert.equal(i.indexOf('i-'), 0);
+ assert.equal(data[i].indexOf('ip-'), 0);
+
+ var matches = data[i].match(/\.eu\-west\-1\.compute\.internal$/);
+ assert.equal(matches[0], '.eu-west-1.compute.internal');
+ assert.equal(matches.index, data[i].length - 27);
+ }
+ assert.isTrue(count > 0);
+ }
+ }
+ }
+ },
+ 'Auto scaling API': {
+ "GIVEN I have an auto scaler": {
+ topic: function() {
+ var callback = this.callback;
+ var aws = require("aws");
+ aws.setRegion('eu-west-1')
+ aws.init(['ec2', 'aws_auto_scaling'], function(api) {
+ callback(undefined, api.aws_auto_scaling, 'ads-stage-adcloud-net')
+ });
+ },
+ "WHEN I describe the auto scaling group": {
+ topic: function(api, loadbalancer) {
+ var callback = this.callback;
+ api.describe_auto_scaling_groups(loadbalancer, function(data) {
+ callback(undefined, data)
+ });
+ },
+ "THEN the result should contain ec2 instances": function(data) {
+ var instances = data.split(/\s+/).filter(function(item) {
+ return item === "INSTANCE"
+ });
+ assert.isTrue(instances.length > 0);
+ }
+ },
+ "WHEN I describe the auto scaling group and filter instances": {
+ topic: function(api, loadbalancer) {
+ var callback = this.callback;
+ api.describe_auto_scaling_groups.instances(loadbalancer, function(data) {
+ callback(undefined, data)
+ });
+ },
+ "THEN the result should contain ec2 instances": function(data) {
+ assert.isTrue(data.length > 0);
+ data.forEach(function(item) {
+ assert.equal(item.indexOf('i-'), 0);
+ });
+ }
+ }
+ }
+ }
+}).export(module);
+

0 comments on commit 9dc908b

Please sign in to comment.
Something went wrong with that request. Please try again.