Giter Site home page Giter Site logo

node-ec2's Introduction

Node EC2 Build Status

Evented Node.js bindings to the EC2 Query API.

  • Node EC2 is a minimal Node.js API with a pinch of sugar.
  • Node EC2 creates a signed request from a AWS EC command name a plain old JavaScript object of command parameters.
  • Node EC2 parses the XML response and converts it into JSON.
  • Node EC2 does not define control flow, so use your favorite control flow library.
  • Node EC2 lets Amazon AWS do all the error checking in one place, then returns the errors as an Error to a Node.js style callback.

Because Node EC2 is such a thin layer over the Amazon AWS EC2 API you can use the Amazon API Reference to find your way around. Node EC2 calls translate directly to Amazon Query API.

Synopsis

An example using RunInstances to launch a 32-bit Fedora 17 instance in Virginia.

Our program reads the AWS secrets from a file named "~/.aws" that contains the key and secret as JSON.

{ "key": "EXAMPLE"
, "secret": "EXAMPLE"
}

Our program launches and instance, then calls "DescribeInstances" until it is ready to use. When it's ready, it prints the TK host name for use with ssh.

// Require EC2.
var ec2 = require("ec2")
  , fs = require("fs")
  , path = require("path")
  , configuration = path.resolve(process.env.HOME, ".aws")
  ;

// Read in the configuration above.
var configuration = JSON.parse(fs.readFileSync(configuration, "utf8"));

// Create an ec2 function that uses your configuration.
ec2 = ec2(configuration)

// Run an instance and wait for it to become ready.
ec2("RunInstances", {
  ImageId: "ami-2d4aa444", KeyName: "launch_key", MinCount: 1, MaxCount: 1
}, running);


var reservationId, instanceId;
function running (error, response) {
  if (error) throw error;
  reservationId = response.reservationId
  instanceId = response.instancesSet[0].instanceId;
  describe();
}

function describe () {
  ec2("DescribeInstances", {}, starting);
}

function starting (error, response) {
  if (error) throw error;
  var reservation, instance;
  reservation = response.reservationSet.filter(function (reservation) {
    return reservation.reservationId == reservationId;
  })[0];
  instance = reservation.instancesSet.filter(function (instance) {
    return instance.instanceId == instanceId;
  })[0];
  if (instance.instanceState.name == "running") ready();
  else setTimeout(describe, 2500);
}

function ready () {
  console.log("Instance created with id: " + instanceId);
}

I'm afraid you'll find that working with Amazon AWS is a bit wordy. The XML documents seem to gravitate toward the longest possible element name that could possibly describe the property

Installing

The easiest way to install is using npm.

npm install ec2

You can also checkout the source code for using git. It has only one dependency, the wonderful little XML parser node-xml.

Initialization

Node EC2 exports a function you can use to build an EC2 function. You can call it directly from require("ec2") to build an ec2 function configured for your application.

var ec2 = require("ec2")({ key: "<REDACTED>", secret: "<REDACTED>" });

ec2("DescribeInstances", {}, function (error, result) {
  if (error) throw error;
  console.log(result)
});

Options to the ec2 function are:

  • key — Your Amazon AWS key.
  • secret — Your Amazon AWS secret key, which you should always keep secret.
  • endpoint — Either the region identifier or else the fully qualified domain name of the AWS server.
  • wsdlVersion — The desired wsdl version to use. Optional, as the default has been left as "2011-05-15" in order to be backward compatible.

The region identifiers are one of the following.

  • us-west-2 — Oregon.
  • us-west-1 — California.
  • us-east-1 — Virginia.
  • sa-east-1 — Sao Paluo.
  • ap-northeast-1 — Tokyo.
  • ap-southeast-1 — Singapore.
  • ap-southeast-2 — Sydney.
  • eu-west-1 — Ireland.

If you do not specify endpoint when you construct your ec2 function, you can specify it later when you construct your ec2 function.

Invocation

Invoke Node EC2 by passing a command name, command parameters in an object, and a callback.

var ec2 = require("ec2")({ key: "<REDACTED>"
                         , secret: "<REDACTED>"
                         , endpoint: "us-east-1"
                         , wsdlVersion: "2012-10-01"
                         })
  , parameters;

parameters =
{ ImageId: "ami-2d4aa444"
, KeyName: "launch_key"
, MinCount: 1
, MaxCount: 1
};

ec2("RunInstances", parameters, function (error, result) {
  if (error) throw error;
  console.log(result)
});

You can override configuration details by passing an options object as the first argument to the Node EC2 function.

var ec2 = require("ec2")({ key: "<REDACTED>"
                         , secret: "<REDACTED>"
                         , endpoint: "us-east-1"
                         , wsdlVersion: "2012-10-01"
                         })
  , parameters;

parameters =
{ ImageId: "ami-e269e5d2"
, KeyName: "launch_key"
, MinCount: 1
, MaxCount: 1
};

ec2({ endpoint: "us-west-2" }, "RunInstances", parameters, function (error, result) {
  if (error) throw error;
  console.log(result)
});

You can also create a new Node EC2 function that extends configuration of an Node EC2 function. You can use this to create a base function that holds your credentials, and specific functions for the specific regions or wsdl Version.

var ec2 = require("ec2")({ key: "<REDACTED>" , secret: "<REDACTED>" })
  , ec2east2012 = ec2({ endpoint: "us-east-1", wsdlVersion: "2012-10-01" })
  , ec2west2012 = ec2({ endpoint: "us-west-2", wsdlVersion: "2012-10-01" })
  , ec2east2011 = ec2(endpoint: "us-east-1")
  , parameters
  ;

parameters =
{ ImageId: "ami-e269e5d2"
, KeyName: "launch_key"
, MinCount: 1
, MaxCount: 1
};

ec2east("RunInstances", parameters, function (error, eastern) {
  if (error) throw error;
  parameters.ImageId = "ami-e269e5d2";
  ec2west("RunInstances", parameters, function (error, western) {
    if (error) throw error;
    console.log(eastern, western);
  });
});

Why So Simple?

Another implementation might set out to define a library of functions, one for each function provided by the AWS EC2 API. This way, you could validate the command name and parameters before you call.

We believe that if there's something wrong with your request, you'll find out soon enough. The Amazon AWS server that handles your request will do a bang up job of error checking, and it will be able to do all the error checking in one place.

On the client side, we could validate parameter names, but on the AWS site validation goes beyond semantics to authorization, service availability, etc.

If the Amazon AWS EC2 API adds a dozen new features overnight, you don't have to wait for a new version of Node EC2 to use them.

Because of this, there is a one to one mapping between the Amazon Query API and the actions provided by Node EC2. Changes to the Amazon Query API are available immediately to Node EC2 applications.

You can learn more about node-ec2 at the node-ec2 GitHub web page and by reading the wiki.

Command Line Interface

Node EC2 also comes with a command line interface. The command line interface is very helpful if you want to examine the JSON results of an Amazon AWS EC2 API call.

The ec2 program will look for a configuration file at ~/.aws or else use the value of the AWS_CONFIG environment variable as the path to the configuration file. The configuration file is the JSON file used to create a Node EC2 function described above. It contains your key, secret key and the service endpoint.

$ ec2 DescribeKeyPairs
{
  "requestId": "1d42624e-a3c8-4dca-8d42-6ac0a11f4468",
  "keySet": [
    {
      "keyName": "automation_key",
      "keyFingerprint": "82:a4:69:ca:89:31:8f:58:75:ae:24:eb:e5:71:78:56:32:09:3a:24"
    },
    {
      "keyName": "temporary_key",
      "keyFingerprint": "c0:14:ff:06:23:dd:52:6a:4d:29:e9:0f:1f:54:13:73:e1:c8:fd:90"
    },
    {
      "keyName": "launch_key",
      "keyFingerprint": "8c:cf:71:0d:84:05:19:cd:7d:89:ca:62:7e:8f:51:0b:16:df:f4:c0"
    }
  ]
}

Invocation is first the command name, then command arguments just as they appear in the Amazon AWS API. Note that some arguments in the API require a number appended to the argument name.

$ ec2 RunInstances ImageId ami-08d97e61 KeyName launch_key MinCount 1 MaxCount 1
{
  "requestId": "7aa586a5-c658-4735-9152-72ad20cb3282",
  "reservationId": "r-de7200bb",
  "ownerId": "341264201128",
  "groupSet": [
    {
      "groupId": "sg-c8f72da7",
      "groupName": "default"
    }
  ],
  "instancesSet": [
    {
      "instanceId": "i-2af0e253",
      "imageId": "ami-08d97e61",
      "instanceState": {
        "code": "0",
        "name": "pending"
      },
      "privateDnsName": null,
      "dnsName": null,
      "reason": null,
      "keyName": "launch_key",
      "amiLaunchIndex": "0",
      "productCodes": null,
      "instanceType": "m1.small",
      "launchTime": "2012-06-28T18:29:55.000Z",
      "placement": {
        "availabilityZone": "us-east-1a",
        "groupName": null,
        "tenancy": "default"
      },
      "kernelId": "aki-407d9529",
      "monitoring": {
        "state": "disabled"
      },
      "groupSet": [
        {
          "groupId": "sg-c8f72da7",
          "groupName": "default"
        }
      ],
      "stateReason": {
        "code": "pending",
        "message": "pending"
      },
      "architecture": "i386",
      "rootDeviceType": "ebs",
      "rootDeviceName": "/dev/sda1",
      "blockDeviceMapping": null,
      "virtualizationType": "paravirtual",
      "clientToken": null,
      "hypervisor": "xen"
    }
  ]
}

Change Log

Changes for each release since 0.1.1.

Version 0.1.1 — Thu Jun 28 22:08:28 UTC 2012

  • Publish a version without junk directories that defeat NPM. #9. #23.
  • Create change log. #13.
  • Specify fully qualified hostname for endpoint. #25. #3
  • Rewrite README.md to describe one function API.
  • Delete Cakefile. #16.
  • Convert to JavaScript. #10.

Versions prior to 0.1.1 were not tracked very well in git. My fault, but I'm not feeling the guilt necessary to perform the git forensics necessary to reconstruct a change log.

node-ec2's People

Contributors

bigeasy avatar flatheadmill avatar glennschler avatar pkrumins avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

node-ec2's Issues

crypto.js error - variation b/t CentOS EC2 instances

Hi,

I created a CloudWatch library yesterday based on node-ec2 library and simple-rest-client, https://github.com/franklovecchio/node-cloudwatch, but I see an interesting error with a particular newer version of CentOS on EC2 with the same dependencies installed. I created a ticket for myself here:

https://github.com/franklovecchio/node-cloudwatch/issues/1

I'm not sure what dependency is different - maybe you have experienced this with node-ec2?

Thanks!

Not able to override endpoint as the first argument to the Node EC2 function.

This test fails. README indicates that node-ec2 should allow overriding of the configuration endpoint. With this test, it shows that us-east-1 is still requested instead of intended us-west-2 override.

I believe I see the resolution in the amazon.js file. I will submit pull to resolve issue #31, before discussing this issue further.

var fs = require('fs');
var configurationPath = './.aws';

// Read in the configuration above.
var configuration = JSON.parse(fs.readFileSync(configurationPath, 'utf8'));
configuration.endpoint = "us-east-1";

var ec2 = require("ec2")(configuration)

var parameters = {};

ec2({ endpoint: "us-west-2" }, "DescribeAvailabilityZones", 
              parameters, function (error, result) {
  if (error) throw error;
    console.log(result)
});

DELETE THIS REPO.

For those of you watching this repo, it is going to be deleted soon and from NPM as well.

Create JSON parser input.

When you get output from the ec2 program as JSON. Save it. Then echo it back through ec2 to get the fields.

Authentication issues

Does this module still work? I am asking because I can't get it to authenticate. I am always getting:

{ Errors: 
   [ { Code: 'SignatureDoesNotMatch'
     , Message: 'The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details.'
     }
   ]
, RequestID: 'b1f6c04a-e249-4ca1-967b-bcb1915ec1e0'
}

Any ideas what might cause it to fail? I tried creating a new key and it still didn't work.

Here is the code that I have:

var ec2 = require('ec2');

var client = ec2.createClient({
    key : '... my key ...',
    secret : '... my secret ..'
});

client.call("StartInstances", { InstanceId : "i-b6ab03db" }, function (resp) {
    console.log(resp);
});

client.on("end", function () {
    console.log('end');
});

client.on("error", function (err, code) {
   console.dir(err);
   console.log(code);
   console.log('----')

});

client.poll("DescribeInstances", function (struct) {
console.log(struct);
return true;
});

client.execute();

Thank you!

DescribeInstances

How does one do a filter on DescribeInstances?

ec2("DescribeInstances", { F: 'tag-key=Env' } ?

Create `CHANGELOG`.

I'll forgive you if you don't weed through your sad commit logs and recreate earlier "releases".

Convert to XML DOM.

Convert the library to XML DOM library XMLDOM. It is being maintained actively.

Delete Twinkie.

This library no longer requires compilation. The older version of Twinkie is causing errors at Travis CI. Remove from .gitmodulesand .travis.yml. Remove CoffeeScript frompackage.json`.

Not a string or buffer?

Hi,

Not sure what this error is being caused by, I run "node amazon-test.js":

var stack = require('../lib/long-stack-traces'); 
var ec2 = require('ec2');

var client = ec2.createClient({ 
    key: process.env['key'], 
    secret: process.env['secret']
});

client.poll("DescribeInstances", function (struct) {
    console.log(struct);
    return true;
}); 
client.execute();

This returns an error at line 40, which is really "client.execute()" after cleaning up some code:
node.js:134
throw e; // process.nextTick error, or 'error' event on first tick
^
TypeError: Not a string or buffer
at Object.createHmac (crypto.js:103:21)
at /node_modules/ec2/lib/request.js:53:19
at AmazonEC2Client. (/node_modules/ec2/lib/amazon.js:53:16)
at AmazonEC2Client.execute (/node_modules/ec2/lib/amazon.js:3:63)
at Object. (amazon-test.js:40:8)
at Module._compile (module.js:404:26)
at Object..js (module.js:410:10)
at Module.load (module.js:336:31)
at Function._load (module.js:297:12)
at Array. (module.js:423:10)

Update `README.md`.

The README.md should say something about the new API, instead of saying nothing about the new API.

Unexpected token error \u0000 when installing with npm

I see this error on Lion, but it's fine on ubuntu

$ sudo npm install ec2
npm http GET https://registry.npmjs.org/ec2
npm http 304 https://registry.npmjs.org/ec2
npm http GET https://registry.npmjs.org/ec2/-/ec2-0.1.0.tgz
npm http 200 https://registry.npmjs.org/ec2/-/ec2-0.1.0.tgz
npm ERR! error reading /tmp/npm-1335796170160/1335796170160-0.39644423476420343/package
npm ERR! couldn't pack /tmp/npm-1335796170160/1335796170160-0.39644423476420343/package to /Users/auser/.npm/ec2/0.1.0/package.tgz

npm ERR! SyntaxError: Unexpected token
npm ERR! at Object.parse (native)
npm ERR! at Packer.readRules (/usr/local/lib/node_modules/npm/node_modules/fstream-npm/fstream-npm.js:179:33)
npm ERR! at Packer. (/usr/local/lib/node_modules/npm/node_modules/fstream-npm/node_modules/fstream-ignore/ignore.js:132:22)
npm ERR! at [object Object]. (fs.js:115:5)
npm ERR! at [object Object].emit (events.js:64:17)
npm ERR! at afterRead (fs.js:1117:12)
npm ERR! at Object.wrapper as oncomplete
npm ERR! You may report this log at:
npm ERR! http://github.com/isaacs/npm/issues
npm ERR! or email it to:
npm ERR! [email protected]
npm ERR!
npm ERR! System Darwin 11.3.0
npm ERR! command "node" "/usr/local/bin/npm" "install" "ec2"
npm ERR! cwd /Users/auser/dev/myapp
npm ERR! node -v v0.6.12
npm ERR! npm -v 1.1.18
npm ERR! file /tmp/npm-1335796170160/1335796170160-0.39644423476420343/package/.AppleDouble/package.json
npm ERR! path /tmp/npm-1335796170160/1335796170160-0.39644423476420343/package/.AppleDouble
npm ERR! type unexpected_token
npm ERR! fstream_path /tmp/npm-1335796170160/1335796170160-0.39644423476420343/package/.AppleDouble
npm ERR! fstream_type Directory
npm ERR! fstream_class Packer
npm ERR! arguments [ '\u0000' ]
npm ERR! message Unexpected token
npm ERR! fstream_stack Packer.readRules (/usr/local/lib/node_modules/npm/node_modules/fstream-npm/fstream-npm.js:182:10)
npm ERR! fstream_stack Packer. (/usr/local/lib/node_modules/npm/node_modules/fstream-npm/node_modules/fstream-ignore/ignore.js:132:22)
npm ERR! fstream_stack [object Object]. (fs.js:115:5)
npm ERR! fstream_stack [object Object].emit (events.js:64:17)
npm ERR! fstream_stack afterRead (fs.js:1117:12)
npm ERR! fstream_stack Object.wrapper as oncomplete

Populate `.npmignore`.

This addresses an issue with the 0.1.0 release where .AppleDouble directories where added to the NPM tarball.

ec2 API wsdl 2012-10-01 has been released

node-ec2 has the wsdl version hard coded to an old version when you send the query string request. Noticed when DescribeSpotInstanceRequests API Action was not returning what was documented by aws.

Possible to create secure minimal API test?

Would it be possible to use a custom API key that has severely limited permissions to test the API against Amazon itself? I could query key pairs, or something, to get a list of key pairs.

Error: getaddrinfo ENOENT

i have this:

$ node app.js                                                                                                                                                                  ""

node.js:201
        throw e; // process.nextTick error, or 'error' event on first tick
          ^
Error: getaddrinfo ENOENT
    at errnoException (dns.js:31:11)
    at Object.onanswer [as oncomplete] (dns.js:140:16)

here is the code:

var ec2 = require("ec2")
, fs = require("fs");

// Read in the configuration above.
var configuration = JSON.parse(fs.readFileSync("configuration.json", "utf8"));

// Create an ec2 function that uses your configuration.
ec2 = ec2(configuration)

// Run an instance and wait for it to become ready.
ec2("RunInstances", {
  ImageId: "ami-5d704b29", KeyName: "micros-ie", InstanceType: "t1.micro"
}, function (error, response) {
  if (error) {
    throw error
  }
  reservationId   = response.reservationId;
  instanceId      = response.instancesSet[0].instanceId;
  ready = function () {
    ec2("DescribeInstances", function (error, struct) {
      if (error) {
        throw error;
      }
      var reservation = struct.reservationSet.filter(function (reservation) {
        return reservation.reservationId == reservationId;
      })[0];
      var instance = reservation.instancesSet.filter(function (instance) {
        return instance.instanceId == instanceId;
      })[0];
      return instance.instanceState.name == "running";
      if (instance.instanceState.name == "running") {
        console.log("Instance created with id: " + instanceId);
      } else {
        setTimeout(ready, 500);
      }
    });
  };
  ready();
});

Specify request host?

Hi,

How about being able to specify the host when calling the createClient() factory function?

Specifying the host should allow folks to use this library for other AWS services besides EC2. As an example, I'd like to use this library for the new Simple Email Service (SES).

Do you know of any other roadblocks I might run into here? Well, I'm gonna fork this and try it out...

Cheers,

Zach

Unable to trap request connection error

It can happen that the http request to the EC2 web service times out. When that occurs, there is no way for the caller to trap the event.

Specifically, I have obtained an unexpected error 10006 (timeout) several times, and this is causing the node process to crash. Please add code to trap a request error and expose it via the existing error event.

load configuration.json securely

hello,
i got this to work, but have some questions.

basically, it checks if a site is running
var http = require('http')
, url = require('url')
, util = require('util')
, exec = require('child_process').exec;

var site = http.createClient(80, "www.domain.tld", false);
var req = site.request("GET", "/");
req.end();
req.on('response', function(res){
    if(res.statusCode !== 200){
        // launch a new instance
        var ec2 = require("ec2")
            , fs = require("fs");
        // Read in the configuration above.
        var configuration = JSON.parse(fs.readFileSync("configuration.json", "utf8"));
        // Create an ec2 function that uses your configuration.
        ec2 = ec2(configuration)
        // Run an instance and wait for it to become ready.
        ec2("RunInstances", {
            ImageId: "ami-XXXXXX"
            , KeyName: "micros-ie"
            , InstanceType: "t1.micro"
            , MinCount: 1
            , MaxCount: 1
        }, function (error, response) {
            if (error) {
                throw error
            }
        });
        } else {
            res.on('data', function(chunk){
            function puts(error, stdout, stderr) { util.puts(stdout) }
              exec("my command", puts);
            }); 
        }
});

basically, i want to start my first instance from my local computer and then chain the second, third ... etc so for example, when the 'site' returns a non 200 OK status code, i want to fire up a new EC2 instance, thus i don't have to have my local machine connected

is there a better way to do this?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.