pax_global_header00006660000000000000000000000064114723324750014522gustar00rootroot0000000000000052 comment=d83116cb15d6b3b0f6d0357e27f2050ba6a7e21b grempe-amazon-ec2-043f1b4/000077500000000000000000000000001147233247500152605ustar00rootroot00000000000000grempe-amazon-ec2-043f1b4/.gitignore000066400000000000000000000001151147233247500172450ustar00rootroot00000000000000*.sw? .DS_Store coverage rdoc doc .yardoc pkg .idea .bundle .rvmrc perftools grempe-amazon-ec2-043f1b4/.yardopts000066400000000000000000000000471147233247500171270ustar00rootroot00000000000000--title amazon-ec2 - ChangeLog LICENSE grempe-amazon-ec2-043f1b4/ChangeLog000066400000000000000000000430401147233247500170330ustar00rootroot00000000000000* (In progress) Close issue #22, allow detach_volume to take a boolean as a string or TrueClass FalseClass === 0.9.17 2010-11-21 * Converted from Jeweler to Bundler, 'bundle install' to install dependencies * Adding ability to launch t1.micro instances for ec2 regular and spot price instances * Adding support for describe/modify/reset instance attributes with tests. * Updated to API version : 2010-08-31 * Added experimental support for EC2 create_tags, describe_tags, delete_tags * Added experimental Eucalyptus support, provide by Sang-Min Park from Eucalyptus. * Instead of having hard coded "/" as URL path, the path can be given to as an option. Setup.rb is changed such that server, port, path, and use_ssl can be correctly set up. * RDS :db_security_groups should be an Array, not a String. * Use HmacSHA256 signatures instead of SHA1 (preferred by AWS and improves support for Eucalyptus) * added AWS::EC2::Base#get_password_data for GetPasswordData API (Windows instances) * Fix #26. Raise an exception immediately if the response is a 5xx Server Error. * Applied experimental CloudWatch Monitoring Patch by fred-secludit, removes limitations on which server to connect to, and better handles statistics and dimensions. * Changed AWS::EC2::Instance from a module to a class to help along an experiment by bdigital * Zarro open boogs. Zarro Open pull requests. W00t === 0.9.16 2010-07-07 * Less strict checking on which server endpoints you can pass in as an environment var. * Moved ec2sh script to awshell to better reflect the more comprehensive nature of the gem. * Better instructions on using awshell upon running * awshell now sets up handles for all of the various services we use, not just @ec2 (+ @as, @rds, @elb, @cw) * awshell prints out the various server endpoints that it will actually use in the shell (you can override with env vars). === 0.9.11 2010-04-23 * RDS#create_db_instance : renamed misspelled :backend_retention_period option to :backup_retention_period. * Better handling of FixNum options in a few methods. * A few bug fixes. === 0.9.10 2010-03-26 * Enhancements to EC2 register_image to handle registration based on EBS snapshots (jamespharaoh) === 0.9.9 2010-03-19 * Bugfix in signing algorithm (wlach) === 0.9.7 2010-03-14 * Added EC2 describe_subnets support (petitbon) === 0.9.0 2010-01-19 * Added EC2 Spot Instance Request Support (nirvdrum) * Added EC2 describe_spot_price_history (tlossen) * Added ELB describe_instance_health method (rubysolo) === 0.7.4 2009-12-05 * Initial support for new EBS AMI's * Updated EC2 API version * Added US West 1 Data Center to list of valid endpoints. (us-west-1.ec2.amazonaws.com) * Updated exceptions.rb to be in sync with latest documented exceptions. * Updated #run_instances to support EBS AMI's and sync with latest options. * Added new #stop_instances and #start_instances methods. * Added new #create_image to allow bundling of a running instance to an EBS backed AMI. * Added stub methods for all known missing EC2 methods. (Please help with patches + tests!) * Added and updated tests for new/modified methods. === 0.6.1 2009-10-13 * Additional commits for AutoScaling. Thanks to Ari (auser)! * Updated README.rdoc installation instructions. Reflects removal of deprecated GitHub gem building. === 0.6.0 2009-09-30 * Added support for AWS AutoScaling for EC2. Thanks to Ari Lerner (auser)! === 0.5.2 2009-08-20 * Converted to YardDoc documentation format. See : http://yard.soen.ca/getting_started === 0.5.0 2009-08-11 * Major re-factor by Kris Rasmussen (krisr) to add support for the AWS Elastic Load Balancer API. Kudos Kris! === 0.4.0 2009-06-06 * Using technicalpickles/jeweler to manage gem now. See : http://github.com/technicalpickles/jeweler/tree/master === 0.3.8 2009-04-16 * Applied patch, with updated tests to fix issue with base64 encoded user data (rsanheim). * Applied patch, fixing an issue with EU Signature version 2 creation (delano). === 0.3.6 2009-03-02 * You can now specify any arbitrary SSL tcp port to connect to (kerryb) * Added rake target to quickly install the gem without docs === 0.3.5 2009-02-26 * Honor the EC2_URL env var if provided in the main lib * Some minor modifications to the exceptions raised when unknown === 0.3.4 2009-01-31 * Added support in the helper binaries for EC2_URL server url for Euro servers * AWS Signature v2 support === 0.3.3 2009-01-24 * Removed docs related to the ability to get Response#xml which is deprecated * Fixed conflict when aws/s3 gem was included in user code === 0.3.2 2008-12-11 * Updated API version to 2008-12-01 * Note : The new European EC2 zone should just work if you specify ':server => "eu-west-1.ec2.amazonaws.com"' when initializing AWS::EC2::Base.new(). Please report any issues you have with using this new service. === 0.3.1 2008-09-18 * Added basic custom kernel id support to run_instances. Thanks to Keith Hudgins for the patch. === 0.3.0 2008-08-24 * Changed response object from AmazonAWS::Response to Hash (patch from Yan Pritzker 'skwp') Thanks! * Added support for Elastic Block Storage (patch from Yann Klis 'yannski') Thanks! * Bumped AWS EC2 API version to 2008-05-05 * Bumped gem version number * Whitespace cleanup === 0.2.15 2008-08-20 * Updated gem install instructions, and dependency specifications in the gemspec. === 0.2.14 2008-06-30 * Merged patch from 'orionz' which adds support for EC2 Availability Zones. Thanks! === 0.2.12 2008-04-25 * A few adjustments to work with GitHub. === 0.2.11 2008-04-25 * Moved gem completely to GitHub. * Removed a LOT of RubyForge related cruft that's no longer needed. === 0.2.10 2008-04-13 * Fix bug where ec2#disassociate_address would return 'undefined method 'reject!' for "xxx.xxx.xxx.xxx":String'. Thanks to Brian Thomas for reporting. === 0.2.9 2008-03-31 * Added initial support for API version 2008-02-01. Support for new 'Elastic IP' functionality added. === 0.2.8 2008-02-25 * Change HTTP API requests to use POST instead of GET. Based on patch #18380 from 'anonymous'. === 0.2.7 2008-02-17 * Add support for HTTP Proxy when :proxy_server argument is passed. Based on patch from Mathias Dalheimer. === 0.2.6 2007-10-16 * Updated to support EC2 API version 2007-08-29 released on 2007-10-16 * Supports new instances type feature. Specify an instance type to launch (m1.small, m1.large, m1.xlarge) when you call the 'run_instances' method. e.g. add to the params hash ':instance_type => "m1.small"' * RunInstances and DescribeInstances now return the time when the Amazon EC2 instance was launched. * Code Tidyup : Removed trailing spaces in code docs. === 0.2.5 2007-09-26 * Updated using Dr. Nic's newgem v. 0.13.5 * Updated email address. * No functional changes in the gem. === 0.2.4 2007-07-09 * Changed how require statement for xmlsimple is called so we don't get warnings when running in rails. Now it looks like: require 'xmlsimple' unless defined? XmlSimple === 0.2.3 2007-07-06 * Updated gem to work with new official release of AWS API version 2007-03-01 which occurred on July 6, 2007. * Added support for primary new feature which supports Paid AMI's and the product codes associated with them. Modified several methods to support this change, updated the test cases, and added a new method EC2#confirm_product_instance. === 0.2.2 2007-07-03 * Minor change to test case. === 0.2.1 2007-07-03 * Some minor changes to the RDocs and README.txt === 0.2.0 2007-07-03 * MAJOR library changes : THESE CHANGES ARE NOT BACKWARD COMPATIBLE!! You will need to update the way in which you make calls, handle responses, and rescue exceptions from this library. If you prefer not to make these changes you can feel free to continue to use the older version of the gem. These older versions however will no longer be maintained. * MAJOR refactoring of how methods calls are made. Now all methods are called with a simple hash of arguments and none of them are positional. This feels much more "Ruby'ish". * MAJOR refactoring of how responses are returned to users. No longer do you have to call the .parse method, and no longer are you getting back simple arrays of information. Responses now come in the form of OpenStruct objects that contain all of the data for an object in Enumerable form so you can use iterators (.each, .each_pair, etc). All methods return an AWS::Response object which inherits from OpenStruct. The return data from EC2, which is in XML form, is parsed with XmlSimple and is used to directly construct the return data structure. This allows us to know with some confidence that the data structure returned from AWS will always be consistent with this library's responses. There is also an .xml attribute for each response object that lets you see the full and complete XML response from AWS if that is useful to you. * Added an exception framework which will now throw appropriate Ruby exceptions that match those handed to us by Amazon EC2. ArgumentError exceptions will also be thrown if you are making calls we know to be illegal or malformed. You should rescue these exceptions in your application instead of parsing text responses. All exceptions descend from AWS::Error. You can see them all in exceptions.rb in the gem install. * Added a full suite of test/spec unit tests which currently cover 100% of the public methods in this library. We have abot 92% code coverage according to rcov. This has greatly enhanced the reliability of the library as well as our confidence in the code. We used to have 0% test coverage. :-/ * Added an EC2 command shell : 'ec2sh' which can be called from anywhere and gives you an interactive irb session with an EC2 connection pre-made for you as @ec2. You can use this to interactively execute any command on EC2 that this library supports. Try @ec2.methods.sort or @ec2.describe_images to test it out. You must first setup two shell environment variables which contain your ACCESS_KEY_ID and SECRET_ACCESS_KEY for this to work. Otherwise an error will be thrown when you try to start it. This is way cool and shamelessly borrowed from Marcel Molina's fine AWS::S3 library. * Updated API version in the query API request to 2007-01-19, and added all known method calls in this version of the API to the gem (including reboot, viewing console output, NAT addressing and more!) * Removed .parse method as it is no longer needed or wanted. * Removed 'verbose' attribute writer and a couple of related debug 'puts' calls in EC2.rb. * Removed deprecated alias's used in the library that were added in v0.0.3 * Gem now requires XmlSimple gem to be installed. === 0.1.0 2007-05-30 * Repackaged with updated newgem generator v. 0.10.3 from http://newgem.rubyforge.org/ to take advantage of new deployment goodness. === 0.0.7 2007-03-15 * Applied patch from Kevin Clark which does the following: * New method to the instances.rb to allow for issuing a reboot command to an EC2 instance. * New Mocha based tests (Mocha test suite must be installed to run tests. 'sudo gem install mocha') * Cleanup of the test directory. * Applied patch from Randy Bias related to CGI escaping error. From his notes: I finally figured out what was going on. It was a compound problem. The first being that you can't CGI::encode the UserData early. You have to just Base64 encode it. Unfortunately, when you Base64 encode it, it means that some encodings will be padded with extra chars, specifically the '=', but &, ? and = get stripped by EC2.canonial_string. So if a Base64 encoding has trailing ='s for padding, these get stripped and then you sign the UserData Base64 payload sans the padding. But it looks like Amazon's side is doing the right thing and is signing the padding. So, the signatures mis-match. I've got the complete patch here and it's about as elegant/clean as I could make it in a short period of time. It's a little tough to strip those equal signs when there are so many in the URI. I think this works pretty well, though. I'm splitting the URI on '&', then for each field ripping out all '&' and '?' and only the first '='. Then stitching it back together. === 0.0.6 2007-03-02 * Patched instances.rb with a bugfix and patch provided by Randy Bias (Thanks Randy!). Only minimally tested so please let me know if this causes any problems for anyone. From his notes: I wanted to let you know that there appears to be a bug in how user data is passed. In instances.rb the line that creates the base64 encoded package of user data is as follows: userData = CGI::escape(Base64.encode64(in_params[:userData]).strip()) This may have worked prior, but at least right now the CGI::escape appears to cause a breakage. More specifically it turns something like this (the actual base64 encoded string): YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh eHh4eHh4eHh4eHh4eHh4eHh4eHgg Into this: YWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFhYWFh% 0AeHh4eHh4eHh4eHh4eHh4eHh4eHgg And it looks like EC2 chokes on the %0, which is CGI::escape's way for handling an EOL. Unfortunately, the Base64.encode64 (at least in my 1.8.5 version of Ruby) inserts a EOL at every 47 chars, no matter what: --- [randyb@master randyb] cat /tmp/foo.rb #!/usr/bin/env ruby # require 'rubygems' require_gem 'amazon-ec2' require 'getoptlong' puts Base64.encode64 ("012345678901234567890123456789012345678901234567890123456789") [randyb@master randyb] /tmp/foo.rb MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0 NTY3ODkwMTIzNDU2Nzg5 --- The best way to handle this is to strip the CRLFs/EOLs before passing to CGI.escape. === 0.0.5 2006-12-21 * Changes to home page documentation and example files to indicate that you should use 'require_gem' instead of a simple require. Not sure if this is a result of something I am doing in the packaging of the gem that is incorrect or if this is right and proper. I will investigate further. * Patched instances.rb run_instances method to allow for submission of user data with the command to start an instance. Patch submitted anonymously on RubyForge. This had not been functionally implemented in the Amazon Web Services sample library prior to this patch. * Added simple framework for adding unit tests for the library under test dir. No functional unit tests exist yet. === 0.0.4 2006-12-21 * Applied patch from Kevin Clark to svn version 7. Thanks for the patch and the description Kevin! Please report if you encounter any issues with this patched version. Here is Kevin's description which I requested : "It helps me to think of modules as boxes full of classes and methods. REXML is a module which holds various classes related to parsing XML including REXML::Node, REXML::Document and REXML::XPath. When you include a module it takes everything out of the box and places it in the local context. So, when you include REXML in the global namespace on line 27 of EC2.rb, it includes classes called Node, Document and XPath in the global object space. This means that I can't have a class called Node in my own project (which I do). The library would be a much better neighbor if it instead accessed the REXML::Document and REXML::XPath classes explicitly through the module." === 0.0.3 2006-12-16 * API CHANGE : Changed method name 'authorize' to 'authorize_security_group_ingress' to ensure consistent naming of Ruby library methods to match AWS EC2 API actions. Alias to 'authorize' for backwards compatibility. * API CHANGE : Changed method name 'revoke' to 'revoke_security_group_ingress' to ensure consistent naming of Ruby library methods to match AWS EC2 API actions. Alias to 'revoke' for backwards compatibility. * API CHANGE : Changed method name 'delete_securitygroup' to 'delete_security_group' to ensure consistent naming of Ruby library methods to match AWS EC2 API actions. Alias to 'delete_securitygroup' for backwards compatibility. * API CHANGE : Changed method name 'describe_securitygroups' to 'describe_security_group' to ensure consistent naming of Ruby library methods to match AWS EC2 API actions. Alias to 'describe_securitygroups' for backwards compatibility. * API CHANGE : Changed method name 'create_securitygroup' to 'create_security_group' to ensure consistent naming of Ruby library methods to match AWS EC2 API actions. Alias to 'create_securitygroup' for backwards compatibility. * Added many API rdoc's, some method descriptions copied from Amazon Query API Developer Guide. * Extracted some parts of the formerly monolithic EC2 library out into separate files for manageability. * Changed the HTTP 'User-Agent' string used for each request so that we have our own user agent to identify this library's calls. Now set the version # in the user agent string based on the master version number for this library which is stored in lib/EC2/version.rb and should only be defined in one place. * Set @http.verify_mode = OpenSSL::SSL::VERIFY_NONE to avoid seeing SSL Cert warning "warning: peer certificate won't be verified in this SSL session". File EC2.rb:96 * Make 'pathlist' utility method a private method (EC2.rb:111). No reason I can see for this to be exposed. === 0.0.2 2006-12-14 * Bugfix in run_instances method. Method works now. Patch submitted by Stephen Caudill on AWS forums. Thanks! === 0.0.1 2006-12-13 * Initial release of the Ruby Gem. This includes the version of the library exactly as provided by Amazon Web Services as example code. No changes or enhancements to that code were made other than packaging it as a Ruby Gem. * RubyForge project created. http://github.com/grempe/amazon-ec2/tree/master grempe-amazon-ec2-043f1b4/Gemfile000066400000000000000000000001401147233247500165460ustar00rootroot00000000000000source "http://rubygems.org" # Specify your gem's dependencies in amazon-ec2.gemspec gemspec grempe-amazon-ec2-043f1b4/Gemfile.lock000066400000000000000000000007041147233247500175030ustar00rootroot00000000000000PATH remote: . specs: amazon-ec2 (0.9.17) xml-simple (>= 1.0.12) GEM remote: http://rubygems.org/ specs: mocha (0.9.9) rake perftools.rb (0.5.4) rake (0.8.7) rcov (0.9.9) test-spec (0.10.0) xml-simple (1.0.12) yard (0.6.2) PLATFORMS ruby DEPENDENCIES amazon-ec2! mocha (>= 0.9.9) perftools.rb (>= 0.5.4) rcov (>= 0.9.9) test-spec (>= 0.10.0) xml-simple (>= 1.0.12) yard (>= 0.6.2) grempe-amazon-ec2-043f1b4/LICENSE000066400000000000000000000053651147233247500162760ustar00rootroot00000000000000Copyright (c) 2007-2009 Glenn Rempe This software is distributed under the Ruby License. A copy of which is provided below. RUBY LICENSE http://www.ruby-lang.org/en/LICENSE.txt Ruby is copyrighted free software by Yukihiro Matsumoto . You can redistribute it and/or modify it under either the terms of the GPL (see COPYING.txt file), or the conditions below: 1. You may make and give away verbatim copies of the source form of the software without restriction, provided that you duplicate all of the original copyright notices and associated disclaimers. 2. You may modify your copy of the software in any way, provided that you do at least ONE of the following: a) place your modifications in the Public Domain or otherwise make them Freely Available, such as by posting said modifications to Usenet or an equivalent medium, or by allowing the author to include your modifications in the software. b) use the modified software only within your corporation or organization. c) rename any non-standard executables so the names do not conflict with standard executables, which must also be provided. d) make other distribution arrangements with the author. 3. You may distribute the software in object code or executable form, provided that you do at least ONE of the following: a) distribute the executables and library files of the software, together with instructions (in the manual page or equivalent) on where to get the original distribution. b) accompany the distribution with the machine-readable source of the software. c) give non-standard executables non-standard names, with instructions on where to get the original software distribution. d) make other distribution arrangements with the author. 4. You may modify and include the part of the software into any other software (possibly commercial). But some files in the distribution are not written by the author, so that they are not under this terms. They are gc.c(partly), utils.c(partly), regex.[ch], st.[ch] and some files under the ./missing directory. See each file for the copying condition. 5. The scripts and library files supplied as input to or produced as output from the software do not automatically fall under the copyright of the software, but belong to whomever generated them, and may be sold commercially, and may be aggregated with this software. 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. grempe-amazon-ec2-043f1b4/README.rdoc000066400000000000000000000412751147233247500170770ustar00rootroot00000000000000= Amazon Web Services Elastic Compute Cloud (EC2) Ruby Gem == About amazon-ec2 Amazon Web Services offers a compute power on demand capability known as the Elastic Compute Cloud (EC2). The server resources in the cloud can be provisioned on demand by making HTTP Query API calls to EC2. This 'amazon-ec2' Ruby Gem is an interface library that can be used to interact with the Amazon EC2 system and control server resources on demand from your Ruby scripts, or from applications written in your Ruby framework of choice (Ruby on Rails, Merb, etc.). More recently, support has been added for the following EC2 related AWS API's as well: * Autoscaling * Cloudwatch * Elastic Load Balancing (ELB) * Relational Database Service (RDS) For the most complete and up-to date README information please visit the project homepage at: http://github.com/grempe/amazon-ec2/tree/master or the official EC2 website at http://aws.amazon.com/ec2 == Installation This gem follows the standard conventions for installation on any system with Ruby and RubyGems installed and uses Bundler for gem installation and build management. If you have worked with gems before this will look very familiar. === Get an AWS account Before you can make use of this gem you will need an Amazon Web Services developer account which you can sign up for at https://aws-portal.amazon.com/gp/aws/developer/registration/index.html. This account must also be specifically enabled for Amazon EC2 usage. AWS will provide you with an 'AWS Access Key ID' and a 'Secret Access Key' which will allow you to authenticate any API calls you make and ensure correct billing to you for usage of the service. Take note of these (and keep them secret!). === Install the amazon-ec2 gem (Canonical Release) This is the standard install for stable releases from RubyGems. # Install the gem [sudo] gem install amazon-ec2 === Install from local Git clone (for amazon-ec2 developers) To install from git for adding features or fixing bugs, you'll need to clone and build. git clone git://github.com/grempe/amazon-ec2.git cd amazon-ec2 bundle install rake test rake build rake install == Using amazon-ec2 The library exposes one main interface class AWS::EC2::Base. It is through an instance of this class that you will perform all the operations for using the EC2 service including query string header signing. The public methods on AWS::EC2::Base closely mirror the EC2 Query API, and as such the Query API Reference in the EC2 Developer Guide ( http://developer.amazonwebservices.com/connect/kbcategory.jspa?categoryID=84 ) will prove helpful. === Setting up The 'awshell' and 'ec2-gem-example.rb' scripts which will be introduced to you shortly expect your AWS EC2 credentials to be stored as shell environment variables which are accessible to those scripts. This makes them convenient to use whenever you need to do a quick query to see what images you have available to you, what's running now, or to start or stop an instance on EC2. You'll find 'awshell' to be a very handy tool. I'll describe only the OS X route for setting up (of course the setup steps will vary depending on your particular system and preferred shell). If you don't want to do it this way, feel free to copy these scripts from the gem dir to any location where you can run them from and modify them directly to include your credentials. Edit the file ~/.bash_login and add the following to the existing contents: # OPTIONAL : Why 'export RUBYOPT'? Because we leave loading libs up to you... See : http://gist.github.com/54177 export RUBYOPT="rubygems" # For amazon-ec2 and amazon s3 ruby gems export AMAZON_ACCESS_KEY_ID="YOUR_ACCESS_KEY_ID" export AMAZON_SECRET_ACCESS_KEY="YOUR_SECRET_ACCESS_KEY_ID" If you are using EC2 in the EU region, make sure you also set: export EC2_URL="https://eu-west-1.ec2.amazonaws.com" (which you have already if you configured standard EC2 command line tools to work with this region). Once you save the file you should close and re-open your terminal so the new variables are made available. You'll need to do this close/re-open step for each terminal window you have open (or issue the 'source ~/.bash_login' command in each). Make sure that this file is only readable by your user so you don't inadvertently expose your credentials to other users on your system. You can verify that this setup is complete by running the 'set' in a command window and seeing that your credentials are in the list of shell variables. === The basics The library exposes one main interface module AWS::EC2::Base This method requires arguments which include your AWS credentials and it will return an object that you can use to make method calls directly against EC2. All the operations for using the EC2 service, including query string header signing, are handled automatically for you. The connection string will look something like this: @ec2 = AWS::EC2::Base.new(:access_key_id => ACCESS_KEY_ID, :secret_access_key => SECRET_ACCESS_KEY) I've tried to keep the public methods on 'amazon-ec2' as close as possible to the AWS EC2 Query API. This similarity allows you to reference the Query API Reference in the EC2 Developer Guide and be able to get started right away. In most cases the methods names only differ in how they are presented. e.g. 'DescribeImages' becomes '#describe_images()' in Ruby. Feel free to browse the full RDoc documentation for all classes and methods of 'amazon-ec2' if you want more details. === Examples The best way to become familiar with 'amazon-ec2' is to take it for a test drive. We have provided a few simple ways to get you started. There is also some sample code below that should help out in using 'amazon-ec2' with a plain Ruby script, or as part of a Ruby on Rails application. ==== Using the 'ec2-gem-example.rb' sample test script An example Ruby script which exercises the library a bit more is installed for you to check out when you install this gem. You can run this script to verify that everything is setup and working correctly in your environment. Consult the file which is installed at : [your amazon-ec2 gem dir]/examples/ec2-example.rb Since we also package this sample file in the gem's bin/ dir you should also be able to run it from anywhere on your shell path (once you have set your environment variables as described above). ==== Using the 'awshell' command shell The 'awshell' command shell is actually a standard 'irb' Ruby shell, with the main difference being we read your AWS credentials from your environment and pre-configure a connection string for you. This lets you run any EC2 command very simply. This has proven to be a valuable tool during the development of this gem and you should try it out. Since we install this tool in your system path as part of the installation of this gem, you should be able to simply run 'awshell' from any terminal command prompt on your local system. You'll see some basic instructions for use, and a few examples when you start 'awshell'. Go ahead and try it out now. We'll wait... If you're not in front of a terminal shell now (perhaps you're browsing this site on your iPhone) this is what you would see: hostname:/tmp/rails/amazon_test glenn$ awshell 'awshell' usage : This is an interactive 'irb' command shell that allows you to use all commands available to the amazon-ec2 gem. You'll find this to be a great tool to help you debug issues and practice running commands against the live EC2 servers prior to putting them in your code. The EC2 connection is wired to the class instance '@ec2'. Make method calls on this to execute commands on EC2. Adding a #to_s at the end of any command should give you a full String representation of the response. Examples to try: returns : all ec2 public methods >> @ec2.methods.sort returns : a string representation of ALL images >> @ec2.describe_images.to_s returns : an Array of AWS::Response objects, each an EC2 image and its data >> @ec2.describe_images.imagesSet.item >> @ec2.describe_images.imagesSet.item[0] (a hash representing a single item in that array) >> @ec2.describe_images.imagesSet.item[0].to_s (a String representation of that item) >> @ec2.describe_images.imagesSet.item[0].to_s => "#>" === Ruby script usage example: Try out the following bit of code. This should walk through each image returned by a call to #describe_images and print out its key data. Note in the example below that you cannot walk through the results of the #describe_images call with the '.each' iterator (You'll get errors if you try). You need to instead walk through the Array of items which are in the 'imagesSet' embedded in the response. This reflects exactly the XML hierarchy of data returned from EC2 which we parse to Ruby OpenStruct objects (AWS::Response). #!/usr/bin/env ruby require 'rubygems' require 'AWS' ACCESS_KEY_ID = '--YOUR AWS ACCESS KEY ID--' SECRET_ACCESS_KEY = '--YOUR AWS SECRET ACCESS KEY--' ec2 = AWS::EC2::Base.new(:access_key_id => ACCESS_KEY_ID, :secret_access_key => SECRET_ACCESS_KEY) puts "----- listing images owned by 'amazon' -----" ec2.describe_images(:owner_id => "amazon").imagesSet.item.each do |image| # OpenStruct objects have members! image.members.each do |member| puts "#{member} => #{image[member]}" end end === Ruby on Rails usage example: Rails 2.3.x - config/environment.rb Rails::Initializer.run do |config| ... config.gem "amazon-ec2", :lib => "AWS", :source => "http://gemcutter.org/" ... end Rails 3.x.x - Gemfile ... gem "amazon-ec2", :require => "AWS" app/controllers/my_controller.rb [some controller code ...] ec2 = AWS::EC2::Base.new(:access_key_id => "YOUR_AWS_ACCESS_KEY_ID", :secret_access_key => "YOUR_AWS_SECRET_ACCESS_KEY") # get ALL public images @ec2_images = ec2.describe_images().imagesSet.item # Get info on all public EC2 images created by the Amazon EC2 team. @ec2_images_amazon = ec2.describe_images(:owner_id => "amazon").imagesSet.item [some more controller code ...] app/views/my/index.rhtml

EC2 Test#index

Sample 1 - debug() view

<%= debug(@ec2_images_amazon) %>

Sample 2 - Build a table

<% for image in @ec2_images_amazon %> <% end %>
image.imageId image.imageLocation image.imageOwnerId image.imageState image.isPublic
<%=h image.imageId %> <%=h image.imageLocation %> <%=h image.imageOwnerId %> <%=h image.imageState %> <%=h image.isPublic %>

Sample 3 - Iterate

<% @ec2_images_amazon.each do |image| %> <% image.each_pair do |key, value| %> <% unless key == 'parent' %> <%= "#{key} => #{value}" %>
<% end %> <% end %>
<% end %> === Important notes regarding the structure of AWS::Response Objects One of the key benefits of this new version of the library is that all responses from EC2 are bundled up in a real data structure and no longer require parsing of text. The hash returned is populated directly from the XML given to us by EC2 in response to any command we issue. This means that future changes to the API and what is returned by EC2 will be handled transparently by the gem. This is a huge benefit. What this means though, is that you may have to do a little homework on what actually gets returned by EC2 as XML. For example, when you make a #describe_images call in 'awshell' what AWS returns behind the scenes looks like: ami-20b65349 ec2-public-images/fedora-core4-base.manifest.xml available amazon true ami-22b6534b ec2-public-images/fedora-core4-mysql.manifest.xml available amazon true ami-23b6534a ec2-public-images/fedora-core4-apache.manifest.xml available amazon true ami-25b6534c ec2-public-images/fedora-core4-apache-mysql.manifest.xml available amazon true ami-26b6534f ec2-public-images/developer-image.manifest.xml available amazon true ami-2bb65342 ec2-public-images/getting-started.manifest.xml available amazon true You can see here the XML the structure that you will need to follow when constructing queries for information and parsing responses from EC2. So, for example, if you wanted to get the image ID of the third image listed in the response above you would need to do: >> puts @ec2.describe_images(:owner_id => 'amazon').imagesSet.item[2].imageId ami-23b6534a EC2 will typically return sets of things (imagesSet, reservationSet, etc.) which we map to ruby Arrays (.imagesSet.item in the example above). If you want to iterate over a response set you will need to iterate over this array. The Arrays will typically contain additional AWS::Response objects that represent each individual item. You'll find that you can use the 'awshell' to help you understand the structure more completely if you try issuing commands there as a way to practice seeing what will be returned and making sure you get exactly what you want. === Handling Exceptions If for some reason an error occurs when executing a method (e.g. its arguments were incorrect, or it simply failed) then an exception will be thrown. The exceptions are defined in exceptions.rb as individual classes and should match the exceptions that AWS has defined in the API. If the exception raised cannot be identified then a more generic exception class will be thrown. The implication of this is that you need to be prepared to handle any exceptions that may be raised by this library in YOUR code with a 'rescue' clause. It is up to you to determine how you want to handle these exceptions in your code. == Additional Resources === Project Websites * Project Home : http://github.com/grempe/amazon-ec2/tree/master * API Documentation : http://rdoc.info/projects/grempe/amazon-ec2 * Discussion Group : http://groups.google.com/group/amazon-ec2 * Report Bugs / Request Features : http://github.com/grempe/amazon-ec2/issues * Amazon Web Services : http://aws.amazon.com == Credits The original code for this library was provided by Amazon Web Services, LLC as sample code. Thanks to them for providing all of us with something to get us started. == Contact Comments, patches, Git pull requests and bug reports are welcome. Send an email to mailto:glenn@rempe.us or join the Google Groups forum. == Patches & Pull Requests Please follow these steps if you want to send a patch or a GitHub pull request: * Fork grempe/amazon-ec2 * Create a topic branch: `git checkout -b my_fix` * Make sure you add tests for your changes and that they all pass with 'rake test' * Don't change files that you don't own like the gemspec or version.rb * Commit your changes, one change/fix per commit * Push your fixes branch: `git push origin my_fix` * Open an Issue on GitHub referencing your branch and send a pull request. * Please do not push to `master` on your fork. Using a feature/bugfix branch will make everyone’s life easier. Enjoy! Glenn Rempe grempe-amazon-ec2-043f1b4/Rakefile000066400000000000000000000030771147233247500167340ustar00rootroot00000000000000require 'bundler' Bundler::GemHelper.install_tasks require 'rake/testtask' Rake::TestTask.new(:test) do |test| test.libs << 'lib' << 'test' test.pattern = 'test/**/test_*.rb' test.verbose = true end begin require 'rcov/rcovtask' Rcov::RcovTask.new do |test| test.libs << 'test' test.pattern = 'test/**/test_*.rb' test.verbose = true test.rcov_opts << "--exclude /gems/,/Library/,spec" end rescue LoadError task :rcov do abort "RCov is not available. In order to run rcov, you must: [sudo] gem install rcov" end end task :default => :test require 'rake/rdoctask' Rake::RDocTask.new do |rdoc| if File.exist?('VERSION.yml') config = YAML.load(File.read('VERSION.yml')) version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}" else version = "" end rdoc.rdoc_dir = 'rdoc' rdoc.title = "amazon-ec2 #{version}" rdoc.rdoc_files.include('README*') rdoc.rdoc_files.include('lib/**/*.rb') end begin require 'yard' YARD::Rake::YardocTask.new do |t| #t.files = ['lib/**/*.rb'] end rescue LoadError puts "YARD (or a dependency) not available. Install it with: [sudo] gem install yard" end desc "Generate a perftools.rb profile" task :profile do system("CPUPROFILE=perftools/ec2prof RUBYOPT='-r/Users/glenn/.rvm/gems/ruby-1.8.7-p302@amazon-ec2/gems/perftools.rb-0.5.4/lib/perftools.bundle' ruby -r'rubygems' bin/ec2-gem-profile.rb") system("pprof.rb --text --ignore=Gem perftools/ec2prof > perftools/ec2prof-results.txt") system("pprof.rb --dot --ignore=Gem perftools/ec2prof > perftools/ec2prof-results.dot") end grempe-amazon-ec2-043f1b4/VERSION000066400000000000000000000000071147233247500163250ustar00rootroot000000000000000.9.15 grempe-amazon-ec2-043f1b4/amazon-ec2.gemspec000066400000000000000000000024101147233247500205560ustar00rootroot00000000000000# -*- encoding: utf-8 -*- $:.push File.expand_path("../lib", __FILE__) require "AWS/version" Gem::Specification.new do |s| s.name = "amazon-ec2" s.version = AWS::VERSION s.platform = Gem::Platform::RUBY s.authors = ["Glenn Rempe"] s.email = ["glenn@rempe.us"] s.homepage = "http://github.com/grempe/amazon-ec2" s.summary = "Amazon EC2 Ruby gem" s.description = "A Ruby library for accessing the Amazon Web Services EC2, ELB, RDS, Cloudwatch, and Autoscaling APIs." s.rubyforge_project = "amazon-ec2" s.rdoc_options = ["--title", "amazon-ec2 documentation", "--line-numbers", "--main", "README.rdoc"] s.extra_rdoc_files = [ "ChangeLog", "LICENSE", "README.rdoc" ] s.add_dependency('xml-simple', '>= 1.0.12') s.add_development_dependency('mocha', '>= 0.9.9') s.add_development_dependency('test-spec', '>= 0.10.0') s.add_development_dependency('rcov', '>= 0.9.9') s.add_development_dependency('perftools.rb', '>= 0.5.4') s.add_development_dependency('yard', '>= 0.6.2') s.files = `git ls-files`.split("\n") s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n") s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) } s.require_paths = ["lib"] end grempe-amazon-ec2-043f1b4/bin/000077500000000000000000000000001147233247500160305ustar00rootroot00000000000000grempe-amazon-ec2-043f1b4/bin/awshell000077500000000000000000000052031147233247500174150ustar00rootroot00000000000000#!/usr/bin/env ruby # Amazon Web Services EC2 Query API Ruby library # # Ruby Gem Name:: amazon-ec2 # Author:: Glenn Rempe (mailto:glenn@rempe.us) # Copyright:: Copyright (c) 2007-2010 Glenn Rempe # License:: Distributes under the same terms as Ruby # Home:: http://github.com/grempe/amazon-ec2/tree/master #++ # CREDITS : Credit for this bit of shameful ripoff coolness # goes to Marcel Molina and his AWS::S3 gem. Thanks! aws_lib = File.dirname(__FILE__) + '/../lib/AWS' setup = File.dirname(__FILE__) + '/setup' irb_name = RUBY_PLATFORM =~ /mswin32/ ? 'irb.bat' : 'irb' welcome_message = <<-MESSAGE Usage : This is an interactive Ruby 'irb' shell that allows you to use the AWS commands available in the 'amazon-ec2' gem. This can be a great tool to help you debug issues and run commands against the live AWS servers. You can do anything in this shell that you can in a normal irb shell. Config : You must set the following environment variables that contain your AWS credentials in your system shell for this to work. AMAZON_ACCESS_KEY_ID AMAZON_SECRET_ACCESS_KEY Each AWS service has its own default server endpoints. You can override the endpoints with the following environment variables set in your system shell: EC2 : EC2_URL Elastic Load Balancing : ELB_URL AutoScaling : AS_URL RDS : RDS_URL CloudWatch : AWS_CLOUDWATCH_URL For your convenience, the various AWS services are wired up in this shell to the following class variables. You can execute methods on each of these: @ec2 (Elastic Compute Cloud) @elb (Elastic Load Balancing) @as (AutoScaling) @rds (Relational Database Service) @cw (CloudWatch) You can make method calls on these instances to execute commands against the various services. Pre-pending a 'pp' should give you a pretty printed version of the response which may be easier to read. Examples: returns : Pretty Print all ec2 public methods >> pp @ec2.methods.sort returns : Pretty Print a Hash describing your EC2 images >> @ec2.describe_images(:owner_id => ['self']) returns : an Array of AWS::Response objects, each an EC2 image and its data >> @ec2.describe_images(:owner_id => ['self']).imagesSet.item >> @ec2.describe_images(:owner_id => ['self']).imagesSet.item[0] MESSAGE if ( ENV['AMAZON_ACCESS_KEY_ID'] && ENV['AMAZON_SECRET_ACCESS_KEY'] ) puts welcome_message exec "#{irb_name} -rubygems -r #{aws_lib} -r #{setup} --simple-prompt" else puts "You must define AMAZON_ACCESS_KEY_ID and AMAZON_SECRET_ACCESS_KEY as shell environment variables before running #{$0}!" puts welcome_message end grempe-amazon-ec2-043f1b4/bin/ec2-gem-example.rb000077500000000000000000000136761147233247500212450ustar00rootroot00000000000000#!/usr/bin/env ruby # Amazon Web Services EC2 Query API Ruby library # # Ruby Gem Name:: amazon-ec2 # Author:: Glenn Rempe (mailto:glenn@rempe.us) # Copyright:: Copyright (c) 2007-2008 Glenn Rempe # License:: Distributes under the same terms as Ruby # Home:: http://github.com/grempe/amazon-ec2/tree/master #++ require File.dirname(__FILE__) + '/../lib/AWS' require 'pp' # pull these from the local shell environment variables set in ~/.bash_login # or using appropriate methods specific to your login shell. # # e.g. in ~/.bash_login # # # For amazon-ec2 and amazon s3 ruby gems # export AMAZON_ACCESS_KEY_ID="FOO" # export AMAZON_SECRET_ACCESS_KEY="BAR" ACCESS_KEY_ID = ENV['AMAZON_ACCESS_KEY_ID'] SECRET_ACCESS_KEY = ENV['AMAZON_SECRET_ACCESS_KEY'] if ACCESS_KEY_ID.nil? || ACCESS_KEY_ID.empty? puts "Error : You must add the shell environment variables AMAZON_ACCESS_KEY_ID and AMAZON_SECRET_ACCESS_KEY before calling #{$0}!" exit end # us-east-1.ec2.amazonaws.com == ec2.amazonaws.com # eu-west-1.ec2.amazonaws.com for the european region # test different servers by running something like: # export EC2_URL='https://ec2.amazonaws.com';./bin/ec2-gem-example.rb if ENV['EC2_URL'] ec2 = AWS::EC2::Base.new( :access_key_id => ACCESS_KEY_ID, :secret_access_key => SECRET_ACCESS_KEY, :server => URI.parse(ENV['EC2_URL']).host ) else # default server is US ec2.amazonaws.com ec2 = AWS::EC2::Base.new( :access_key_id => ACCESS_KEY_ID, :secret_access_key => SECRET_ACCESS_KEY ) end puts "----- ec2.methods.sort -----" p ec2.methods.sort puts "----- listing images owned by 'amazon' -----" ec2.describe_images(:owner_id => "amazon").imagesSet.item.each do |image| image.keys.each do |key| puts "#{key} => #{image[key]}" end end puts "----- listing all running instances -----" pp ec2.describe_instances() puts "----- creating a security group -----" pp ec2.create_security_group(:group_name => "ec2-example-rb-test-group", :group_description => "ec-example.rb test group description.") puts "----- listing security groups -----" pp ec2.describe_security_groups() puts "----- deleting a security group -----" pp ec2.delete_security_group(:group_name => "ec2-example-rb-test-group") puts "----- listing my keypairs (verbose mode) -----" pp ec2.describe_keypairs() # ELB examples # Autoscaling examples if ENV['ELB_URL'] elb = AWS::ELB::Base.new( :access_key_id => ACCESS_KEY_ID, :secret_access_key => SECRET_ACCESS_KEY, :server => URI.parse(ENV['ELB_URL']).host ) else elb = AWS::ELB::Base.new( :access_key_id => ACCESS_KEY_ID, :secret_access_key => SECRET_ACCESS_KEY) end puts "----- creating an elastic load balancer -----" pp elb.create_load_balancer( :availability_zones => ["us-east-1a"], :load_balancer_name => "elb-test-load-balancer", :listeners => [{:protocol => "tcp", :load_balancer_port => "80", :instance_port => "8080"}] ) puts "----- listing elastic load balancers -----" pp elb.describe_load_balancers(:load_balancer_names => ["elb-test-load-balancer"]) puts "----- deleting load balancer -----" pp elb.delete_load_balancer(:load_balancer_name => "elb-test-load-balancer") # Autoscaling examples if ENV['AS_URL'] as = AWS::Autoscaling::Base.new( :access_key_id => ACCESS_KEY_ID, :secret_access_key => SECRET_ACCESS_KEY, :server => URI.parse(ENV['AS_URL']).host ) else as = AWS::Autoscaling::Base.new( :access_key_id => ACCESS_KEY_ID, :secret_access_key => SECRET_ACCESS_KEY) end puts "---- creating a launch configuration group -----" pp as.create_launch_configuration( :image_id => "ami-ed46a784", :instance_type => "m1.small", :availability_zones => ["us-east-1a"], :launch_configuration_name => "ec2-example-test-launch-configuration" ) puts "---- creating an autoscaling group -----" pp as.create_autoscaling_group( :autoscaling_group_name => "ec2-example-test-autoscaling-group", :availability_zones => ["us-east-1a"], :min_size => 0, :max_size => 0, :launch_configuration_name => "ec2-example-test-launch-configuration" ) puts "---- listing autoscaling groups -----" pp as.describe_autoscaling_groups(:autoscaling_group_names => []) puts "---- creating a new autoscaling trigger ----" pp as.create_or_updated_scaling_trigger( :autoscaling_group_name => "ec2-example-test-autoscaling-group", :measure_name => "CPUUtilization", :statistic => "Average", :period => 300, :trigger_name => "test-auto-scaling-trigger-name", :lower_threshold => 0.2, :lower_breach_scale_increment => 0, :upper_threshold => 1.5, :upper_breach_scale_increment => 0, :breach_duration => 1200, :dimensions => ["AutoScalingGroupName", "ec2-example-test-autoscaling-group"] ) puts "---- deleting scaling trigger -----" pp as.delete_trigger(:trigger_name => "test-auto-scaling-trigger-name", :autoscaling_group_name => "ec2-example-test-autoscaling-group") puts "---- deleting autoscaling group -----" pp as.delete_autoscaling_group(:autoscaling_group_name => "ec2-example-test-autoscaling-group") puts "---- deleting launch configuration group -----" pp as.delete_launch_configuration(:launch_configuration_name => "ec2-example-test-launch-configuration")grempe-amazon-ec2-043f1b4/bin/ec2-gem-profile.rb000077500000000000000000000006121147233247500212340ustar00rootroot00000000000000#!/usr/bin/env ruby # Basic single command application that we can call with perftools.rb to get consistent results. require File.dirname(__FILE__) + '/../lib/AWS' ACCESS_KEY_ID = ENV['AMAZON_ACCESS_KEY_ID'] SECRET_ACCESS_KEY = ENV['AMAZON_SECRET_ACCESS_KEY'] ec2 = AWS::EC2::Base.new( :access_key_id => ACCESS_KEY_ID, :secret_access_key => SECRET_ACCESS_KEY ) @images = ec2.describe_images grempe-amazon-ec2-043f1b4/bin/ec2sh000077500000000000000000000007311147233247500167630ustar00rootroot00000000000000#!/usr/bin/env ruby # Amazon Web Services EC2 Query API Ruby library # # Ruby Gem Name:: amazon-ec2 # Author:: Glenn Rempe (mailto:glenn@rempe.us) # Copyright:: Copyright (c) 2007-2010 Glenn Rempe # License:: Distributes under the same terms as Ruby # Home:: http://github.com/grempe/amazon-ec2/tree/master #++ message = <<-MESSAGE DEPRECATION WARNING: This script has been renamed to 'awshell'. Please run that command instead. MESSAGE puts message grempe-amazon-ec2-043f1b4/bin/setup.rb000077500000000000000000000040071147233247500175210ustar00rootroot00000000000000#!/usr/bin/env ruby # Amazon Web Services EC2 Query API Ruby library # # Ruby Gem Name:: amazon-ec2 # Author:: Glenn Rempe (mailto:glenn@rempe.us) # Copyright:: Copyright (c) 2007-2010 Glenn Rempe # License:: Distributes under the same terms as Ruby # Home:: http://github.com/grempe/amazon-ec2/tree/master #++ if ENV['AMAZON_ACCESS_KEY_ID'] && ENV['AMAZON_SECRET_ACCESS_KEY'] opts = { :access_key_id => ENV['AMAZON_ACCESS_KEY_ID'], :secret_access_key => ENV['AMAZON_SECRET_ACCESS_KEY'] } if ENV['EC2_URL'] ec2uri = URI.parse(ENV['EC2_URL']) opts[:server] = ec2uri.host if ec2uri.path.downcase.include?("eucalyptus") opts[:path] = ec2uri.path opts[:port] = ec2uri.port if ec2uri.class == URI::HTTPS opts[:use_ssl] = true else opts[:use_ssl] = false end end @ec2 = AWS::EC2::Base.new(opts) else @ec2 = AWS::EC2::Base.new(opts) end if ENV['ELB_URL'] opts[:server] = URI.parse(ENV['ELB_URL']).host @elb = AWS::ELB::Base.new(opts) else @elb = AWS::ELB::Base.new(opts) end if ENV['AS_URL'] opts[:server] = URI.parse(ENV['AS_URL']).host @as = AWS::Autoscaling::Base.new(opts) else @as = AWS::Autoscaling::Base.new(opts) end if ENV['RDS_URL'] opts[:server] = URI.parse(ENV['RDS_URL']).host @rds = AWS::RDS::Base.new(opts) else @rds = AWS::RDS::Base.new(opts) end if ENV['AWS_CLOUDWATCH_URL'] opts[:server] = URI.parse(ENV['AWS_CLOUDWATCH_URL']).host @cw = AWS::Cloudwatch::Base.new(opts) else @cw = AWS::Cloudwatch::Base.new(opts) end puts "" puts "Server Endpoints Configured" puts "--" puts "@ec2.default_host (Elastic Compute Cloud) : #{@ec2.default_host}" puts "@elb.default_host (Elastic Load Balancer) : #{@elb.default_host}" puts "@as.default_host (Autoscaling) : #{@as.default_host}" puts "@rds.default_host (Relational DB Service) : #{@rds.default_host}" puts "@cw.default_host (Cloudwatch) : #{@cw.default_host}" puts "" end require 'pp' include AWS grempe-amazon-ec2-043f1b4/deps.rip000066400000000000000000000000221147233247500167210ustar00rootroot00000000000000xml-simple 1.0.12 grempe-amazon-ec2-043f1b4/lib/000077500000000000000000000000001147233247500160265ustar00rootroot00000000000000grempe-amazon-ec2-043f1b4/lib/AWS.rb000066400000000000000000000352641147233247500170170ustar00rootroot00000000000000#-- # Amazon Web Services EC2 + ELB API Ruby library # # Ruby Gem Name:: amazon-ec2 # Author:: Glenn Rempe (mailto:glenn@rempe.us) # Copyright:: Copyright (c) 2007-2009 Glenn Rempe # License:: Distributes under the same terms as Ruby # Home:: http://github.com/grempe/amazon-ec2/tree/master #++ %w[ base64 cgi openssl digest/sha1 net/https net/http rexml/document time ostruct ].each { |f| require f } begin require 'URI' unless defined? URI rescue Exception => e # nothing end begin require 'xmlsimple' unless defined? XmlSimple rescue Exception => e require 'xml-simple' unless defined? XmlSimple end # A custom implementation of Hash that allows us to access hash values using dot notation # # @example Access the hash keys in the standard way or using dot notation # foo[:bar] => "baz" # foo.bar => "baz" class Hash def method_missing(meth, *args, &block) if args.size == 0 self[meth.to_s] || self[meth.to_sym] end end def type self['type'] end def has?(key) self[key] && !self[key].to_s.empty? end def does_not_have?(key) self[key].nil? || self[key].to_s.empty? end end module AWS # Builds the canonical string for signing requests. This strips out all '&', '?', and '=' # from the query string to be signed. The parameters in the path passed in must already # be sorted in case-insensitive alphabetical order and must not be url encoded. # # @param [String] params the params that will be sorted and encoded as a canonical string. # @param [String] host the hostname of the API endpoint. # @param [String] method the HTTP method that will be used to submit the params. # @param [String] base the URI path that this information will be submitted to. # @return [String] the canonical request description string. def AWS.canonical_string(params, host, method="POST", base="/") # Sort, and encode parameters into a canonical string. sorted_params = params.sort {|x,y| x[0] <=> y[0]} encoded_params = sorted_params.collect do |p| encoded = (CGI::escape(p[0].to_s) + "=" + CGI::escape(p[1].to_s)) # Ensure spaces are encoded as '%20', not '+' encoded = encoded.gsub('+', '%20') # According to RFC3986 (the scheme for values expected by signing requests), '~' # should not be encoded encoded = encoded.gsub('%7E', '~') end sigquery = encoded_params.join("&") # Generate the request description string req_desc = method + "\n" + host + "\n" + base + "\n" + sigquery end # Encodes the given string with the secret_access_key by taking the # hmac-sha1 sum, and then base64 encoding it. Optionally, it will also # url encode the result of that to protect the string if it's going to # be used as a query string parameter. # # @param [String] secret_access_key the user's secret access key for signing. # @param [String] str the string to be hashed and encoded. # @param [Boolean] urlencode whether or not to url encode the result., true or false # @return [String] the signed and encoded string. def AWS.encode(secret_access_key, str, urlencode=true) digest = OpenSSL::Digest::Digest.new('sha256') b64_hmac = Base64.encode64( OpenSSL::HMAC.digest(digest, secret_access_key, str)).gsub("\n","") if urlencode return CGI::escape(b64_hmac) else return b64_hmac end end # This class provides all the methods for using the EC2 or ELB service # including the handling of header signing and other security concerns. # This class uses the Net::HTTP library to interface with the AWS Query API # interface. You should not instantiate this directly, instead # you should setup an instance of 'AWS::EC2::Base' or 'AWS::ELB::Base'. class Base attr_reader :use_ssl, :server, :proxy_server, :port # @option options [String] :access_key_id ("") The user's AWS Access Key ID # @option options [String] :secret_access_key ("") The user's AWS Secret Access Key # @option options [Boolean] :use_ssl (true) Connect using SSL? # @option options [String] :server ("ec2.amazonaws.com") The server API endpoint host # @option options [String] :proxy_server (nil) An HTTP proxy server FQDN # @return [Object] the object. def initialize( options = {} ) options = { :access_key_id => "", :secret_access_key => "", :use_ssl => true, :server => default_host, :path => "/", :proxy_server => nil }.merge(options) @server = options[:server] @proxy_server = options[:proxy_server] @use_ssl = options[:use_ssl] @path = options[:path] raise ArgumentError, "No :access_key_id provided" if options[:access_key_id].nil? || options[:access_key_id].empty? raise ArgumentError, "No :secret_access_key provided" if options[:secret_access_key].nil? || options[:secret_access_key].empty? raise ArgumentError, "No :use_ssl value provided" if options[:use_ssl].nil? raise ArgumentError, "Invalid :use_ssl value provided, only 'true' or 'false' allowed" unless options[:use_ssl] == true || options[:use_ssl] == false raise ArgumentError, "No :server provided" if options[:server].nil? || options[:server].empty? if options[:port] # user-specified port @port = options[:port] elsif @use_ssl # https @port = 443 else # http @port = 80 end @access_key_id = options[:access_key_id] @secret_access_key = options[:secret_access_key] # Use proxy server if defined # Based on patch by Mathias Dalheimer. 20070217 proxy = @proxy_server ? URI.parse(@proxy_server) : OpenStruct.new @http = Net::HTTP::Proxy( proxy.host, proxy.port, proxy.user, proxy.password).new(options[:server], @port) @http.use_ssl = @use_ssl # Don't verify the SSL certificates. Avoids SSL Cert warning in log on every GET. @http.verify_mode = OpenSSL::SSL::VERIFY_NONE end # If :user_data is passed in then URL escape and Base64 encode it # as needed. Need for URL Escape + Base64 encoding is determined # by :base64_encoded param. def extract_user_data( options = {} ) return unless options[:user_data] if options[:user_data] if options[:base64_encoded] Base64.encode64(options[:user_data]).gsub(/\n/, "").strip() else options[:user_data] end end end protected # pathlist is a utility method which takes a key string and and array as input. # It converts the array into a Hash with the hash key being 'Key.n' where # 'n' increments by 1 for each iteration. So if you pass in args # ("ImageId", ["123", "456"]) you should get # {"ImageId.1"=>"123", "ImageId.2"=>"456"} returned. def pathlist(key, arr) params = {} # ruby 1.9 will barf if we pass in a string instead of the array expected. # it will fail on each_with_index below since string is not enumerable. if arr.is_a? String new_arr = [] new_arr << arr arr = new_arr end arr.each_with_index do |value, i| params["#{key}.#{i+1}"] = value end params end # Same as _pathlist_ except it deals with arrays of hashes. # So if you pass in args # ("People", [{:name=>'jon', :age=>'22'}, {:name=>'chris'}], {:name => 'Name', :age => 'Age'}) you should get # {"People.1.Name"=>"jon", "People.1.Age"=>'22', 'People.2.Name'=>'chris'} def pathhashlist(key, arr_of_hashes, mappings) raise ArgumentError, "expected a key that is a String" unless key.is_a? String raise ArgumentError, "expected a arr_of_hashes that is an Array" unless arr_of_hashes.is_a? Array arr_of_hashes.each{|h| raise ArgumentError, "expected each element of arr_of_hashes to be a Hash" unless h.is_a?(Hash)} raise ArgumentError, "expected a mappings that is an Hash" unless mappings.is_a? Hash params = {} arr_of_hashes.each_with_index do |hash, i| hash.each do |attribute, value| if value.is_a? Array params["#{key}.#{i+1}.Name"] = mappings[attribute] value.each_with_index do |item, j| params["#{key}.#{i+1}.Value.#{j+1}"] = item.to_s end else params["#{key}.#{i+1}.#{mappings[attribute]}"] = value.to_s end end end params end # Same as _pathhashlist_ except it generates explicit .Key= and .Value or .Value.1, .Value.2 # depending on whether the value is a scalar or an array. # # So if you pass in args # ("People", [{:name=>'jon'}, {:names=>['chris', 'bob']} with key_name = 'Key' and value_name = 'Value', # you should get # {"People.1.Key"=>"name", "People.1.Value"=>'jon', "People.2.Key"=>'names', 'People.2.Value.1'=>'chris', 'People.2.Value.2'=>'bob'} def pathkvlist(key, arr_of_hashes, key_name, value_name, mappings) raise ArgumentError, "expected a key that is a String" unless key.is_a? String raise ArgumentError, "expected a arr_of_hashes that is an Array" unless arr_of_hashes.is_a? Array arr_of_hashes.each{|h| raise ArgumentError, "expected each element of arr_of_hashes to be a Hash" unless h.is_a?(Hash)} raise ArgumentError, "expected a key_nam that is a String" unless key_name.is_a? String raise ArgumentError, "expected a value_name that is a String" unless value_name.is_a? String raise ArgumentError, "expected a mappings that is an Hash" unless mappings.is_a? Hash params = {} arr_of_hashes.each_with_index do |hash, i| hash.each do |attribute, value| params["#{key}.#{i+1}.#{key_name}"] = mappings.fetch(attribute, attribute) if !value.nil? if value.is_a? Array value.each_with_index do |item, j| params["#{key}.#{i+1}.#{value_name}.#{j+1}"] = item.to_s end else params["#{key}.#{i+1}.#{value_name}"] = value.to_s end end end end params end # Make the connection to AWS EC2 passing in our request. This is generally called from # within a 'Response' class object or one of its sub-classes so the response is interpreted # in its proper context. See lib/EC2/responses.rb def make_request(action, params, data='') @http.start do # remove any keys that have nil or empty values params.reject! { |key, value| value.nil? or value.empty?} params.merge!( {"Action" => action, "SignatureVersion" => "2", "SignatureMethod" => 'HmacSHA256', "AWSAccessKeyId" => @access_key_id, "Version" => api_version, "Timestamp"=>Time.now.getutc.iso8601} ) sig = get_aws_auth_param(params, @secret_access_key, @server) query = params.sort.collect do |param| CGI::escape(param[0]) + "=" + CGI::escape(param[1]) end.join("&") + "&Signature=" + sig req = Net::HTTP::Post.new(@path) req.content_type = 'application/x-www-form-urlencoded' req['User-Agent'] = "github-amazon-ec2-ruby-gem" response = @http.request(req, query) # Make a call to see if we need to throw an error based on the response given by EC2 # All error classes are defined in EC2/exceptions.rb aws_error?(response) return response end end # Set the Authorization header using AWS signed header authentication def get_aws_auth_param(params, secret_access_key, server) canonical_string = AWS.canonical_string(params, server,"POST", @path) encoded_canonical = AWS.encode(secret_access_key, canonical_string) end # allow us to have a one line call in each method which will do all of the work # in making the actual request to AWS. def response_generator( options = {} ) options = { :action => "", :params => {} }.merge(options) raise ArgumentError, ":action must be provided to response_generator" if options[:action].nil? || options[:action].empty? http_response = make_request(options[:action], options[:params]) http_xml = http_response.body return Response.parse(:xml => http_xml) end # Raises the appropriate error if the specified Net::HTTPResponse object # contains an AWS error; returns +false+ otherwise. def aws_error?(response) # return false if we got a HTTP 200 code, # otherwise there is some type of error (40x,50x) and # we should try to raise an appropriate exception # from one of our exception classes defined in # exceptions.rb return false if response.is_a?(Net::HTTPSuccess) raise AWS::Error, "Unexpected server error. response.body is: #{response.body}" if response.is_a?(Net::HTTPServerError) # parse the XML document so we can walk through it doc = REXML::Document.new(response.body) # Check that the Error element is in the place we would expect. # and if not raise a generic error exception unless doc.root.elements['Errors'].elements['Error'].name == 'Error' raise Error, "Unexpected error format. response.body is: #{response.body}" end # An valid error response looks like this: # InvalidParameterCombinationUnknown parameter: foo291cef62-3e86-414b-900e-17246eccfae8 # AWS throws some exception codes that look like Error.SubError. Since we can't name classes this way # we need to strip out the '.' in the error 'Code' and we name the error exceptions with this # non '.' name as well. error_code = doc.root.elements['Errors'].elements['Error'].elements['Code'].text.gsub('.', '') error_message = doc.root.elements['Errors'].elements['Error'].elements['Message'].text # Raise one of our specific error classes if it exists. # otherwise, throw a generic EC2 Error with a few details. if AWS.const_defined?(error_code) raise AWS.const_get(error_code), error_message else raise AWS::Error, error_message end end end end Dir[File.join(File.dirname(__FILE__), 'AWS/**/*.rb')].sort.each { |lib| require lib } grempe-amazon-ec2-043f1b4/lib/AWS/000077500000000000000000000000001147233247500164605ustar00rootroot00000000000000grempe-amazon-ec2-043f1b4/lib/AWS/Autoscaling.rb000066400000000000000000000047171147233247500212670ustar00rootroot00000000000000module AWS module Autoscaling # Which host FQDN will we connect to for all API calls to AWS? # If AS_URL is defined in the users ENV we can override the default with that. # # @example # export AS_URL='http://autoscaling.amazonaws.com' if ENV['AS_URL'] AS_URL = ENV['AS_URL'] DEFAULT_HOST = URI.parse(AS_URL).host else # Default US API endpoint DEFAULT_HOST = 'autoscaling.amazonaws.com' end API_VERSION = '2009-05-15' class Base < AWS::Base def api_version API_VERSION end def default_host DEFAULT_HOST end # Raises the appropriate error if the specified Net::HTTPResponse object # contains an Amazon EC2 error; returns +false+ otherwise. def aws_error?(response) # return false if we got a HTTP 200 code, # otherwise there is some type of error (40x,50x) and # we should try to raise an appropriate exception # from one of our exception classes defined in # exceptions.rb return false if response.is_a?(Net::HTTPSuccess) # parse the XML document so we can walk through it doc = REXML::Document.new(response.body) # Check that the Error element is in the place we would expect. # and if not raise a generic error exception unless doc.root.elements[1].name == "Error" raise Error, "Unexpected error format. response.body is: #{response.body}" end # An valid error response looks like this: # InvalidParameterCombinationUnknown parameter: foo291cef62-3e86-414b-900e-17246eccfae8 # AWS EC2 throws some exception codes that look like Error.SubError. Since we can't name classes this way # we need to strip out the '.' in the error 'Code' and we name the error exceptions with this # non '.' name as well. error_code = doc.root.elements['//ErrorResponse/Error/Code'].text.gsub('.', '') error_message = doc.root.elements['//ErrorResponse/Error/Message'].text # Raise one of our specific error classes if it exists. # otherwise, throw a generic EC2 Error with a few details. if AWS.const_defined?(error_code) raise AWS.const_get(error_code), error_message else raise AWS::Error, error_message end end end end endgrempe-amazon-ec2-043f1b4/lib/AWS/Autoscaling/000077500000000000000000000000001147233247500207315ustar00rootroot00000000000000grempe-amazon-ec2-043f1b4/lib/AWS/Autoscaling/autoscaling.rb000066400000000000000000000510511147233247500235710ustar00rootroot00000000000000module AWS module Autoscaling class Base < AWS::Base # Create a launch configuration # Creates a new Launch Configuration. Please note that the launch configuration name used must be unique, within the scope of your AWS account, and the maximum limit of launch configurations must not yet have been met, or else the call will fail. # Once created, the new launch configuration is available for immediate use. # # @option options [String] :launch_configuration_name (nil) the name of the launch configuration # @option options [String] :image_id (nil) the image id to use with this launch configuration # @option options [String] :instance_type (nil) the type of instance to launch # @option options [Array] :security_groups (nil) the names of security_groups to launch within # @option options [String] :key_name (nil) the name of the EC2 key pair # @option options [String] :user_data (nil) the user data available to the launched EC2 instances # @option options [String] :kernel_id (nil) the ID of the kernel associated with the EC2 ami # @option options [String] :ramdisk_id (nil) the name of the RAM disk associated with the EC2 ami # @option options [Array] :block_device_mappings (nil) specifies how block devices are exposed to the instance def create_launch_configuration( options = {}) raise ArgumentError, "No :image_id provided" if options[:image_id].nil? || options[:image_id].empty? raise ArgumentError, "No :launch_configuration_name provided" if options[:launch_configuration_name].nil? || options[:launch_configuration_name].empty? raise ArgumentError, "No :instance_type provided" if options[:instance_type].nil? || options[:instance_type].empty? params = {} params["ImageId"] = options[:image_id] params["KeyName"] = options[:key_name] if options[:key_name] params["LaunchConfigurationName"] = options[:launch_configuration_name] params.merge!(pathlist('SecurityGroups.member', [options[:security_groups]].flatten)) if options[:security_groups] params["UserData"] = options[:user_data] if options[:user_data] params["InstanceType"] = options[:instance_type] if options[:instance_type] params["KernelId"] = options[:kernel_id] if options[:kernel_id] params["RamdiskId"] = options[:ramdisk_id] if options[:ramdisk_id] params.merge!(pathlist('BlockDeviceMappings.member', [options[:block_device_mappings]].flatten)) if options[:block_device_mappings] return response_generator(:action => "CreateLaunchConfiguration", :params => params) end # Creates a new AutoScalingGroup with the specified name. # You must not have already used up your entire quota of AutoScalingGroups in order for this call to be successful. Once the creation request is completed, the AutoScalingGroup is ready to be used in other calls. # # @option options [String] :autoscaling_group_name (nil) the name of the autoscaling group # @option options [Array] :availability_zones (nil) The availability_zones for the group # @option options [String] :launch_configuration_name (nil) the name of the launch_configuration group # @option options [String] :min_size (nil) minimum size of the group # @option options [String] :max_size (nil) the maximum size of the group # @option options [optional,Array] :load_balancer_names (nil) the names of the load balancers # @option options [optional,String] :cooldown (nil) the amount of time after a scaling activity complese before any further trigger-related scaling activities can start def create_autoscaling_group( options = {} ) raise ArgumentError, "No :autoscaling_group_name provided" if options[:autoscaling_group_name].nil? || options[:autoscaling_group_name].empty? raise ArgumentError, "No :availability_zones provided" if options[:availability_zones].nil? || options[:availability_zones].empty? raise ArgumentError, "No :launch_configuration_name provided" if options[:launch_configuration_name].nil? || options[:launch_configuration_name].empty? raise ArgumentError, "No :min_size provided" if options[:min_size].nil? raise ArgumentError, "No :max_size provided" if options[:max_size].nil? params = {} params.merge!(pathlist('AvailabilityZones.member', [options[:availability_zones]].flatten)) params['LaunchConfigurationName'] = options[:launch_configuration_name] params['AutoScalingGroupName'] = options[:autoscaling_group_name] params['MinSize'] = options[:min_size].to_s params['MaxSize'] = options[:max_size].to_s params.merge!(pathlist("LoadBalancerNames.member", [options[:load_balancer_names]].flatten)) if options.has_key?(:load_balancer_names) params['Cooldown'] = options[:cooldown] if options[:cooldown] return response_generator(:action => "CreateAutoScalingGroup", :params => params) end # Create or update scaling trigger # This call sets the parameters that governs when and how to scale an AutoScalingGroup. # # @option options [String] :autoscaling_group_name (nil) the name of the autoscaling group # @option options [Array|Hash] :dimensions (nil) The dimensions associated with the metric used by the trigger to determine whether to activate # This must be given as either an array or a hash # When called as a hash, the values must look like: {:name => "name", :value => "value"} # In the array format, the first value is assumed to be the name and the second is assumed to be the value # @option options [String] :measure_name (nil) the measure name associated with the metric used by the trigger # @option options [optional,String] :namespace (nil) namespace of the metric on which to trigger. Used to describe the monitoring metric. # @option options [String|Integer] :period (nil) the period associated with the metric in seconds # @option options [String] :statistic (nil) The particular statistic used by the trigger when fetching metric statistics to examine. Must be one of the following: Minimum, Maximum, Sum, Average # @option options [String] :trigger_name (nil) the name for this trigger # @option options [String] :unit (nil) the standard unit of measurement for a given measure # @option options [String|Integer] :lower_threshold (nil) the lower limit for the metric. If all datapoints in the last :breach_duration seconds fall below the lower threshold, the trigger will activate # @option options [String|Integer] :lower_breach_scale_increment (nil) the incremental amount to use when performing scaling activities when the lower threshold has been breached # @option options [String|Integer] :upper_threshold (nil) the upper limit for the metric. If all datapoints in the last :breach_duration seconds exceed the upper threshold, the trigger will activate # @option options [String|Integer] :upper_breach_scale_increment (nil) the incremental amount to use when performing scaling activities when the upper threshold has been breached def create_or_updated_scaling_trigger( options = {} ) if options[:dimensions].nil? || options[:dimensions].empty? raise ArgumentError, "No :dimensions provided" end raise ArgumentError, "No :autoscaling_group_name provided" if options[:autoscaling_group_name].nil? || options[:autoscaling_group_name].empty? raise ArgumentError, "No :measure_name provided" if options[:measure_name].nil? || options[:measure_name].empty? raise ArgumentError, "No :statistic provided" if options[:statistic].nil? || options[:statistic].empty? raise ArgumentError, "No :period provided" if options[:period].nil? raise ArgumentError, "No :trigger_name provided" if options[:trigger_name].nil? || options[:trigger_name].empty? raise ArgumentError, "No :lower_threshold provided" if options[:lower_threshold].nil? raise ArgumentError, "No :lower_breach_scale_increment provided" if options[:lower_breach_scale_increment].nil? raise ArgumentError, "No :upper_threshold provided" if options[:upper_threshold].nil? raise ArgumentError, "No :upper_breach_scale_increment provided" if options[:upper_breach_scale_increment].nil? raise ArgumentError, "No :breach_duration provided" if options[:breach_duration].nil? statistic_option_list = %w(minimum maximum average sum) unless statistic_option_list.include?(options[:statistic].downcase) raise ArgumentError, "The statistic option must be one of the following: #{statistic_option_list.join(", ")}" end params = {} params['Unit'] = options[:unit] if options[:unit] params['AutoScalingGroupName'] = options[:autoscaling_group_name] case options[:dimensions] when Array params["Dimensions.member.1.Name"] = options[:dimensions][0] params["Dimensions.member.1.Value"] = options[:dimensions][1] when Hash params["Dimensions.member.1.Name"] = options[:dimensions][:name] params["Dimensions.member.1.Value"] = options[:dimensions][:value] else raise ArgumentError, "Dimensions must be either an array or a hash" end params['MeasureName'] = options[:measure_name] params['Namespace'] = options[:namespace] if options[:namespace] params['Statistic'] = options[:statistic] params['Period'] = options[:period].to_s params['TriggerName'] = options[:trigger_name] params['LowerThreshold'] = options[:lower_threshold].to_s params['LowerBreachScaleIncrement'] = options[:lower_breach_scale_increment].to_s params['UpperThreshold'] = options[:upper_threshold].to_s params['UpperBreachScaleIncrement'] = options[:upper_breach_scale_increment].to_s params['BreachDuration'] = options[:breach_duration].to_s return response_generator(:action => "CreateOrUpdateScalingTrigger", :params => params) end # Deletes all configuration for this AutoScalingGroup and also deletes the group. # In order to successfully call this API, no triggers (and therefore, Scaling Activity) can be currently in progress. Once this call successfully executes, no further triggers will begin and the AutoScalingGroup will not be available for use in other API calls. See key term Trigger. # # @option options [String] :autoscaling_group_name (nil) the name of the autoscaling group def delete_autoscaling_group( options = {} ) raise ArgumentError, "No :autoscaling_group_name provided" if options[:autoscaling_group_name].nil? || options[:autoscaling_group_name].empty? params = { 'AutoScalingGroupName' => options[:autoscaling_group_name] } return response_generator(:action => "DeleteAutoScalingGroup", :params => params) end # Deletes the given Launch Configuration. # The launch configuration to be deleted must not be currently attached to any AutoScalingGroup. Once this call completes, the launch configuration is no longer available for use by any other API call. # # @option options [String] :launch_configuration_name (nil) the name of the launch_configuration def delete_launch_configuration( options = {} ) raise ArgumentError, "No :launch_configuration_name provided" if options[:launch_configuration_name].nil? || options[:launch_configuration_name].empty? params = { 'LaunchConfigurationName' => options[:launch_configuration_name] } return response_generator(:action => "DeleteLaunchConfiguration", :params => params) end # Deletes the given trigger # If a trigger is currently in progress, it will continue to run until its activities are complete. # # @option options [String] :trigger_name (nil) the name of the trigger to delete def delete_trigger( options = {} ) raise ArgumentError, "No :trigger_name provided" if options[:trigger_name].nil? || options[:trigger_name].empty? raise ArgumentError, "No :autoscaling_group_name provided" if options[:autoscaling_group_name].nil? || options[:autoscaling_group_name].empty? params = { 'TriggerName' => options[:trigger_name], 'AutoScalingGroupName' => options[:autoscaling_group_name] } return response_generator(:action => "DeleteTrigger", :params => params) end # Describe autoscaling group # Returns a full description of the AutoScalingGroups from the given list. This includes all EC2 instances that are members of the group. If a list of names is not provided, then the full details of all AutoScalingGroups is returned. This style conforms to the EC2 DescribeInstances API behavior. See key term AutoScalingGroup. # # @option options [Array] :autoscaling_group_names (nil) the name of the autoscaling groups to describe def describe_autoscaling_groups( options = {} ) options = { :autoscaling_group_names => [] }.merge(options) params = pathlist("AutoScalingGroupNames.member", options[:autoscaling_group_names]) return response_generator(:action => "DescribeAutoScalingGroups", :params => params) end # Describe launch configurations # Returns a full description of the launch configurations given the specified names. If no names are specified, then the full details of all launch configurations are returned. See key term Launch Configuration. # # @option options [Array] :launch_configuration_names (nil) the name of the launch_configurations to describe def describe_launch_configurations( options = {} ) options = { :launch_configuration_names => [] }.merge(options) params = pathlist("AutoScalingGroupNames.member", options[:launch_configuration_names]) params['MaxRecords'] = options[:max_records].to_s if options.has_key?(:max_records) return response_generator(:action => "DescribeLaunchConfigurations", :params => params) end # Describe autoscaling activities # Returns the scaling activities specified for the given group. If the input list is empty, all the activities from the past six weeks will be returned. Activities will be sorted by completion time. Activities that have no completion time will be considered as using the most recent possible time. See key term Scaling Activity. # # @option options [String] :autoscaling_group_name (nil) the name of the autoscaling_group_name # @option options [String] :max_records (nil) the maximum number of scaling activities to return # @option options [String] :launch_configuration_names (nil) activity_ids to return def describe_scaling_activities( options = {} ) raise ArgumentError, "No :autoscaling_group_name provided" if options[:autoscaling_group_name].nil? || options[:autoscaling_group_name].empty? params = {} params['AutoScalingGroupName'] = options[:autoscaling_group_name] params['MaxRecords'] = options[:max_records] if options.has_key?(:max_records) params['ActivityIds'] = options[:activity_ids] if options.has_key?(:activity_ids) return response_generator(:action => "DescribeScalingActivities", :params => params) end # Describe triggers # Returns a full description of the trigger (see Trigger), in the specified AutoScalingGroup. # # @option options [String] :autoscaling_group_name (nil) the name of the autoscaling_group_name def describe_triggers( options = {} ) raise ArgumentError, "No :autoscaling_group_name provided" if options[:autoscaling_group_name].nil? || options[:autoscaling_group_name].empty? params = {} params['AutoScalingGroupName'] = options[:autoscaling_group_name] return response_generator(:action => "DescribeTriggers", :params => params) end # Set desired capacity # This API adjusts the desired size of the AutoScalingGroup by initiating scaling activities, as necessary. When adjusting the size of the group downward, it is not possible to define which EC2 instances will be terminated. This applies to any auto-scaling decisions that might result in the termination of instances. # To check the scaling status of the system, query the desired capacity using DescribeAutoScalingGroups and then query the actual capacity using DescribeAutoScalingGroups and looking at the instance lifecycle state in order to understand how close the system is to the desired capacity at any given time. # # @option options [String] :autoscaling_group_name (nil) the name of the autoscaling_group_name # @option options [String] :desired_capacity (nil) the new capacity setting for the group def set_desired_capacity( options = {} ) raise ArgumentError, "No :autoscaling_group_name provided" if options[:autoscaling_group_name].nil? || options[:autoscaling_group_name].empty? raise ArgumentError, "No :desired_capacity provided" if options[:desired_capacity].nil? || options[:desired_capacity].empty? params = {} params['AutoScalingGroupName'] = options[:autoscaling_group_name] params['DesiredCapacity'] = options[:desired_capacity].to_s return response_generator(:action => "SetDesiredCapacity", :params => params) end # Terminate instance in an autoscaling group # This call will terminate the specified Instance. Optionally, the desired group size can be adjusted. If set to true, the default, the AutoScalingGroup size will decrease by one. If the AutoScalingGroup is associated with a LoadBalancer, the system will deregister the instance before terminating it. # This call simply registers a termination request. The termination of the instance can not happen immediately. # # @option options [String] :instance_id (nil) the instance id to terminate # @option options [String] :decrement_desired_capacity (nil) specified whether terminating this instance should also decrement the size of the autoscaling group def terminate_instance_in_autoscaling_group( options = {} ) raise ArgumentError, "No :instance_id provided" if options[:instance_id].nil? || options[:instance_id].empty? params = {} params['InstanceId'] = options[:instance_id] params['ShouldDecrementDesiredCapacity'] = options[:decrement_desired_capacity].to_s if options.has_key?(:decrement_desired_capacity) return response_generator(:action => "TerminateInstanceInAutoScalingGroup", :params => params) end # Creates a new AutoScalingGroup with the specified name. # Updates the configuration for the given AutoScalingGroup. If MaxSize is lower than the current size, then there will be an implicit call to SetDesiredCapacity to set the group to the new MaxSize. The same is true for MinSize there will also be an implicit call to SetDesiredCapacity. All optional parameters are left unchanged if not passed in the request.= # The new settings are registered upon the completion of this call. Any launch configuration settings will take effect on any triggers after this call returns. However, triggers that are currently in progress can not be affected. See key term Trigger. # # @option options [String] :autoscaling_group_name (nil) the name of the autoscaling group # @option options [Array] :availability_zones (nil) The availability_zones for the group # @option options [String] :launch_configuration_name (nil) the name of the launch_configuration group # @option options [String] :min_size (nil) minimum size of the group # @option options [String] :max_size (nil) the maximum size of the group # @option options [String] :cooldown (nil) the amount of time after a scaling activity complese before any further trigger-related scaling activities can start def update_autoscaling_group( options = {}) raise ArgumentError, "No :autoscaling_group_name provided" if options[:autoscaling_group_name].nil? || options[:autoscaling_group_name].empty? params = {} params.merge!(pathlist('AvailabilityZones.member', [options[:availability_zones]].flatten)) if options.has_key?(:availability_zones) params['LaunchConfigurationName'] = options[:launch_configuration_name] if options.has_key?(:launch_configuration_name) params['AutoScalingGroupName'] = options[:autoscaling_group_name] params['MinSize'] = options[:min_size] if options.has_key?(:min_size) params['MaxSize'] = options[:max_size] if options.has_key?(:max_size) params['Cooldown'] = options[:cooldown] if options.has_key?(:cooldown) return response_generator(:action => "UpdateAutoScalingGroup", :params => params) end end end end grempe-amazon-ec2-043f1b4/lib/AWS/Cloudwatch.rb000066400000000000000000000013031147233247500210770ustar00rootroot00000000000000module AWS module Cloudwatch # Which host FQDN will we connect to for all API calls to AWS? # If AWS_CLOUDWATCH_URL is defined in the users ENV we can override the default with that. # # @example # export AWS_CLOUDWATCH_URL='https://montoring.amazonaws.com' if ENV['AWS_CLOUDWATCH_URL'] AWS_CLOUDWATCH_URL = ENV['AWS_CLOUDWATCH_URL'] DEFAULT_HOST = URI.parse(AWS_CLOUDWATCH_URL).host else # Default US API endpoint DEFAULT_HOST = 'monitoring.amazonaws.com' end API_VERSION = '2009-05-15' class Base < AWS::Base def api_version API_VERSION end def default_host DEFAULT_HOST end end end endgrempe-amazon-ec2-043f1b4/lib/AWS/Cloudwatch/000077500000000000000000000000001147233247500205555ustar00rootroot00000000000000grempe-amazon-ec2-043f1b4/lib/AWS/Cloudwatch/monitoring.rb000066400000000000000000000113541147233247500232730ustar00rootroot00000000000000module AWS module Cloudwatch class Base < AWS::Base # This method call lists available Cloudwatch metrics attached to your EC2 # account. To get further information from the metrics, you'll then need to # call get_metric_statistics. # # there are no options available to this method. def list_metrics return response_generator(:action => 'ListMetrics', :params => {}) end # get_metric_statistics pulls a hashed array from Cloudwatch with the stats # of your requested metric. # Once you get the data out, if you assign the results into an object like: # res = @mon.get_metric_statistics(:measure_name => 'RequestCount', \ # :statistics => 'Average', :namespace => 'AWS/ELB') # # This call gets the average request count against your ELB at each sampling period # for the last 24 hours. You can then attach a block to the following iterator # to do whatever you need to: # res['GetMetricStatisticsResult']['Datapoints']['member'].each # # @option options [String] :custom_unit (nil) not currently available, placeholder # @option options [String] :dimensions (nil) Option to filter your data on. Check the developer guide # @option options [Time] :end_time (Time.now()) Outer bound of the date range you want to view # @option options [String] :measure_name (nil) The measure you want to check. Must correspond to # => provided options # @option options [String] :namespace ('AWS/EC2') The namespace of your measure_name. Currently, 'AWS/EC2' and 'AWS/ELB' are available # @option options [Integer] :period (60) Granularity in seconds of the returned datapoints. Multiples of 60 only # @option options [String] :statistics (nil) The statistics to be returned for your metric. See the developer guide for valid options. Required. # @option options [Time] :start_time (Time.now() - 86400) Inner bound of the date range you want to view. Defaults to 24 hours ago # @option options [String] :unit (nil) Standard unit for a given Measure. See the developer guide for valid options. def get_metric_statistics ( options ={} ) options = { :custom_unit => nil, :dimensions => nil, :end_time => Time.now(), #req :measure_name => "", #req :namespace => "AWS/EC2", :period => 60, :statistics => "", # req :start_time => (Time.now() - 86400), # Default to yesterday :unit => "" }.merge(options) raise ArgumentError, ":end_time must be provided" if options[:end_time].nil? raise ArgumentError, ":end_time must be a Time object" if options[:end_time].class != Time raise ArgumentError, ":start_time must be provided" if options[:start_time].nil? raise ArgumentError, ":start_time must be a Time object" if options[:start_time].class != Time raise ArgumentError, ":start_time must be before :end_time" if options[:start_time] > options[:end_time] raise ArgumentError, ":measure_name must be provided" if options[:measure_name].nil? || options[:measure_name].empty? raise ArgumentError, ":statistics must be provided" if options[:statistics].nil? || options[:statistics].empty? params = { "CustomUnit" => options[:custom_unit], "EndTime" => options[:end_time].iso8601, "MeasureName" => options[:measure_name], "Namespace" => options[:namespace], "Period" => options[:period].to_s, "StartTime" => options[:start_time].iso8601, "Unit" => options[:unit] } # FDT: Fix statistics and dimensions values if !(options[:statistics].nil? || options[:statistics].empty?) stats_params = {} i = 1 options[:statistics].split(',').each{ |stat| stats_params.merge!( "Statistics.member.#{i}" => "#{stat}" ) i += 1 } params.merge!( stats_params ) end if !(options[:dimensions].nil? || options[:dimensions].empty?) dims_params = {} i = 1 options[:dimensions].split(',').each{ |dimension| dimension_var = dimension.split('=') dims_params = dims_params.merge!( "Dimensions.member.#{i}.Name" => "#{dimension_var[0]}", "Dimensions.member.#{i}.Value" => "#{dimension_var[1]}" ) i += 1 } params.merge!( dims_params ) end return response_generator(:action => 'GetMetricStatistics', :params => params) end end end end grempe-amazon-ec2-043f1b4/lib/AWS/EC2.rb000066400000000000000000000011571147233247500173620ustar00rootroot00000000000000module AWS module EC2 # Which host FQDN will we connect to for all API calls to AWS? # If EC2_URL is defined in the users ENV we can override the default with that. # # @example # export EC2_URL='https://ec2.amazonaws.com' if ENV['EC2_URL'] EC2_URL = ENV['EC2_URL'] DEFAULT_HOST = URI.parse(EC2_URL).host else # Default US API endpoint DEFAULT_HOST = 'ec2.amazonaws.com' end API_VERSION = '2010-08-31' class Base < AWS::Base def api_version API_VERSION end def default_host DEFAULT_HOST end end end end grempe-amazon-ec2-043f1b4/lib/AWS/EC2/000077500000000000000000000000001147233247500170315ustar00rootroot00000000000000grempe-amazon-ec2-043f1b4/lib/AWS/EC2/availability_zones.rb000066400000000000000000000014641147233247500232530ustar00rootroot00000000000000module AWS module EC2 class Base < AWS::Base # The DescribeAvailabilityZones operation describes availability zones that are currently # available to the account and their states. # # An optional list of zone names can be passed. # # @option options [optional, String] :zone_name ([]) an Array of zone names # def describe_availability_zones( options = {} ) options = { :zone_name => [] }.merge(options) params = pathlist("ZoneName", options[:zone_name] ) return response_generator(:action => "DescribeAvailabilityZones", :params => params) end # Not yet implemented # # @todo Implement this method # def describe_regions( options = {} ) raise "Not yet implemented" end end end end grempe-amazon-ec2-043f1b4/lib/AWS/EC2/console.rb000066400000000000000000000016341147233247500210240ustar00rootroot00000000000000module AWS module EC2 class Base < AWS::Base # The GetConsoleOutput operation retrieves console output that has been posted for the specified instance. # # Instance console output is buffered and posted shortly after instance boot, reboot and once the instance # is terminated. Only the most recent 64 KB of posted output is available. Console output is available for # at least 1 hour after the most recent post. # # @option options [String] :instance_id ("") an Instance ID # def get_console_output( options = {} ) options = {:instance_id => ""}.merge(options) raise ArgumentError, "No instance ID provided" if options[:instance_id].nil? || options[:instance_id].empty? params = { "InstanceId" => options[:instance_id] } return response_generator(:action => "GetConsoleOutput", :params => params) end end end end grempe-amazon-ec2-043f1b4/lib/AWS/EC2/devpay.rb000066400000000000000000000003731147233247500206510ustar00rootroot00000000000000module AWS module EC2 class Base < AWS::Base # Not yet implemented # # @todo Implement this method # def confirm_product_instance( options = {} ) raise "Not yet implemented" end end end end grempe-amazon-ec2-043f1b4/lib/AWS/EC2/elastic_ips.rb000066400000000000000000000072611147233247500216630ustar00rootroot00000000000000module AWS module EC2 class Base < AWS::Base # The AllocateAddress operation acquires an elastic IP address for use with your account. # def allocate_address return response_generator(:action => "AllocateAddress") end # The AssociateAddress operation associates an elastic IP address with an instance. # # If the IP address is currently assigned to another instance, the IP address # is assigned to the new instance. This is an idempotent operation. If you enter # it more than once, Amazon EC2 does not return an error. # # @option options [String] :instance_id ('') the instance ID to associate an IP with. # @option options [String] :public_ip ('') the public IP to associate an instance with. # def associate_address( options = {} ) options = { :instance_id => '', :public_ip => '' }.merge(options) raise ArgumentError, "No ':instance_id' provided" if options[:instance_id].nil? || options[:instance_id].empty? raise ArgumentError, "No ':public_ip' provided" if options[:public_ip].nil? || options[:public_ip].empty? params = { "InstanceId" => options[:instance_id], "PublicIp" => options[:public_ip] } return response_generator(:action => "AssociateAddress", :params => params) end # The DescribeAddresses operation lists elastic IP addresses assigned to your account. # # @option options [Array] :public_ip ([]) an IP address to be described # def describe_addresses( options = {} ) options = { :public_ip => [] }.merge(options) params = pathlist("PublicIp", options[:public_ip]) return response_generator(:action => "DescribeAddresses", :params => params) end # The DisassociateAddress operation disassociates the specified elastic IP # address from the instance to which it is assigned. This is an idempotent # operation. If you enter it more than once, Amazon EC2 does not return # an error. # # @option options [String] :public_ip ('') the public IP to be dis-associated. # def disassociate_address( options = {} ) options = { :public_ip => '' }.merge(options) raise ArgumentError, "No ':public_ip' provided" if options[:public_ip].nil? || options[:public_ip].empty? params = { "PublicIp" => options[:public_ip] } return response_generator(:action => "DisassociateAddress", :params => params) end # The ReleaseAddress operation releases an elastic IP address associated with your account. # # If you run this operation on an elastic IP address that is already released, the address # might be assigned to another account which will cause Amazon EC2 to return an error. # # Note : Releasing an IP address automatically disassociates it from any instance # with which it is associated. For more information, see DisassociateAddress. # # Important! After releasing an elastic IP address, it is released to the IP # address pool and might no longer be available to your account. Make sure # to update your DNS records and any servers or devices that communicate # with the address. # # @option options [String] :public_ip ('') an IP address to be released. # def release_address( options = {} ) options = { :public_ip => '' }.merge(options) raise ArgumentError, "No ':public_ip' provided" if options[:public_ip].nil? || options[:public_ip].empty? params = { "PublicIp" => options[:public_ip] } return response_generator(:action => "ReleaseAddress", :params => params) end end end end grempe-amazon-ec2-043f1b4/lib/AWS/EC2/image_attributes.rb000066400000000000000000000133141147233247500227100ustar00rootroot00000000000000module AWS module EC2 class Base < AWS::Base # The ModifyImageAttribute operation modifies an attribute of an AMI. The following attributes may # currently be modified: # # 'launchPermission' : Controls who has permission to launch the AMI. Launch permissions can be # granted to specific users by adding userIds. The AMI can be made public by adding the 'all' group. # # 'productCodes' : Associates product codes with AMIs. This allows a developer to charge a user extra # for using the AMIs. productCodes is a write once attribute - once it has been set it can not be # changed or removed. Currently only one product code is supported per AMI. # # @option options [String] :image_id ("") # @option options [String] :attribute ("launchPermission") An attribute to modify, "launchPermission" or "productCodes" # @option options [String] :operation_type ("") # @option options [optional, Array] :user_id ([]) # @option options [optional, Array] :group ([]) # @option options [optional, Array] :product_code ([]) # def modify_image_attribute( options = {} ) # defaults options = { :image_id => "", :attribute => "launchPermission", :operation_type => "", :user_id => [], :group => [], :product_code => [] }.merge(options) raise ArgumentError, "No ':image_id' provided" if options[:image_id].nil? || options[:image_id].empty? raise ArgumentError, "No ':attribute' provided" if options[:attribute].nil? || options[:attribute].empty? # OperationType is not required if modifying a product code. unless options[:attribute] == 'productCodes' raise ArgumentError, "No ':operation_type' provided" if options[:operation_type].nil? || options[:operation_type].empty? end params = { "ImageId" => options[:image_id], "Attribute" => options[:attribute], "OperationType" => options[:operation_type] } # test options provided and make sure they are valid case options[:attribute] when "launchPermission" unless options[:operation_type] == "add" || options[:operation_type] == "remove" raise ArgumentError, ":operation_type was #{options[:operation_type].to_s} but must be either 'add' or 'remove'" end if (options[:user_id].nil? || options[:user_id].empty?) && (options[:group].nil? || options[:group].empty?) raise ArgumentError, "Option :attribute=>'launchPermission' requires ':user_id' or ':group' options to also be specified" end params.merge!(pathlist("UserId", options[:user_id])) unless options[:user_id].nil? params.merge!(pathlist("Group", options[:group])) unless options[:group].nil? when "productCodes" if (options[:product_code].nil? || options[:product_code].empty?) raise ArgumentError, "Option :attribute=>'productCodes' requires ':product_code' to be specified" end params.merge!(pathlist("ProductCode", options[:product_code])) unless options[:product_code].nil? else raise ArgumentError, "attribute : #{options[:attribute].to_s} is not an known attribute." end return response_generator(:action => "ModifyImageAttribute", :params => params) end # The DescribeImageAttribute operation returns information about an attribute of an AMI. # # @option options [String] :image_id ("") # @option options [String] :attribute ("launchPermission") An attribute to describe, "launchPermission" or "productCodes" # def describe_image_attribute( options = {} ) # defaults options = {:image_id => "", :attribute => "launchPermission" }.merge(options) raise ArgumentError, "No ':image_id' provided" if options[:image_id].nil? || options[:image_id].empty? raise ArgumentError, "No ':attribute' provided" if options[:attribute].nil? || options[:attribute].empty? params = { "ImageId" => options[:image_id], "Attribute" => options[:attribute] } # test options provided and make sure they are valid case options[:attribute] when "launchPermission", "productCodes" # these args are ok else raise ArgumentError, "attribute : #{options[:attribute].to_s} is not an known attribute." end return response_generator(:action => "DescribeImageAttribute", :params => params) end # The ResetImageAttribute operation resets an attribute of an AMI to its default value. # # @option options [String] :image_id ("") # @option options [String] :attribute ("launchPermission") An attribute to reset # def reset_image_attribute( options = {} ) # defaults options = {:image_id => "", :attribute => "launchPermission"}.merge(options) raise ArgumentError, "No ':image_id' provided" if options[:image_id].nil? || options[:image_id].empty? raise ArgumentError, "No ':attribute' provided" if options[:attribute].nil? || options[:attribute].empty? params = {"ImageId" => options[:image_id], "Attribute" => options[:attribute] } # test options provided and make sure they are valid case options[:attribute] when "launchPermission" # these args are ok else raise ArgumentError, "attribute : #{options[:attribute].to_s} is not an known attribute." end return response_generator(:action => "ResetImageAttribute", :params => params) end end end endgrempe-amazon-ec2-043f1b4/lib/AWS/EC2/images.rb000066400000000000000000000224371147233247500206330ustar00rootroot00000000000000module AWS module EC2 class Base < AWS::Base # Creates an AMI that uses an Amazon EBS root device from a "running" or "stopped" instance. # # AMIs that use an Amazon EBS root device boot faster than AMIs that use instance stores. # They can be up to 1 TiB in size, use storage that persists on instance failure, and can be # stopped and started. # # @option options [String] :instance_id ("") The ID of the instance. # @option options [String] :name ("") The name of the AMI that was provided during image creation. Constraints 3-128 alphanumeric characters, parenthesis (()), commas (,), slashes (/), dashes (-), or underscores(_) # @option options [optional,String] :description ("") The description of the AMI that was provided during image creation. # @option options [optional,Boolean] :no_reboot (false) By default this property is set to false, which means Amazon EC2 attempts to cleanly shut down the instance before image creation and reboots the instance afterwards. When set to true, Amazon EC2 does not shut down the instance before creating the image. When this option is used, file system integrity on the created image cannot be guaranteed. # def create_image( options = {} ) options = { :instance_id => "", :name => "" }.merge(options) raise ArgumentError, "No :instance_id provided" if options.does_not_have? :instance_id raise ArgumentError, "No :name provided" if options.does_not_have? :name raise ArgumentError, "Invalid string length for :name provided" if options[:name] && options[:name].size < 3 || options[:name].size > 128 raise ArgumentError, "Invalid string length for :description provided (too long)" if options[:description] && options[:description].size > 255 raise ArgumentError, ":no_reboot option must be a Boolean" unless options[:no_reboot].nil? || [true, false].include?(options[:no_reboot]) params = {} params["InstanceId"] = options[:instance_id].to_s params["Name"] = options[:name].to_s params["Description"] = options[:description].to_s params["NoReboot"] = options[:no_reboot].to_s return response_generator(:action => "CreateImage", :params => params) end # The DeregisterImage operation deregisters an AMI. Once deregistered, instances of the AMI may no # longer be launched. # # @option options [String] :image_id ("") # def deregister_image( options = {} ) options = { :image_id => "" }.merge(options) raise ArgumentError, "No :image_id provided" if options[:image_id].nil? || options[:image_id].empty? params = { "ImageId" => options[:image_id] } return response_generator(:action => "DeregisterImage", :params => params) end # Registers an AMI with Amazon EC2. Images must be registered before they can be launched. # To launch instances, use the RunInstances operation. Each AMI is associated with an unique ID # which is provided by the Amazon EC2 service through this operation. If needed, you can deregister # an AMI at any time. # # AMIs backed by Amazon EBS are automatically registered when you create the image. # However, you can use this to register a snapshot of an instance backed by Amazon EBS. # # Amazon EBS snapshots are not guaranteed to be bootable. For information on creating AMIs # backed by Amazon EBS, go to the Amazon Elastic Compute Cloud Developer Guide or Amazon # Elastic Compute Cloud User Guide. # # Any modifications to an AMI backed by Amazon S3 invalidates this registration. # If you make changes to an image, deregister the previous image and register the new image. # # If an :image_location is specified then an old-style S3-backed AMI is created. If the other # parameters are used then a new style EBS-backed AMI is created from a pre-existing snapshot. # # @option options [optional, String] :image_location ("") S3 URL for the XML manifest # @option options [optional, String] :name ("") Name of EBS image # @option options [optional, String] :description ("") Description of EBS image # @option options [optional, String] :architecture ("") Architecture of EBS image, currently 'i386' or 'x86_64' # @option options [optional, String] :kernel_id ("") Kernel ID of EBS image # @option options [optional, String] :ramdisk_id ("") Ramdisk ID of EBS image # @option options [optional, String] :root_device_name ("") Root device name of EBS image, eg '/dev/sda1' # @option options [optional, Array] :block_device_mapping ([]) An array of Hashes representing the elements of the block device mapping. e.g. [{:device_name => '/dev/sdh', :virtual_name => '', :ebs_snapshot_id => '', :ebs_volume_size => '', :ebs_delete_on_termination => ''},{},...] # def register_image( options = {} ) params = {} if options.does_not_have?(:image_location) && options.does_not_have?(:root_device_name) raise ArgumentError, "No :image_location or :root_device_name" end params["ImageLocation"] = options[:image_location].to_s unless options[:image_location].nil? params["Name"] = options[:name].to_s unless options[:name].nil? params["Description"] = options[:description].to_s unless options[:description].nil? params["Architecture"] = options[:architecture].to_s unless options[:architecture].nil? params["KernelId"] = options[:kernel_id].to_s unless options[:kernel_id].nil? params["RamdiskId"] = options[:ramdisk_id].to_s unless options[:ramdisk_id].nil? params["RootDeviceName"] = options[:root_device_name].to_s unless options[:root_device_name].nil? if options[:block_device_mapping] params.merge!(pathhashlist("BlockDeviceMapping", options[:block_device_mapping].flatten, { :device_name => "DeviceName", :virtual_name => "VirtualName", :ebs_snapshot_id => "Ebs.SnapshotId", :ebs_volume_size => "Ebs.VolumeSize", :ebs_delete_on_termination => "Ebs.DeleteOnTermination" })) end return response_generator(:action => "RegisterImage", :params => params) end # The DescribeImages operation returns information about AMIs available for use by the user. This # includes both public AMIs (those available for any user to launch) and private AMIs (those owned by # the user making the request and those owned by other users that the user making the request has explicit # launch permissions for). # # The list of AMIs returned can be modified via optional lists of AMI IDs, owners or users with launch # permissions. If all three optional lists are empty all AMIs the user has launch permissions for are # returned. Launch permissions fall into three categories: # # Launch Permission Description # # public - The all group has launch permissions for the AMI. All users have launch permissions for these AMIs. # explicit - The owner of the AMIs has granted a specific user launch permissions for the AMI. # implicit - A user has implicit launch permissions for all AMIs he or she owns. # # If one or more of the lists are specified the result set is the intersection of AMIs matching the criteria of # the individual lists. # # Providing the list of AMI IDs requests information for those AMIs only. If no AMI IDs are provided, # information of all relevant AMIs will be returned. If an AMI is specified that does not exist a fault is # returned. If an AMI is specified that exists but the user making the request does not have launch # permissions for, then that AMI will not be included in the returned results. # # Providing the list of owners requests information for AMIs owned by the specified owners only. Only # AMIs the user has launch permissions for are returned. The items of the list may be account ids for # AMIs owned by users with those account ids, amazon for AMIs owned by Amazon or self for AMIs # owned by the user making the request. # # The executable list may be provided to request information for AMIs that only the specified users have # launch permissions for. The items of the list may be account ids for AMIs owned by the user making the # request that the users with the specified account ids have explicit launch permissions for, self for AMIs # the user making the request has explicit launch permissions for or all for public AMIs. # # Deregistered images will be included in the returned results for an unspecified interval subsequent to # deregistration. # # @option options [Array] :image_id ([]) # @option options [Array] :owner_id ([]) # @option options [Array] :executable_by ([]) # def describe_images( options = {} ) options = { :image_id => [], :owner_id => [], :executable_by => [] }.merge(options) params = pathlist( "ImageId", options[:image_id] ) params.merge!(pathlist( "Owner", options[:owner_id] )) params.merge!(pathlist( "ExecutableBy", options[:executable_by] )) return response_generator(:action => "DescribeImages", :params => params) end end end end grempe-amazon-ec2-043f1b4/lib/AWS/EC2/instances.rb000066400000000000000000000416041147233247500213520ustar00rootroot00000000000000module AWS module EC2 class Base < AWS::Base # Launches a specified number of instances of an AMI for which you have permissions. # # Amazon API Docs : HTML[http://docs.amazonwebservices.com/AWSEC2/2009-10-31/APIReference/index.html?ApiReference-query-RunInstances.html] # # @option options [String] :image_id ("") Unique ID of a machine image. # @option options [Integer] :min_count (1) Minimum number of instances to launch. If the value is more than Amazon EC2 can launch, no instances are launched at all. # @option options [Integer] :max_count (1) Maximum number of instances to launch. If the value is more than Amazon EC2 can launch, the largest possible number above minCount will be launched instead. # @option options [optional, String] :key_name (nil) The name of the key pair. # @option options [optional, Array] :security_group (nil) Name of the security group(s). Array of Strings or String. # @option options [optional, String] :additional_info (nil) Specifies additional information to make available to the instance(s). # @option options [optional, String] :user_data (nil) MIME, Base64-encoded user data. # @option options [optional, String] :instance_type (nil) Specifies the instance type. # @option options [optional, String] :availability_zone (nil) Specifies the placement constraints (Availability Zones) for launching the instances. # @option options [optional, String] :kernel_id (nil) The ID of the kernel with which to launch the instance. # @option options [optional, String] :ramdisk_id (nil) The ID of the RAM disk with which to launch the instance. Some kernels require additional drivers at launch. Check the kernel requirements for information on whether you need to specify a RAM disk. To find kernel requirements, go to the Resource Center and search for the kernel ID. # @option options [optional, Array] :block_device_mapping ([]) An array of Hashes representing the elements of the block device mapping. e.g. [{:device_name => '/dev/sdh', :virtual_name => '', :ebs_snapshot_id => '', :ebs_volume_size => '', :ebs_delete_on_termination => ''},{},...] # @option options [optional, Boolean] :monitoring_enabled (false) Enables monitoring for the instance. # @option options [optional, String] :subnet_id (nil) Specifies the Amazon VPC subnet ID within which to launch the instance(s) for Amazon Virtual Private Cloud. # @option options [optional, Boolean] :disable_api_termination (true) Specifies whether the instance can be terminated using the APIs. You must modify this attribute before you can terminate any "locked" instances from the APIs. # @option options [optional, String] :instance_initiated_shutdown_behavior ('stop') Specifies whether the instance's Amazon EBS volumes are stopped or terminated when the instance is shut down. Valid values : 'stop', 'terminate' # @option options [optional, Boolean] :base64_encoded (false) # def run_instances( options = {} ) options = { :image_id => "", :min_count => 1, :max_count => 1, :base64_encoded => false }.merge(options) raise ArgumentError, ":addressing_type has been deprecated." if options[:addressing_type] raise ArgumentError, ":group_id has been deprecated." if options[:group_id] raise ArgumentError, ":image_id must be provided" if options[:image_id].nil? || options[:image_id].empty? raise ArgumentError, ":min_count is not valid" unless options[:min_count].to_i > 0 raise ArgumentError, ":max_count is not valid or must be >= :min_count" unless options[:max_count].to_i > 0 && options[:max_count].to_i >= options[:min_count].to_i raise ArgumentError, ":instance_type must specify a valid instance type" unless options[:instance_type].nil? || ["t1.micro", "m1.small", "m1.large", "m1.xlarge", "m2.xlarge", "c1.medium", "c1.xlarge", "m2.2xlarge", "m2.4xlarge", "cc1.4xlarge"].include?(options[:instance_type]) raise ArgumentError, ":monitoring_enabled must be 'true' or 'false'" unless options[:monitoring_enabled].nil? || [true, false].include?(options[:monitoring_enabled]) raise ArgumentError, ":disable_api_termination must be 'true' or 'false'" unless options[:disable_api_termination].nil? || [true, false].include?(options[:disable_api_termination]) raise ArgumentError, ":instance_initiated_shutdown_behavior must be 'stop' or 'terminate'" unless options[:instance_initiated_shutdown_behavior].nil? || ["stop", "terminate"].include?(options[:instance_initiated_shutdown_behavior]) raise ArgumentError, ":base64_encoded must be 'true' or 'false'" unless [true, false].include?(options[:base64_encoded]) user_data = extract_user_data(options) params = {} if options[:security_group] params.merge!(pathlist("SecurityGroup", options[:security_group])) end if options[:block_device_mapping] params.merge!(pathhashlist('BlockDeviceMapping', options[:block_device_mapping].flatten, {:device_name => 'DeviceName', :virtual_name => 'VirtualName', :ebs_snapshot_id => 'Ebs.SnapshotId', :ebs_volume_size => 'Ebs.VolumeSize', :ebs_delete_on_termination => 'Ebs.DeleteOnTermination' })) end params["ImageId"] = options[:image_id] params["MinCount"] = options[:min_count].to_s params["MaxCount"] = options[:max_count].to_s params["KeyName"] = options[:key_name] unless options[:key_name].nil? params["AdditionalInfo"] = options[:additional_info] unless options[:additional_info].nil? params["UserData"] = user_data unless user_data.nil? params["InstanceType"] = options[:instance_type] unless options[:instance_type].nil? params["Placement.AvailabilityZone"] = options[:availability_zone] unless options[:availability_zone].nil? params["KernelId"] = options[:kernel_id] unless options[:kernel_id].nil? params["RamdiskId"] = options[:ramdisk_id] unless options[:ramdisk_id].nil? params["Monitoring.Enabled"] = options[:monitoring_enabled].to_s unless options[:monitoring_enabled].nil? params["SubnetId"] = options[:subnet_id] unless options[:subnet_id].nil? params["DisableApiTermination"] = options[:disable_api_termination].to_s unless options[:disable_api_termination].nil? params["InstanceInitiatedShutdownBehavior"] = options[:instance_initiated_shutdown_behavior] unless options[:instance_initiated_shutdown_behavior].nil? return response_generator(:action => "RunInstances", :params => params) end # The DescribeInstances operation returns information about instances owned by the user # making the request. # # An optional list of instance IDs may be provided to request information for those instances only. If no # instance IDs are provided, information of all relevant instances information will be returned. If an # instance is specified that does not exist a fault is returned. If an instance is specified that exists but is not # owned by the user making the request, then that instance will not be included in the returned results. # # Recently terminated instances will be included in the returned results for a small interval subsequent to # their termination. This interval is typically of the order of one hour # # @option options [Array] :instance_id ([]) # def describe_instances( options = {} ) options = { :instance_id => [] }.merge(options) params = pathlist("InstanceId", options[:instance_id]) return response_generator(:action => "DescribeInstances", :params => params) end # Returns information about an attribute of an instance. # # @option options [String] :instance_id (nil) ID of the instance on which the attribute will be queried. # @option options [String] :attribute (nil) Specifies the attribute to query.. # def describe_instance_attribute( options = {} ) raise ArgumentError, "No :instance_id provided" if options[:instance_id].nil? || options[:instance_id].empty? raise ArgumentError, "No :attribute provided" if options[:attribute].nil? || options[:attribute].empty? valid_attributes = %w(instanceType kernel ramdisk userData disableApiTermination instanceInitiatedShutdownBehavior rootDevice blockDeviceMapping) raise ArgumentError, "Invalid :attribute provided" unless valid_attributes.include?(options[:attribute].to_s) params = {} params["InstanceId"] = options[:instance_id] params["Attribute"] = options[:attribute] return response_generator(:action => "DescribeInstanceAttribute", :params => params) end # Modifies an attribute of an instance. # # @option options [String] :instance_id (nil) ID of the instance on which the attribute will be modified. # @option options [String] :attribute (nil) Specifies the attribute to modify. # @option options [String] :value (nil) The value of the attribute being modified. # def modify_instance_attribute( options = {} ) raise ArgumentError, "No :instance_id provided" if options[:instance_id].nil? || options[:instance_id].empty? raise ArgumentError, "No :attribute provided" if options[:attribute].nil? || options[:attribute].empty? raise ArgumentError, "No :value provided" if options[:value].nil? valid_attributes = %w(instanceType kernel ramdisk userData disableApiTermination instanceInitiatedShutdownBehavior rootDevice blockDeviceMapping) raise ArgumentError, "Invalid :attribute provided" unless valid_attributes.include?(options[:attribute].to_s) params = {} params["InstanceId"] = options[:instance_id] params["Attribute"] = options[:attribute] params["Value"] = options[:value].to_s return response_generator(:action => "ModifyInstanceAttribute", :params => params) end # Resets an attribute of an instance to its default value. # # @option options [String] :instance_id (nil) ID of the instance on which the attribute will be reset. # @option options [String] :attribute (nil) The instance attribute to reset to the default value. # def reset_instance_attribute( options = {} ) raise ArgumentError, "No :instance_id provided" if options[:instance_id].nil? || options[:instance_id].empty? raise ArgumentError, "No :attribute provided" if options[:attribute].nil? || options[:attribute].empty? valid_attributes = %w(kernel ramdisk) raise ArgumentError, "Invalid :attribute provided" unless valid_attributes.include?(options[:attribute].to_s) params = {} params["InstanceId"] = options[:instance_id] params["Attribute"] = options[:attribute] return response_generator(:action => "ResetInstanceAttribute", :params => params) end # Starts an instance that uses an Amazon EBS volume as its root device. # # @option options [Array] :instance_id ([]) Array of unique instance ID's of stopped instances. # def start_instances( options = {} ) options = { :instance_id => [] }.merge(options) raise ArgumentError, "No :instance_id provided" if options[:instance_id].nil? || options[:instance_id].empty? params = {} params.merge!(pathlist("InstanceId", options[:instance_id])) return response_generator(:action => "StartInstances", :params => params) end # Stops an instance that uses an Amazon EBS volume as its root device. # # @option options [Array] :instance_id ([]) Unique instance ID of a running instance. # @option options [optional, Boolean] :force (false) Forces the instance to stop. The instance will not have an opportunity to flush file system caches nor file system meta data. If you use this option, you must perform file system check and repair procedures. This option is not recommended for Windows instances. # def stop_instances( options = {} ) options = { :instance_id => [] }.merge(options) raise ArgumentError, "No :instance_id provided" if options[:instance_id].nil? || options[:instance_id].empty? raise ArgumentError, ":force must be 'true' or 'false'" unless options[:force].nil? || [true, false].include?(options[:force]) params = {} params.merge!(pathlist("InstanceId", options[:instance_id])) params["Force"] = options[:force].to_s unless options[:force].nil? return response_generator(:action => "StopInstances", :params => params) end # The RebootInstances operation requests a reboot of one or more instances. This operation is # asynchronous; it only queues a request to reboot the specified instance(s). The operation will succeed # provided the instances are valid and belong to the user. Terminated instances will be ignored. # # @option options [Array] :instance_id ([]) # def reboot_instances( options = {} ) options = { :instance_id => [] }.merge(options) raise ArgumentError, "No instance IDs provided" if options[:instance_id].nil? || options[:instance_id].empty? params = pathlist("InstanceId", options[:instance_id]) return response_generator(:action => "RebootInstances", :params => params) end # The TerminateInstances operation shuts down one or more instances. This operation is idempotent # and terminating an instance that is in the process of shutting down (or already terminated) will succeed. # Terminated instances remain visible for a short period of time (approximately one hour) after # termination, after which their instance ID is invalidated. # # @option options [Array] :instance_id ([]) # def terminate_instances( options = {} ) options = { :instance_id => [] }.merge(options) raise ArgumentError, "No :instance_id provided" if options[:instance_id].nil? || options[:instance_id].empty? params = pathlist("InstanceId", options[:instance_id]) return response_generator(:action => "TerminateInstances", :params => params) end # The MonitorInstances operation tells Cloudwatch to begin logging metrics from one or more EC2 instances # # @option options [Array] :instance_id ([]) # def monitor_instances( options = {} ) options = { :instance_id => [] }.merge(options) raise ArgumentError, "No :instance_id provided" if options[:instance_id].nil? || options[:instance_id].empty? params = pathlist("InstanceId", options[:instance_id]) return response_generator(:action => "MonitorInstances", :params => params) end # The UnmonitorInstances operation tells Cloudwatch to stop logging metrics from one or more EC2 instances # # @option options [Array] :instance_id ([]) # def unmonitor_instances( options = {} ) options = { :instance_id => [] }.merge(options) raise ArgumentError, "No :instance_id provided" if options[:instance_id].nil? || options[:instance_id].empty? params = pathlist("InstanceId", options[:instance_id]) return response_generator(:action => "UnmonitorInstances", :params => params) end # Not yet implemented # # @todo Implement this method # def describe_reserved_instances( options = {} ) raise "Not yet implemented" end # Not yet implemented # # @todo Implement this method # def describe_reserved_instances_offerings( options = {} ) raise "Not yet implemented" end # Not yet implemented # # @todo Implement this method # def purchase_reserved_instances_offering( options = {} ) raise "Not yet implemented" end end # # A set of methods for querying amazon's ec2 meta-data service. # Note : This can ONLY be run on an actual running EC2 instance. # # Example Class Method Usage : # instance_id = AWS::EC2::Instance.local_instance_id # class Instance EC2_META_URL_BASE = 'http://169.254.169.254/latest/meta-data/' # # Returns the current instance-id when called from a host within EC2. # def self.local_instance_id Net::HTTP.get URI.parse(EC2_META_URL_BASE + 'instance-id') end # # Returns a hash of all available instance meta data. # def self.local_instance_meta_data meta_data = {} Net::HTTP.get(URI.parse(EC2_META_URL_BASE)).split("\n").each do |meta_type| meta_data.merge!({meta_type => Net::HTTP.get(URI.parse(EC2_META_URL_BASE + meta_type)) }) end return meta_data end end end end grempe-amazon-ec2-043f1b4/lib/AWS/EC2/keypairs.rb000066400000000000000000000032501147233247500212050ustar00rootroot00000000000000module AWS module EC2 class Base < AWS::Base # The CreateKeyPair operation creates a new 2048 bit RSA keypair and returns a unique ID that can be # used to reference this keypair when launching new instances. # # @option options [String] :key_name ("") # def create_keypair( options = {} ) options = { :key_name => "" }.merge(options) raise ArgumentError, "No :key_name provided" if options[:key_name].nil? || options[:key_name].empty? params = { "KeyName" => options[:key_name] } return response_generator(:action => "CreateKeyPair", :params => params) end # The DescribeKeyPairs operation returns information about keypairs available for use by the user # making the request. Selected keypairs may be specified or the list may be left empty if information for # all registered keypairs is required. # # @option options [Array] :key_name ([]) # def describe_keypairs( options = {} ) options = { :key_name => [] }.merge(options) params = pathlist("KeyName", options[:key_name] ) return response_generator(:action => "DescribeKeyPairs", :params => params) end # The DeleteKeyPair operation deletes a keypair. # # @option options [String] :key_name ("") # def delete_keypair( options = {} ) options = { :key_name => "" }.merge(options) raise ArgumentError, "No :key_name provided" if options[:key_name].nil? || options[:key_name].empty? params = { "KeyName" => options[:key_name] } return response_generator(:action => "DeleteKeyPair", :params => params) end end end end grempe-amazon-ec2-043f1b4/lib/AWS/EC2/password.rb000066400000000000000000000012011147233247500212120ustar00rootroot00000000000000module AWS module EC2 class Base < AWS::Base # The GetPasswordData operation retrieves the encrypted administrator password for the instances running Window. # # @option options [String] :instance_id ("") an Instance ID # def get_password_data( options = {} ) options = {:instance_id => ""}.merge(options) raise ArgumentError, "No instance ID provided" if options[:instance_id].nil? || options[:instance_id].empty? params = { "InstanceId" => options[:instance_id] } return response_generator(:action => "GetPasswordData", :params => params) end end end end grempe-amazon-ec2-043f1b4/lib/AWS/EC2/products.rb000066400000000000000000000017121147233247500212220ustar00rootroot00000000000000module AWS module EC2 class Base < AWS::Base # The ConfirmProductInstance operation returns true if the given product code is attached to the instance # with the given instance id. False is returned if the product code is not attached to the instance. # # @option options [String] :product_code ("") # @option options [String] :instance_id ("") # def confirm_product_instance( options ={} ) options = {:product_code => "", :instance_id => ""}.merge(options) raise ArgumentError, "No product code provided" if options[:product_code].nil? || options[:product_code].empty? raise ArgumentError, "No instance ID provided" if options[:instance_id].nil? || options[:instance_id].empty? params = { "ProductCode" => options[:product_code], "InstanceId" => options[:instance_id] } return response_generator(:action => "ConfirmProductInstance", :params => params) end end end endgrempe-amazon-ec2-043f1b4/lib/AWS/EC2/security_groups.rb000066400000000000000000000217661147233247500226400ustar00rootroot00000000000000module AWS module EC2 class Base < AWS::Base # The CreateSecurityGroup operation creates a new security group. Every instance is launched # in a security group. If none is specified as part of the launch request then instances # are launched in the default security group. Instances within the same security group have # unrestricted network access to one another. Instances will reject network access attempts from other # instances in a different security group. As the owner of instances you may grant or revoke specific # permissions using the AuthorizeSecurityGroupIngress and RevokeSecurityGroupIngress operations. # # @option options [String] :group_name ("") # @option options [String] :group_description ("") # def create_security_group( options = {} ) options = {:group_name => "", :group_description => "" }.merge(options) raise ArgumentError, "No :group_name provided" if options[:group_name].nil? || options[:group_name].empty? raise ArgumentError, "No :group_description provided" if options[:group_description].nil? || options[:group_description].empty? params = { "GroupName" => options[:group_name], "GroupDescription" => options[:group_description] } return response_generator(:action => "CreateSecurityGroup", :params => params) end # The DescribeSecurityGroups operation returns information about security groups owned by the # user making the request. # # An optional list of security group names may be provided to request information for those security # groups only. If no security group names are provided, information of all security groups will be # returned. If a group is specified that does not exist an exception is returned. # # @option options [optional, Array] :group_name ([]) # def describe_security_groups( options = {} ) options = { :group_name => [] }.merge(options) params = pathlist("GroupName", options[:group_name] ) return response_generator(:action => "DescribeSecurityGroups", :params => params) end # The DeleteSecurityGroup operation deletes a security group. # # If an attempt is made to delete a security group and any instances exist that are members of that group a # fault is returned. # # @option options [String] :group_name ("") # def delete_security_group( options = {} ) options = { :group_name => "" }.merge(options) raise ArgumentError, "No :group_name provided" if options[:group_name].nil? || options[:group_name].empty? params = { "GroupName" => options[:group_name] } return response_generator(:action => "DeleteSecurityGroup", :params => params) end # The AuthorizeSecurityGroupIngress operation adds permissions to a security group. # # Permissions are specified in terms of the IP protocol (TCP, UDP or ICMP), the source of the request (by # IP range or an Amazon EC2 user-group pair), source and destination port ranges (for TCP and UDP), # and ICMP codes and types (for ICMP). When authorizing ICMP, -1 may be used as a wildcard in the # type and code fields. # # Permission changes are propagated to instances within the security group being modified as quickly as # possible. However, a small delay is likely, depending on the number of instances that are members of # the indicated group. # # When authorizing a user/group pair permission, GroupName, SourceSecurityGroupName and # SourceSecurityGroupOwnerId must be specified. When authorizing a CIDR IP permission, # GroupName, IpProtocol, FromPort, ToPort and CidrIp must be specified. Mixing these two types # of parameters is not allowed. # # @option options [String] :group_name ("") # @option options [optional, String] :ip_protocol (nil) Required when authorizing CIDR IP permission # @option options [optional, Integer] :from_port (nil) Required when authorizing CIDR IP permission # @option options [optional, Integer] :to_port (nil) Required when authorizing CIDR IP permission # @option options [optional, String] :cidr_ip (nil) Required when authorizing CIDR IP permission # @option options [optional, String] :source_security_group_name (nil) Required when authorizing user group pair permissions # @option options [optional, String] :source_security_group_owner_id (nil) Required when authorizing user group pair permissions # def authorize_security_group_ingress( options = {} ) options = { :group_name => nil, :ip_protocol => nil, :from_port => nil, :to_port => nil, :cidr_ip => nil, :source_security_group_name => nil, :source_security_group_owner_id => nil }.merge(options) # lets not validate the rest of the possible permutations of required params and instead let # EC2 sort it out on the server side. We'll only require :group_name as that is always needed. raise ArgumentError, "No :group_name provided" if options[:group_name].nil? || options[:group_name].empty? params = { "GroupName" => options[:group_name], "IpProtocol" => options[:ip_protocol], "FromPort" => options[:from_port].to_s, "ToPort" => options[:to_port].to_s, "CidrIp" => options[:cidr_ip], "SourceSecurityGroupName" => options[:source_security_group_name], "SourceSecurityGroupOwnerId" => options[:source_security_group_owner_id] } return response_generator(:action => "AuthorizeSecurityGroupIngress", :params => params) end # The RevokeSecurityGroupIngress operation revokes existing permissions that were previously # granted to a security group. The permissions to revoke must be specified using the same values # originally used to grant the permission. # # Permissions are specified in terms of the IP protocol (TCP, UDP or ICMP), the source of the request (by # IP range or an Amazon EC2 user-group pair), source and destination port ranges (for TCP and UDP), # and ICMP codes and types (for ICMP). When authorizing ICMP, -1 may be used as a wildcard in the # type and code fields. # # Permission changes are propagated to instances within the security group being modified as quickly as # possible. However, a small delay is likely, depending on the number of instances that are members of # the indicated group. # # When revoking a user/group pair permission, GroupName, SourceSecurityGroupName and # SourceSecurityGroupOwnerId must be specified. When authorizing a CIDR IP permission, # GroupName, IpProtocol, FromPort, ToPort and CidrIp must be specified. Mixing these two types # of parameters is not allowed. # # @option options [String] :group_name ("") # @option options [optional, String] :ip_protocol (nil) Required when revoking CIDR IP permission # @option options [optional, Integer] :from_port (nil) Required when revoking CIDR IP permission # @option options [optional, Integer] :to_port (nil) Required when revoking CIDR IP permission # @option options [optional, String] :cidr_ip (nil) Required when revoking CIDR IP permission # @option options [optional, String] :source_security_group_name (nil) Required when revoking user group pair permissions # @option options [optional, String] :source_security_group_owner_id (nil) Required when revoking user group pair permissions # def revoke_security_group_ingress( options = {} ) options = { :group_name => nil, :ip_protocol => nil, :from_port => nil, :to_port => nil, :cidr_ip => nil, :source_security_group_name => nil, :source_security_group_owner_id => nil }.merge(options) # lets not validate the rest of the possible permutations of required params and instead let # EC2 sort it out on the server side. We'll only require :group_name as that is always needed. raise ArgumentError, "No :group_name provided" if options[:group_name].nil? || options[:group_name].empty? params = { "GroupName" => options[:group_name], "IpProtocol" => options[:ip_protocol], "FromPort" => options[:from_port].to_s, "ToPort" => options[:to_port].to_s, "CidrIp" => options[:cidr_ip], "SourceSecurityGroupName" => options[:source_security_group_name], "SourceSecurityGroupOwnerId" => options[:source_security_group_owner_id] } return response_generator(:action => "RevokeSecurityGroupIngress", :params => params) end end end end grempe-amazon-ec2-043f1b4/lib/AWS/EC2/snapshots.rb000066400000000000000000000126371147233247500214110ustar00rootroot00000000000000module AWS module EC2 class Base < AWS::Base # The DescribeSnapshots operation describes the status of Amazon EBS snapshots. # # @option options [optional,Array] :snapshot_id ([]) The ID of the Amazon EBS snapshot. # @option options [optional,String] :owner ('') Returns snapshots owned by the specified owner. Multiple owners can be specified. Valid values self | amazon | AWS Account ID # @option options [optional,String] :restorable_by ('') Account ID of a user that can create volumes from the snapshot. # def describe_snapshots( options = {} ) params = {} params.merge!(pathlist("SnapshotId", options[:snapshot_id] )) unless options[:snapshot_id].nil? || options[:snapshot_id] == [] params["RestorableBy"] = options[:restorable_by] unless options[:restorable_by].nil? params["Owner"] = options[:owner] unless options[:owner].nil? return response_generator(:action => "DescribeSnapshots", :params => params) end # The CreateSnapshot operation creates a snapshot of an Amazon EBS volume and stores it in Amazon S3. You can use snapshots for backups, to launch instances from identical snapshots, and to save data before shutting down an instance. # # @option options [String] :volume_id ('') # @option options [optional,String] :description ('') Description of the Amazon EBS snapshot. # def create_snapshot( options = {} ) options = { :volume_id => '' }.merge(options) raise ArgumentError, "No :volume_id provided" if options[:volume_id].nil? || options[:volume_id].empty? params = { "VolumeId" => options[:volume_id] } params["Description"] = options[:description] unless options[:description].nil? return response_generator(:action => "CreateSnapshot", :params => params) end # The DeleteSnapshot operation deletes a snapshot of an Amazon EBS volume that is stored in Amazon S3. # # @option options [String] :snapshot_id ('') # def delete_snapshot( options = {} ) options = { :snapshot_id => '' }.merge(options) raise ArgumentError, "No :snapshot_id provided" if options[:snapshot_id].nil? || options[:snapshot_id].empty? params = { "SnapshotId" => options[:snapshot_id] } return response_generator(:action => "DeleteSnapshot", :params => params) end # The DescribeSnapshotAttribute operation returns information about an attribute of a snapshot. Only one attribute can be specified per call. # # @option options [String] :attribute ('createVolumePermission') Attribute to modify. # @option options [optional,Array] :snapshot_id ([]) The ID of the Amazon EBS snapshot. # def describe_snapshot_attribute( options = {} ) params = { "Attribute" => options[:attribute] || 'createVolumePermission' } params.merge!(pathlist("SnapshotId", options[:snapshot_id] )) unless options[:snapshot_id].nil? || options[:snapshot_id] == [] return response_generator(:action => "DescribeSnapshotAttribute", :params => params) end # The ModifySnapshotAttribute operation adds or remove permission settings for the specified snapshot. # # @option options [String] :snapshot_id ('') The ID of the Amazon EBS snapshot. # @option options [String] :attribute ('createVolumePermission') Attribute to modify. # @option options [String] :operation_type ('') Operation to perform on the attribute. # @option options [optional,String] :user_id ('') Account ID of a user that can create volumes from the snapshot. # @option options [optional,String] :user_group ('') Group that is allowed to create volumes from the snapshot. # def modify_snapshot_attribute( options = {} ) options = { :snapshot_id => '' }.merge(options) raise ArgumentError, "No :snapshot_id provided" if options[:snapshot_id].nil? || options[:snapshot_id].empty? options = { :operation_type => '' }.merge(options) raise ArgumentError, "No :operation_type provided" if options[:snapshot_id].nil? || options[:snapshot_id].empty? params = { "Attribute" => options[:attribute] || 'createVolumePermission', "SnapshotId" => options[:snapshot_id], "OperationType" => options[:operation_type] } params["UserId"] = options[:user_id] unless options[:user_id].nil? params["UserGroup"] = options[:user_group] unless options[:user_group].nil? return response_generator(:action => "ModifySnapshotAttribute", :params => params) end # The ResetSnapshotAttribute operation resets permission settings for the specified snapshot. # # @option options [optional,Array] :snapshot_id ([]) The ID of the Amazon EBS snapshot. # @option options [String] :attribute ('createVolumePermission') Attribute to reset. # def reset_snapshot_attribute( options = {} ) options = { :snapshot_id => '' }.merge(options) raise ArgumentError, "No :snapshot_id provided" if options[:snapshot_id].nil? || options[:snapshot_id].empty? params = { "Attribute" => options[:attribute] || 'createVolumePermission' } params["SnapshotId"] = options[:snapshot_id] unless options[:snapshot_id].nil? || options[:snapshot_id].empty? return response_generator(:action => "ResetSnapshotAttribute", :params => params) end end end end grempe-amazon-ec2-043f1b4/lib/AWS/EC2/spot_instance_requests.rb000066400000000000000000000216301147233247500241640ustar00rootroot00000000000000module AWS module EC2 class Base < AWS::Base # Creates a Spot Instance request. Spot Instances are instances that Amazon EC2 starts on your behalf # when the maximum price that you specify exceeds the current Spot Price. Amazon EC2 periodically sets # the Spot Price based on available Spot Instance capacity and current spot instance requests. For conceptual # information about Spot Instances, refer to the Amazon Elastic Compute Cloud Developer Guide or Amazon Elastic # Compute Cloud User Guide. # # @option options [String] :spot_price (nil) Specifies the maximum hourly price for any Spot Instance launched to fulfill the request. # @option options [optional,Integer] :instance_count (1) The maximum number of Spot Instances to launch. # @option options [optional,String] :type (nil) Specifies the Spot Instance type. # @option options [optional,Date] :valid_from (nil) Start date of the request. If this is a one-time request, the request becomes active at this date and time and remains active until all instances launch, the request expires, or the request is canceled. If the request is persistent, the request becomes active at this date and time and remains active until it expires or is canceled. # @option options [optional,Date] :valid_until (nil) End date of the request. If this is a one-time request, the request remains active until all instances launch, the request is canceled, or this date is reached. If the request is persistent, it remains active until it is canceled or this date and time is reached. # @option options [optional,String] :launch_group (nil) Specifies the instance launch group. Launch groups are Spot Instances that launch together and terminate together. # @option options [optional,String] :availability_zone_group ("") Specifies the Availability Zone group. If you specify the same Availability Zone group for all Spot Instance requests, all Spot Instances are launched in the same Availability Zone. # @option options [optional,String] :image_id (nil) The AMI ID. # @option options [optional,String] :key_name (nil) The name of the key pair. # @option options [optional,Array of Strings or String] :security_group (nil) Name of the security group(s). # @option options [optional,String] :user_data (nil) MIME, Base64-encoded user data. # @option options [optional,String] :instance_type ("m1.small") Specifies the instance type. # @option options [optional,String] :kernel_id (nil) The ID of the kernel to select. # @option options [optional,String] :ramdisk_id (nil) The ID of the RAM disk to select. Some kernels require additional drivers at launch. Check the kernel requirements for information on whether you need to specify a RAM disk and search for the kernel ID. # @option options [optional,String] :subnet_id (nil) Specifies the Amazon VPC subnet ID within which to launch the instance(s) for Amazon Virtual Private Cloud. # @option options [optional,String] :availability_zone (nil) Specifies the placement constraints (Availability Zones) for launching the instances. # @option options [optional, Array] :block_device_mapping ([]) An array of Hashes representing the elements of the block device mapping. e.g. [{:device_name => '/dev/sdh', :virtual_name => '', :ebs_snapshot_id => '', :ebs_volume_size => '', :ebs_delete_on_termination => ''},{},...] # @option options [optional, Boolean] :monitoring_enabled (false) Enables monitoring for the instance. # @option options [optional, Boolean] :base64_encoded (false) # def request_spot_instances( options = {} ) options = { :instance_count => 1, :instance_type => 'm1.small', :base64_encoded => false }.merge(options) raise ArgumentError, ":addressing_type has been deprecated." if options[:addressing_type] raise ArgumentError, ":spot_price must be provided" if options[:spot_price].nil? || options[:spot_price].empty? raise ArgumentError, ":base64_encoded must be 'true' or 'false'" unless [true, false].include?(options[:base64_encoded]) raise ArgumentError, ":instance_type must specify a valid instance type" unless options[:instance_type].nil? || ["t1.micro", "m1.small", "m1.large", "m1.xlarge", "m2.xlarge", "c1.medium", "c1.xlarge", "m2.2xlarge", "m2.4xlarge", "cc1.4xlarge"].include?(options[:instance_type]) user_data = extract_user_data(options) params = {} if options[:security_group] params.merge!(pathlist("LaunchSpecification.SecurityGroup", options[:security_group])) end if options[:block_device_mapping] params.merge!(pathhashlist('LaunchSpecification.BlockDeviceMapping', options[:block_device_mapping].flatten, {:device_name => 'DeviceName', :virtual_name => 'VirtualName', :ebs_snapshot_id => 'Ebs.SnapshotId', :ebs_volume_size => 'Ebs.VolumeSize', :ebs_delete_on_termination => 'Ebs.DeleteOnTermination' })) end params["SpotPrice"] = options[:spot_price] params["InstanceCount"] = options[:instance_count].to_s params["Type"] = options[:type] unless options[:type].nil? params["ValidFrom"] = options[:valid_from].to_s unless options[:valid_from].nil? params["ValidUntil"] = options[:valid_until].to_s unless options[:valid_until].nil? params["LaunchGroup"] = options[:launch_group] unless options[:launch_group].nil? params["AvailabilityZoneGroup"] = options[:availability_zone_group] unless options[:availability_zone_group].nil? params["LaunchSpecification.ImageId"] = options[:image_id] unless options[:image_id].nil? params["LaunchSpecification.KeyName"] = options[:key_name] unless options[:key_name].nil? params["LaunchSpecification.UserData"] = user_data unless user_data.nil? params["LaunchSpecification.InstanceType"] = options[:instance_type] unless options[:instance_type].nil? params["LaunchSpecification.KernelId"] = options[:kernel_id] unless options[:kernel_id].nil? params["LaunchSpecification.RamdiskId"] = options[:ramdisk_id] unless options[:ramdisk_id].nil? params["LaunchSpecification.SubnetId"] = options[:subnet_id] unless options[:subnet_id].nil? params["LaunchSpecification.Placement.AvailabilityZone"] = options[:availability_zone] unless options[:availability_zone].nil? params["LaunchSpecification.Monitoring.Enabled"] = options[:monitoring_enabled].to_s unless options[:monitoring_enabled].nil? return response_generator(:action => "RequestSpotInstances", :params => params) end # Describes Spot Instance requests. Spot Instances are instances that Amazon EC2 starts on your behalf when the # maximum price that you specify exceeds the current Spot Price. Amazon EC2 periodically sets the Spot Price # based on available Spot Instance capacity and current spot instance requests. For conceptual information about # Spot Instances, refer to the Amazon Elastic Compute Cloud Developer Guide or Amazon Elastic Compute Cloud User Guide. # # @option options [Array] :spot_instance_request_id ([]) # def describe_spot_instance_requests( options = {} ) options = { :spot_instance_request_id => []}.merge(options) params = pathlist( "SpotInstanceRequestId", options[:spot_instance_request_id] ) return response_generator(:action => "DescribeSpotInstanceRequests", :params => params) end # Cancels one or more Spot Instance requests. Spot Instances are instances that Amazon EC2 starts on your behalf # when the maximum price that you specify exceeds the current Spot Price. Amazon EC2 periodically sets the Spot # Price based on available Spot Instance capacity and current spot instance requests. For conceptual information # about Spot Instances, refer to the Amazon Elastic Compute Cloud Developer Guide or Amazon Elastic Compute Cloud # User Guide. # # NB: Canceling a Spot Instance request does not terminate running Spot Instances associated with the request. # # @option options [Array] :spot_instance_request_id ([]) # def cancel_spot_instance_requests( options = {} ) options = { :spot_instance_request_id => []}.merge(options) params = pathlist( "SpotInstanceRequestId", options[:spot_instance_request_id] ) return response_generator(:action => "CancelSpotInstanceRequests", :params => params) end end end end grempe-amazon-ec2-043f1b4/lib/AWS/EC2/spot_prices.rb000066400000000000000000000034451147233247500217160ustar00rootroot00000000000000module AWS module EC2 class Base < AWS::Base # This method returns historical information about spot prices. # # Amazon periodically sets the spot price for each instance type based on # available capacity and current spot instance requests. # # @option options [Time] :start_time (nil) # @option options [Time] :end_time (nil) # @option options [String] :instance_type (nil) # @option options [String] :product_description (nil) # def describe_spot_price_history( options = {} ) raise ArgumentError, ":start_time must be a Time object" unless options[:start_time].nil? || options[:start_time].kind_of?(Time) raise ArgumentError, ":end_time must be a Time object" unless options[:end_time].nil? || options[:end_time].kind_of?(Time) raise ArgumentError, ":instance_type must specify a valid instance type" unless options[:instance_type].nil? || ["t1.micro", "m1.small", "m1.large", "m1.xlarge", "m2.xlarge", "c1.medium", "c1.xlarge", "m2.2xlarge", "m2.4xlarge", "cc1.4xlarge"].include?(options[:instance_type]) raise ArgumentError, ":product_description must be 'Linux/UNIX' or 'Windows'" unless options[:product_description].nil? || ["Linux/UNIX", "Windows"].include?(options[:product_description]) params = {} params.merge!("StartTime" => options[:start_time].iso8601) if options[:start_time] params.merge!("EndTime" => options[:end_time].iso8601) if options[:end_time] params.merge!("InstanceType" => options[:instance_type]) if options[:instance_type] params.merge!("ProductDescription" => options[:product_description]) if options[:product_description] return response_generator(:action => "DescribeSpotPriceHistory", :params => params) end end end end grempe-amazon-ec2-043f1b4/lib/AWS/EC2/subnets.rb000066400000000000000000000012031147233247500210350ustar00rootroot00000000000000module AWS module EC2 class Base < AWS::Base # The DescribeSubnets operation returns information about subnets available for use by the user # making the request. Selected subnets may be specified or the list may be left empty if information for # all registered subnets is required. # # @option options [Array] :subnet_id ([]) # def describe_subnets( options = {} ) options = { :subnet_id => [] }.merge(options) params = pathlist("SubnetId", options[:subnet_id] ) return response_generator(:action => "DescribeSubnets", :params => params) end end end end grempe-amazon-ec2-043f1b4/lib/AWS/EC2/tags.rb000066400000000000000000000046311147233247500203200ustar00rootroot00000000000000module AWS module EC2 class Base < AWS::Base # The CreateTags operation adds or overwrites tags for the specified resource(s). # # @option options [Array] :resource_id ([]) The ids of the resource(s) to tag # @option options [Array] :tag ([]) An array of Hashes representing the tags { tag_name => tag_value }. Use nil or empty string to get a tag without a value # def create_tags( options = {} ) raise ArgumentError, "No :resource_id provided" if options[:resource_id].nil? || options[:resource_id].empty? raise ArgumentError, "No :tag provided" if options[:tag].nil? || options[:tag].empty? params = pathlist("ResourceId", options[:resource_id] ) params.merge!(pathkvlist('Tag', options[:tag], 'Key', 'Value', {})) return response_generator(:action => "CreateTags", :params => params) end # The DescribeTags operation lists the tags, If you do not specify any filters, all tags will be returned. # # @option options [optional, Array] :filter ([]) An array of Hashes representing the filters. Note that the values in the hashes have to be arrays. E.g. [{:key => ['name']}, {:resource_type => ['instance']},...] # def describe_tags( options = {} ) params = {} if options[:filter] params.merge!(pathkvlist('Filter', options[:filter], 'Name', 'Value', {:resource_id => 'resource-id', :resource_type => 'resource-type' })) end return response_generator(:action => "DescribeTags", :params => params) end # The DeleteTags operation deletes tags for the specified resource(s). # # @option options [Array] :resource_id ([]) The ids of the resource(s) to tag # @option options [Array] :tag ([]) An array of Hashes representing the tags { tag_name => tag_value }. If a value is given (instead of nil/empty string), then the tag is only deleted if it has this value # def delete_tags( options = {} ) raise ArgumentError, "No :resource_id provided" if options[:resource_id].nil? || options[:resource_id].empty? raise ArgumentError, "No :tag provided" if options[:tag].nil? || options[:tag].empty? params = pathlist("ResourceId", options[:resource_id] ) params.merge!(pathkvlist('Tag', options[:tag], 'Key', 'Value', {})) return response_generator(:action => "DeleteTags", :params => params) end end end end grempe-amazon-ec2-043f1b4/lib/AWS/EC2/volumes.rb000066400000000000000000000076331147233247500210610ustar00rootroot00000000000000module AWS module EC2 class Base < AWS::Base # The DescribeVolumes operation lists one or more Amazon EBS volumes that you own, If you do not specify any volumes, Amazon EBS returns all volumes that you own. # # @option options [optional, String] :volume_id ([]) # def describe_volumes( options = {} ) options = { :volume_id => [] }.merge(options) params = pathlist("VolumeId", options[:volume_id] ) return response_generator(:action => "DescribeVolumes", :params => params) end # The CreateVolume operation creates a new Amazon EBS volume that you can mount from any Amazon EC2 instance. # # @option options [String] :availability_zone ('') # @option options [optional, String] :size ('') # @option options [optional, String] :snapshot_id ('') # def create_volume( options = {} ) options = { :availability_zone => '' }.merge(options) raise ArgumentError, "No :availability_zone provided" if options[:availability_zone].nil? || options[:availability_zone].empty? options = { :size => '' }.merge(options) options = { :snapshot_id => '' }.merge(options) params = { "AvailabilityZone" => options[:availability_zone], "Size" => options[:size], "SnapshotId" => options[:snapshot_id] } return response_generator(:action => "CreateVolume", :params => params) end # The DeleteVolume operation deletes an Amazon EBS volume. # # @option options [String] :volume_id ('') # def delete_volume( options = {} ) options = { :volume_id => '' }.merge(options) raise ArgumentError, "No :volume_id provided" if options[:volume_id].nil? || options[:volume_id].empty? params = { "VolumeId" => options[:volume_id] } return response_generator(:action => "DeleteVolume", :params => params) end # The AttachVolume operation attaches an Amazon EBS volume to an instance. # # @option options [String] :volume_id ('') # @option options [String] :instance_id ('') # @option options [String] :device ('') # def attach_volume( options = {} ) options = { :volume_id => '' }.merge(options) options = { :instance_id => '' }.merge(options) options = { :device => '' }.merge(options) raise ArgumentError, "No :volume_id provided" if options[:volume_id].nil? || options[:volume_id].empty? raise ArgumentError, "No :instance_id provided" if options[:instance_id].nil? || options[:instance_id].empty? raise ArgumentError, "No :device provided" if options[:device].nil? || options[:device].empty? params = { "VolumeId" => options[:volume_id], "InstanceId" => options[:instance_id], "Device" => options[:device] } return response_generator(:action => "AttachVolume", :params => params) end # The DetachVolume operation detaches an Amazon EBS volume from an instance. # # @option options [String] :volume_id ('') # @option options [optional, String] :instance_id ('') # @option options [optional, String] :device ('') # @option options [optional, Boolean] :force ('') # def detach_volume( options = {} ) options = { :volume_id => '' }.merge(options) raise ArgumentError, "No :volume_id provided" if options[:volume_id].nil? || options[:volume_id].empty? options = { :instance_id => '' }.merge(options) options = { :device => '' }.merge(options) options = { :force => '' }.merge(options) params = { "VolumeId" => options[:volume_id], "InstanceId" => options[:instance_id], "Device" => options[:device], "Force" => options[:force].to_s } return response_generator(:action => "DetachVolume", :params => params) end end end end grempe-amazon-ec2-043f1b4/lib/AWS/ELB.rb000066400000000000000000000047561147233247500174230ustar00rootroot00000000000000module AWS module ELB # Which host FQDN will we connect to for all API calls to AWS? # If ELB_URL is defined in the users ENV we can override the default with that. # # @example # export ELB_URL='https://elasticloadbalancing.amazonaws.com' if ENV['ELB_URL'] ELB_URL = ENV['ELB_URL'] DEFAULT_HOST = URI.parse(ELB_URL).host else # Default US API endpoint DEFAULT_HOST = 'elasticloadbalancing.amazonaws.com' end API_VERSION = '2009-05-15' class Base < AWS::Base def api_version API_VERSION end def default_host DEFAULT_HOST end # Raises the appropriate error if the specified Net::HTTPResponse object # contains an Amazon EC2 error; returns +false+ otherwise. def aws_error?(response) # return false if we got a HTTP 200 code, # otherwise there is some type of error (40x,50x) and # we should try to raise an appropriate exception # from one of our exception classes defined in # exceptions.rb return false if response.is_a?(Net::HTTPSuccess) # parse the XML document so we can walk through it doc = REXML::Document.new(response.body) # Check that the Error element is in the place we would expect. # and if not raise a generic error exception unless doc.root.elements[1].name == "Error" raise Error, "Unexpected error format. response.body is: #{response.body}" end # An valid error response looks like this: # InvalidParameterCombinationUnknown parameter: foo291cef62-3e86-414b-900e-17246eccfae8 # AWS EC2 throws some exception codes that look like Error.SubError. Since we can't name classes this way # we need to strip out the '.' in the error 'Code' and we name the error exceptions with this # non '.' name as well. error_code = doc.root.elements['//ErrorResponse/Error/Code'].text.gsub('.', '') error_message = doc.root.elements['//ErrorResponse/Error/Message'].text # Raise one of our specific error classes if it exists. # otherwise, throw a generic EC2 Error with a few details. if AWS.const_defined?(error_code) raise AWS.const_get(error_code), error_message else raise AWS::Error, error_message end end end end endgrempe-amazon-ec2-043f1b4/lib/AWS/ELB/000077500000000000000000000000001147233247500170625ustar00rootroot00000000000000grempe-amazon-ec2-043f1b4/lib/AWS/ELB/load_balancers.rb000066400000000000000000000307271147233247500223510ustar00rootroot00000000000000module AWS module ELB class Base < AWS::Base # This API creates a new LoadBalancer. Once the call has completed # successfully, a new LoadBalancer will be created, but it will not be # usable until at least one instance has been registered. When the # LoadBalancer creation is completed, you can check whether it is usable # by using the DescribeInstanceHealth API. The LoadBalancer is usable as # soon as any registered instance is InService. # # @option options [String] :load_balancer_name (nil) the name of the load balancer # @option options [Array] :availability_zones (nil) # @option options [Array] :listeners (nil) An Array of Hashes (:protocol, :load_balancer_port, :instance_port) # @option options [Array] :availability_zones (nil) An Array of Strings # def create_load_balancer( options = {} ) raise ArgumentError, "No :availability_zones provided" if options[:availability_zones].nil? || options[:availability_zones].empty? raise ArgumentError, "No :listeners provided" if options[:listeners].nil? || options[:listeners].empty? raise ArgumentError, "No :load_balancer_name provided" if options[:load_balancer_name].nil? || options[:load_balancer_name].empty? params = {} params.merge!(pathlist('AvailabilityZones.member', [options[:availability_zones]].flatten)) params.merge!(pathhashlist('Listeners.member', [options[:listeners]].flatten, { :protocol => 'Protocol', :load_balancer_port => 'LoadBalancerPort', :instance_port => 'InstancePort' })) params['LoadBalancerName'] = options[:load_balancer_name] return response_generator(:action => "CreateLoadBalancer", :params => params) end # This API deletes the specified LoadBalancer. On deletion, all of the # configured properties of the LoadBalancer will be deleted. If you # attempt to recreate the LoadBalancer, you need to reconfigure all the # settings. The DNS name associated with a deleted LoadBalancer is no # longer be usable. Once deleted, the name and associated DNS record of # the LoadBalancer no longer exist and traffic sent to any of its IP # addresses will no longer be delivered to your instances. You will not # get the same DNS name even if you create a new LoadBalancer with same # LoadBalancerName. # # @option options [String] :load_balancer_name the name of the load balancer # def delete_load_balancer( options = {} ) raise ArgumentError, "No :load_balancer_name provided" if options[:load_balancer_name].nil? || options[:load_balancer_name].empty? params = { 'LoadBalancerName' => options[:load_balancer_name] } return response_generator(:action => "DeleteLoadBalancer", :params => params) end # This API returns detailed configuration information for the specified # LoadBalancers, or if no LoadBalancers are specified, then the API # returns configuration information for all LoadBalancers created by the # caller. For more information, please see LoadBalancer. # # You must have created the specified input LoadBalancers in order to # retrieve this information. In other words, in order to successfully call # this API, you must provide the same account credentials as those that # were used to create the LoadBalancer. # # @option options [Array] :load_balancer_names ([]) An Array of names of load balancers to describe. # def describe_load_balancers( options = {} ) options = { :load_balancer_names => [] }.merge(options) params = pathlist("LoadBalancerName.member", options[:load_balancer_names]) return response_generator(:action => "DescribeLoadBalancers", :params => params) end # This API adds new instances to the LoadBalancer. # # Once the instance is registered, it starts receiving traffic and # requests from the LoadBalancer. Any instance that is not in any of the # Availability Zones registered for the LoadBalancer will be moved to # the OutOfService state. It will move to the InService state when the # Availability Zone is added to the LoadBalancer. # # You must have been the one who created the LoadBalancer. In other # words, in order to successfully call this API, you must provide the # same account credentials as those that were used to create the # LoadBalancer. # # NOTE: Completion of this API does not guarantee that operation has # completed. Rather, it means that the request has been registered and # the changes will happen shortly. # # @option options [Array] :instances An Array of instance names to add to the load balancer. # @option options [String] :load_balancer_name The name of the load balancer. # def register_instances_with_load_balancer( options = {} ) raise ArgumentError, "No :instances provided" if options[:instances].nil? || options[:instances].empty? raise ArgumentError, "No :load_balancer_name provided" if options[:load_balancer_name].nil? || options[:load_balancer_name].empty? params = {} params.merge!(pathhashlist('Instances.member', options[:instances].flatten.collect{|e| {:instance_id => e}}, {:instance_id => 'InstanceId'})) params['LoadBalancerName'] = options[:load_balancer_name] return response_generator(:action => "RegisterInstancesWithLoadBalancer", :params => params) end # This API deregisters instances from the LoadBalancer. Trying to # deregister an instance that is not registered with the LoadBalancer # does nothing. # # In order to successfully call this API, you must provide the same # account credentials as those that were used to create the # LoadBalancer. # # Once the instance is deregistered, it will stop receiving traffic from # the LoadBalancer. # # @option options [Array] :instances An Array of instance names to remove from the load balancer. # @option options [String] :load_balancer_name The name of the load balancer. # def deregister_instances_from_load_balancer( options = {} ) raise ArgumentError, "No :instances provided" if options[:instances].nil? || options[:instances].empty? raise ArgumentError, "No :load_balancer_name provided" if options[:load_balancer_name].nil? || options[:load_balancer_name].empty? params = {} params.merge!(pathhashlist('Instances.member', options[:instances].flatten.collect{|e| {:instance_id => e}}, {:instance_id => 'InstanceId'})) params['LoadBalancerName'] = options[:load_balancer_name] return response_generator(:action => "DeregisterInstancesFromLoadBalancer", :params => params) end # This API enables you to define an application healthcheck for the # instances. # # Note: Completion of this API does not guarantee that operation has completed. Rather, it means that the request has been registered and the changes will happen shortly. # # @option options [String] :load_balancer_name The name of the load balancer. # @option options [Hash] :health_check A Hash with the key values provided as String or FixNum values (:timeout, :interval, :unhealthy_threshold, :healthy_threshold) # def configure_health_check( options = {} ) raise ArgumentError, "No :load_balancer_name provided" if options[:load_balancer_name].nil? || options[:load_balancer_name].empty? raise ArgumentError, "No :health_check Hash provided" if options[:health_check].nil? || options[:health_check].empty? params = {} params['LoadBalancerName'] = options[:load_balancer_name] params['HealthCheck.Target'] = options[:health_check][:target] unless options[:health_check][:target].nil? params['HealthCheck.Timeout'] = options[:health_check][:timeout].to_s unless options[:health_check][:timeout].nil? params['HealthCheck.Interval'] = options[:health_check][:interval].to_s unless options[:health_check][:interval].nil? params['HealthCheck.UnhealthyThreshold'] = options[:health_check][:unhealthy_threshold].to_s unless options[:health_check][:unhealthy_threshold].nil? params['HealthCheck.HealthyThreshold'] = options[:health_check][:healthy_threshold].to_s unless options[:health_check][:healthy_threshold].nil? return response_generator(:action => "ConfigureHealthCheck", :params => params) end # This API returns the current state of the instances of the specified LoadBalancer. If no instances are specified, # the state of all the instances for the LoadBalancer is returned. # # You must have been the one who created in the LoadBalancer. In other words, in order to successfully call this API, # you must provide the same account credentials as those that were used to create the LoadBalancer. # # @option options [Array] :instances List of instances IDs whose state is being queried. # @option options [String] :load_balancer_name The name of the load balancer # def describe_instance_health( options = {} ) raise ArgumentError, "No :load_balancer_name provided" if options[:load_balancer_name].nil? || options[:load_balancer_name].empty? params = {} params['LoadBalancerName'] = options[:load_balancer_name] params.merge!(pathlist('Instances.member', [options[:instances]].flatten)) if options.has_key?(:instances) return response_generator(:action => "DescribeInstanceHealth", :params => params) end # This API removes the specified EC2 Availability Zones from the set of configured Availability Zones for the # LoadBalancer. Once an Availability Zone is removed, all the instances registered with the LoadBalancer that # are in the removed Availability Zone go into the OutOfService state. Upon Availability Zone removal, the # LoadBalancer attempts to equally balance the traffic among its remaining usable Availability Zones. Trying to # remove an Availability Zone that was not associated with the LoadBalancer does nothing. # # There must be at least one Availability Zone registered with a LoadBalancer at all times. You cannot remove # all the Availability Zones from a LoadBalancer. # # In order for this call to be successful, you must have created the LoadBalancer. In other words, in order to # successfully call this API, you must provide the same account credentials as those that were used to create # the LoadBalancer. # # @option options [Array] :availability_zones List of Availability Zones to be removed from the LoadBalancer. # @option options [String] :load_balancer_name The name of the load balancer # def disable_availability_zones_for_load_balancer( options = {} ) raise ArgumentError, "No :load_balancer_name provided" if options[:load_balancer_name].nil? || options[:load_balancer_name].empty? raise ArgumentError, "No :availability_zones provided" if options[:availability_zones].nil? || options[:availability_zones].empty? params = {} params['LoadBalancerName'] = options[:load_balancer_name] params.merge!(pathlist('AvailabilityZones.member', [options[:availability_zones]].flatten)) return response_generator(:action => "DisableAvailabilityZonesForLoadBalancer", :params => params) end # This API is used to add one or more EC2 Availability Zones to the LoadBalancer. # # @option options [Array] :availability_zones List of Availability Zones to be added to the LoadBalancer. # @option options [String] :load_balancer_name The name of the load balancer # def enable_availability_zones_for_load_balancer( options = {} ) raise ArgumentError, "No :load_balancer_name provided" if options[:load_balancer_name].nil? || options[:load_balancer_name].empty? raise ArgumentError, "No :availability_zones provided" if options[:availability_zones].nil? || options[:availability_zones].empty? params = {} params['LoadBalancerName'] = options[:load_balancer_name] params.merge!(pathlist('AvailabilityZones.member', [options[:availability_zones]].flatten)) return response_generator(:action => "EnableAvailabilityZonesForLoadBalancer", :params => params) end end end endgrempe-amazon-ec2-043f1b4/lib/AWS/RDS.rb000066400000000000000000000047021147233247500174400ustar00rootroot00000000000000module AWS module RDS # Which host FQDN will we connect to for all API calls to AWS? # If RDS_URL is defined in the users ENV we can override the default with that. # # @example # export RDS_URL='https://rds.amazonaws.com' if ENV['RDS_URL'] RDS_URL = ENV['RDS_URL'] DEFAULT_HOST = URI.parse(RDS_URL).host else # Default US API endpoint DEFAULT_HOST = 'rds.amazonaws.com' end API_VERSION = '2009-10-16' class Base < AWS::Base def api_version API_VERSION end def default_host DEFAULT_HOST end # Raises the appropriate error if the specified Net::HTTPResponse object # contains an Amazon EC2 error; returns +false+ otherwise. def aws_error?(response) # return false if we got a HTTP 200 code, # otherwise there is some type of error (40x,50x) and # we should try to raise an appropriate exception # from one of our exception classes defined in # exceptions.rb return false if response.is_a?(Net::HTTPSuccess) # parse the XML document so we can walk through it doc = REXML::Document.new(response.body) # Check that the Error element is in the place we would expect. # and if not raise a generic error exception unless doc.root.elements[1].name == "Error" raise Error, "Unexpected error format. response.body is: #{response.body}" end # An valid error response looks like this: # InvalidParameterCombinationUnknown parameter: foo291cef62-3e86-414b-900e-17246eccfae8 # AWS EC2 throws some exception codes that look like Error.SubError. Since we can't name classes this way # we need to strip out the '.' in the error 'Code' and we name the error exceptions with this # non '.' name as well. error_code = doc.root.elements['//ErrorResponse/Error/Code'].text.gsub('.', '') error_message = doc.root.elements['//ErrorResponse/Error/Message'].text # Raise one of our specific error classes if it exists. # otherwise, throw a generic EC2 Error with a few details. if AWS.const_defined?(error_code) raise AWS.const_get(error_code), error_message else raise AWS::Error, error_message end end end end end grempe-amazon-ec2-043f1b4/lib/AWS/RDS/000077500000000000000000000000001147233247500171105ustar00rootroot00000000000000grempe-amazon-ec2-043f1b4/lib/AWS/RDS/rds.rb000066400000000000000000000777661147233247500202540ustar00rootroot00000000000000module AWS module RDS class Base < AWS::Base # This API creates a new DB instance. Once the call has completed # successfully, a new DB instance will be created, but it will not be # # @option options [String] :db_instance_identifier (nil) the name of the db_instance # @option options [String] :allocated_storage in gigabytes (nil) # @option options [String] :db_instance_class in contains compute and memory capacity (nil) # @option options [String] :engine type i.e. MySQL5.1 (nil) # @option options [String] :master_username is the master username for the db instance (nil) # @option options [String] :master_user_password is the master password for the db instance (nil) # @option options [String] :port is the port the database accepts connections on (3306) # @option options [String] :db_name contains the name of the database to create when created (nil) # @option options [String] :db_parameter_group is the database parameter group to associate with this instance (nil) # @option options [Array] :db_security_groups are the list of db security groups to associate with the instance (nil) # @option options [String] :availability_zone is the availability_zone to create the instance in (nil) # @option options [String] :preferred_maintenance_window in format: ddd:hh24:mi-ddd:hh24:mi (nil) # @option options [String] :backup_retention_period is the number of days which automated backups are retained (1) # @option options [String] :preferred_backup_window is the daily time range for which automated backups are created # def create_db_instance( options = {}) raise ArgumentError, "No :db_instance_identifier provided" if options.does_not_have?(:db_instance_identifier) raise ArgumentError, "No :allocated_storage provided" if options.does_not_have?(:allocated_storage) raise ArgumentError, "No :db_instance_class provided" if options.does_not_have?(:db_instance_class) raise ArgumentError, "No :engine provided" if options.does_not_have?(:engine) raise ArgumentError, "No :master_username provided" if options.does_not_have?(:master_username) raise ArgumentError, "No :master_user_password provided" if options.does_not_have?(:master_user_password) raise ArgumentError, "No :db_instance_class provided" if options.does_not_have?(:db_instance_class) # handle a former argument that was misspelled raise ArgumentError, "Perhaps you meant :backup_retention_period" if options.has?(:backend_retention_period) params = {} params['DBInstanceIdentifier'] = options[:db_instance_identifier] params["AllocatedStorage"] = options[:allocated_storage].to_s params["DBInstanceClass"] = options[:db_instance_class] params["Engine"] = options[:engine] params["MasterUsername"] = options[:master_username] params["MasterUserPassword"] = options[:master_user_password] params["Port"] = options[:port].to_s if options.has?(:port) params["DBName"] = options[:db_name] if options.has?(:db_name) params["DBParameterGroup"] = options[:db_parameter_group] if options.has?(:db_parameter_group) params.merge!(pathlist("DBSecurityGroups.member", [options[:db_security_groups]].flatten)) if options.has_key?(:db_security_groups) params["AvailabilityZone"] = options[:availability_zone] if options.has?(:availability_zone) params["PreferredMaintenanceWindow"] = options[:preferred_maintenance_window] if options.has?(:preferred_maintenance_window) params["BackupRetentionPeriod"] = options[:backup_retention_period].to_s if options.has?(:backup_retention_period) params["PreferredBackupWindow"] = options[:preferred_backup_window] if options.has?(:preferred_backup_window) return response_generator(:action => "CreateDBInstance", :params => params) end # This API method deletes a db instance identifier # # @option options [String] :db_instance_identifier is the instance identifier for the DB instance to be deleted (nil) # @option options [String] :skip_final_snapshot determines to create a snapshot or not before it's deleted (no) # @option options [String] :final_db_snapshot_identifier is the name of the snapshot created before the instance is deleted (name) # def delete_db_instance( options = {} ) raise ArgumentError, "No :db_instance_identifier provided" if options.does_not_have?(:db_instance_identifier) params = {} params['DBInstanceIdentifier'] = options[:db_instance_identifier] params["SkipFinalSnapshot"] = options[:skip_final_snapshot].to_s if options.has?(:skip_final_snapshot) params["FinalDBSnapshotIdentifier"] = options[:final_db_snapshot_identifier].to_s if options.has?(:final_db_snapshot_identifier) return response_generator(:action => "DeleteDBInstance", :params => params) end # This API method creates a db parameter group # # @option options [String] :db_parameter_group_name is the name of the parameter group (nil) # @option options [String] :engine is the engine the db parameter group can be used with (nil) # @option options [String] :description is the description of the paramter group # def create_db_parameter_group( options = {} ) raise ArgumentError, "No :db_parameter_group_name provided" if options.does_not_have?(:db_parameter_group_name) raise ArgumentError, "No :engine provided" if options.does_not_have?(:engine) raise ArgumentError, "No :description provided" if options.does_not_have?(:description) params = {} params['DBParameterGroupName'] = options[:db_parameter_group_name] params['Engine'] = options[:engine] params['Description'] = options[:description] return response_generator(:action => "CreateDBParameterGroup", :params => params) end # This API method creates a db security group # # @option options [String] :db_security_group_name is the name of the db security group (nil) # @option options [String] :db_security_group_description is the description of the db security group # def create_db_security_group( options = {} ) raise ArgumentError, "No :db_security_group_name provided" if options.does_not_have?(:db_security_group_name) raise ArgumentError, "No :db_security_group_description provided" if options.does_not_have?(:db_security_group_description) params = {} params['DBSecurityGroupName'] = options[:db_security_group_name] params['DBSecurityGroupDescription'] = options[:db_security_group_description] return response_generator(:action => "CreateDBSecurityGroup", :params => params) end # This API method creates a restoreable db snapshot # # @option options [String] :db_snapshot_identifier is the identifier of the db snapshot # @option options [String] :db_instance_identifier is the identifier of the db instance # def create_db_snapshot( options = {} ) raise ArgumentError, "No :db_snapshot_identifier provided" if options.does_not_have?(:db_snapshot_identifier) raise ArgumentError, "No :db_instance_identifier provided" if options.does_not_have?(:db_instance_identifier) params = {} params['DBSnapshotIdentifier'] = options[:db_snapshot_identifier] params['DBInstanceIdentifier'] = options[:db_instance_identifier] return response_generator(:action => "CreateDBSnapshot", :params => params) end # This API method authorizes network ingress for an amazon ec2 group # # @option options [String] :db_security_group_name is the name of the db security group # @option options [String] :cidrip is the network ip to authorize # @option options [String] :ec2_security_group_name is the name of the ec2 security group to authorize # @option options [String] :ec2_security_group_owner_id is the owner id of the security group # def authorize_db_security_group( options = {} ) raise ArgumentError, "No :db_security_group_name provided" if options.does_not_have?(:db_security_group_name) params = {} params['DBSecurityGroupName'] = options[:db_security_group_name] if options.has?(:cidrip) params['CIDRIP'] = options[:cidrip] elsif options.has?(:ec2_security_group_name) && options.has?(:ec2_security_group_owner_id) params['EC2SecurityGroupName'] = options[:ec2_security_group_name] params['EC2SecurityGroupOwnerId'] = options[:ec2_security_group_owner_id] else raise ArgumentError, "No :cidrip or :ec2_security_group_name and :ec2_security_group_owner_id provided" end return response_generator(:action => "AuthorizeDBSecurityGroupIngress", :params => params) end # This API method deletes a db paramter group # # @option options [String] :db_parameter_group_name is the name of the db paramter group to be deleted (nil) # def delete_db_parameter_group( options = {} ) raise ArgumentError, "No :db_parameter_group_name provided" if options.does_not_have?(:db_parameter_group_name) params = {} params['DBParameterGroupName'] = options[:db_parameter_group_name] return response_generator(:action => "DeleteDBParameterGroup", :params => params) end # This API method deletes a db security group # # @option options [String] :db_security_group_name is the name of the db security group to be deleted (nil) # def delete_db_security_group( options = {} ) raise ArgumentError, "No :db_security_group_name provided" if options.does_not_have?(:db_security_group_name) params = {} params['DBSecurityGroupName'] = options[:db_security_group_name] return response_generator(:action => "DeleteDBSecurityGroup", :params => params) end # This API method deletes a db snapshot # # @option options [String] :db_snapshot_identifier is the name of the db snapshot to be deleted (nil) # def delete_db_snapshot( options = {} ) raise ArgumentError, "No :db_snapshot_identifier provided" if options.does_not_have?(:db_snapshot_identifier) params = {} params['DBSnapshotIdentifier'] = options[:db_snapshot_identifier] return response_generator(:action => "DeleteDBSnapshot", :params => params) end # This API method describes the db instances # # @option options [String] :db_instance_identifier if passed, only the description for the db instance matching this identifier is returned # @option options [String] :max_records is the maximum number of records to include in the response # @option options [String] :marker provided in the previous request # def describe_db_instances( options = {} ) params = {} params['DBInstanceIdentifier'] = options[:db_instance_identifier] if options.has?(:db_instance_identifier) params['MaxRecords'] = options[:max_records].to_s if options.has?(:max_records) params['Marker'] = options[:marker] if options.has?(:marker) return response_generator(:action => "DescribeDBInstances", :params => params) end # This API method describes the default engine parameters # # @option options [String] :engine is the name of the database engine # @option options [String] :max_records is the maximum number of records to include in the response # @option options [String] :marker provided in the previous request # def describe_engine_default_parameters( options = {} ) raise ArgumentError, "No :engine provided" if options.does_not_have?(:engine) params = {} params['Engine'] = options[:engine] params['MaxRecords'] = options[:max_records].to_s if options.has?(:max_records) params['Marker'] = options[:marker] if options.has?(:marker) return response_generator(:action => "DescribeEngineDefaultParameters", :params => params) end # This API method returns information about all DB Parameter Groups for an account if no # DB Parameter Group name is supplied, or displays information about a specific named DB Parameter Group. # You can call this operation recursively using the Marker parameter. # # @option options [String] :db_parameter_group_name is the name of the parameter group # @option options [String] :max_records is the maximum number of records to include in the response # @option options [String] :marker provided in the previous request # def describe_db_parameter_groups( options = {} ) params = {} params['DBParameterGroupName'] = options[:db_parameter_group_name] if options.has?(:db_parameter_group_name) params['MaxRecords'] = options[:max_records].to_s if options.has?(:max_records) params['Marker'] = options[:marker] if options.has?(:marker) return response_generator(:action => "DescribeDBParameterGroups", :params => params) end # This API method returns information about parameters that are part of a parameter group. # You can optionally request only parameters from a specific source. # You can call this operation recursively using the Marker parameter. # # @option options [String] :db_parameter_group_name is the name parameter group # @option options [String] :source is the type of parameter to return # @option options [String] :max_records is the maximum number of records to include in the response # @option options [String] :marker provided in the previous request # def describe_db_parameters( options = {} ) raise ArgumentError, "No :db_parameter_group_name provided" if options.does_not_have?(:db_parameter_group_name) params = {} params['DBParameterGroupName'] = options[:db_parameter_group_name] params['Source'] = options[:source] if options.has?(:source) params['MaxRecords'] = options[:max_records].to_s if options.has?(:max_records) params['Marker'] = options[:marker] if options.has?(:marker) return response_generator(:action => "DescribeDBParameters", :params => params) end # This API method returns all the DB Security Group details for a particular AWS account, # or for a particular DB Security Group if a name is specified. # You can call this operation recursively using the Marker parameter. # # @option options [String] :db_security_group_name is the name of the security group # @option options [String] :max_records is the maximum number of records to include in the response # @option options [String] :marker provided in the previous request # def describe_db_security_groups( options = {} ) params = {} params['DBSecurityGroupName'] = options[:db_security_group_name] if options.has?(:db_security_group_name) params['MaxRecords'] = options[:max_records].to_s if options.has?(:max_records) params['Marker'] = options[:marker] if options.has?(:marker) return response_generator(:action => "DescribeDBSecurityGroups", :params => params) end # This API method returns information about the DB Snapshots for this account. # If you pass in a DBInstanceIdentifier, it returns information only about DB Snapshots taken for that DB Instance. # If you pass in a DBSnapshotIdentifier,it will return information only about the specified snapshot. # If you omit both DBInstanceIdentifier and DBSnapshotIdentifier, it returns all snapshot information for all # database instances, up to the maximum number of records specified. Passing both DBInstanceIdentifier and # DBSnapshotIdentifier results in an error. # # @option options [String] :db_instance_identifier is the unique identifier that identifies a DB instance # @option options [String] :db_snapshot_identifier is a unique identifier for an amazon RDS snapshot # @option options [String] :max_records is the maximum number of records to include in the response # @option options [String] :marker provided in the previous request # def describe_db_snapshots( options = {} ) raise ArgumentError, "No :db_instance_identifier provided" if options.does_not_have?(:db_instance_identifier) params = {} params['DBInstanceIdentifier'] = options[:db_instance_identifier] params['DBSnapshotIdentifier'] = options[:db_snapshot_identifier] if options.has?(:db_snapshot_identifier) params['MaxRecords'] = options[:max_records].to_s if options.has?(:max_records) params['Marker'] = options[:marker] if options.has?(:marker) return response_generator(:action => "DescribeDBSnapshots", :params => params) end # This API method Returns information about events related to your DB Instances, DB Security Groups, # and DB Parameter Groups for up to the past 14 days. # You can get events specific to a particular DB Instance or DB Security Group by providing the name as a parameter. # By default, the past hour of events are returned. # # If neither DBInstanceIdentifier or DBSecurityGroupName are provided, # all events are be retrieved for DB Instances and DB Security Groups. # # @option options [String] :source_identifier is the identifier for the source for which events will be included # @option options [String] :source_type is the type of event sources to return # @option options [String] :start_time is the beginning of the time interval to return records for (ISO 8601 format) # @option options [String] :end_time is the end of the time interval to return records (ISO 8601 format) # @option options [String] :duration is the number of minutes to return events for. # @option options [String] :max_records is the maximum number of records to include in the response # @option options [String] :marker provided in the previous request # def describe_events( options = {} ) params = {} params['SourceIdentifier'] = options[:source_identifier] if options.has?(:source_identifier) params['SourceType'] = options[:source_type] if options.has?(:source_type) params['StartTime'] = options[:start_time] if options.has?(:start_time) params['EndTime'] = options[:end_time] if options.has?(:end_time) params['Duration'] = options[:duration] if options.has?(:duration) params['MaxRecords'] = options[:max_records].to_s if options.has?(:max_records) params['Marker'] = options[:marker] if options.has?(:marker) return response_generator(:action => "DescribeEvents", :params => params) end # This API changes the settings of an existing DB Instance. # # Changes are applied in the following manner: A ModifyDBInstance API call to modify security groups or to # change the maintenance windows results in immediate action. Modification of the DB Parameter Group applies # immediate parameters as soon as possible and pending-reboot parameters only when the RDS instance is rebooted. # A request to scale the DB Instance class results puts the database instance into the modifying state. # # The DB Instance must be in available or modifying state for this API to accept changes. # # @option options [String] :db_instance_identifier (nil) the name of the db_instance # @option options [String] :allocated_storage in gigabytes (nil) # @option options [String] :db_instance_class in contains compute and memory capacity (nil) # @option options [String] :engine type i.e. MySQL5.1 (nil) # @option options [String] :master_username is the master username for the db instance (nil) # @option options [String] :master_user_password is the master password for the db instance (nil) # @option options [String] :port is the port the database accepts connections on (3306) # @option options [String] :db_name contains the name of the database to create when created (nil) # @option options [String] :db_parameter_group_name is the database parameter group to associate with this instance (nil) # @option options [Array] :db_security_groups are the list of db security groups to associate with the instance (nil) # @option options [String] :availability_zone is the availability_zone to create the instance in (nil) # @option options [String] :preferred_maintenance_window in format: ddd:hh24:mi-ddd:hh24:mi (nil) # @option options [String] :backup_retention_period is the number of days which automated backups are retained (1) # @option options [String] :preferred_backup_window is the daily time range for which automated backups are created # def modify_db_instance( options = {}) raise ArgumentError, "No :db_instance_identifier provided" if options.does_not_have?(:db_instance_identifier) # handle a former argument that was misspelled raise ArgumentError, "Perhaps you meant :backup_retention_period" if options.has?(:backend_retention_period) params = {} params['DBInstanceIdentifier'] = options[:db_instance_identifier] params["AllocatedStorage"] = options[:allocated_storage].to_s if options.has?(:allocated_storage) params["DBInstanceClass"] = options[:db_instance_class] if options.has?(:db_instance_class) params["Engine"] = options[:engine] if options.has?(:engine) params["MasterUsername"] = options[:master_username] if options.has?(:master_username) params["MasterUserPassword"] = options[:master_user_password] if options.has?(:master_user_password) params["Port"] = options[:port].to_s if options.has?(:port) params["DBName"] = options[:db_name] if options.has?(:db_name) params["DBParameterGroupName"] = options[:db_parameter_group_name] if options.has?(:db_parameter_group_name) params.merge!(pathlist("DBSecurityGroups.member", [options[:db_security_groups]].flatten)) if options.has_key?(:db_security_groups) params["AvailabilityZone"] = options[:availability_zone] if options.has?(:availability_zone) params["PreferredMaintenanceWindow"] = options[:preferred_maintenance_window] if options.has?(:preferred_maintenance_window) params["BackupRetentionPeriod"] = options[:backup_retention_period].to_s if options.has?(:backup_retention_period) params["PreferredBackupWindow"] = options[:preferred_backup_window] if options.has?(:preferred_backup_window) return response_generator(:action => "ModifyDBInstance", :params => params) end # This API method modifies the parameters of a DB Parameter Group. # To modify more than one parameter, submit a list of the following: ParameterName, ParameterValue, and ApplyMethod. # You can modify a maximum of 20 parameters in a single request. # # @option options [String] :db_parameter_group_name is the name of the parameter group to modify # @option options [String] :parameters is the array of parameters to update in a hash format # {:name => "ParameterName", :value => "ParameterValue", :apply_method => "pending-reboot"} # def modify_db_parameter_group( options = {} ) raise ArgumentError, "No :db_parameter_group_name provided" if options.does_not_have?(:db_parameter_group_name) raise ArgumentError, "No :parameters provided" if options.does_not_have?(:parameters) params = {} params['DBParameterGroupName'] = options[:db_parameter_group_name] params.merge!(pathhashlist('Parameters.member', [options[:parameters]].flatten, { :name => 'ParameterName', :value => 'ParameterValue', :apply_method => "ApplyMethod" })) return response_generator(:action => "ModifyDBParameterGroup", :params => params) end # This API method reboots a DB Instance. # Once started, the process cannot be stopped, and the database instance will be unavailable until the reboot completes. # # @option options [String] :db_instance_identifier is the identifier for the db instance to restart # def reboot_db_instance( options = {} ) raise ArgumentError, "No :db_instance_identifier provided" if options.does_not_have?(:db_instance_identifier ) params = {} params['DBInstanceIdentifier'] = options[:db_instance_identifier] if options.has?(:db_instance_identifier) return response_generator(:action => "RebootDBInstance", :params => params) end # This API method modifies the parameters of a DB Parameter Group. # To modify more than one parameter, submit a list of the following: ParameterName, ParameterValue, and ApplyMethod. # You can modify a maximum of 20 parameters in a single request. # # @option options [String] :db_parameter_group_name is the name of the parameter group to modify # @option options [String] :reset_all_parameters specified whether to reset all the db parameters # @option options [String] :parameters is the array of parameters to update in a hash format # {:name => "ParameterName", :apply_method => "pending-reboot"} # def reset_db_parameter_group( options = {} ) raise ArgumentError, "No :db_parameter_group_name provided" if options.does_not_have?(:db_parameter_group_name) raise ArgumentError, "No :parameters provided" if options.does_not_have?(:parameters) params = {} params['DBParameterGroupName'] = options[:db_parameter_group_name] params.merge!(pathhashlist('Parameters.member', [options[:parameters]].flatten, { :name => 'ParameterName', :apply_method => "ApplyMethod" })) params['ResetAllParameters'] = options[:reset_all_parameters] if options.has?(:reset_all_parameters) return response_generator(:action => "ResetDBParameterGroup", :params => params) end # This API method restores a db instance to a snapshot of the instance # # @option options [String] :db_snapshot_identifier is the db identifier of the snapshot to restore from # @option options [String] :db_instance_identifier is the identifier of the db instance # @option options [String] :db_instance_class is the class of db compute and memory instance for the db instance # @option options [String] :port is the port which the db can accept connections on # @option options [String] :availability_zone is the EC2 zone which the db instance will be created # def restore_db_instance_from_snapshot( options = {} ) raise ArgumentError, "No :db_snapshot_identifier provided" if options.does_not_have?(:db_snapshot_identifier) raise ArgumentError, "No :db_instance_identifier provided" if options.does_not_have?(:db_instance_identifier) raise ArgumentError, "No :db_instance_class provided" if options.does_not_have?(:db_instance_class) params = {} params['DBSnapshotIdentifier'] = options[:db_snapshot_identifier] params['DBInstanceIdentifier'] = options[:db_instance_identifier] params['DBInstanceClass'] = options[:db_instance_class] params['Port'] = options[:port].to_s if options.has?(:port) params['AvailabilityZone'] = options[:availability_zone] if options.has?(:availability_zone) return response_generator(:action => "RestoreDBInstanceFromDBSnapshot", :params => params) end # This API method restores a DB Instance to a specified time, creating a new DB Instance. # # Some characteristics of the new DB Instance can be modified using optional parameters. # If these options are omitted, the new DB Instance defaults to the characteristics of the DB Instance from which the # DB Snapshot was created. # # @option options [String] :source_db_instance_identifier the identifier of the source DB Instance from which to restore. # @option options [optional, Boolean] :use_latest_restorable_time specifies that the db be restored to the latest restored time. Conditional, cannot be specified if :restore_time parameter is provided. # @option options [optional, Date] :restore_time specifies the date and time to restore from. Conditional, cannot be specified if :use_latest_restorable_time parameter is true. # @option options [String] :target_db_instance_identifier is the name of the new database instance to be created. # @option options [optional, String] :db_instance_class specifies the class of the compute and memory of the EC2 instance, Options : db.m1.small | db.m1.large | db.m1.xlarge | db.m2.2xlarge | db.m2.4xlarge | db.cc1.4xlarge # @option options [optional, Integer] :port is the port which the db can accept connections on. Constraints: Value must be 1115-65535 # @option options [optional, String] :availability_zone is the EC2 zone which the db instance will be created # def restore_db_instance_to_point_in_time( options = {} ) raise ArgumentError, "No :source_db_instance_identifier provided" if options.does_not_have?(:source_db_instance_identifier) raise ArgumentError, "No :target_db_instance_identifier provided" if options.does_not_have?(:target_db_instance_identifier) params = {} params['SourceDBInstanceIdentifier'] = options[:source_db_instance_identifier] params['TargetDBInstanceIdentifier'] = options[:target_db_instance_identifier] if options.has?(:use_latest_restorable_time) && options.has?(:restore_time) raise ArgumentError, "You cannot provide both :use_latest_restorable_time and :restore_time" elsif options.has?(:use_latest_restorable_time) params['UseLatestRestorableTime'] = case options[:use_latest_restorable_time] when 'true', 'false' options[:use_latest_restorable_time] when true 'true' when false 'false' else raise ArgumentError, "Invalid value provided for :use_latest_restorable_time. Expected boolean." end elsif options.has?(:restore_time) params['RestoreTime'] = options[:restore_time] end params['DBInstanceClass'] = options[:db_instance_class] if options.has?(:db_instance_class) params['Port'] = options[:port].to_s if options.has?(:port) params['AvailabilityZone'] = options[:availability_zone] if options.has?(:availability_zone) return response_generator(:action => "RestoreDBInstanceToPointInTime", :params => params) end # This API method authorizes network ingress for an amazon ec2 group # # @option options [String] :db_security_group_name is the name of the db security group # @option options [String] :cidrip is the network ip to revoke # @option options [String] :ec2_security_group_name is the name of the ec2 security group to authorize # @option options [String] :ec2_security_group_owner_id is the owner id of the security group # def revoke_db_security_group( options = {} ) raise ArgumentError, "No :db_security_group_name provided" if options.does_not_have?(:db_security_group_name) params = {} params['DBSecurityGroupName'] = options[:db_security_group_name] if options.has?(:cidrip) params['CIDRIP'] = options[:cidrip] elsif options.has?(:ec2_security_group_name) && options.has?(:ec2_security_group_owner_id) params['EC2SecurityGroupName'] = options[:ec2_security_group_name] params['EC2SecurityGroupOwnerId'] = options[:ec2_security_group_owner_id] else raise ArgumentError, "No :cidrip or :ec2_security_group_name and :ec2_security_group_owner_id provided" end return response_generator(:action => "RevokeDBSecurityGroupIngress", :params => params) end end end end grempe-amazon-ec2-043f1b4/lib/AWS/exceptions.rb000066400000000000000000000145521147233247500211750ustar00rootroot00000000000000#-- # AWS ERROR CODES # AWS can throw error exceptions that contain a '.' in them. # since we can't name an exception class with that '.' I compressed # each class name into the non-dot version which allows us to retain # the granularity of the exception. #++ module AWS # All AWS errors are superclassed by Error < RuntimeError class Error < RuntimeError; end # CLIENT : A client side argument error class ArgumentError < Error; end # Elastic Compute Cloud ############################ # EC2 : User has the maximum number of allowed IP addresses. class AddressLimitExceeded < Error; end # EC2 : The limit on the number of Amazon EBS volumes attached to one instance has been exceeded. class AttachmentLimitExceeded < Error; end # EC2 : User not authorized. class AuthFailure < Error; end # EC2 : Volume is in incorrect state class IncorrectState < Error; end # EC2 : User has max allowed concurrent running instances. class InstanceLimitExceeded < Error; end # EC2 : The value of an item added to, or removed from, an image attribute is invalid. class InvalidAMIAttributeItemValue < Error; end # EC2 : Specified AMI ID is not valid. class InvalidAMIIDMalformed < Error; end # EC2 : Specified AMI ID does not exist. class InvalidAMIIDNotFound < Error; end # EC2 : Specified AMI ID has been deregistered and is no longer available. class InvalidAMIIDUnavailable < Error; end # EC2 : The instance cannot detach from a volume to which it is not attached. class InvalidAttachmentNotFound < Error; end # EC2 : The device to which you are trying to attach (i.e. /dev/sdh) is already in use on the instance. class InvalidDeviceInUse < Error; end # EC2 : Specified instance ID is not valid. class InvalidInstanceIDMalformed < Error; end # EC2 : Specified instance ID does not exist. class InvalidInstanceIDNotFound < Error; end # EC2 : Specified keypair name does not exist. class InvalidKeyPairNotFound < Error; end # EC2 : Attempt to create a duplicate keypair. class InvalidKeyPairDuplicate < Error; end # EC2 : Specified group name does not exist. class InvalidGroupNotFound < Error; end # EC2 : Attempt to create a duplicate group. class InvalidGroupDuplicate < Error; end # EC2 : Specified group can not be deleted because it is in use. class InvalidGroupInUse < Error; end # EC2 : Specified group name is a reserved name. class InvalidGroupReserved < Error; end # EC2 : Specified AMI has an unparsable manifest. class InvalidManifest < Error; end # EC2 : RunInstances was called with minCount and maxCount set to 0 or minCount > maxCount. class InvalidParameterCombination < Error; end # EC2 : The value supplied for a parameter was invalid. class InvalidParameterValue < Error; end # EC2 : Attempt to authorize a permission that has already been authorized. class InvalidPermissionDuplicate < Error; end # EC2 : Specified permission is invalid. class InvalidPermissionMalformed < Error; end # EC2 : Specified reservation ID is invalid. class InvalidReservationIDMalformed < Error; end # EC2 : Specified reservation ID does not exist. class InvalidReservationIDNotFound < Error; end # EC2 : The snapshot ID that was passed as an argument was malformed. class InvalidSnapshotIDMalformed < Error; end # EC2 : The specified snapshot does not exist. class InvalidSnapshotIDNotFound < Error; end # EC2 : The user ID is neither in the form of an AWS account ID or one # of the special values accepted by the owner or executableBy flags # in the DescribeImages call. class InvalidUserIDMalformed < Error; end # EC2 : Reserved Instances ID not found. class InvalidReservedInstancesId < Error; end # EC2 : Reserved Instances Offering ID not found. class InvalidReservedInstancesOfferingId < Error; end # EC2 : The volume ID that was passed as an argument was malformed. class InvalidVolumeIDMalformed < Error; end # EC2 : The volume specified does not exist. class InvalidVolumeIDNotFound < Error; end # EC2 : The volume already exists in the system. class InvalidVolumeIDDuplicate < Error; end # EC2 : The specified volume ID and instance ID are in different Availability Zones. class InvalidVolumeIDZoneMismatch < Error; end # EC2 : The zone specified does not exist. class InvalidZoneNotFound < Error; end # EC2 : Insufficient Reserved Instances capacity. class InsufficientReservedInstancesCapacity < Error; end # EC2 : The instance specified does not support EBS. class NonEBSInstance < Error; end # EC2 : The limit on the number of Amazon EBS snapshots in the pending state has been exceeded. class PendingSnapshotLimitExceeded < Error; end # EC2 : Your current quota does not allow you to purchase the required number of reserved instances. class ReservedInstancesLimitExceeded < Error; end # EC2 : The limit on the number of Amazon EBS snapshots has been exceeded. class SnapshotLimitExceeded < Error; end # EC2 : An unknown parameter was passed as an argument class UnknownParameter < Error; end # EC2 : The limit on the number of Amazon EBS volumes has been exceeded. class VolumeLimitExceeded < Error; end # Server Error Codes ### # Server : Internal Error. class InternalError < Error; end # Server : Not enough available addresses to satisfy your minimum request. class InsufficientAddressCapacity < Error; end # Server : There are not enough available instances to satisfy your minimum request. class InsufficientInstanceCapacity < Error; end # Server : There are not enough available reserved instances to satisfy your minimum request. class InsufficientReservedInstanceCapacity < Error; end # Server : The server is overloaded and cannot handle the request. class Unavailable < Error; end # Elastic Load Balancer ############################ # ELB : The Load balancer specified was not found. class LoadBalancerNotFound < Error; end # ELB : class ValidationError < Error; end # ELB : class DuplicateLoadBalancerName < Error; end # ELB : class TooManyLoadBalancers < Error; end # ELB : class InvalidInstance < Error; end # ELB : class InvalidConfigurationRequest < Error; end # API Errors ############################ # Server : Invalid AWS Account class InvalidClientTokenId < Error; end # Server : The provided signature does not match. class SignatureDoesNotMatch < Error; end end grempe-amazon-ec2-043f1b4/lib/AWS/responses.rb000066400000000000000000000012131147233247500210230ustar00rootroot00000000000000module AWS class Response # Parse the XML response from AWS # # @option options [String] :xml The XML response from AWS that we want to parse # @option options [Hash] :parse_options Override the options for XmlSimple. # @return [Hash] the input :xml converted to a custom Ruby Hash by XmlSimple. def self.parse(options = {}) options = { :xml => "", :parse_options => { 'forcearray' => ['item', 'member'], 'suppressempty' => nil, 'keeproot' => false } }.merge(options) response = XmlSimple.xml_in(options[:xml], options[:parse_options]) end end # class Response end # module AWS grempe-amazon-ec2-043f1b4/lib/AWS/version.rb000066400000000000000000000000441147233247500204700ustar00rootroot00000000000000module AWS VERSION = "0.9.17" end grempe-amazon-ec2-043f1b4/test/000077500000000000000000000000001147233247500162375ustar00rootroot00000000000000grempe-amazon-ec2-043f1b4/test/test_Autoscaling_groups.rb000066400000000000000000000411631147233247500235000ustar00rootroot00000000000000require File.dirname(__FILE__) + '/test_helper.rb' context "autoscaling " do before do @as = AWS::Autoscaling::Base.new( :access_key_id => "not a key", :secret_access_key => "not a secret" ) @valid_create_launch_configuration_params = { :image_id => "ami-ed46a784", :launch_configuration_name => "TestAutoscalingGroupName", :instance_type => "m1.small" } @error_response_for_creation = <<-RESPONSE Sender AlreadyExists Launch Configuration by this name already exists - A launch configuration already exists with the name TestAutoscalingGroupName 31d00b03-ad6a-11de-a47f-a5c562feca13 RESPONSE @delete_launch_configuration_response = <<-RESPONSE 5f5717d3-ad6c-11de-b1c0-1b00aadc5f72 RESPONSE @create_launch_configuration_response = "\n \n 6062466f-ad6c-11de-b82f-996c936914c5\n \n\n" @create_autoscaling_group_response = "\n \n cc4f9960-ad6e-11de-b82f-996c936914c5\n \n\n" @delete_autoscaling_group = " e64fc4c3-e10b-11dd-a73e-2d774d6aee71" @create_or_update_trigger_response = " 503d309d-e10b-11dd-a73e-2d774d6aee71 " end specify "AWS::Autoscaling::Base should give back a nice response if there is an error" do @as.stubs(:make_request).with('CreateLaunchConfiguration', { 'ImageId' => 'ami-ed46a784', 'LaunchConfigurationName' => 'TestAutoscalingGroupName', 'InstanceType' => "m1.small" }).returns stub(:body => @error_response_for_creation, :is_a? => true) response = @as.create_launch_configuration( :image_id => "ami-ed46a784", :launch_configuration_name => "TestAutoscalingGroupName", :instance_type => "m1.small") response.should.be.an.instance_of Hash response["Error"]["Message"].should.equal "Launch Configuration by this name already exists - A launch configuration already exists with the name TestAutoscalingGroupName" end specify "AWS::Autoscaling::Base should destroy a launch configuration just fine" do @as.stubs(:make_request).with('DeleteLaunchConfiguration', { 'LaunchConfigurationName' => 'TestAutoscalingGroupName1' }).returns stub(:body => @delete_launch_configuration_response, :is_a? => true) response = @as.delete_launch_configuration( :launch_configuration_name => "TestAutoscalingGroupName1" ) response.should.be.an.instance_of Hash end specify "AWS::Autoscaling::Base should create a launch configuration" do @as.stubs(:make_request).with('CreateLaunchConfiguration', { 'ImageId' => 'ami-ed46a784', 'LaunchConfigurationName' => 'CustomTestAutoscalingGroupName', 'InstanceType' => "m1.small" }).returns stub(:body => @create_launch_configuration_response, :is_a? => true) response = @as.create_launch_configuration( :image_id => "ami-ed46a784", :launch_configuration_name => "CustomTestAutoscalingGroupName", :instance_type => "m1.small") response.should.be.an.instance_of Hash end specify "AWS::Autoscaling::Base should be able to create a new autoscaling group" do @as.stubs(:make_request).with("CreateAutoScalingGroup", { 'AutoScalingGroupName' => 'CloudteamTestAutoscalingGroup1', 'AvailabilityZones.member.1' => 'us-east-1a', 'LoadBalancerNames.member.1' => 'TestLoadBalancerName', 'LoadBalancerNames.member.2' => 'TestLoadBalancerName2', 'LaunchConfigurationName' => 'CloudteamTestAutoscaling', 'MinSize' => "1", 'MaxSize' => "3", 'Cooldown' => 300 }).returns stub(:body => @create_autoscaling_group_response, :is_a? => true) response = @as.create_autoscaling_group(:autoscaling_group_name => "CloudteamTestAutoscalingGroup1", :availability_zones => "us-east-1a", :load_balancer_names => ["TestLoadBalancerName", "TestLoadBalancerName2"], :launch_configuration_name => "CloudteamTestAutoscaling", :min_size => 1, :max_size => 3, :cooldown => 300) response.should.be.an.instance_of Hash end specify "AWS::Autoscaling::Base should destroy an autoscaling group" do @as.stubs(:make_request).with('DeleteAutoScalingGroup', { 'AutoScalingGroupName' => 'TestAutoscalingGroupName1' }).returns stub(:body => @delete_autoscaling_group, :is_a? => true) response = @as.delete_autoscaling_group( :autoscaling_group_name => "TestAutoscalingGroupName1" ) response.should.be.an.instance_of Hash end specify "AWS::Autoscaling::Base should be able to create a new scaling trigger" do @as.stubs(:make_request).with("CreateOrUpdateScalingTrigger", { 'AutoScalingGroupName' => 'AutoScalingGroupName', 'Unit' => "Seconds", 'Dimensions.member.1.Name' => "AutoScalingGroupName", 'Dimensions.member.1.Value' => "Bob", 'MeasureName' => "CPUUtilization", 'Statistic' => 'Average', 'Period' => '120', 'TriggerName' => "AFunNameForATrigger", 'LowerThreshold' => "0.2", 'LowerBreachScaleIncrement' => "-1", 'UpperThreshold' => "1.5", 'UpperBreachScaleIncrement' => "1", 'BreachDuration' => "120", 'Namespace' => "AWS/EC2", }).returns stub(:body => @create_or_update_trigger_response, :is_a? => true) valid_create_or_update_scaling_trigger_params = {:autoscaling_group_name => "AutoScalingGroupName", :dimensions => {:name => "AutoScalingGroupName", :value => "Bob"}, :unit => "Seconds", :measure_name => "CPUUtilization", :namespace => "AWS/EC2", :statistic => "Average", :period => 120, :trigger_name => "AFunNameForATrigger", :lower_threshold => 0.2, :lower_breach_scale_increment => "-1", :upper_threshold => 1.5, :upper_breach_scale_increment => 1, :breach_duration => 120} %w(dimensions autoscaling_group_name measure_name statistic period trigger_name lower_threshold lower_breach_scale_increment upper_threshold upper_breach_scale_increment breach_duration).each do |meth_str| lambda { @as.create_or_updated_scaling_trigger(valid_create_or_update_scaling_trigger_params.merge(meth_str.to_sym=>nil)) }.should.raise(AWS::ArgumentError) end response = @as.create_or_updated_scaling_trigger(valid_create_or_update_scaling_trigger_params) response.should.be.an.instance_of Hash end specify "AWS::Autoscaling::Base should destroy a launch configuration group" do @as.stubs(:make_request).with('DeleteLaunchConfiguration', { 'LaunchConfigurationName' => 'LaunchConfiguration' }).returns stub(:body => " e64fc4c3-e10b-11dd-a73e-2d774d6aee71 ", :is_a? => true) response = @as.delete_launch_configuration( :launch_configuration_name => "LaunchConfiguration" ) response.should.be.an.instance_of Hash end specify "AWS::Autoscaling::Base should destroy a scaling trigger" do @as.stubs(:make_request).with('DeleteTrigger', { 'TriggerName' => 'DeletingTrigger', 'AutoScalingGroupName' => "Name" }).returns stub(:body => " cca38097-e10b-11dd-a73e-2d774d6aee71 ", :is_a? => true) response = @as.delete_trigger( :trigger_name => "DeletingTrigger", :autoscaling_group_name => "Name" ) response.should.be.an.instance_of Hash end specify "AWS::Autoscaling::Base should describe the autoscaling groups" do @as.stubs(:make_request).with('DescribeAutoScalingGroups', { 'AutoScalingGroupNames.member.1' => "webtier" }).returns stub(:body => " 0 2009-01-13T00:38:54Z us-east-1c 0 wt20080929 webtier 1 i-8fa224e6 InService us-east-1c 1 70f2e8af-e10b-11dd-a73e-2d774d6aee71 ", :is_a? => true) response = @as.describe_autoscaling_groups( :autoscaling_group_names => ["webtier"] ) response.should.be.an.instance_of Hash end specify "AWS::Autoscaling::Base should describe the launch configurations" do @as.stubs(:make_request).with('DescribeLaunchConfigurations', { 'AutoScalingGroupNames.member.1' => "webtier" }).returns stub(:body => " m1.small ami-f7c5219e 2009-01-13T00:35:31Z wt20080929 2e14cb6c-e10a-11dd-a73e-2d774d6aee71 ", :is_a? => true) response = @as.describe_launch_configurations( :launch_configuration_names => ["webtier"] ) response.should.be.an.instance_of Hash end specify "AWS::Autoscaling::Base should describe the launch configurations" do @as.stubs(:make_request).with('DescribeScalingActivities', { 'AutoScalingGroupName' => "webtier" }).returns stub(:body => " 885b2900-0f2e-497a-8ec6-b1b90a9ddee0 2009-03-29T04:07:07Z 0 InProgress Automated Capacity Adjustment Launching a new EC2 instance f0321780-e10a-11dd-a73e-2d774d6aee71 ", :is_a? => true) response = @as.describe_scaling_activities( :autoscaling_group_name => "webtier" ) response.should.be.an.instance_of Hash end specify "AWS::Autoscaling::Base should describe triggers" do @as.stubs(:make_request).with('DescribeTriggers', { 'AutoScalingGroupName' => "webtier" }).returns stub(:body => " 300 1 2009-01-13T00:44:19Z 60.0 NoData 0.0 60 -1 tenpct Average None AWS/EC2 AutoScalingGroupName webtier webtier CPUUtilization 5c33c82a-e10b-11dd-a73e-2d774d6aee71 ", :is_a? => true) response = @as.describe_triggers( :autoscaling_group_name => "webtier" ) response.should.be.an.instance_of Hash end specify "AWS::Autoscaling::Base should describe triggers" do @as.stubs(:make_request).with('SetDesiredCapacity', { 'AutoScalingGroupName' => "name", 'DesiredCapacity' => '10' }).returns stub(:body => " d3f2091c-e10a-11dd-a73e- 2d774d6aee71 ", :is_a? => true) response = @as.set_desired_capacity( :autoscaling_group_name => "name", :desired_capacity => "10" ) response.should.be.an.instance_of Hash end specify "AWS::Autoscaling::Base should terminate an instance in an autoscaling group" do @as.stubs(:make_request).with('TerminateInstanceInAutoScalingGroup', { 'InstanceId' => "i-instance1" }).returns stub(:body => " 300 1 2009-01-13T00:44:19Z 60.0 NoData 0.0 60 -1 tenpct Average None AWS/EC2 AutoScalingGroupName webtier webtier CPUUtilization 5c33c82a-e10b-11dd-a73e-2d774d6aee71 ", :is_a? => true) response = @as.terminate_instance_in_autoscaling_group( :instance_id => "i-instance1" ) response.should.be.an.instance_of Hash end end grempe-amazon-ec2-043f1b4/test/test_EC2.rb000066400000000000000000000055161147233247500202030ustar00rootroot00000000000000#-- # Amazon Web Services EC2 Query API Ruby library # # Ruby Gem Name:: amazon-ec2 # Author:: Glenn Rempe (mailto:glenn@rempe.us) # Copyright:: Copyright (c) 2007-2008 Glenn Rempe # License:: Distributes under the same terms as Ruby # Home:: http://github.com/grempe/amazon-ec2/tree/master #++ require File.dirname(__FILE__) + '/test_helper.rb' context "The EC2 method " do before do end specify "AWS::EC2::Base attribute readers should be available" do @ec2 = AWS::EC2::Base.new( :access_key_id => "not a key", :secret_access_key => "not a secret", :use_ssl => true, :server => "foo.example.com" ) @ec2.use_ssl.should.equal true @ec2.port.should.equal 443 @ec2.server.should.equal "foo.example.com" end specify "AWS::EC2::Base should work with insecure connections as well" do @ec2 = AWS::EC2::Base.new( :access_key_id => "not a key", :secret_access_key => "not a secret", :use_ssl => false, :server => "foo.example.com" ) @ec2.use_ssl.should.equal false @ec2.port.should.equal 80 @ec2.server.should.equal "foo.example.com" end specify "AWS::EC2::Base should allow specification of port" do @ec2 = AWS::EC2::Base.new( :access_key_id => "not a key", :secret_access_key => "not a secret", :use_ssl => true, :server => "foo.example.com", :port => 8443 ) @ec2.use_ssl.should.equal true @ec2.port.should.equal 8443 @ec2.server.should.equal "foo.example.com" end specify "AWS.canonical_string(path) should conform to Amazon's requirements " do path = {"name1" => "value1", "name2" => "value2 has spaces", "name3" => "value3~"} if ENV['EC2_URL'].nil? || ENV['EC2_URL'] == 'https://ec2.amazonaws.com' AWS.canonical_string(path, 'ec2.amazonaws.com').should.equal "POST\nec2.amazonaws.com\n/\nname1=value1&name2=value2%20has%20spaces&name3=value3~" elsif ENV['EC2_URL'] == 'https://us-east-1.ec2.amazonaws.com' AWS.canonical_string(path, 'ec2.amazonaws.com').should.equal "POST\nus-east-1.ec2.amazonaws.com\n/\nname1=value1&name2=value2%20has%20spaces&name3=value3~" elsif ENV['EC2_URL'] == 'https://eu-west-1.ec2.amazonaws.com' AWS.canonical_string(path, 'ec2.amazonaws.com').should.equal "POST\neu-west-1.ec2.amazonaws.com\n/\nname1=value1&name2=value2%20has%20spaces&name3=value3~" end end specify "AWS.encode should return the expected string" do AWS.encode("secretaccesskey", "foobar123", urlencode=true).should.equal "CPzGGhtvlG3P3yp88fPZp0HKouUV8mQK1ZcdFGQeAug%3D" AWS.encode("secretaccesskey", "foobar123", urlencode=false).should.equal "CPzGGhtvlG3P3yp88fPZp0HKouUV8mQK1ZcdFGQeAug=" end end grempe-amazon-ec2-043f1b4/test/test_EC2_availability_zones.rb000066400000000000000000000034561147233247500241540ustar00rootroot00000000000000#-- # Amazon Web Services EC2 Query API Ruby library # # Ruby Gem Name:: amazon-ec2 # Author:: Glenn Rempe (mailto:glenn@rempe.us) # Copyright:: Copyright (c) 2007-2008 Glenn Rempe # License:: Distributes under the same terms as Ruby # Home:: http://github.com/grempe/amazon-ec2/tree/master #++ require File.dirname(__FILE__) + '/test_helper.rb' context "EC2 availability zones" do before do @ec2 = AWS::EC2::Base.new( :access_key_id => "not a key", :secret_access_key => "not a secret" ) @describe_availability_zones_response_body = <<-RESPONSE us-east-1a available us-east-1b available RESPONSE end specify "should be able to be described with describe_availability_zones" do @ec2.stubs(:make_request).with('DescribeAvailabilityZones', { "ZoneName.1" => "us-east-1a", "ZoneName.2" => "us-east-1b" }). returns stub(:body => @describe_availability_zones_response_body, :is_a? => true) @ec2.describe_availability_zones( :zone_name => ["us-east-1a", "us-east-1b"] ).should.be.an.instance_of Hash response = @ec2.describe_availability_zones( :zone_name => ["us-east-1a", "us-east-1b"] ) response.availabilityZoneInfo.item[0].zoneName.should.equal "us-east-1a" response.availabilityZoneInfo.item[0].zoneState.should.equal "available" response.availabilityZoneInfo.item[1].zoneName.should.equal "us-east-1b" response.availabilityZoneInfo.item[1].zoneState.should.equal "available" end end grempe-amazon-ec2-043f1b4/test/test_EC2_console.rb000066400000000000000000000043671147233247500217300ustar00rootroot00000000000000#-- # Amazon Web Services EC2 Query API Ruby library # # Ruby Gem Name:: amazon-ec2 # Author:: Glenn Rempe (mailto:glenn@rempe.us) # Copyright:: Copyright (c) 2007-2008 Glenn Rempe # License:: Distributes under the same terms as Ruby # Home:: http://github.com/grempe/amazon-ec2/tree/master #++ require File.dirname(__FILE__) + '/test_helper.rb' context "The EC2 console " do before do @ec2 = AWS::EC2::Base.new( :access_key_id => "not a key", :secret_access_key => "not a secret" ) @get_console_output_response_body = <<-RESPONSE i-28a64341 2007-01-03 15:00:00 YyB2ZXJzaW9uIDQuMC4xIDIwMDUwNzI3IChSZWQgSGF0IDQuMC4xLTUpKSAjMSBTTVAgVGh1IE9j dCAyNiAwODo0MToyNiBTQVNUIDIwMDYKQklPUy1wcm92aWRlZCBwaHlzaWNhbCBSQU0gbWFwOgpY ZW46IDAwMDAwMDAwMDAwMDAwMDAgLSAwMDAwMDAwMDZhNDAwMDAwICh1c2FibGUpCjk4ME1CIEhJ R0hNRU0gYXZhaWxhYmxlLgo3MjdNQiBMT1dNRU0gYXZhaWxhYmxlLgpOWCAoRXhlY3V0ZSBEaXNh YmxlKSBwcm90ZWN0aW9uOiBhY3RpdmUKSVJRIGxvY2t1cCBkZXRlY3Rpb24gZGlzYWJsZWQKQnVp bHQgMSB6b25lbGlzdHMKS2VybmVsIGNvbW1hbmQgbGluZTogcm9vdD0vZGV2L3NkYTEgcm8gNApF bmFibGluZyBmYXN0IEZQVSBzYXZlIGFuZCByZXN0b3JlLi4uIGRvbmUuCg== RESPONSE end specify "should return info written to a specific instances console" do @ec2.stubs(:make_request).with('GetConsoleOutput', {"InstanceId"=>"i-2ea64347"}). returns stub(:body => @get_console_output_response_body, :is_a? => true) @ec2.get_console_output( :instance_id => "i-2ea64347" ).should.be.an.instance_of Hash response = @ec2.get_console_output( :instance_id => "i-2ea64347" ) response.instanceId.should.equal "i-28a64341" response.timestamp.should.equal "2007-01-03 15:00:00" end specify "method get_console_output should raise an exception when called without nil/empty string arguments" do lambda { @ec2.get_console_output() }.should.raise(AWS::ArgumentError) lambda { @ec2.get_console_output(:instance_id => nil) }.should.raise(AWS::ArgumentError) lambda { @ec2.get_console_output(:instance_id => "") }.should.raise(AWS::ArgumentError) end end grempe-amazon-ec2-043f1b4/test/test_EC2_elastic_ips.rb000066400000000000000000000133301147233247500225530ustar00rootroot00000000000000#-- # Amazon Web Services EC2 Query API Ruby library # # Ruby Gem Name:: amazon-ec2 # Author:: Glenn Rempe (mailto:glenn@rempe.us) # Copyright:: Copyright (c) 2007-2008 Glenn Rempe # License:: Distributes under the same terms as Ruby # Home:: http://github.com/grempe/amazon-ec2/tree/master #++ require File.dirname(__FILE__) + '/test_helper.rb' context "EC2 elastic IP addresses " do before do @ec2 = AWS::EC2::Base.new( :access_key_id => "not a key", :secret_access_key => "not a secret" ) @allocate_address_body = <<-RESPONSE 67.202.55.255 RESPONSE @describe_addresses_response_body = <<-RESPONSE i-28a64341 67.202.55.255 RESPONSE @release_address_response_body = <<-RESPONSE true RESPONSE @associate_address_response_body = <<-RESPONSE true RESPONSE @disassociate_address_response_body = <<-RESPONSE true RESPONSE end specify "should be able to be created" do @ec2.stubs(:make_request).with('AllocateAddress', {}). returns stub(:body => @allocate_address_body, :is_a? => true) @ec2.allocate_address.should.be.an.instance_of Hash response = @ec2.allocate_address response.publicIp.should.equal "67.202.55.255" end #specify "method create_keypair should reject bad arguments" do # @ec2.stubs(:make_request).with('CreateKeyPair', {"KeyName"=>"example-key-name"}). # returns stub(:body => @create_keypair_response_body, :is_a? => true) # # lambda { @ec2.create_keypair( :key_name => "example-key-name" ) }.should.not.raise(AWS::ArgumentError) # lambda { @ec2.create_keypair() }.should.raise(AWS::ArgumentError) # lambda { @ec2.create_keypair( :key_name => nil ) }.should.raise(AWS::ArgumentError) # lambda { @ec2.create_keypair( :key_name => "" ) }.should.raise(AWS::ArgumentError) #end specify "should be able to be described with describe_addresses" do @ec2.stubs(:make_request).with('DescribeAddresses', {"PublicIp.1"=>"67.202.55.255"}). returns stub(:body => @describe_addresses_response_body, :is_a? => true) @ec2.describe_addresses( :public_ip => "67.202.55.255" ).should.be.an.instance_of Hash response = @ec2.describe_addresses( :public_ip => "67.202.55.255" ) response.addressesSet.item[0].instanceId.should.equal "i-28a64341" response.addressesSet.item[0].publicIp.should.equal "67.202.55.255" end specify "should be able to be released with release_address" do @ec2.stubs(:make_request).with('ReleaseAddress', {"PublicIp" => "67.202.55.255"}). returns stub(:body => @release_address_response_body, :is_a? => true) @ec2.release_address( :public_ip => "67.202.55.255" ).should.be.an.instance_of Hash response = @ec2.release_address( :public_ip => "67.202.55.255" ) response.return.should.equal "true" end specify "should be able to be associated with an instance with associate_address" do @ec2.stubs(:make_request).with('AssociateAddress', {"InstanceId" => "i-2ea64347", "PublicIp"=>"67.202.55.255"}). returns stub(:body => @associate_address_response_body, :is_a? => true) @ec2.associate_address( :instance_id => "i-2ea64347", :public_ip => "67.202.55.255" ).should.be.an.instance_of Hash response = @ec2.associate_address( :instance_id => "i-2ea64347", :public_ip => "67.202.55.255" ) response.return.should.equal "true" end specify "method associate_address should reject bad arguments" do @ec2.stubs(:make_request).with('AssociateAddress', {"InstanceId" => "i-2ea64347", "PublicIp"=>"67.202.55.255"}). returns stub(:body => @associate_address_response_body, :is_a? => true) lambda { @ec2.associate_address( :instance_id => "i-2ea64347", :public_ip => "67.202.55.255" ) }.should.not.raise(AWS::ArgumentError) lambda { @ec2.associate_address() }.should.raise(AWS::ArgumentError) lambda { @ec2.associate_address( :instance_id => nil ) }.should.raise(AWS::ArgumentError) lambda { @ec2.associate_address( :public_ip => "" ) }.should.raise(AWS::ArgumentError) end specify "should be able to be disassociated with an instance with disassociate_address" do @ec2.stubs(:make_request).with('DisassociateAddress', {'PublicIp' => '67.202.55.255'}). returns stub(:body => @disassociate_address_response_body, :is_a? => true) @ec2.disassociate_address( :public_ip => "67.202.55.255" ).should.be.an.instance_of Hash response = @ec2.disassociate_address( :public_ip => "67.202.55.255" ) response.return.should.equal "true" end specify "method disassociate_address should reject bad arguments" do @ec2.stubs(:make_request).with('DisassociateAddress', {'PublicIp' => '67.202.55.255'}). returns stub(:body => @disassociate_address_response_body, :is_a? => true) lambda { @ec2.disassociate_address( :public_ip => "67.202.55.255" ) }.should.not.raise(AWS::ArgumentError) lambda { @ec2.disassociate_address() }.should.raise(AWS::ArgumentError) lambda { @ec2.disassociate_address( :public_ip => "" ) }.should.raise(AWS::ArgumentError) end end grempe-amazon-ec2-043f1b4/test/test_EC2_image_attributes.rb000066400000000000000000000346731147233247500236210ustar00rootroot00000000000000#-- # Amazon Web Services EC2 Query API Ruby library # # Ruby Gem Name:: amazon-ec2 # Author:: Glenn Rempe (mailto:glenn@rempe.us) # Copyright:: Copyright (c) 2007-2008 Glenn Rempe # License:: Distributes under the same terms as Ruby # Home:: http://github.com/grempe/amazon-ec2/tree/master #++ require File.dirname(__FILE__) + '/test_helper.rb' context "EC2 image_attributes " do before do @ec2 = AWS::EC2::Base.new( :access_key_id => "not a key", :secret_access_key => "not a secret" ) @modify_image_attribute_response_body = <<-RESPONSE true RESPONSE @reset_image_attribute_response_body = <<-RESPONSE true RESPONSE @describe_image_attribute_response_body_launch_permissions = <<-RESPONSE ami-61a54008 all 495219933132 RESPONSE @describe_image_attribute_response_body_product_codes = <<-RESPONSE ami-61a54008 774F4FF8 RESPONSE end specify "should be able to be changed with modify_image_attribute (with :attribute and single value :user_id and :group)" do @ec2.stubs(:make_request).with('ModifyImageAttribute', {"ImageId"=>"ami-61a54008", "Attribute"=>"launchPermission", "OperationType"=>"add", "UserId.1"=>"123", "Group.1"=>"all"}). returns stub(:body => @modify_image_attribute_response_body, :is_a? => true) @ec2.modify_image_attribute(:image_id=>"ami-61a54008", :attribute=>"launchPermission", :operation_type=>"add", :user_id=>["123"], :group=>["all"]).should.be.an.instance_of Hash end specify "should be able to be changed with modify_image_attribute ( with :attribute but specifying :group only)" do @ec2.stubs(:make_request).with('ModifyImageAttribute', {"ImageId"=>"ami-61a54008", "Attribute"=>"launchPermission", "OperationType"=>"add", "Group.1"=>"all"}). returns stub(:body => @modify_image_attribute_response_body, :is_a? => true) @ec2.modify_image_attribute(:image_id=>"ami-61a54008", :attribute=>"launchPermission", :operation_type=>"add", :group=>["all"]).should.be.an.instance_of Hash end specify "should be able to be changed with modify_image_attribute ( with :operation_type 'remove')" do @ec2.stubs(:make_request).with('ModifyImageAttribute', {"ImageId"=>"ami-61a54008", "Attribute"=>"launchPermission", "OperationType"=>"remove", "Group.1"=>"all"}). returns stub(:body => @modify_image_attribute_response_body, :is_a? => true) @ec2.modify_image_attribute(:image_id=>"ami-61a54008", :attribute=>"launchPermission", :operation_type=>"remove", :group=>["all"]).should.be.an.instance_of Hash end specify "should be able to be changed with modify_image_attribute ( with :attribute but specifying :user_id only)" do @ec2.stubs(:make_request).with('ModifyImageAttribute', {"ImageId"=>"ami-61a54008", "Attribute"=>"launchPermission", "OperationType"=>"add", "UserId.1"=>"123"}).returns stub(:body => @modify_image_attribute_response_body, :is_a? => true) @ec2.modify_image_attribute(:image_id=>"ami-61a54008", :attribute=>"launchPermission", :operation_type=>"add", :user_id=>["123"]).should.be.an.instance_of Hash end specify "should be able to be changed with modify_image_attribute ( with :attribute=>'productCodes')" do @ec2.stubs(:make_request).with('ModifyImageAttribute', {"ImageId"=>"ami-61a54008", "Attribute"=>"productCodes", "OperationType"=>"", "ProductCode.1"=>"774F4FF8"}).returns stub(:body => @modify_image_attribute_response_body, :is_a? => true) @ec2.modify_image_attribute(:image_id=>"ami-61a54008", :attribute=>"productCodes", :product_code=>["774F4FF8"]).should.be.an.instance_of Hash end specify "should be able to be changed with modify_image_attribute ( with :attribute and multiple :user_id and :group elements)" do @ec2.stubs(:make_request).with('ModifyImageAttribute', {"ImageId"=>"ami-61a54008", "Attribute"=>"launchPermission", "OperationType"=>"add", "UserId.1"=>"123", "UserId.2"=>"345", "Group.1"=>"123", "Group.2"=>"all"}).returns stub(:body => @modify_image_attribute_response_body, :is_a? => true) @ec2.modify_image_attribute(:image_id=>"ami-61a54008", :attribute=>"launchPermission", :operation_type=>"add", :user_id=>["123", "345"], :group=>["123", "all"]).should.be.an.instance_of Hash end specify "should raise an exception when modify_image_attribute is called with incorrect arguments" do # method args can't be nil or empty lambda { @ec2.modify_image_attribute() }.should.raise(AWS::ArgumentError) lambda { @ec2.modify_image_attribute(:image_id=>"") }.should.raise(AWS::ArgumentError) # :image_id option must be not be empty or nil lambda { @ec2.modify_image_attribute(:image_id=>nil, :attribute=>"launchPermission", :operation_type=>"add", :group=>["all"]) }.should.raise(AWS::ArgumentError) lambda { @ec2.modify_image_attribute(:image_id=>"", :attribute=>"launchPermission", :operation_type=>"add", :group=>["all"]) }.should.raise(AWS::ArgumentError) # :attribute currently has two options which are 'launchPermission' and 'productCodes, it should fail with any other value, nil, or empty lambda { @ec2.modify_image_attribute(:image_id=>"ami-61a54008", :attribute=>nil, :operation_type=>"add", :group=>["all"]) }.should.raise(AWS::ArgumentError) lambda { @ec2.modify_image_attribute(:image_id=>"ami-61a54008", :attribute=>"", :operation_type=>"add", :group=>["all"]) }.should.raise(AWS::ArgumentError) lambda { @ec2.modify_image_attribute(:image_id=>"ami-61a54008", :attribute=>"foo", :operation_type=>"add", :group=>["all"]) }.should.raise(AWS::ArgumentError) # :attribute => 'launchPermission' option should fail if neither :group nor :user_id are also provided lambda { @ec2.modify_image_attribute(:image_id=>"ami-61a54008", :attribute=>"launchPermission", :operation_type=>"add") }.should.raise(AWS::ArgumentError) lambda { @ec2.modify_image_attribute(:image_id=>"ami-61a54008", :attribute=>"launchPermission", :operation_type=>"add", :group => nil) }.should.raise(AWS::ArgumentError) lambda { @ec2.modify_image_attribute(:image_id=>"ami-61a54008", :attribute=>"launchPermission", :operation_type=>"add", :group => "") }.should.raise(AWS::ArgumentError) lambda { @ec2.modify_image_attribute(:image_id=>"ami-61a54008", :attribute=>"launchPermission", :operation_type=>"add", :user_id => nil) }.should.raise(AWS::ArgumentError) lambda { @ec2.modify_image_attribute(:image_id=>"ami-61a54008", :attribute=>"launchPermission", :operation_type=>"add", :user_id => "") }.should.raise(AWS::ArgumentError) # :attribute => 'productCodes' option should fail if :product_code isn't also provided lambda { @ec2.modify_image_attribute(:image_id=>"ami-61a54008", :attribute=>"productCodes", :product_code=>nil) }.should.raise(AWS::ArgumentError) lambda { @ec2.modify_image_attribute(:image_id=>"ami-61a54008", :attribute=>"productCodes", :product_code=>"") }.should.raise(AWS::ArgumentError) # :operation_type currently has two options which are 'add' and 'remove', and it should fail with any other, nil or empty lambda { @ec2.modify_image_attribute(:image_id=>"ami-61a54008", :attribute=>"launchPermission", :operation_type=>nil, :group=>["all"]) }.should.raise(AWS::ArgumentError) lambda { @ec2.modify_image_attribute(:image_id=>"ami-61a54008", :attribute=>"launchPermission", :operation_type=>"", :group=>["all"]) }.should.raise(AWS::ArgumentError) lambda { @ec2.modify_image_attribute(:image_id=>"ami-61a54008", :attribute=>"launchPermission", :operation_type=>"foo", :group=>["all"]) }.should.raise(AWS::ArgumentError) end specify "method describe_image_attribute should return the proper attributes when called with launchPermission" do @ec2.stubs(:make_request).with('DescribeImageAttribute', {"ImageId"=>"ami-61a54008", "Attribute"=>"launchPermission" }). returns stub(:body => @describe_image_attribute_response_body_launch_permissions, :is_a? => true) @ec2.describe_image_attribute(:image_id => "ami-61a54008", :attribute => "launchPermission"). should.be.an.instance_of Hash response = @ec2.describe_image_attribute(:image_id=>"ami-61a54008", :attribute=>"launchPermission") response.imageId.should.equal "ami-61a54008" response.launchPermission.item[0].group.should.equal "all" response.launchPermission.item[1].userId.should.equal "495219933132" end specify "method describe_image_attribute should return the proper attributes when called with productCodes" do @ec2.stubs(:make_request).with('DescribeImageAttribute', {"ImageId"=>"ami-61a54008", "Attribute"=>"productCodes" }). returns stub(:body => @describe_image_attribute_response_body_product_codes, :is_a? => true) @ec2.describe_image_attribute(:image_id => "ami-61a54008", :attribute => "productCodes"). should.be.an.instance_of Hash response = @ec2.describe_image_attribute(:image_id=>"ami-61a54008", :attribute=>"productCodes") response.imageId.should.equal "ami-61a54008" response.productCodes.item[0].productCode.should.equal "774F4FF8" end specify "should raise an exception when describe_image_attribute is called with incorrect arguments" do # method args can't be nil or empty lambda { @ec2.describe_image_attribute() }.should.raise(AWS::ArgumentError) lambda { @ec2.describe_image_attribute(:image_id=>"") }.should.raise(AWS::ArgumentError) # :image_id option must be not be empty or nil w/ launchPermission lambda { @ec2.describe_image_attribute(:image_id=>nil, :attribute=>"launchPermission") }.should.raise(AWS::ArgumentError) lambda { @ec2.describe_image_attribute(:image_id=>"", :attribute=>"launchPermission") }.should.raise(AWS::ArgumentError) # :image_id option must be not be empty or nil w/ productCodes lambda { @ec2.describe_image_attribute(:image_id=>nil, :attribute=>"productCodes") }.should.raise(AWS::ArgumentError) lambda { @ec2.describe_image_attribute(:image_id=>"", :attribute=>"productCodes") }.should.raise(AWS::ArgumentError) # :attribute currently has two options which are 'launchPermission' and 'productCodes', it should fail with any other values, # nil, or empty lambda { @ec2.describe_image_attribute(:image_id=>"ami-61a54008", :attribute=>nil) }.should.raise(AWS::ArgumentError) lambda { @ec2.describe_image_attribute(:image_id=>"ami-61a54008", :attribute=>"") }.should.raise(AWS::ArgumentError) lambda { @ec2.describe_image_attribute(:image_id=>"ami-61a54008", :attribute=>"foo") }.should.raise(AWS::ArgumentError) end specify "should be able to reset attributes with reset_image_attribute " do @ec2.stubs(:make_request).with('ResetImageAttribute', {"ImageId"=>"ami-61a54008", "Attribute"=>"launchPermission"}). returns stub(:body => @reset_image_attribute_response_body, :is_a? => true) @ec2.reset_image_attribute(:image_id=>"ami-61a54008", :attribute=>"launchPermission").should.be.an.instance_of Hash @ec2.reset_image_attribute(:image_id=>"ami-61a54008", :attribute=>"launchPermission").return.should.equal "true" end specify "should raise an exception when reset_image_attribute is called with incorrect arguments" do # method args can't be nil or empty lambda { @ec2.reset_image_attribute() }.should.raise(AWS::ArgumentError) lambda { @ec2.reset_image_attribute(:image_id=>"") }.should.raise(AWS::ArgumentError) # :image_id option must be not be empty or nil lambda { @ec2.reset_image_attribute(:image_id=>nil, :attribute=>"launchPermission") }.should.raise(AWS::ArgumentError) lambda { @ec2.reset_image_attribute(:image_id=>"", :attribute=>"launchPermission") }.should.raise(AWS::ArgumentError) # :attribute currently has one option which is 'launchPermission', it should fail with any other value, nil, or empty lambda { @ec2.reset_image_attribute(:image_id=>"ami-61a54008", :attribute=>nil) }.should.raise(AWS::ArgumentError) lambda { @ec2.reset_image_attribute(:image_id=>"ami-61a54008", :attribute=>"") }.should.raise(AWS::ArgumentError) lambda { @ec2.reset_image_attribute(:image_id=>"ami-61a54008", :attribute=>"foo") }.should.raise(AWS::ArgumentError) end end grempe-amazon-ec2-043f1b4/test/test_EC2_images.rb000066400000000000000000000303311147233247500215210ustar00rootroot00000000000000#-- # Amazon Web Services EC2 Query API Ruby library # # Ruby Gem Name:: amazon-ec2 # Author:: Glenn Rempe (mailto:glenn@rempe.us) # Copyright:: Copyright (c) 2007-2008 Glenn Rempe # License:: Distributes under the same terms as Ruby # Home:: http://github.com/grempe/amazon-ec2/tree/master #++ require File.dirname(__FILE__) + '/test_helper.rb' context "An EC2 image " do before do @ec2 = AWS::EC2::Base.new( :access_key_id => "not a key", :secret_access_key => "not a secret" ) @create_image_response_body = <<-RESPONSE ami-4fa54026 RESPONSE @register_image_response_body = <<-RESPONSE ami-61a54008 RESPONSE @describe_image_response_body = <<-RESPONSE ami-61a54008 foobar1/image.manifest.xml available AAAATLBUXIEON5NQVUUX6OMPWBZIAAAA true 774F4FF8 ami-61a54009 foobar2/image.manifest.xml deregistered ZZZZTLBUXIEON5NQVUUX6OMPWBZIZZZZ false RESPONSE @deregister_image_response_body = <<-RESPONSE true RESPONSE end specify "should be able to be created" do @ec2.stubs(:make_request).with('CreateImage', {"InstanceId"=>"fooid", "Name" => "fooname", "Description" => "foodesc", "NoReboot" => "true"}). returns stub(:body => @create_image_response_body, :is_a? => true) @ec2.create_image(:instance_id => "fooid", :name => "fooname", :description => "foodesc", :no_reboot => true).should.be.an.instance_of Hash @ec2.create_image(:instance_id => "fooid", :name => "fooname", :description => "foodesc", :no_reboot => true).imageId.should.equal "ami-4fa54026" end specify "method create_image should raise an exception when called with nil/empty string arguments" do lambda { @ec2.create_image() }.should.raise(AWS::ArgumentError) lambda { @ec2.create_image(:instance_id => "", :name => "fooname") }.should.raise(AWS::ArgumentError) lambda { @ec2.create_image(:instance_id => "fooid", :name => "") }.should.raise(AWS::ArgumentError) lambda { @ec2.create_image(:instance_id => nil, :name => "fooname") }.should.raise(AWS::ArgumentError) lambda { @ec2.create_image(:instance_id => "fooid", :name => nil) }.should.raise(AWS::ArgumentError) end specify "method create_image should raise an exception when called with bad arguments" do lambda { @ec2.create_image(:instance_id => "fooid", :name => "f"*2) }.should.raise(AWS::ArgumentError) lambda { @ec2.create_image(:instance_id => "fooid", :name => "f"*129) }.should.raise(AWS::ArgumentError) lambda { @ec2.create_image(:instance_id => "fooid", :name => "f"*128, :description => "f"*256) }.should.raise(AWS::ArgumentError) lambda { @ec2.create_image(:instance_id => "fooid", :name => "f"*128, :no_reboot => "true") }.should.raise(AWS::ArgumentError) lambda { @ec2.create_image(:instance_id => "fooid", :name => "f"*128, :no_reboot => "false") }.should.raise(AWS::ArgumentError) end specify "should be able to be registered with manifest" do @ec2.stubs(:make_request).with('RegisterImage', {"ImageLocation"=>"mybucket-myimage.manifest.xml"}). returns stub(:body => @register_image_response_body, :is_a? => true) @ec2.register_image(:image_location => "mybucket-myimage.manifest.xml").imageId.should.equal "ami-61a54008" @ec2.register_image(:image_location => "mybucket-myimage.manifest.xml").should.be.an.instance_of Hash end specify "should be able to be registered with snapshot" do @ec2.stubs(:make_request).with('RegisterImage', { "Name" => "image_name", "Architecture" => "i386", "KernelId" => "aki-01234567", "RamdiskId" => "ari-01234567", "RootDeviceName" => "/dev/sda1", "BlockDeviceMapping.1.DeviceName" => "/dev/sda1", "BlockDeviceMapping.1.Ebs.SnapshotId" => "snap-01234567", "BlockDeviceMapping.1.Ebs.DeleteOnTermination" => "true", }).returns stub(:body => @register_image_response_body, :is_a? => true) ret = @ec2.register_image({ :name => "image_name", :architecture => "i386", :kernel_id => "aki-01234567", :ramdisk_id => "ari-01234567", :root_device_name => "/dev/sda1", :block_device_mapping => [{ :device_name => "/dev/sda1", :ebs_snapshot_id => "snap-01234567", :ebs_delete_on_termination => true, }] }) ret.imageId.should.equal "ami-61a54008" ret.should.be.an.instance_of Hash end specify "method register_image should raise an exception when called without :name or :root_device_name" do lambda { @ec2.register_image() }.should.raise(AWS::ArgumentError) lambda { @ec2.register_image(:image_location => "", :root_device_name => "") }.should.raise(AWS::ArgumentError) end specify "should be able to be described and return the correct Ruby response class for parent and members" do @ec2.stubs(:make_request).with('DescribeImages', {}). returns stub(:body => @describe_image_response_body, :is_a? => true) @ec2.describe_images.should.be.an.instance_of Hash response = @ec2.describe_images response.should.be.an.instance_of Hash end specify "should be able to be described with no params and return an imagesSet" do @ec2.stubs(:make_request).with('DescribeImages', {}). returns stub(:body => @describe_image_response_body, :is_a? => true) @ec2.describe_images.imagesSet.item.length.should.equal 2 end specify "should be able to be described by an Array of ImageId.N ID's and return an array of Items" do @ec2.stubs(:make_request).with('DescribeImages', {"ImageId.1"=>"ami-61a54008", "ImageId.2"=>"ami-61a54009"}). returns stub(:body => @describe_image_response_body, :is_a? => true) @ec2.describe_images( :image_id => ["ami-61a54008", "ami-61a54009"] ).imagesSet.item.length.should.equal 2 response = @ec2.describe_images( :image_id => ["ami-61a54008", "ami-61a54009"] ) # test first 'Item' object returned response.imagesSet.item[0].imageId.should.equal "ami-61a54008" response.imagesSet.item[0].imageLocation.should.equal "foobar1/image.manifest.xml" response.imagesSet.item[0].imageState.should.equal "available" response.imagesSet.item[0].imageOwnerId.should.equal "AAAATLBUXIEON5NQVUUX6OMPWBZIAAAA" response.imagesSet.item[0].isPublic.should.equal "true" response.imagesSet.item[0].productCodes.item[0].productCode.should.equal "774F4FF8" # test second 'Item' object returned response.imagesSet.item[1].imageId.should.equal "ami-61a54009" response.imagesSet.item[1].imageLocation.should.equal "foobar2/image.manifest.xml" response.imagesSet.item[1].imageState.should.equal "deregistered" response.imagesSet.item[1].imageOwnerId.should.equal "ZZZZTLBUXIEON5NQVUUX6OMPWBZIZZZZ" response.imagesSet.item[1].isPublic.should.equal "false" end specify "should be able to be described by an owners with Owner.N ID's and return an array of Items" do @ec2.stubs(:make_request).with('DescribeImages', "Owner.1" => "AAAATLBUXIEON5NQVUUX6OMPWBZIAAAA", "Owner.2" => "ZZZZTLBUXIEON5NQVUUX6OMPWBZIZZZZ"). returns stub(:body => @describe_image_response_body, :is_a? => true) @ec2.describe_images( :owner_id => ["AAAATLBUXIEON5NQVUUX6OMPWBZIAAAA", "ZZZZTLBUXIEON5NQVUUX6OMPWBZIZZZZ"] ).imagesSet.item.length.should.equal 2 # owner ID's response = @ec2.describe_images( :owner_id => ["AAAATLBUXIEON5NQVUUX6OMPWBZIAAAA", "ZZZZTLBUXIEON5NQVUUX6OMPWBZIZZZZ"] ) response.imagesSet.item[0].imageId.should.equal "ami-61a54008" response.imagesSet.item[1].imageId.should.equal "ami-61a54009" end specify "should be able to be described by an owner of 'self' and return an array of Items that I own" do @ec2.stubs(:make_request).with('DescribeImages', "Owner.1" => "self"). returns stub(:body => @describe_image_response_body, :is_a? => true) @ec2.describe_images( :owner_id => "self" ).imagesSet.item.length.should.equal 2 # 'self' - Those that I own response = @ec2.describe_images( :owner_id => "self" ) response.imagesSet.item[0].imageId.should.equal "ami-61a54008" end specify "should be able to be described by an owner of 'amazon' and return an array of Items that are Amazon Public AMI's" do @ec2.stubs(:make_request).with('DescribeImages', "Owner.1" => "amazon"). returns stub(:body => @describe_image_response_body, :is_a? => true) @ec2.describe_images( :owner_id => "amazon" ).imagesSet.item.length.should.equal 2 # 'amazon' - Those that are owned and created by AWS response = @ec2.describe_images( :owner_id => "amazon" ) response.imagesSet.item[0].imageId.should.equal "ami-61a54008" end specify "should be able to be described by an owners with Owner.N ID's who can execute AMI's and return an array of Items" do @ec2.stubs(:make_request).with('DescribeImages', "ExecutableBy.1" => "AAAATLBUXIEON5NQVUUX6OMPWBZIAAAA", "ExecutableBy.2" => "ZZZZTLBUXIEON5NQVUUX6OMPWBZIZZZZ"). returns stub(:body => @describe_image_response_body, :is_a? => true) @ec2.describe_images( :executable_by => ["AAAATLBUXIEON5NQVUUX6OMPWBZIAAAA", "ZZZZTLBUXIEON5NQVUUX6OMPWBZIZZZZ"] ).imagesSet.item.length.should.equal 2 # executable by owner ID's response = @ec2.describe_images( :executable_by => ["AAAATLBUXIEON5NQVUUX6OMPWBZIAAAA", "ZZZZTLBUXIEON5NQVUUX6OMPWBZIZZZZ"] ) response.imagesSet.item[0].imageId.should.equal "ami-61a54008" response.imagesSet.item[1].imageId.should.equal "ami-61a54009" end specify "should be able to be described by an owners with Owner.N of 'self' who can execute AMI's and return an array of Items" do @ec2.stubs(:make_request).with('DescribeImages', "ExecutableBy.1" => "self"). returns stub(:body => @describe_image_response_body, :is_a? => true) @ec2.describe_images( :executable_by => "self" ).imagesSet.item.length.should.equal 2 # executable by owner ID's response = @ec2.describe_images( :executable_by => "self" ) response.imagesSet.item[0].imageId.should.equal "ami-61a54008" response.imagesSet.item[1].imageId.should.equal "ami-61a54009" end specify "should be able to be described by an owners with Owner.N of 'all' who can execute AMI's and return an array of Items" do @ec2.stubs(:make_request).with('DescribeImages', "ExecutableBy.1" => "all"). returns stub(:body => @describe_image_response_body, :is_a? => true) @ec2.describe_images( :executable_by => "all" ).imagesSet.item.length.should.equal 2 # executable by owner ID's response = @ec2.describe_images( :executable_by => "all" ) response.imagesSet.item[0].imageId.should.equal "ami-61a54008" response.imagesSet.item[1].imageId.should.equal "ami-61a54009" end specify "should be able to be de-registered" do @ec2.stubs(:make_request).with('DeregisterImage', {"ImageId"=>"ami-61a54008"}). returns stub(:body => @deregister_image_response_body, :is_a? => true) @ec2.deregister_image(:image_id => "ami-61a54008" ).should.be.an.instance_of Hash @ec2.deregister_image(:image_id => "ami-61a54008" ).return.should.equal "true" end specify "method deregister_image should raise an exception when called without nil/empty string arguments" do lambda { @ec2.deregister_image() }.should.raise(AWS::ArgumentError) lambda { @ec2.deregister_image( :image_id => nil ) }.should.raise(AWS::ArgumentError) lambda { @ec2.deregister_image( :image_id => "" ) }.should.raise(AWS::ArgumentError) end end grempe-amazon-ec2-043f1b4/test/test_EC2_instances.rb000066400000000000000000001163561147233247500222570ustar00rootroot00000000000000#-- # Amazon Web Services EC2 Query API Ruby library # # Ruby Gem Name:: amazon-ec2 # Author:: Glenn Rempe (mailto:glenn@rempe.us) # Copyright:: Copyright (c) 2007-2008 Glenn Rempe # License:: Distributes under the same terms as Ruby # Home:: http://github.com/grempe/amazon-ec2/tree/master #++ require File.dirname(__FILE__) + '/test_helper.rb' context "EC2 instances " do before do @ec2 = AWS::EC2::Base.new( :access_key_id => "not a key", :secret_access_key => "not a secret" ) @run_instances_response_body = <<-RESPONSE r-47a5402e 495219933132 default i-2ba64342 ami-60a54009 0 pending example-key-name 0 m1.small 2007-08-07T11:51:50.000Z i-2bc64242 ami-60a54009 0 pending example-key-name 1 m1.small 2007-08-07T11:51:50.000Z i-2be64332 ami-60a54009 0 pending example-key-name 2 m1.small 2007-08-07T11:51:50.000Z RESPONSE @describe_instances_response_body = <<-RESPONSE r-44a5402d UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM default i-28a64341 ami-6ea54007 0 running domU-12-31-35-00-1E-01.z-2.compute-1.internal ec2-72-44-33-4.z-2.compute-1.amazonaws.com example-key-name 774F4FF8 m1.small 2007-08-07T11:54:42.000Z RESPONSE @reboot_instances_response_body = <<-RESPONSE true RESPONSE @start_instances_response_body = <<-RESPONSE i-10a64379 0 pending 80 stopped RESPONSE @stop_instances_response_body = <<-RESPONSE i-28a64341 64 stopping 16 running RESPONSE @terminate_instances_response_body = <<-RESPONSE i-28a64341 32 shutting-down 0 pending i-21a64348 32 shutting-down 0 pending RESPONSE @monitor_instances_response_body = <<-RESPONSE fe62a64c-49fb-4a3c-8d9b-61aba146d390 i-138fc47a pending i-33457a5a pending RESPONSE @unmonitor_instances_response_body = <<-RESPONSE 7dbc5095-f3ae-46d8-a5b1-19df118ceb05 i-138fc47a disabling i-33457a5a disabling RESPONSE @describe_instance_attribute_response_body = <<-RESPONSE i-10a64379 aki-f70657b2 RESPONSE @modify_instance_attribute_response_body = <<-RESPONSE true RESPONSE @reset_instance_attribute_response_body = <<-RESPONSE true RESPONSE end specify "should be able to be run" do @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1'). returns stub(:body => @run_instances_response_body, :is_a? => true) @ec2.run_instances( :image_id => "ami-60a54009" ).should.be.an.instance_of Hash response = @ec2.run_instances( :image_id => "ami-60a54009" ) response.reservationId.should.equal "r-47a5402e" response.ownerId.should.equal "495219933132" response.instancesSet.item.length.should.equal 3 response.instancesSet.item[0].instanceId.should.equal "i-2ba64342" response.instancesSet.item[0].imageId.should.equal "ami-60a54009" response.instancesSet.item[0].instanceState.code.should.equal "0" response.instancesSet.item[0].instanceState.name.should.equal "pending" response.instancesSet.item[0].privateDnsName response.instancesSet.item[0].dnsName.should.be.nil response.instancesSet.item[0].keyName.should.equal "example-key-name" response.instancesSet.item[0].instanceType.should.equal "m1.small" response.instancesSet.item[0].launchTime.should.equal "2007-08-07T11:51:50.000Z" response.instancesSet.item[1].instanceId.should.equal "i-2bc64242" response.instancesSet.item[1].imageId.should.equal "ami-60a54009" response.instancesSet.item[1].instanceState.code.should.equal "0" response.instancesSet.item[1].instanceState.name.should.equal "pending" response.instancesSet.item[1].privateDnsName response.instancesSet.item[1].dnsName.should.be.nil response.instancesSet.item[1].keyName.should.equal "example-key-name" response.instancesSet.item[1].instanceType.should.equal "m1.small" response.instancesSet.item[1].launchTime.should.equal "2007-08-07T11:51:50.000Z" response.instancesSet.item[2].instanceId.should.equal "i-2be64332" response.instancesSet.item[2].imageId.should.equal "ami-60a54009" response.instancesSet.item[2].instanceState.code.should.equal "0" response.instancesSet.item[2].instanceState.name.should.equal "pending" response.instancesSet.item[2].privateDnsName response.instancesSet.item[2].dnsName.should.be.nil response.instancesSet.item[2].keyName.should.equal "example-key-name" response.instancesSet.item[2].instanceType.should.equal "m1.small" response.instancesSet.item[2].launchTime.should.equal "2007-08-07T11:51:50.000Z" end specify "method 'run_instances' should reject invalid arguments" do @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1'). returns stub(:body => @run_instances_response_body, :is_a? => true) lambda { @ec2.run_instances() }.should.raise(AWS::ArgumentError) # :addressing_type is deprecated lambda { @ec2.run_instances( :image_id => "ami-60a54009", :addressing_type => nil ) }.should.not.raise(AWS::ArgumentError) lambda { @ec2.run_instances( :image_id => "ami-60a54009", :addressing_type => "" ) }.should.raise(AWS::ArgumentError) lambda { @ec2.run_instances( :image_id => "ami-60a54009", :addressing_type => "foo" ) }.should.raise(AWS::ArgumentError) # :group_id is deprecated lambda { @ec2.run_instances( :image_id => "ami-60a54009", :group_id => nil ) }.should.not.raise(AWS::ArgumentError) lambda { @ec2.run_instances( :image_id => "ami-60a54009", :group_id => "" ) }.should.raise(AWS::ArgumentError) lambda { @ec2.run_instances( :image_id => "ami-60a54009", :group_id => "foo" ) }.should.raise(AWS::ArgumentError) # :image_id lambda { @ec2.run_instances( :image_id => nil ) }.should.raise(AWS::ArgumentError) lambda { @ec2.run_instances( :image_id => "" ) }.should.raise(AWS::ArgumentError) # :min_count lambda { @ec2.run_instances( :image_id => "ami-60a54009", :min_count => 1 ) }.should.not.raise(AWS::ArgumentError) lambda { @ec2.run_instances( :image_id => "ami-60a54009", :min_count => 0 ) }.should.raise(AWS::ArgumentError) lambda { @ec2.run_instances( :image_id => "ami-60a54009", :min_count => nil ) }.should.raise(AWS::ArgumentError) lambda { @ec2.run_instances( :image_id => "ami-60a54009", :min_count => "" ) }.should.raise(AWS::ArgumentError) lambda { @ec2.run_instances( :image_id => "ami-60a54009", :min_count => "foo" ) }.should.raise(AWS::ArgumentError) # :max_count lambda { @ec2.run_instances( :image_id => "ami-60a54009", :max_count => 1 ) }.should.not.raise(AWS::ArgumentError) lambda { @ec2.run_instances( :image_id => "ami-60a54009", :max_count => 0 ) }.should.raise(AWS::ArgumentError) lambda { @ec2.run_instances( :image_id => "ami-60a54009", :max_count => nil ) }.should.raise(AWS::ArgumentError) lambda { @ec2.run_instances( :image_id => "ami-60a54009", :max_count => "" ) }.should.raise(AWS::ArgumentError) lambda { @ec2.run_instances( :image_id => "ami-60a54009", :max_count => "foo" ) }.should.raise(AWS::ArgumentError) # :min_count & :max_count lambda { @ec2.run_instances( :image_id => "ami-60a54009", :min_count => 1, :max_count => 1 ) }.should.not.raise(AWS::ArgumentError) lambda { @ec2.run_instances( :image_id => "ami-60a54009", :min_count => 2, :max_count => 1 ) }.should.raise(AWS::ArgumentError) # :instance_type ["t1.micro", "m1.small", "m1.large", "m1.xlarge", "m2.xlarge", "c1.medium", "c1.xlarge", "m2.2xlarge", "m2.4xlarge", "cc1.4xlarge"].each do |type| @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', "InstanceType" => type). returns stub(:body => @run_instances_response_body, :is_a? => true) lambda { @ec2.run_instances( :image_id => "ami-60a54009", :instance_type => type ) }.should.not.raise(AWS::ArgumentError) end lambda { @ec2.run_instances( :image_id => "ami-60a54009", :instance_type => "m1.notarealsize" ) }.should.raise(AWS::ArgumentError) # :monitoring_enabled @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', "Monitoring.Enabled" => 'true'). returns stub(:body => @run_instances_response_body, :is_a? => true) lambda { @ec2.run_instances( :image_id => "ami-60a54009", :monitoring_enabled => true ) }.should.not.raise(AWS::ArgumentError) @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', "Monitoring.Enabled" => 'false'). returns stub(:body => @run_instances_response_body, :is_a? => true) lambda { @ec2.run_instances( :image_id => "ami-60a54009", :monitoring_enabled => false ) }.should.not.raise(AWS::ArgumentError) @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', "Monitoring.Enabled" => 'false'). returns stub(:body => @run_instances_response_body, :is_a? => true) lambda { @ec2.run_instances( :image_id => "ami-60a54009", :monitoring_enabled => "foo" ) }.should.raise(AWS::ArgumentError) # :disable_api_termination @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', "DisableApiTermination" => 'true'). returns stub(:body => @run_instances_response_body, :is_a? => true) lambda { @ec2.run_instances( :image_id => "ami-60a54009", :disable_api_termination => true ) }.should.not.raise(AWS::ArgumentError) @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', "DisableApiTermination" => 'false'). returns stub(:body => @run_instances_response_body, :is_a? => true) lambda { @ec2.run_instances( :image_id => "ami-60a54009", :disable_api_termination => false ) }.should.not.raise(AWS::ArgumentError) @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', "DisableApiTermination" => 'false'). returns stub(:body => @run_instances_response_body, :is_a? => true) lambda { @ec2.run_instances( :image_id => "ami-60a54009", :disable_api_termination => "foo" ) }.should.raise(AWS::ArgumentError) # :instance_initiated_shutdown_behavior @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', "InstanceInitiatedShutdownBehavior" => 'stop'). returns stub(:body => @run_instances_response_body, :is_a? => true) lambda { @ec2.run_instances( :image_id => "ami-60a54009", :instance_initiated_shutdown_behavior => 'stop' ) }.should.not.raise(AWS::ArgumentError) @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', "InstanceInitiatedShutdownBehavior" => 'terminate'). returns stub(:body => @run_instances_response_body, :is_a? => true) lambda { @ec2.run_instances( :image_id => "ami-60a54009", :instance_initiated_shutdown_behavior => 'terminate' ) }.should.not.raise(AWS::ArgumentError) @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', "InstanceInitiatedShutdownBehavior" => 'stop'). returns stub(:body => @run_instances_response_body, :is_a? => true) lambda { @ec2.run_instances( :image_id => "ami-60a54009", :instance_initiated_shutdown_behavior => "foo" ) }.should.raise(AWS::ArgumentError) @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', "InstanceInitiatedShutdownBehavior" => 'stop'). returns stub(:body => @run_instances_response_body, :is_a? => true) lambda { @ec2.run_instances( :image_id => "ami-60a54009", :instance_initiated_shutdown_behavior => true ) }.should.raise(AWS::ArgumentError) # :base64_encoded lambda { @ec2.run_instances( :image_id => "ami-60a54009", :base64_encoded => true ) }.should.not.raise(AWS::ArgumentError) lambda { @ec2.run_instances( :image_id => "ami-60a54009", :base64_encoded => false ) }.should.not.raise(AWS::ArgumentError) lambda { @ec2.run_instances( :image_id => "ami-60a54009", :base64_encoded => nil ) }.should.raise(AWS::ArgumentError) lambda { @ec2.run_instances( :image_id => "ami-60a54009", :base64_encoded => "" ) }.should.raise(AWS::ArgumentError) lambda { @ec2.run_instances( :image_id => "ami-60a54009", :base64_encoded => "foo" ) }.should.raise(AWS::ArgumentError) end specify "should be able specify a key_name" do @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', "KeyName" => 'foo'). returns stub(:body => @run_instances_response_body, :is_a? => true) @ec2.run_instances( :image_id => "ami-60a54009", :key_name => "foo" ).should.be.an.instance_of Hash end specify "should be able specify a security_group" do @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', "SecurityGroup.1" => 'foo', "SecurityGroup.2" => 'bar'). returns stub(:body => @run_instances_response_body, :is_a? => true) @ec2.run_instances( :image_id => "ami-60a54009", :security_group => ["foo","bar"] ).should.be.an.instance_of Hash end specify "should be able specify additional_info" do @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', "AdditionalInfo" => 'foo'). returns stub(:body => @run_instances_response_body, :is_a? => true) @ec2.run_instances( :image_id => "ami-60a54009", :additional_info => "foo" ).should.be.an.instance_of Hash end specify "should be able to call run_instances with :user_data and :base64_encoded => true (default is false)" do @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', "UserData" => "Zm9v"). returns stub(:body => @run_instances_response_body, :is_a? => true) @ec2.run_instances( :image_id => "ami-60a54009", :min_count => 1, :max_count => 1, :user_data => "foo", :base64_encoded => true ).should.be.an.instance_of Hash end specify "should be able to call run_instances with :user_data and :base64_encoded => false" do @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', "UserData" => "foo"). returns stub(:body => @run_instances_response_body, :is_a? => true) @ec2.run_instances( :image_id => "ami-60a54009", :min_count => 1, :max_count => 1, :user_data => "foo", :base64_encoded => false ).should.be.an.instance_of Hash end specify "should be able specify instance_type" do @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', "InstanceType" => 'm1.small'). returns stub(:body => @run_instances_response_body, :is_a? => true) @ec2.run_instances( :image_id => "ami-60a54009", :instance_type => "m1.small" ).should.be.an.instance_of Hash end specify "should be able specify an availability_zone (Placement.AvailabilityZone)" do @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', "Placement.AvailabilityZone" => "zone123"). returns stub(:body => @run_instances_response_body, :is_a? => true) @ec2.run_instances( :image_id => "ami-60a54009", :availability_zone => "zone123" ).should.be.an.instance_of Hash end specify "should be able specify an kernel_id" do @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', 'KernelId' => 'kernfoo'). returns stub(:body => @run_instances_response_body, :is_a? => true) @ec2.run_instances( :image_id => "ami-60a54009", :kernel_id => 'kernfoo' ).should.be.an.instance_of Hash end specify "should be able specify an ramdisk_id" do @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', 'RamdiskId' => 'foo'). returns stub(:body => @run_instances_response_body, :is_a? => true) @ec2.run_instances( :image_id => "ami-60a54009", :ramdisk_id => 'foo' ).should.be.an.instance_of Hash end specify "should be able specify monitoring_enabled" do @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', 'Monitoring.Enabled' => 'true'). returns stub(:body => @run_instances_response_body, :is_a? => true) @ec2.run_instances( :image_id => "ami-60a54009", :monitoring_enabled => true ).should.be.an.instance_of Hash end specify "should be able specify an subnet_id" do @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', 'SubnetId' => 'foo'). returns stub(:body => @run_instances_response_body, :is_a? => true) @ec2.run_instances( :image_id => "ami-60a54009", :subnet_id => 'foo' ).should.be.an.instance_of Hash end specify "should be able specify disable_api_termination" do @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', 'DisableApiTermination' => 'true'). returns stub(:body => @run_instances_response_body, :is_a? => true) @ec2.run_instances( :image_id => "ami-60a54009", :disable_api_termination => true ).should.be.an.instance_of Hash end specify "should be able specify instance_initiated_shutdown_behavior" do @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', 'InstanceInitiatedShutdownBehavior' => 'stop'). returns stub(:body => @run_instances_response_body, :is_a? => true) @ec2.run_instances( :image_id => "ami-60a54009", :instance_initiated_shutdown_behavior => 'stop' ).should.be.an.instance_of Hash end specify "should be able specify block_device_mapping" do @ec2.stubs(:make_request).with('RunInstances', "ImageId" => "ami-60a54009", "MinCount" => '1', "MaxCount" => '1', 'BlockDeviceMapping.1.DeviceName' => '/dev/sdh', 'BlockDeviceMapping.1.VirtualName' => 'foo', 'BlockDeviceMapping.1.Ebs.SnapshotId' => 'foosnap', 'BlockDeviceMapping.1.Ebs.VolumeSize' => 'foovolsize', 'BlockDeviceMapping.1.Ebs.DeleteOnTermination' => 'true', 'BlockDeviceMapping.2.DeviceName' => '/dev/sdi', 'BlockDeviceMapping.2.VirtualName' => 'foo2', 'BlockDeviceMapping.2.Ebs.SnapshotId' => 'foosnap2', 'BlockDeviceMapping.2.Ebs.VolumeSize' => 'foovolsize2', 'BlockDeviceMapping.2.Ebs.DeleteOnTermination' => 'false'). returns stub(:body => @run_instances_response_body, :is_a? => true) @ec2.run_instances( :image_id => "ami-60a54009", :block_device_mapping => [{:device_name => '/dev/sdh', :virtual_name => 'foo', :ebs_snapshot_id => 'foosnap', :ebs_volume_size => 'foovolsize', :ebs_delete_on_termination => true},{:device_name => '/dev/sdi', :virtual_name => 'foo2', :ebs_snapshot_id => 'foosnap2', :ebs_volume_size => 'foovolsize2', :ebs_delete_on_termination => false}] ).should.be.an.instance_of Hash end specify "should get no user data for when options has no user_data key" do @ec2.extract_user_data({}).should == nil end specify "should get plain string user data when options has user_data and no base64 key" do @ec2.extract_user_data({:user_data => "foo\nbar"}).should == "foo\nbar" end specify "should strip new lines and base64 encode when options has both user_data and base64" do @ec2.extract_user_data({:user_data => "binary\ndata\nhere\n", :base64_encoded => true}).should == "YmluYXJ5CmRhdGEKaGVyZQo=" end specify "should be able to be described and return the correct Ruby response class" do @ec2.stubs(:make_request).with('DescribeInstances', {}). returns stub(:body => @describe_instances_response_body, :is_a? => true) @ec2.describe_instances.should.be.an.instance_of Hash response = @ec2.describe_instances response.reservationSet.item[0].reservationId.should.equal "r-44a5402d" end specify "should be able to be described with no params and return an array of Items" do @ec2.stubs(:make_request).with('DescribeInstances', {}). returns stub(:body => @describe_instances_response_body, :is_a? => true) @ec2.describe_instances.reservationSet.item.length.should.equal 1 response = @ec2.describe_instances response.reservationSet.item[0].reservationId.should.equal "r-44a5402d" response.reservationSet.item[0].ownerId.should.equal "UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM" response.reservationSet.item[0].instancesSet.item[0].instanceId.should.equal "i-28a64341" response.reservationSet.item[0].instancesSet.item[0].imageId.should.equal "ami-6ea54007" response.reservationSet.item[0].instancesSet.item[0].instanceState.code.should.equal "0" response.reservationSet.item[0].instancesSet.item[0].instanceState.name.should.equal "running" response.reservationSet.item[0].instancesSet.item[0].privateDnsName.should.equal "domU-12-31-35-00-1E-01.z-2.compute-1.internal" response.reservationSet.item[0].instancesSet.item[0].dnsName.should.equal "ec2-72-44-33-4.z-2.compute-1.amazonaws.com" response.reservationSet.item[0].instancesSet.item[0].keyName.should.equal "example-key-name" response.reservationSet.item[0].instancesSet.item[0].productCodesSet.item[0].productCode.should.equal "774F4FF8" end specify "should be able to be described with params of Array of :instance_id's and return an array of Items" do @ec2.stubs(:make_request).with('DescribeInstances', {"InstanceId.1" => "i-28a64341"}). returns stub(:body => @describe_instances_response_body, :is_a? => true) @ec2.describe_instances( :instance_id => "i-28a64341" ).reservationSet.item.length.should.equal 1 response = @ec2.describe_instances( :instance_id => "i-28a64341" ) response.reservationSet.item[0].reservationId.should.equal "r-44a5402d" response.reservationSet.item[0].ownerId.should.equal "UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM" response.reservationSet.item[0].instancesSet.item[0].instanceId.should.equal "i-28a64341" response.reservationSet.item[0].instancesSet.item[0].imageId.should.equal "ami-6ea54007" response.reservationSet.item[0].instancesSet.item[0].instanceState.code.should.equal "0" response.reservationSet.item[0].instancesSet.item[0].instanceState.name.should.equal "running" response.reservationSet.item[0].instancesSet.item[0].privateDnsName.should.equal "domU-12-31-35-00-1E-01.z-2.compute-1.internal" response.reservationSet.item[0].instancesSet.item[0].dnsName.should.equal "ec2-72-44-33-4.z-2.compute-1.amazonaws.com" response.reservationSet.item[0].instancesSet.item[0].keyName.should.equal "example-key-name" response.reservationSet.item[0].instancesSet.item[0].productCodesSet.item[0].productCode.should.equal "774F4FF8" end specify "method reboot_instances should raise an exception when called without nil/empty string arguments" do lambda { @ec2.reboot_instances() }.should.raise(AWS::ArgumentError) lambda { @ec2.reboot_instances( :instance_id => nil ) }.should.raise(AWS::ArgumentError) lambda { @ec2.reboot_instances( :instance_id => "" ) }.should.raise(AWS::ArgumentError) end specify "should be able to be rebooted when provided with an :instance_id" do @ec2.expects(:make_request).with('RebootInstances', {"InstanceId.1"=>"i-2ea64347", "InstanceId.2"=>"i-21a64348"}). returns stub(:body => @reboot_instances_response_body, :is_a? => true) @ec2.reboot_instances( :instance_id => ["i-2ea64347", "i-21a64348"] ).class.should.equal Hash end specify "method start_instances should raise an exception when called without nil/empty string arguments" do lambda { @ec2.start_instances() }.should.raise(AWS::ArgumentError) lambda { @ec2.start_instances( :instance_id => nil ) }.should.raise(AWS::ArgumentError) lambda { @ec2.start_instances( :instance_id => "" ) }.should.raise(AWS::ArgumentError) end specify "should be able to be started when provided with an :instance_id" do @ec2.stubs(:make_request).with('StartInstances', {"InstanceId.1"=>"i-28a64341", "InstanceId.2"=>"i-21a64348"}). returns stub(:body => @start_instances_response_body, :is_a? => true) @ec2.start_instances( :instance_id => ["i-28a64341", "i-21a64348"] ).class.should.equal Hash end specify "method stop_instances should raise an exception when called without nil/empty string arguments" do lambda { @ec2.stop_instances() }.should.raise(AWS::ArgumentError) lambda { @ec2.stop_instances( :instance_id => nil ) }.should.raise(AWS::ArgumentError) lambda { @ec2.stop_instances( :instance_id => "" ) }.should.raise(AWS::ArgumentError) end specify "should be able to be stopped when provided with an :instance_id" do @ec2.stubs(:make_request).with('StopInstances', {"InstanceId.1"=>"i-28a64341", "InstanceId.2"=>"i-21a64348"}). returns stub(:body => @stop_instances_response_body, :is_a? => true) @ec2.stop_instances( :instance_id => ["i-28a64341", "i-21a64348"] ).class.should.equal Hash end specify "method terminate_instances should raise an exception when called without nil/empty string arguments" do lambda { @ec2.terminate_instances() }.should.raise(AWS::ArgumentError) lambda { @ec2.terminate_instances( :instance_id => nil ) }.should.raise(AWS::ArgumentError) lambda { @ec2.terminate_instances( :instance_id => "" ) }.should.raise(AWS::ArgumentError) end specify "should be able to be terminated when provided with an :instance_id" do @ec2.stubs(:make_request).with('TerminateInstances', {"InstanceId.1"=>"i-28a64341", "InstanceId.2"=>"i-21a64348"}). returns stub(:body => @terminate_instances_response_body, :is_a? => true) @ec2.terminate_instances( :instance_id => ["i-28a64341", "i-21a64348"] ).class.should.equal Hash @response = @ec2.terminate_instances( :instance_id => ["i-28a64341", "i-21a64348"] ) @response.instancesSet.item[0].instanceId.should.equal "i-28a64341" @response.instancesSet.item[0].shutdownState.code.should.equal "32" @response.instancesSet.item[0].shutdownState.name.should.equal "shutting-down" @response.instancesSet.item[0].previousState.code.should.equal "0" @response.instancesSet.item[0].previousState.name.should.equal "pending" @response.instancesSet.item[1].instanceId.should.equal "i-21a64348" @response.instancesSet.item[1].shutdownState.code.should.equal "32" @response.instancesSet.item[1].shutdownState.name.should.equal "shutting-down" @response.instancesSet.item[1].previousState.code.should.equal "0" @response.instancesSet.item[1].previousState.name.should.equal "pending" end specify "method monitor_instances should raise an exception when called without nil/empty string arguments" do lambda { @ec2.monitor_instances() }.should.raise(AWS::ArgumentError) lambda { @ec2.monitor_instances( :instance_id => nil ) }.should.raise(AWS::ArgumentError) lambda { @ec2.monitor_instances( :instance_id => "" ) }.should.raise(AWS::ArgumentError) end specify "should be able to be monitored when provided with an :instance_id" do @ec2.stubs(:make_request).with('MonitorInstances', {"InstanceId.1"=>"i-138fc47a", "InstanceId.2"=>"i-33457a5a"}). returns stub(:body => @monitor_instances_response_body, :is_a? => true) @ec2.monitor_instances( :instance_id => ["i-138fc47a", "i-33457a5a"] ).class.should.equal Hash @response = @ec2.monitor_instances( :instance_id => ["i-138fc47a", "i-33457a5a"] ) @response.instancesSet.item[0].instanceId.should.equal "i-138fc47a" @response.instancesSet.item[0].monitoring.state.should.equal "pending" @response.instancesSet.item[1].instanceId.should.equal "i-33457a5a" @response.instancesSet.item[1].monitoring.state.should.equal "pending" end specify "method unmonitor_instances should raise an exception when called without nil/empty string arguments" do lambda { @ec2.unmonitor_instances() }.should.raise(AWS::ArgumentError) lambda { @ec2.unmonitor_instances( :instance_id => nil ) }.should.raise(AWS::ArgumentError) lambda { @ec2.unmonitor_instances( :instance_id => "" ) }.should.raise(AWS::ArgumentError) end specify "should be able to be unmonitored when provided with an :instance_id" do @ec2.stubs(:make_request).with('UnmonitorInstances', {"InstanceId.1"=>"i-138fc47a", "InstanceId.2"=>"i-33457a5a"}). returns stub(:body => @unmonitor_instances_response_body, :is_a? => true) @ec2.unmonitor_instances( :instance_id => ["i-138fc47a", "i-33457a5a"] ).class.should.equal Hash @response = @ec2.unmonitor_instances( :instance_id => ["i-138fc47a", "i-33457a5a"] ) @response.instancesSet.item[0].instanceId.should.equal "i-138fc47a" @response.instancesSet.item[0].monitoring.state.should.equal "disabling" @response.instancesSet.item[1].instanceId.should.equal "i-33457a5a" @response.instancesSet.item[1].monitoring.state.should.equal "disabling" end specify "should get an ArgumentError when trying to describe/modify/reset an instance attribute without an istance id" do lambda { @ec2.describe_instance_attribute(:attribute => "ramdisk") }.should.raise(AWS::ArgumentError) lambda { @ec2.modify_instance_attribute(:attribute => "ramdisk") }.should.raise(AWS::ArgumentError) lambda { @ec2.reset_instance_attribute(:attribute => "ramdisk") }.should.raise(AWS::ArgumentError) lambda { @ec2.describe_instance_attribute(:attribute => "ramdisk", :instance_id => nil) }.should.raise(AWS::ArgumentError) lambda { @ec2.modify_instance_attribute(:attribute => "ramdisk", :instance_id => nil) }.should.raise(AWS::ArgumentError) lambda { @ec2.reset_instance_attribute(:attribute => "ramdisk", :instance_id => nil) }.should.raise(AWS::ArgumentError) lambda { @ec2.describe_instance_attribute(:attribute => "ramdisk", :instance_id => "") }.should.raise(AWS::ArgumentError) lambda { @ec2.modify_instance_attribute(:attribute => "ramdisk", :instance_id => "") }.should.raise(AWS::ArgumentError) lambda { @ec2.reset_instance_attribute(:attribute => "ramdisk", :instance_id => "") }.should.raise(AWS::ArgumentError) end specify "should get an ArgumentError when trying to describe/modify/reset an instance attribute without an attribute" do lambda { @ec2.describe_instance_attribute(:instance_id => "i-33457a5a") }.should.raise(AWS::ArgumentError) lambda { @ec2.modify_instance_attribute(:instance_id => "i-33457a5a") }.should.raise(AWS::ArgumentError) lambda { @ec2.reset_instance_attribute(:instance_id => "i-33457a5a") }.should.raise(AWS::ArgumentError) lambda { @ec2.describe_instance_attribute(:instance_id => "i-33457a5a", :attribute => nil) }.should.raise(AWS::ArgumentError) lambda { @ec2.modify_instance_attribute(:instance_id => "i-33457a5a", :attribute => nil) }.should.raise(AWS::ArgumentError) lambda { @ec2.reset_instance_attribute(:instance_id => "i-33457a5a", :attribute => nil) }.should.raise(AWS::ArgumentError) lambda { @ec2.describe_instance_attribute(:instance_id => "i-33457a5a", :attribute => "") }.should.raise(AWS::ArgumentError) lambda { @ec2.modify_instance_attribute(:instance_id => "i-33457a5a", :attribute => "") }.should.raise(AWS::ArgumentError) lambda { @ec2.reset_instance_attribute(:instance_id => "i-33457a5a", :attribute => "") }.should.raise(AWS::ArgumentError) end specify "should get an ArgumentError when trying to describe/modify/reset an instance attribute without a valid attribute" do lambda { @ec2.describe_instance_attribute(:instance_id => "i-33457a5a", :attribute => 'party') }.should.raise(AWS::ArgumentError) lambda { @ec2.modify_instance_attribute(:instance_id => "i-33457a5a", :attribute => 'party') }.should.raise(AWS::ArgumentError) lambda { @ec2.reset_instance_attribute(:instance_id => "i-33457a5a", :attribute => 'party') }.should.raise(AWS::ArgumentError) end specify "should not get an ArgumentError when trying to describe/modify/reset an instance attribute with a valid attribute" do @ec2.stubs(:make_request).returns stub(:body => @describe_instance_attribute_response_body, :is_a? => true) %w(instanceType kernel ramdisk userData disableApiTermination instanceInitiatedShutdownBehavior rootDevice blockDeviceMapping).each do |a| lambda { @ec2.describe_instance_attribute(:instance_id => "i-33457a5a", :attribute => a) }.should.not.raise(AWS::ArgumentError) lambda { @ec2.modify_instance_attribute(:instance_id => "i-33457a5a", :attribute => 'party') }.should.raise(AWS::ArgumentError) end %w(kernel ramdisk).each do |a| lambda { @ec2.reset_instance_attribute(:instance_id => "i-33457a5a", :attribute => 'party') }.should.raise(AWS::ArgumentError) end end specify "should successfully describe instance attribute" do @ec2.stubs(:make_request).with('DescribeInstanceAttribute', {"InstanceId"=>"i-33457a5a", "Attribute" => "kernel"}). returns stub(:body => @describe_instance_attribute_response_body, :is_a? => true) @response = @ec2.describe_instance_attribute(:instance_id => "i-33457a5a", :attribute => 'kernel') @response.class.should.equal Hash @response.kernel.value.should.equal "aki-f70657b2" end specify "should successfully modify instance attribute" do @ec2.stubs(:make_request).with('ModifyInstanceAttribute', {"InstanceId"=>"i-33457a5a", "Attribute" => "disableApiTermination", "Value" => "true"}). returns stub(:body => @modify_instance_attribute_response_body, :is_a? => true) @response = @ec2.modify_instance_attribute(:instance_id => "i-33457a5a", :attribute => 'disableApiTermination', :value => true) @response.class.should.equal Hash @response.return.should.equal "true" end specify "should successfully reset instance attribute" do @ec2.stubs(:make_request).with('ResetInstanceAttribute', {"InstanceId"=>"i-33457a5a", "Attribute" => "kernel"}). returns stub(:body => @reset_instance_attribute_response_body, :is_a? => true) @response = @ec2.reset_instance_attribute(:instance_id => "i-33457a5a", :attribute => 'kernel') @response.class.should.equal Hash @response.return.should.equal "true" end end grempe-amazon-ec2-043f1b4/test/test_EC2_keypairs.rb000066400000000000000000000136061147233247500221110ustar00rootroot00000000000000#-- # Amazon Web Services EC2 Query API Ruby library # # Ruby Gem Name:: amazon-ec2 # Author:: Glenn Rempe (mailto:glenn@rempe.us) # Copyright:: Copyright (c) 2007-2008 Glenn Rempe # License:: Distributes under the same terms as Ruby # Home:: http://github.com/grempe/amazon-ec2/tree/master #++ require File.dirname(__FILE__) + '/test_helper.rb' context "EC2 keypairs " do before do @ec2 = AWS::EC2::Base.new( :access_key_id => "not a key", :secret_access_key => "not a secret" ) @create_keypair_response_body = <<-RESPONSE example-key-name 1f:51:ae:28:bf:89:e9:d8:1f:25:5d:37:2d:7d:b8:ca:9f:f5:f1:6f -----BEGIN RSA PRIVATE KEY----- MIIEoQIBAAKCAQBuLFg5ujHrtm1jnutSuoO8Xe56LlT+HM8v/xkaa39EstM3/aFxTHgElQiJLChp HungXQ29VTc8rc1bW0lkdi23OH5eqkMHGhvEwqa0HWASUMll4o3o/IX+0f2UcPoKCOVUR+jx71Sg 5AU52EQfanIn3ZQ8lFW7Edp5a3q4DhjGlUKToHVbicL5E+g45zfB95wIyywWZfeW/UUF3LpGZyq/ ebIUlq1qTbHkLbCC2r7RTn8vpQWp47BGVYGtGSBMpTRP5hnbzzuqj3itkiLHjU39S2sJCJ0TrJx5 i8BygR4s3mHKBj8l+ePQxG1kGbF6R4yg6sECmXn17MRQVXODNHZbAgMBAAECggEAY1tsiUsIwDl5 91CXirkYGuVfLyLflXenxfI50mDFms/mumTqloHO7tr0oriHDR5K7wMcY/YY5YkcXNo7mvUVD1pM ZNUJs7rw9gZRTrf7LylaJ58kOcyajw8TsC4e4LPbFaHwS1d6K8rXh64o6WgW4SrsB6ICmr1kGQI7 3wcfgt5ecIu4TZf0OE9IHjn+2eRlsrjBdeORi7KiUNC/pAG23I6MdDOFEQRcCSigCj+4/mciFUSA SWS4dMbrpb9FNSIcf9dcLxVM7/6KxgJNfZc9XWzUw77Jg8x92Zd0fVhHOux5IZC+UvSKWB4dyfcI tE8C3p9bbU9VGyY5vLCAiIb4qQKBgQDLiO24GXrIkswF32YtBBMuVgLGCwU9h9HlO9mKAc2m8Cm1 jUE5IpzRjTedc9I2qiIMUTwtgnw42auSCzbUeYMURPtDqyQ7p6AjMujp9EPemcSVOK9vXYL0Ptco xW9MC0dtV6iPkCN7gOqiZXPRKaFbWADp16p8UAIvS/a5XXk5jwKBgQCKkpHi2EISh1uRkhxljyWC iDCiK6JBRsMvpLbc0v5dKwP5alo1fmdR5PJaV2qvZSj5CYNpMAy1/EDNTY5OSIJU+0KFmQbyhsbm rdLNLDL4+TcnT7c62/aH01ohYaf/VCbRhtLlBfqGoQc7+sAc8vmKkesnF7CqCEKDyF/dhrxYdQKB gC0iZzzNAapayz1+JcVTwwEid6j9JqNXbBc+Z2YwMi+T0Fv/P/hwkX/ypeOXnIUcw0Ih/YtGBVAC DQbsz7LcY1HqXiHKYNWNvXgwwO+oiChjxvEkSdsTTIfnK4VSCvU9BxDbQHjdiNDJbL6oar92UN7V rBYvChJZF7LvUH4YmVpHAoGAbZ2X7XvoeEO+uZ58/BGKOIGHByHBDiXtzMhdJr15HTYjxK7OgTZm gK+8zp4L9IbvLGDMJO8vft32XPEWuvI8twCzFH+CsWLQADZMZKSsBasOZ/h1FwhdMgCMcY+Qlzd4 JZKjTSu3i7vhvx6RzdSedXEMNTZWN4qlIx3kR5aHcukCgYA9T+Zrvm1F0seQPbLknn7EqhXIjBaT P8TTvW/6bdPi23ExzxZn7KOdrfclYRph1LHMpAONv/x2xALIf91UB+v5ohy1oDoasL0gij1houRe 2ERKKdwz0ZL9SWq6VTdhr/5G994CK72fy5WhyERbDjUIdHaK3M849JJuf8cSrvSb4g== -----END RSA PRIVATE KEY----- RESPONSE @describe_keypairs_response_body = <<-RESPONSE example-key-name 1f:51:ae:28:bf:89:e9:d8:1f:25:5d:37:2d:7d:b8:ca:9f:f5:f1:6f RESPONSE @delete_keypair_body = <<-RESPONSE true RESPONSE end specify "should be able to be created" do @ec2.stubs(:make_request).with('CreateKeyPair', {"KeyName"=>"example-key-name"}). returns stub(:body => @create_keypair_response_body, :is_a? => true) @ec2.create_keypair( :key_name => "example-key-name" ).should.be.an.instance_of Hash response = @ec2.create_keypair( :key_name => "example-key-name" ) response.keyName.should.equal "example-key-name" response.keyFingerprint.should.equal "1f:51:ae:28:bf:89:e9:d8:1f:25:5d:37:2d:7d:b8:ca:9f:f5:f1:6f" response.keyMaterial.should.not.equal "" response.keyMaterial.should.not.be.nil end specify "method create_keypair should reject bad arguments" do @ec2.stubs(:make_request).with('CreateKeyPair', {"KeyName"=>"example-key-name"}). returns stub(:body => @create_keypair_response_body, :is_a? => true) lambda { @ec2.create_keypair( :key_name => "example-key-name" ) }.should.not.raise(AWS::ArgumentError) lambda { @ec2.create_keypair() }.should.raise(AWS::ArgumentError) lambda { @ec2.create_keypair( :key_name => nil ) }.should.raise(AWS::ArgumentError) lambda { @ec2.create_keypair( :key_name => "" ) }.should.raise(AWS::ArgumentError) end specify "should be able to be described with describe_keypairs" do @ec2.stubs(:make_request).with('DescribeKeyPairs', {"KeyName.1"=>"example-key-name"}). returns stub(:body => @describe_keypairs_response_body, :is_a? => true) @ec2.describe_keypairs( :key_name => "example-key-name" ).should.be.an.instance_of Hash response = @ec2.describe_keypairs( :key_name => "example-key-name" ) response.keySet.item[0].keyName.should.equal "example-key-name" response.keySet.item[0].keyFingerprint.should.equal "1f:51:ae:28:bf:89:e9:d8:1f:25:5d:37:2d:7d:b8:ca:9f:f5:f1:6f" end specify "should be able to be deleted with delete_keypairs" do @ec2.stubs(:make_request).with('DeleteKeyPair', {"KeyName"=>"example-key-name"}). returns stub(:body => @delete_keypair_body, :is_a? => true) @ec2.delete_keypair( :key_name => "example-key-name" ).should.be.an.instance_of Hash response = @ec2.delete_keypair( :key_name => "example-key-name" ) response.return.should.equal "true" end specify "method delete_keypair should reject bad argument" do @ec2.stubs(:make_request).with('DeleteKeyPair', {"KeyName"=>"example-key-name"}). returns stub(:body => @delete_keypair_body, :is_a? => true) lambda { @ec2.delete_keypair( :key_name => "example-key-name" ) }.should.not.raise(AWS::ArgumentError) lambda { @ec2.delete_keypair() }.should.raise(AWS::ArgumentError) lambda { @ec2.delete_keypair( :key_name => nil ) }.should.raise(AWS::ArgumentError) lambda { @ec2.delete_keypair( :key_name => "" ) }.should.raise(AWS::ArgumentError) end end grempe-amazon-ec2-043f1b4/test/test_EC2_password.rb000066400000000000000000000035471147233247500221270ustar00rootroot00000000000000#-- # Amazon Web Services EC2 Query API Ruby library # # Ruby Gem Name:: amazon-ec2 # Author:: Glenn Rempe (mailto:glenn@rempe.us) # Copyright:: Copyright (c) 2007-2008 Glenn Rempe # License:: Distributes under the same terms as Ruby # Home:: http://github.com/grempe/amazon-ec2/tree/master #++ require File.dirname(__FILE__) + '/test_helper.rb' context "The EC2 password " do before do @ec2 = AWS::EC2::Base.new( :access_key_id => "not a key", :secret_access_key => "not a secret" ) @get_password_data_response_body = <<-RESPONSE i-2574e22a 2009-10-24 15:00:00 TGludXggdmVyc2lvbiAyLjYuMTYteGVuVSAoYnVpbGRlckBwYXRjaGJhdC5hbWF6b25zYSkgKGdj RESPONSE end specify "should return an encrypted password encoded by base64 " do @ec2.stubs(:make_request).with('GetPasswordData', {"InstanceId"=>"i-2574e22a"}). returns stub(:body => @get_password_data_response_body, :is_a? => true) @ec2.get_password_data( :instance_id => "i-2574e22a" ).should.be.an.instance_of Hash response = @ec2.get_password_data( :instance_id => "i-2574e22a" ) response.instanceId.should.equal "i-2574e22a" response.timestamp.should.equal "2009-10-24 15:00:00" response.passwordData.should.equal "TGludXggdmVyc2lvbiAyLjYuMTYteGVuVSAoYnVpbGRlckBwYXRjaGJhdC5hbWF6b25zYSkgKGdj" end specify "method get_password_data should raise an exception when called without nil/empty string arguments" do lambda { @ec2.get_password_data() }.should.raise(AWS::ArgumentError) lambda { @ec2.get_password_data(:instance_id => nil) }.should.raise(AWS::ArgumentError) lambda { @ec2.get_password_data(:instance_id => "") }.should.raise(AWS::ArgumentError) end end grempe-amazon-ec2-043f1b4/test/test_EC2_products.rb000066400000000000000000000040741147233247500221240ustar00rootroot00000000000000#-- # Amazon Web Services EC2 Query API Ruby library # # Ruby Gem Name:: amazon-ec2 # Author:: Glenn Rempe (mailto:glenn@rempe.us) # Copyright:: Copyright (c) 2007-2008 Glenn Rempe # License:: Distributes under the same terms as Ruby # Home:: http://github.com/grempe/amazon-ec2/tree/master #++ require File.dirname(__FILE__) + '/test_helper.rb' context "An EC2 instance " do before do @ec2 = AWS::EC2::Base.new( :access_key_id => "not a key", :secret_access_key => "not a secret" ) @confirm_product_instance_response_body = <<-RESPONSE true 254933287430 RESPONSE end specify "should indicate whether a product code is attached to an instance" do @ec2.stubs(:make_request).with('ConfirmProductInstance', {"ProductCode"=>"774F4FF8", "InstanceId"=>"i-10a64379"}). returns stub(:body => @confirm_product_instance_response_body, :is_a? => true) @ec2.confirm_product_instance( :product_code => "774F4FF8", :instance_id => "i-10a64379" ).should.be.an.instance_of Hash response = @ec2.confirm_product_instance( :product_code => "774F4FF8", :instance_id => "i-10a64379" ) response.ownerId.should.equal "254933287430" response.result.should.equal "true" end specify "method get_console_output should raise an exception when called without nil/empty string arguments" do lambda { @ec2.confirm_product_instance() }.should.raise(AWS::ArgumentError) lambda { @ec2.confirm_product_instance(:product_code => "774F4FF8", :instance_id => nil) }.should.raise(AWS::ArgumentError) lambda { @ec2.confirm_product_instance(:product_code => "774F4FF8", :instance_id => "") }.should.raise(AWS::ArgumentError) lambda { @ec2.confirm_product_instance(:product_code => nil, :instance_id => "i-10a64379") }.should.raise(AWS::ArgumentError) lambda { @ec2.confirm_product_instance(:product_code => "", :instance_id => "i-10a64379") }.should.raise(AWS::ArgumentError) end endgrempe-amazon-ec2-043f1b4/test/test_EC2_responses.rb000066400000000000000000000031211147233247500222720ustar00rootroot00000000000000#-- # Amazon Web Services EC2 Query API Ruby library # # Ruby Gem Name:: amazon-ec2 # Author:: Glenn Rempe (mailto:glenn@rempe.us) # Copyright:: Copyright (c) 2007-2008 Glenn Rempe # License:: Distributes under the same terms as Ruby # Home:: http://github.com/grempe/amazon-ec2/tree/master #++ require File.dirname(__FILE__) + '/test_helper.rb' context "The Response classes " do before do @http_xml = <<-RESPONSE true RESPONSE @response = AWS::Response.parse(:xml => @http_xml) end specify "should show the response as a formatted string when calling #inspect" do # sorting the response hash first since ruby 1.8.6 and ruby 1.9.1 sort the hash differently before the inspect @response.sort.inspect.should.equal %{[[\"return\", \"true\"], [\"xmlns\", \"http://ec2.amazonaws.com/doc/2007-03-01\"]]} end specify "should be a Hash" do @response.kind_of?(Hash).should.equal true end specify "should return its members" do @response.keys.length.should.equal 2 test_array = ["return", "xmlns"].sort @response.keys.sort.should.equal test_array end # Note: since we are now returning a hash of the xml, there should be no need for anyone to re-parse the xml. # Therefore storing the xml on the object is a waste of memory, and is not done. # # specify "should return the original amazon XML response in the 'xml' attribute of the response object." do # @response.xml.should.equal @http_xml # end end grempe-amazon-ec2-043f1b4/test/test_EC2_s3_xmlsimple.rb000066400000000000000000000056241147233247500227020ustar00rootroot00000000000000#-- # Amazon Web Services EC2 Query API Ruby library # # Ruby Gem Name:: amazon-ec2 # Author:: Glenn Rempe (mailto:glenn@rempe.us) # Copyright:: Copyright (c) 2007-2008 Glenn Rempe # License:: Distributes under the same terms as Ruby # Home:: http://github.com/grempe/amazon-ec2/tree/master #++ require File.dirname(__FILE__) + '/test_helper.rb' # NOTE : These tests exercise amazon-ec2 when used with the aws/s3 gem # which was demonstrating some breaking behavior. The fix was to # add the XmlSimple option "'keeproot' => false" in responses.rb context "EC2 aws-s3 compat test" do before do @ec2 = AWS::EC2::Base.new( :access_key_id => "not a key", :secret_access_key => "not a secret" ) @describe_instances_response_body = <<-RESPONSE r-44a5402d UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM default i-28a64341 ami-6ea54007 0 running domU-12-31-35-00-1E-01.z-2.compute-1.internal ec2-72-44-33-4.z-2.compute-1.amazonaws.com example-key-name 774F4FF8 m1.small 2007-08-07T11:54:42.000Z RESPONSE end specify "should be able to be described and return the correct Ruby response class" do @ec2.stubs(:make_request).with('DescribeInstances', {}). returns stub(:body => @describe_instances_response_body, :is_a? => true) @ec2.describe_instances.should.be.an.instance_of Hash response = @ec2.describe_instances response.reservationSet.item[0].reservationId.should.equal "r-44a5402d" end specify "should be able to be described and return the correct Ruby response class when the aws/s3 lib is required" do begin require 'aws/s3s' @ec2.stubs(:make_request).with('DescribeInstances', {}). returns stub(:body => @describe_instances_response_body, :is_a? => true) @ec2.describe_instances.should.be.an.instance_of Hash response = @ec2.describe_instances response.reservationSet.item[0].reservationId.should.equal "r-44a5402d" rescue LoadError # do nothing. no aws/s3 gem installed to test against end end end grempe-amazon-ec2-043f1b4/test/test_EC2_security_groups.rb000066400000000000000000000241751147233247500235330ustar00rootroot00000000000000#-- # Amazon Web Services EC2 Query API Ruby library # # Ruby Gem Name:: amazon-ec2 # Author:: Glenn Rempe (mailto:glenn@rempe.us) # Copyright:: Copyright (c) 2007-2008 Glenn Rempe # License:: Distributes under the same terms as Ruby # Home:: http://github.com/grempe/amazon-ec2/tree/master #++ require File.dirname(__FILE__) + '/test_helper.rb' context "EC2 security groups " do before do @ec2 = AWS::EC2::Base.new( :access_key_id => "not a key", :secret_access_key => "not a secret" ) @create_security_group_response_body = <<-RESPONSE true RESPONSE @delete_security_group_response_body = <<-RESPONSE true RESPONSE @describe_security_groups_response_body = <<-RESPONSE UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM WebServers Web tcp 80 80 0.0.0.0/0 UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM RangedPortsBySource A tcp 6000 7000 RESPONSE @authorize_security_group_ingress_response_body = <<-RESPONSE true RESPONSE @revoke_security_group_ingress_response_body = <<-RESPONSE true RESPONSE end specify "should be able to be created" do @ec2.stubs(:make_request).with('CreateSecurityGroup', {"GroupName"=>"WebServers", "GroupDescription"=>"Web"}). returns stub(:body => @create_security_group_response_body, :is_a? => true) @ec2.create_security_group( :group_name => "WebServers", :group_description => "Web" ).should.be.an.instance_of Hash end specify "method create_security_group should reject bad arguments" do @ec2.stubs(:make_request).with('CreateSecurityGroup', {"GroupName"=>"WebServers", "GroupDescription"=>"Web"}). returns stub(:body => @create_security_group_response_body, :is_a? => true) lambda { @ec2.create_security_group( :group_name => "WebServers", :group_description => "Web" ) }.should.not.raise(AWS::ArgumentError) lambda { @ec2.create_security_group() }.should.raise(AWS::ArgumentError) # :group_name can't be nil or empty lambda { @ec2.create_security_group( :group_name => "", :group_description => "Web" ) }.should.raise(AWS::ArgumentError) lambda { @ec2.create_security_group( :group_name => nil, :group_description => "Web" ) }.should.raise(AWS::ArgumentError) # :group_description can't be nil or empty lambda { @ec2.create_security_group( :group_name => "WebServers", :group_description => "" ) }.should.raise(AWS::ArgumentError) lambda { @ec2.create_security_group( :group_name => "WebServers", :group_description => nil ) }.should.raise(AWS::ArgumentError) end specify "should be able to be deleted" do @ec2.stubs(:make_request).with('DeleteSecurityGroup', {"GroupName"=>"WebServers"}). returns stub(:body => @delete_security_group_response_body, :is_a? => true) @ec2.delete_security_group( :group_name => "WebServers" ).should.be.an.instance_of Hash end specify "method delete_security_group should reject bad arguments" do @ec2.stubs(:make_request).with('DeleteSecurityGroup', {"GroupName"=>"WebServers"}). returns stub(:body => @delete_security_group_response_body, :is_a? => true) lambda { @ec2.delete_security_group( :group_name => "WebServers" ) }.should.not.raise(AWS::ArgumentError) lambda { @ec2.delete_security_group() }.should.raise(AWS::ArgumentError) # :group_name can't be nil or empty lambda { @ec2.delete_security_group( :group_name => "" ) }.should.raise(AWS::ArgumentError) lambda { @ec2.delete_security_group( :group_name => nil ) }.should.raise(AWS::ArgumentError) end specify "should be able to be described with describe_security_groups" do @ec2.stubs(:make_request).with('DescribeSecurityGroups', { "GroupName.1" => "WebServers", "GroupName.2" => "RangedPortsBySource" }). returns stub(:body => @describe_security_groups_response_body, :is_a? => true) @ec2.describe_security_groups( :group_name => ["WebServers", "RangedPortsBySource"] ).should.be.an.instance_of Hash response = @ec2.describe_security_groups( :group_name => ["WebServers", "RangedPortsBySource"] ) response.securityGroupInfo.item[0].ownerId.should.equal "UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM" response.securityGroupInfo.item[0].groupName.should.equal "WebServers" response.securityGroupInfo.item[0].groupDescription.should.equal "Web" response.securityGroupInfo.item[0].ipPermissions.item[0].ipProtocol.should.equal "tcp" response.securityGroupInfo.item[0].ipPermissions.item[0].fromPort.should.equal "80" response.securityGroupInfo.item[0].ipPermissions.item[0].toPort.should.equal "80" response.securityGroupInfo.item[0].ipPermissions.item[0].groups.should.be.nil response.securityGroupInfo.item[0].ipPermissions.item[0].ipRanges.item[0].cidrIp.should.equal "0.0.0.0/0" response.securityGroupInfo.item[1].ownerId.should.equal "UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM" response.securityGroupInfo.item[1].groupName.should.equal "RangedPortsBySource" response.securityGroupInfo.item[1].groupDescription.should.equal "A" response.securityGroupInfo.item[1].ipPermissions.item[0].ipProtocol.should.equal "tcp" response.securityGroupInfo.item[1].ipPermissions.item[0].fromPort.should.equal "6000" response.securityGroupInfo.item[1].ipPermissions.item[0].toPort.should.equal "7000" response.securityGroupInfo.item[1].ipPermissions.item[0].groups.should.be.nil response.securityGroupInfo.item[1].ipPermissions.item[0].ipRanges.should.be.nil end specify "method describe_security_groups should reject bad arguments" do @ec2.stubs(:make_request).with('DescribeSecurityGroups', {"GroupName.1"=>"WebServers"}). returns stub(:body => @describe_security_groups_response_body, :is_a? => true) lambda { @ec2.describe_security_groups( :group_name => "WebServers" ) }.should.not.raise(AWS::ArgumentError) end specify "permissions should be able to be added to a security group with authorize_security_group_ingress." do @ec2.stubs(:make_request).with('AuthorizeSecurityGroupIngress', { "GroupName"=>"WebServers", "IpProtocol"=>"tcp", "FromPort"=>"8000", "ToPort"=>"80", "CidrIp"=>"0.0.0.0/24", "SourceSecurityGroupName"=>"Source SG Name", "SourceSecurityGroupOwnerId"=>"123"}). returns stub(:body => @authorize_security_group_ingress_response_body, :is_a? => true) @ec2.authorize_security_group_ingress( :group_name => "WebServers", :ip_protocol => "tcp", :from_port => "8000", :to_port => "80", :cidr_ip => "0.0.0.0/24", :source_security_group_name => "Source SG Name", :source_security_group_owner_id => "123" ).should.be.an.instance_of Hash end specify "permissions should be able to be revoked from a security group with revoke_security_group_ingress." do @ec2.stubs(:make_request).with('RevokeSecurityGroupIngress', { "GroupName"=>"WebServers", "IpProtocol"=>"tcp", "FromPort"=>"8000", "ToPort"=>"80", "CidrIp"=>"0.0.0.0/24", "SourceSecurityGroupName"=>"Source SG Name", "SourceSecurityGroupOwnerId"=>"123"}). returns stub(:body => @revoke_security_group_ingress_response_body, :is_a? => true) @ec2.revoke_security_group_ingress( :group_name => "WebServers", :ip_protocol => "tcp", :from_port => "8000", :to_port => "80", :cidr_ip => "0.0.0.0/24", :source_security_group_name => "Source SG Name", :source_security_group_owner_id => "123" ).should.be.an.instance_of Hash end end grempe-amazon-ec2-043f1b4/test/test_EC2_snapshots.rb000066400000000000000000000074471147233247500223120ustar00rootroot00000000000000#-- # Amazon Web Services EC2 Query API Ruby library, EBS snapshots support # # Ruby Gem Name:: amazon-ec2 # Author:: Yann Klis (mailto:yann.klis@novelys.com) # Copyright:: Copyright (c) 2008 Yann Klis # License:: Distributes under the same terms as Ruby # Home:: http://github.com/grempe/amazon-ec2/tree/master #++ require File.dirname(__FILE__) + '/test_helper.rb' context "EC2 snaphots " do before do @ec2 = AWS::EC2::Base.new( :access_key_id => "not a key", :secret_access_key => "not a secret" ) @describe_snapshots_response_body = <<-RESPONSE snap-78a54011 vol-4d826724 pending 2008-05-07T12:51:50.000Z 80% RESPONSE @create_snapshot_response_body = <<-RESPONSE snap-78a54011 vol-4d826724 pending 2008-05-07T12:51:50.000Z Daily Backup RESPONSE @delete_snapshot_response_body = <<-RESPONSE true RESPONSE end specify "should be able to be described with describe_snapshots" do @ec2.stubs(:make_request).with('DescribeSnapshots', {'SnapshotId.1' => 'snap-78a54011'}). returns stub(:body => @describe_snapshots_response_body, :is_a? => true) @ec2.describe_snapshots( :snapshot_id => "snap-78a54011" ).should.be.an.instance_of Hash response = @ec2.describe_snapshots( :snapshot_id => "snap-78a54011" ) response.snapshotId.should.equal "snap-78a54011" response.volumeId.should.equal "vol-4d826724" response.status.should.equal "pending" response.progress.should.equal "80%" end specify "should be able to be created with a volume_id" do @ec2.stubs(:make_request).with('CreateSnapshot', {"VolumeId" => "vol-4d826724"}). returns stub(:body => @create_snapshot_response_body, :is_a? => true) @ec2.create_snapshot( :volume_id => "vol-4d826724" ).should.be.an.instance_of Hash response = @ec2.create_snapshot( :volume_id => "vol-4d826724" ) response.snapshotId.should.equal "snap-78a54011" response.volumeId.should.equal "vol-4d826724" response.status.should.equal "pending" response.progress.should.equal nil end specify "should be able to be created with a volume_id and description" do @ec2.stubs(:make_request).with('CreateSnapshot', {"VolumeId" => "vol-4d826724", "Description" => "Daily Backup"}). returns stub(:body => @create_snapshot_response_body, :is_a? => true) @ec2.create_snapshot( :volume_id => "vol-4d826724", :description => "Daily Backup" ).should.be.an.instance_of Hash response = @ec2.create_snapshot( :volume_id => "vol-4d826724", :description => "Daily Backup") response.snapshotId.should.equal "snap-78a54011" response.volumeId.should.equal "vol-4d826724" response.status.should.equal "pending" response.progress.should.equal nil response.description.should.equal "Daily Backup" end specify "should be able to be deleted with a snapsot_id" do @ec2.stubs(:make_request).with('DeleteSnapshot', {"SnapshotId" => "snap-78a54011"}). returns stub(:body => @delete_snapshot_response_body, :is_a? => true) @ec2.delete_snapshot( :snapshot_id => "snap-78a54011" ).should.be.an.instance_of Hash response = @ec2.delete_snapshot( :snapshot_id => "snap-78a54011" ) response.return.should.equal "true" end end grempe-amazon-ec2-043f1b4/test/test_EC2_spot_instance_requests.rb000066400000000000000000000221551147233247500250650ustar00rootroot00000000000000#-- # Amazon Web Services EC2 Query API Ruby library # # Ruby Gem Name:: amazon-ec2 # Author:: Glenn Rempe (mailto:glenn@rempe.us) # Copyright:: Copyright (c) 2007-2008 Glenn Rempe # License:: Distributes under the same terms as Ruby # Home:: http://github.com/grempe/amazon-ec2/tree/master #++ require File.dirname(__FILE__) + '/test_helper.rb' context "An EC2 spot instances request " do before do @ec2 = AWS::EC2::Base.new( :access_key_id => "not a key", :secret_access_key => "not a secret" ) @create_spot_instances_request_response_body = <<-RESPONSE sir-f102a405 0.50 one-time open MyAzGroup i-43a4412a MyKeypair websrv m1.small i-123345678 2009-10-19T00:00:00+0000 RESPONSE @describe_spot_instance_requests_response_body = <<-RESPONSE sir-e95fae02 0.01 one-time open 2009-12-04T22:51:14.000Z Linux/UNIX ami-235fba4a default m1.small false i-2fd4ca67 sir-e95fae03 0.10 persistent open 2009-12-04T22:51:14.000Z Linux/UNIX ami-235fba4a default m1.medium false i-2fd4ca90 RESPONSE @cancel_spot_instance_requests_response_body = <<-RESPONSE 59dbff89-35bd-4eac-99ed-be587ed81825 sir-e95fae02 cancelled RESPONSE end specify "should be able to be requested with various instance sizes" do ["t1.micro", "m1.small", "m1.large", "m1.xlarge", "m2.xlarge", "c1.medium", "c1.xlarge", "m2.2xlarge", "m2.4xlarge", "cc1.4xlarge"].each do |type| @ec2.stubs(:make_request).with('RequestSpotInstances', {"SpotPrice"=>"0.50", 'LaunchSpecification.InstanceType' => type, 'LaunchSpecification.ImageId' => 'ami-60a54009', "InstanceCount"=>"1"}). returns stub(:body => @create_spot_instances_request_response_body, :is_a? => true) lambda { @ec2.request_spot_instances( :image_id => "ami-60a54009", :instance_type => type, :spot_price => '0.50' ) }.should.not.raise(AWS::ArgumentError) end end specify "should raise an exception with a bad instance type" do lambda { @ec2.request_spot_instances({"SpotPrice"=>"0.50", 'LaunchSpecification.InstanceType' => 'm1.notarealsize', "InstanceCount"=>"1"}) }.should.raise(AWS::ArgumentError) end specify "should be able to be created" do @ec2.stubs(:make_request).with('RequestSpotInstances', {"SpotPrice"=>"0.50", 'LaunchSpecification.InstanceType' => 'm1.small', "InstanceCount"=>"1"}). returns stub(:body => @create_spot_instances_request_response_body, :is_a? => true) @ec2.request_spot_instances(:spot_price => "0.50").should.be.an.instance_of Hash @ec2.request_spot_instances(:spot_price => "0.50").spotInstanceRequestSet.item[0].spotInstanceRequestId.should.equal "sir-f102a405" end specify "method create_spot_instances_request should raise an exception when called with nil/empty string arguments" do lambda { @ec2.request_spot_instances() }.should.raise(AWS::ArgumentError) lambda { @ec2.request_spot_instances(:spot_price => "") }.should.raise(AWS::ArgumentError) lambda { @ec2.request_spot_instances(:spot_price => nil) }.should.raise(AWS::ArgumentError) end specify "should be able to be described and return the correct Ruby response class for parent and members" do @ec2.stubs(:make_request).with('DescribeSpotInstanceRequests', {}). returns stub(:body => @describe_spot_instance_requests_response_body, :is_a? => true) @ec2.describe_spot_instance_requests.should.be.an.instance_of Hash response = @ec2.describe_spot_instance_requests response.should.be.an.instance_of Hash end specify "should be able to be described with no params and return a spotInstanceRequestSet" do @ec2.stubs(:make_request).with('DescribeSpotInstanceRequests', {}). returns stub(:body => @describe_spot_instance_requests_response_body, :is_a? => true) @ec2.describe_spot_instance_requests.spotInstanceRequestSet.item.length.should.equal 2 end specify "should be able to be described by an Array of SpotInstanceRequestId.N ID's and return an array of Items" do @ec2.stubs(:make_request).with('DescribeSpotInstanceRequests', {"SpotInstanceRequestId.1"=>"sir-e95fae02", "SpotInstanceRequestId.2"=>"sir-e95fae03"}). returns stub(:body => @describe_spot_instance_requests_response_body, :is_a? => true) @ec2.describe_spot_instance_requests( :spot_instance_request_id => ["sir-e95fae02", "sir-e95fae03"] ).spotInstanceRequestSet.item.length.should.equal 2 response = @ec2.describe_spot_instance_requests( :spot_instance_request_id => ["sir-e95fae02", "sir-e95fae03"] ) # test first 'Item' object returned response.spotInstanceRequestSet.item[0].spotInstanceRequestId.should.equal "sir-e95fae02" response.spotInstanceRequestSet.item[0].spotPrice.should.equal "0.01" response.spotInstanceRequestSet.item[0].type.should.equal "one-time" response.spotInstanceRequestSet.item[0].state.should.equal "open" response.spotInstanceRequestSet.item[0].createTime.should.equal "2009-12-04T22:51:14.000Z" response.spotInstanceRequestSet.item[0].productDescription.should.equal "Linux/UNIX" response.spotInstanceRequestSet.item[0].launchSpecification.imageId.should.equal "ami-235fba4a" response.spotInstanceRequestSet.item[0].launchSpecification.instanceType.should.equal "m1.small" response.spotInstanceRequestSet.item[0].instanceId.should.equal "i-2fd4ca67" # test second 'Item' object returned response.spotInstanceRequestSet.item[1].spotInstanceRequestId.should.equal "sir-e95fae03" response.spotInstanceRequestSet.item[1].spotPrice.should.equal "0.10" response.spotInstanceRequestSet.item[1].type.should.equal "persistent" response.spotInstanceRequestSet.item[1].state.should.equal "open" response.spotInstanceRequestSet.item[1].createTime.should.equal "2009-12-04T22:51:14.000Z" response.spotInstanceRequestSet.item[1].productDescription.should.equal "Linux/UNIX" response.spotInstanceRequestSet.item[1].launchSpecification.imageId.should.equal "ami-235fba4a" response.spotInstanceRequestSet.item[1].launchSpecification.instanceType.should.equal "m1.medium" response.spotInstanceRequestSet.item[1].instanceId.should.equal "i-2fd4ca90" end specify "should be able to be destroyed" do @ec2.stubs(:make_request).with('CancelSpotInstanceRequests', {"SpotInstanceRequestId.1"=>"sir-e95fae02"}). returns stub(:body => @cancel_spot_instance_requests_response_body, :is_a? => true) @ec2.cancel_spot_instance_requests(:spot_instance_request_id => "sir-e95fae02" ).should.be.an.instance_of Hash @ec2.cancel_spot_instance_requests(:spot_instance_request_id => "sir-e95fae02" ).spotInstanceRequestSet.item[0].state.should.equal "cancelled" end end grempe-amazon-ec2-043f1b4/test/test_EC2_spot_prices.rb000066400000000000000000000047721147233247500226200ustar00rootroot00000000000000require File.dirname(__FILE__) + '/test_helper.rb' context "Spot price history " do before do @ec2 = AWS::EC2::Base.new( :access_key_id => "not a key", :secret_access_key => "not a secret" ) @describe_spot_price_history_response_body = <<-RESPONSE m1.small Linux/UNIX 0.287 2009-12-04T20:56:05.000Z m1.small Windows 0.033 2009-12-04T22:33:47.000Z RESPONSE end specify "should be able to be listed" do @ec2.stubs(:make_request).with('DescribeSpotPriceHistory', {}). returns stub(:body => @describe_spot_price_history_response_body, :is_a? => true) @ec2.describe_spot_price_history().should.be.an.instance_of Hash @ec2.describe_spot_price_history().spotPriceHistorySet.item.should.be.an.instance_of Array end specify "should reject a start_time which is not a Time object" do lambda { @ec2.describe_spot_price_history(:start_time => "foo") }.should.raise(AWS::ArgumentError) end specify "should reject an end_time which is not a Time object" do lambda { @ec2.describe_spot_price_history(:end_time => 42) }.should.raise(AWS::ArgumentError) end specify "should be able to be requested with various instance types" do ["t1.micro", "m1.small", "m1.large", "m1.xlarge", "m2.xlarge", "c1.medium", "c1.xlarge", "m2.2xlarge", "m2.4xlarge", "cc1.4xlarge"].each do |type| @ec2.stubs(:make_request).with('DescribeSpotPriceHistory', {'InstanceType' => type}). returns stub(:body => @describe_spot_price_history_response_body, :is_a? => true) lambda { @ec2.describe_spot_price_history( :instance_type => type ) }.should.not.raise(AWS::ArgumentError) end end specify "should reject an invalid instance type" do lambda { @ec2.describe_spot_price_history(:instance_type => 'm1.tiny') }.should.raise(AWS::ArgumentError) end specify "should reject an invalid product description" do lambda { @ec2.describe_spot_price_history(:product_description => 'Solaris') }.should.raise(AWS::ArgumentError) end end grempe-amazon-ec2-043f1b4/test/test_EC2_subnets.rb000066400000000000000000000047321147233247500217450ustar00rootroot00000000000000#-- # Amazon Web Services EC2 Query API Ruby library # # Ruby Gem Name:: amazon-ec2 # Author:: Glenn Rempe (mailto:glenn@rempe.us) # Copyright:: Copyright (c) 2007-2010 Glenn Rempe # License:: Distributes under the same terms as Ruby # Home:: http://github.com/grempe/amazon-ec2/tree/master #++ require File.dirname(__FILE__) + '/test_helper.rb' context "The EC2 subnets " do before do @ec2 = AWS::EC2::Base.new( :access_key_id => "not a key", :secret_access_key => "not a secret" ) @describe_subnets_response_body = <<-RESPONSE available 251 subnet-000000e0 10.225.251.0/24 vpc-b00000db us-east-1a available 251 subnet-11111!e1 10.225.251.0/24 vpc-b00000db us-east-1a RESPONSE end specify "should be able to be described with no params and return a subnetSet" do @ec2.stubs(:make_request).with('DescribeSubnets', {}). returns stub(:body => @describe_subnets_response_body, :is_a? => true) @ec2.describe_subnets.subnetSet.item.length.should.equal 2 end specify "should be able to be described with describe_subnet" do @ec2.stubs(:make_request).with('DescribeSubnets', {"SubnetId.1"=>"subnet-000000e0"}). returns stub(:body => @describe_subnets_response_body, :is_a? => true) @ec2.describe_subnets( :subnet_id => "subnet-000000e0" ).should.be.an.instance_of Hash response = @ec2.describe_subnets( :subnet_id => "subnet-000000e0" ) response.subnetSet.item[0].state.should.equal "available" response.subnetSet.item[0].availableIpAddressCount.should.equal "251" response.subnetSet.item[0].subnetId.should.equal "subnet-000000e0" response.subnetSet.item[0].cidrBlock.should.equal "10.225.251.0/24" response.subnetSet.item[0].vpcId.should.equal "vpc-b00000db" response.subnetSet.item[0].availabilityZone.should.equal "us-east-1a" end end grempe-amazon-ec2-043f1b4/test/test_EC2_volumes.rb000066400000000000000000000151341147233247500217520ustar00rootroot00000000000000#-- # Amazon Web Services EC2 Query API Ruby library, EBS volumes support # # Ruby Gem Name:: amazon-ec2 # Author:: Yann Klis (mailto:yann.klis@novelys.com) # Copyright:: Copyright (c) 2008 Yann Klis # License:: Distributes under the same terms as Ruby # Home:: http://github.com/grempe/amazon-ec2/tree/master #++ require File.dirname(__FILE__) + '/test_helper.rb' context "EC2 volumes " do before do @ec2 = AWS::EC2::Base.new( :access_key_id => "not a key", :secret_access_key => "not a secret" ) @describe_volumes_response_body = <<-RESPONSE vol-4282672b 800 in-use 2008-05-07T11:51:50.000Z vol-4282672b i-6058a509 800 attached 2008-05-07T12:51:50.000Z RESPONSE @create_volume_response_body = <<-RESPONSE vol-4d826724 800 creating 2008-05-07T11:51:50.000Z us-east-1a RESPONSE @delete_volume_response_body = <<-RESPONSE true RESPONSE @attach_volume_response_body = <<-RESPONSE vol-4d826724 i-6058a509 /dev/sdh attaching 2008-05-07T11:51:50.000Z RESPONSE @detach_volume_response_body = <<-RESPONSE vol-4d826724 i-6058a509 /dev/sdh detaching 2008-05-08T11:51:50.000Z RESPONSE end specify "should be able to be described with describe_volumes" do @ec2.stubs(:make_request).with('DescribeVolumes', {"VolumeId.1"=>"vol-4282672b"}). returns stub(:body => @describe_volumes_response_body, :is_a? => true) @ec2.describe_volumes( :volume_id => ["vol-4282672b"] ).should.be.an.instance_of Hash response = @ec2.describe_volumes( :volume_id => ["vol-4282672b"] ) response.volumeSet.item[0].volumeId.should.equal "vol-4282672b" response.volumeSet.item[0].attachmentSet.item[0]['size'].should.equal "800" response.volumeSet.item[0].attachmentSet.item[0].volumeId.should.equal "vol-4282672b" response.volumeSet.item[0].attachmentSet.item[0].instanceId.should.equal "i-6058a509" end specify "should be able to be created with an availability_zone with size" do @ec2.stubs(:make_request).with('CreateVolume', {"AvailabilityZone" => "us-east-1a", "Size"=>"800", "SnapshotId"=>""}). returns stub(:body => @create_volume_response_body, :is_a? => true) @ec2.create_volume( :availability_zone => "us-east-1a", :size => "800" ).should.be.an.instance_of Hash response = @ec2.create_volume( :availability_zone => "us-east-1a", :size => "800" ) response.volumeId.should.equal "vol-4d826724" response['size'].should.equal "800" response.status.should.equal "creating" response.zone.should.equal "us-east-1a" end specify "should be able to be deleted with a volume_id" do @ec2.stubs(:make_request).with('DeleteVolume', {"VolumeId" => "vol-4282672b"}). returns stub(:body => @delete_volume_response_body, :is_a? => true) @ec2.delete_volume( :volume_id => "vol-4282672b" ).should.be.an.instance_of Hash response = @ec2.delete_volume( :volume_id => "vol-4282672b" ) response.return.should.equal "true" end specify "should be able to be attached with a volume_id with an instance_id with a device" do @ec2.stubs(:make_request).with('AttachVolume', {"VolumeId" => "vol-4d826724", "InstanceId"=>"i-6058a509", "Device"=>"/dev/sdh"}). returns stub(:body => @attach_volume_response_body, :is_a? => true) @ec2.attach_volume( :volume_id => "vol-4d826724", :instance_id => "i-6058a509", :device => "/dev/sdh" ).should.be.an.instance_of Hash response = @ec2.attach_volume( :volume_id => "vol-4d826724", :instance_id => "i-6058a509", :device => "/dev/sdh" ) response.volumeId.should.equal "vol-4d826724" response.instanceId.should.equal "i-6058a509" response.device.should.equal "/dev/sdh" response.status.should.equal "attaching" end specify "should be able to be detached with a volume_id with an instance_id" do @ec2.stubs(:make_request).with('DetachVolume', {"VolumeId" => "vol-4d826724", "InstanceId"=>"i-6058a509", "Device"=>"", "Force"=>""}). returns stub(:body => @detach_volume_response_body, :is_a? => true) @ec2.detach_volume( :volume_id => "vol-4d826724", :instance_id => "i-6058a509" ).should.be.an.instance_of Hash response = @ec2.detach_volume( :volume_id => "vol-4d826724", :instance_id => "i-6058a509" ) response.volumeId.should.equal "vol-4d826724" response.instanceId.should.equal "i-6058a509" response.device.should.equal "/dev/sdh" response.status.should.equal "detaching" end specify "should be able to be force detached with a string" do @ec2.stubs(:make_request).with('DetachVolume', {"VolumeId" => "vol-4d826724", "InstanceId"=>"i-6058a509", "Device"=>"", "Force"=>"true"}). returns stub(:body => @detach_volume_response_body, :is_a? => true) response = @ec2.detach_volume( :volume_id => "vol-4d826724", :instance_id => "i-6058a509", :force => 'true' ) response.volumeId.should.equal "vol-4d826724" end specify "should be able to be force detached with a Boolean" do @ec2.stubs(:make_request).with('DetachVolume', {"VolumeId" => "vol-4d826724", "InstanceId"=>"i-6058a509", "Device"=>"", "Force"=>"true"}). returns stub(:body => @detach_volume_response_body, :is_a? => true) response = @ec2.detach_volume( :volume_id => "vol-4d826724", :instance_id => "i-6058a509", :force => true ) response.volumeId.should.equal "vol-4d826724" end end grempe-amazon-ec2-043f1b4/test/test_ELB_load_balancers.rb000066400000000000000000000327511147233247500232460ustar00rootroot00000000000000require File.dirname(__FILE__) + '/test_helper.rb' context "elb load balancers " do before do @elb = AWS::ELB::Base.new( :access_key_id => "not a key", :secret_access_key => "not a secret" ) @valid_create_load_balancer_params = { :load_balancer_name => 'Test Name', :availability_zones => ['east-1a'], :listeners => [{:protocol => 'HTTP', :load_balancer_port => '80', :instance_port => '80'}] } @create_load_balancer_response_body = <<-RESPONSE TestLoadBalancer-380544827.us-east-1.ec2.amazonaws.com RESPONSE @valid_delete_load_balancer_params = { :load_balancer_name => 'Test Name' } @delete_load_balancer_response_body = <<-RESPONSE true RESPONSE @valid_describe_load_balancer_params = { } @describe_load_balancer_response_body = <<-RESPONSE HTTP 80 80 2009-07-02T01:07:55.080Z TestLB TestLB-1459724896.us-east-1.elb.amazonaws.com 30 TCP:80 10 5 2 us-east-1a 67dd800e-66a5-11de-b844-07deabfcc881 RESPONSE @valid_register_instances_with_load_balancer_params = { :load_balancer_name => 'Test Name', :instances => ['i-6055fa09'] } @register_instances_with_load_balancer_response_body = <<-RESPONSE i-6055fa09 RESPONSE @valid_deregister_instances_from_load_balancer_params = @valid_register_instances_with_load_balancer_params @deregister_instances_from_load_balancer_response_body = <<-RESPONSE RESPONSE @valid_configure_health_check_params = { :load_balancer_name => 'Test Name', :health_check => { :target => 'HTTP:80/servlets-examples/servlet/', :timeout => '2', :interval => '5', :unhealthy_threshold => '2', :healthy_threshold => '2' } } @configure_health_check_response_body = <<-RESPONSE 5 HTTP:80/servlets-examples/servlet/ 2 2 2 RESPONSE end specify "should be able to be created" do @elb.stubs(:make_request).with('CreateLoadBalancer', { 'LoadBalancerName' => 'Test Name', 'AvailabilityZones.member.1' => 'east-1a', 'Listeners.member.1.Protocol' => 'HTTP', 'Listeners.member.1.LoadBalancerPort' => '80', 'Listeners.member.1.InstancePort' => '80' }).returns stub(:body => @create_load_balancer_response_body, :is_a? => true) response = @elb.create_load_balancer(@valid_create_load_balancer_params) response.should.be.an.instance_of Hash response.DNSName.should.equal "TestLoadBalancer-380544827.us-east-1.ec2.amazonaws.com" end specify "method create_load_balancer should reject bad arguments" do @elb.stubs(:make_request).with('CreateLoadBalancer', { 'LoadBalancerName' => 'Test Name', 'AvailabilityZones.member.1' => 'east-1a', 'Listeners.member.1.Protocol' => 'HTTP', 'Listeners.member.1.LoadBalancerPort' => '80', 'Listeners.member.1.InstancePort' => '80' }).returns stub(:body => @create_load_balancer_response_body, :is_a? => true) lambda { @elb.create_load_balancer(@valid_create_load_balancer_params) }.should.not.raise(AWS::ArgumentError) lambda { @elb.create_load_balancer(@valid_create_load_balancer_params.merge(:load_balancer_name=>nil)) }.should.raise(AWS::ArgumentError) lambda { @elb.create_load_balancer(@valid_create_load_balancer_params.merge(:load_balancer_name=>'')) }.should.raise(AWS::ArgumentError) lambda { @elb.create_load_balancer(@valid_create_load_balancer_params.merge(:availability_zones=>'')) }.should.raise(AWS::ArgumentError) lambda { @elb.create_load_balancer(@valid_create_load_balancer_params.merge(:availability_zones=>[])) }.should.raise(AWS::ArgumentError) lambda { @elb.create_load_balancer(@valid_create_load_balancer_params.merge(:listeners=>[])) }.should.raise(AWS::ArgumentError) lambda { @elb.create_load_balancer(@valid_create_load_balancer_params.merge(:listeners=>nil)) }.should.raise(AWS::ArgumentError) end specify "should be able to be deleted with delete_load_balancer" do @elb.stubs(:make_request).with('DeleteLoadBalancer', {'LoadBalancerName' => 'Test Name'}). returns stub(:body => @delete_load_balancer_response_body, :is_a? => true) response = @elb.delete_load_balancer( :load_balancer_name => "Test Name" ) response.should.be.an.instance_of Hash response.return.should.equal "true" end specify "should be able to be described with describe_load_balancer" do @elb.stubs(:make_request).with('DescribeLoadBalancers', {}). returns stub(:body => @describe_load_balancer_response_body, :is_a? => true) response = @elb.describe_load_balancers() response.should.be.an.instance_of Hash response.DescribeLoadBalancersResult.LoadBalancerDescriptions.member.length.should == 1 end specify "should be able to be register instances to load balancers with register_instances_with_load_balancer" do @elb.stubs(:make_request).with('RegisterInstancesWithLoadBalancer', { 'LoadBalancerName' => 'Test Name', 'Instances.member.1.InstanceId' => 'i-6055fa09' }).returns stub(:body => @register_instances_with_load_balancer_response_body, :is_a? => true) response = @elb.register_instances_with_load_balancer(@valid_register_instances_with_load_balancer_params) response.should.be.an.instance_of Hash response.Instances.member.length.should == 1 end specify "method register_instances_with_load_balancer should reject bad arguments" do @elb.stubs(:make_request).with('RegisterInstancesWithLoadBalancer', { 'LoadBalancerName' => 'Test Name', 'Instances.member.1.InstanceId' => 'i-6055fa09' }).returns stub(:body => @register_instances_with_load_balancer_response_body, :is_a? => true) lambda { @elb.register_instances_with_load_balancer(@valid_register_instances_with_load_balancer_params) }.should.not.raise(AWS::ArgumentError) lambda { @elb.register_instances_with_load_balancer(@valid_register_instances_with_load_balancer_params.merge(:load_balancer_name=>nil)) }.should.raise(AWS::ArgumentError) lambda { @elb.register_instances_with_load_balancer(@valid_register_instances_with_load_balancer_params.merge(:instances=>nil)) }.should.raise(AWS::ArgumentError) lambda { @elb.register_instances_with_load_balancer(@valid_register_instances_with_load_balancer_params.merge(:instances=>[])) }.should.raise(AWS::ArgumentError) end specify "should be able to deregister instances from load balancers with deregister_instances_from_load_balancer" do @elb.stubs(:make_request).with('DeregisterInstancesFromLoadBalancer', { 'LoadBalancerName' => 'Test Name', 'Instances.member.1.InstanceId' => 'i-6055fa09' }).returns stub(:body => @deregister_instances_from_load_balancer_response_body, :is_a? => true) response = @elb.deregister_instances_from_load_balancer(@valid_deregister_instances_from_load_balancer_params) response.should.be.an.instance_of Hash end specify "method deregister_instances_from_load_balancer should reject bad arguments" do @elb.stubs(:make_request).with('DeregisterInstancesFromLoadBalancer', { 'LoadBalancerName' => 'Test Name', 'Instances.member.1.InstanceId' => 'i-6055fa09' }).returns stub(:body => @deregister_instances_from_load_balancer_response_body, :is_a? => true) lambda { @elb.deregister_instances_from_load_balancer(@valid_deregister_instances_from_load_balancer_params) }.should.not.raise(AWS::ArgumentError) lambda { @elb.deregister_instances_from_load_balancer(@valid_deregister_instances_from_load_balancer_params.merge(:load_balancer_name=>nil)) }.should.raise(AWS::ArgumentError) lambda { @elb.deregister_instances_from_load_balancer(@valid_deregister_instances_from_load_balancer_params.merge(:instances=>nil)) }.should.raise(AWS::ArgumentError) lambda { @elb.deregister_instances_from_load_balancer(@valid_deregister_instances_from_load_balancer_params.merge(:instances=>[])) }.should.raise(AWS::ArgumentError) end specify "should be able to configure_health_check for instances from load balancers" do @elb.stubs(:make_request).with('ConfigureHealthCheck', { 'LoadBalancerName' => 'Test Name', 'HealthCheck.Interval' => '5', 'HealthCheck.Target' => 'HTTP:80/servlets-examples/servlet/', 'HealthCheck.HealthyThreshold' => '2', 'HealthCheck.Timeout' => '2', 'HealthCheck.UnhealthyThreshold' => '2' }).returns stub(:body => @configure_health_check_response_body, :is_a? => true) response = @elb.configure_health_check(@valid_configure_health_check_params) response.should.be.an.instance_of Hash lambda { @elb.configure_health_check(@valid_configure_health_check_params) }.should.not.raise(AWS::ArgumentError) lambda { @elb.configure_health_check(@valid_configure_health_check_params.merge(:load_balancer_name => nil)) }.should.raise(AWS::ArgumentError) lambda { @elb.configure_health_check(@valid_configure_health_check_params.merge(:load_balancer_name => "")) }.should.raise(AWS::ArgumentError) lambda { @elb.configure_health_check(@valid_configure_health_check_params.merge(:health_check => nil)) }.should.raise(AWS::ArgumentError) lambda { @elb.configure_health_check(@valid_configure_health_check_params.merge(:health_check => "")) }.should.raise(AWS::ArgumentError) end specify "should be able to configure_health_check for instances from load balancers with string health check args" do @elb.stubs(:make_request).with('ConfigureHealthCheck', { 'LoadBalancerName' => 'Test Name', 'HealthCheck.Interval' => '5', 'HealthCheck.Target' => 'HTTP:80/servlets-examples/servlet/', 'HealthCheck.HealthyThreshold' => '2', 'HealthCheck.Timeout' => '2', 'HealthCheck.UnhealthyThreshold' => '2' }).returns stub(:body => @configure_health_check_response_body, :is_a? => true) response = @elb.configure_health_check(@valid_configure_health_check_params.merge(:health_check => {:target => 'HTTP:80/servlets-examples/servlet/', :timeout => '2', :interval => '5', :unhealthy_threshold => '2', :healthy_threshold => '2' })) response.should.be.an.instance_of Hash end specify "should be able to configure_health_check for instances from load balancers with FixNum health check args" do @elb.stubs(:make_request).with('ConfigureHealthCheck', { 'LoadBalancerName' => 'Test Name', 'HealthCheck.Interval' => '5', 'HealthCheck.Target' => 'HTTP:80/servlets-examples/servlet/', 'HealthCheck.HealthyThreshold' => '2', 'HealthCheck.Timeout' => '2', 'HealthCheck.UnhealthyThreshold' => '2' }).returns stub(:body => @configure_health_check_response_body, :is_a? => true) response = @elb.configure_health_check(@valid_configure_health_check_params.merge(:health_check => {:target => 'HTTP:80/servlets-examples/servlet/', :timeout => 2, :interval => 5, :unhealthy_threshold => 2, :healthy_threshold => 2 })) response.should.be.an.instance_of Hash end specify "method degregister_instances_from_load_balancer should reject bad arguments" do @elb.stubs(:make_request).with('ConfigureHealthCheck', { 'LoadBalancerName' => 'Test Name', 'HealthCheck.Interval' => '5', 'HealthCheck.Target' => 'HTTP:80/servlets-examples/servlet/', 'HealthCheck.HealthyThreshold' => '2', 'HealthCheck.Timeout' => '2', 'HealthCheck.UnhealthyThreshold' => '2' }).returns stub(:body => @configure_health_check_response_body, :is_a? => true) lambda { @elb.configure_health_check(@valid_configure_health_check_params) }.should.not.raise(AWS::ArgumentError) lambda { @elb.configure_health_check(@valid_configure_health_check_params.merge(:load_balancer_name=>nil)) }.should.raise(AWS::ArgumentError) lambda { @elb.configure_health_check(@valid_configure_health_check_params.merge(:health_check=>nil)) }.should.raise(AWS::ArgumentError) end end grempe-amazon-ec2-043f1b4/test/test_RDS.rb000066400000000000000000000355061147233247500202640ustar00rootroot00000000000000require File.dirname(__FILE__) + '/test_helper.rb' context "rds databases " do before do @rds = AWS::RDS::Base.new( :access_key_id => "not a key", :secret_access_key => "not a secret" ) @create_db_instance_body = <<-RESPONSE MySQL5.1 1 creating mydbinstance 03:00-05:00 active default sun:05:00-sun:09:00 10 db.m1.large master e6fb58c5-bf34-11de-b88d-993294bf1c81 RESPONSE @create_db_security_group = <<-RESPONSE My new DBSecurityGroup 621567473609 mydbsecuritygroup4 c9cf9ff2-bf36-11de-b88d-993294bf1c81 RESPONSE end specify "should be able to be create a db_instance" do @rds.stubs(:make_request).with('CreateDBInstance', {'Engine' => 'MySQL5.1', 'MasterUsername' => 'master', 'DBInstanceClass' => 'db.m1.large', 'DBInstanceIdentifier' => 'testdb', 'AllocatedStorage' => '10', 'MasterUserPassword' => 'SecretPassword01'}). returns stub(:body => @create_db_instance_body, :is_a? => true) response = @rds.create_db_instance( :db_instance_class => "db.m1.large", :db_instance_identifier=>"testdb", :allocated_storage => 10, :engine => "MySQL5.1", :master_user_password => "SecretPassword01", :master_username => "master" ) response.should.be.an.instance_of Hash assert_equal response.CreateDBInstanceResult.DBInstance.AllocatedStorage, "10" end specify "should be able to create_db_security_group" do @rds.stubs(:make_request).with('CreateDBSecurityGroup', { 'DBSecurityGroupName' => 'mydbsecuritygroup', 'DBSecurityGroupDescription' => 'My new DBSecurityGroup'}). returns stub(:body => @create_db_security_group, :is_a? => true) response = @rds.create_db_security_group( :db_security_group_name => "mydbsecuritygroup", :db_security_group_description => "My new DBSecurityGroup" ) response.should.be.an.instance_of Hash assert_equal response.CreateDBSecurityGroupResult.DBSecurityGroup.DBSecurityGroupName, "mydbsecuritygroup4" end specify "should be able to create_db_parameter_group" do body =<<-EOE mysql5.1 My new DBParameterGroup mydbparametergroup3 0b447b66-bf36-11de-a88b-7b5b3d23b3a7 EOE @rds.stubs(:make_request).with('CreateDBParameterGroup', {'Engine' => 'MySQL5.1', 'DBParameterGroupName' => 'mydbsecuritygroup', 'Description' => 'My test DBSecurity group'}). returns stub(:body => body, :is_a? => true) response = @rds.create_db_parameter_group( :db_parameter_group_name => "mydbsecuritygroup", :description => "My test DBSecurity group", :engine => "MySQL5.1" ) response.should.be.an.instance_of Hash assert_equal response.CreateDBParameterGroupResult.DBParameterGroup.DBParameterGroupName, "mydbparametergroup3" end specify "should be able to create_db_snapshot" do body =<<-EOE 3306 creating mysql5.1 us-east-1d 2009-10-21T04:05:43.609Z 50 mynewdbinstance sa mynewdbsnapshot3 48e870fd-bf38-11de-a88b-7b5b3d23b3a7 EOE @rds.stubs(:make_request).with('CreateDBSnapshot', {'DBSnapshotIdentifier' => 'mynewdbsnapshot3', 'DBInstanceIdentifier' => 'mynewdbinstance'}). returns stub(:body => body, :is_a? => true) response = @rds.create_db_snapshot( :db_snapshot_identifier => "mynewdbsnapshot3", :db_instance_identifier => "mynewdbinstance" ) response.should.be.an.instance_of Hash assert_equal response.CreateDBSnapshotResult.DBSnapshot.DBSnapshotIdentifier, "mynewdbsnapshot3" end specify "should be able to authorize_db_security_group" do body =<<-EOE My new DBSecurityGroup 192.168.1.1/24 authorizing 621567473609 mydbsecuritygroup d9799197-bf2d-11de-b88d-993294bf1c81 EOE @rds.stubs(:make_request).with('AuthorizeDBSecurityGroupIngress', {'CIDRIP' => '192.168.1.1/24', 'DBSecurityGroupName' => 'mydbsecuritygroup'}). returns stub(:body => body, :is_a? => true) response = @rds.authorize_db_security_group( :db_security_group_name => "mydbsecuritygroup", :cidrip => "192.168.1.1/24" ) response.should.be.an.instance_of Hash assert_equal response.AuthorizeDBSecurityGroupIngressResult.DBSecurityGroup.IPRanges.IPRange.CIDRIP, "192.168.1.1/24" end specify "should be able to delete_db_parameter_group" do body =<<-EOE 4dc38be9-bf3b-11de-a88b-7b5b3d23b3a7 EOE @rds.stubs(:make_request).with('DeleteDBParameterGroup', {'DBParameterGroupName' => 'mydbsecuritygroup'}). returns stub(:body => body, :is_a? => true) response = @rds.delete_db_parameter_group( :db_parameter_group_name => "mydbsecuritygroup" ) response.should.be.an.instance_of Hash end specify "should be able to delete_db_security_group" do body =<<-EOE 4dc38be9-bf3b-11de-a88b-7b5b3d23b3a7 EOE @rds.stubs(:make_request).with('DeleteDBSecurityGroup', {'DBSecurityGroupName' => 'mydbsecuritygroup'}). returns stub(:body => body, :is_a? => true) response = @rds.delete_db_security_group( :db_security_group_name => "mydbsecuritygroup" ) response.should.be.an.instance_of Hash end specify "should be able to delete_db_snapshot" do body =<<-EOE 4dc38be9-bf3b-11de-a88b-7b5b3d23b3a7 EOE @rds.stubs(:make_request).with('DeleteDBSnapshot', {'DBSnapshotIdentifier' => 'snapshotname'}). returns stub(:body => body, :is_a? => true) response = @rds.delete_db_snapshot( :db_snapshot_identifier => "snapshotname" ) response.should.be.an.instance_of Hash end specify "should be able to describe_db_instances" do body =<<-EOE 2009-10-22T18:59:59Z mysql5.1 3 available pending-reboot default.mysql5.1 8443
dbinstancename.clouwupjnvmq.us-east-1-devo.rds.amazonaws.com
dbinstancename 03:00-05:00 active default testdb sun:05:00-sun:09:00 us-east-1a 2009-09-11T00:50:45.523Z 20 db.m1.xlarge sa
4f1fae46-bf3d-11de-a88b-7b5b3d23b3a7
EOE @rds.stubs(:make_request).with('DescribeDBInstances', {'MaxRecords' => '100'}). returns stub(:body => body, :is_a? => true) response = @rds.describe_db_instances( :max_records => "100" ) response.should.be.an.instance_of Hash end specify "should be able to describe_db_instances" do body =<<-EOE mysql5.1 bWF4X3VzZXJfY29ubmVjdGlvbnM= boolean engine-default true Controls whether user-defined functions that have only an xxx symbol for the main function can be loaded static ON,OFF allow-suspicious-udfs integer engine-default true Intended for use with master-to-master replication, and can be used to control the operation of AUTO_INCREMENT columns dynamic 1-65535 auto_increment_increment 811f4032-bf3e-11de-b88d-993294bf1c81 EOE @rds.stubs(:make_request).with('DescribeEngineDefaultParameters', {'Engine' => 'MySQL5.1'}). returns stub(:body => body, :is_a? => true) response = @rds.describe_engine_default_parameters( :engine => "MySQL5.1" ) response.should.be.an.instance_of Hash end specify "should be able to describe_db_instances" do body =<<-EOE mydbparametergroup 5ba91f97-bf51-11de-bf60-ef2e377db6f3 EOE @rds.stubs(:make_request).with('ModifyDBParameterGroup', { 'DBParameterGroupName' => 'mytestdb', 'Parameters.member.1.ParameterName' => 'max_user_connections', 'Parameters.member.1.ParameterValue' => '24', 'Parameters.member.1.ApplyMethod' => 'pending-reboot', 'Parameters.member.2.ParameterName' => 'max_allowed_packet', 'Parameters.member.2.ParameterValue' => '1024', 'Parameters.member.2.ApplyMethod' => 'immediate', }). returns stub(:body => body, :is_a? => true) response = @rds.modify_db_parameter_group( :db_parameter_group_name => "mytestdb", :parameters => [ {:name => "max_user_connections", :value => "24", :apply_method => "pending-reboot"}, {:name => "max_allowed_packet", :value => "1024", :apply_method => "immediate"} ] ) response.should.be.an.instance_of Hash end end grempe-amazon-ec2-043f1b4/test/test_helper.rb000066400000000000000000000010341147233247500211000ustar00rootroot00000000000000#-- # Amazon Web Services EC2 Query API Ruby library # # Ruby Gem Name:: amazon-ec2 # Author:: Glenn Rempe (mailto:glenn@rempe.us) # Copyright:: Copyright (c) 2007-2008 Glenn Rempe # License:: Distributes under the same terms as Ruby # Home:: http://github.com/grempe/amazon-ec2/tree/master #++ require 'rubygems' gem 'test-unit' %w[ test/unit test/spec mocha ].each { |f| begin require f rescue LoadError abort "Unable to load required gem for test: #{f}" end } require File.dirname(__FILE__) + '/../lib/AWS' grempe-amazon-ec2-043f1b4/wsdl/000077500000000000000000000000001147233247500162315ustar00rootroot00000000000000grempe-amazon-ec2-043f1b4/wsdl/2007-08-29.ec2.wsdl000066400000000000000000001243441147233247500206510ustar00rootroot00000000000000 This API call should be treated as under development. The current API specification supports a richer set of semantics than we intend to retain in future releases, and the details for this call are still under review. Semantically, clients can depend on fine grained CIDR based access control (as currently exposed) but for group based access control clients should only depend on the ability to control access for an entire (user,group) tuple. Fine grained group based access control at the protocol and port or icmp code:type level are not guaranteed to be supported in future releases of this API. This API call should be treated as under development. The current API specification supports a richer set of semantics than we intend to retain in future releases, and the details for this call are still under review. Semantically, clients can depend on fine grained CIDR based access control (as currently exposed) but for group based access control clients should only depend on the ability to control access for an entire (user,group) tuple. Fine grained group based access control at the protocol and port or icmp code:type level are not guaranteed to be supported in future releases of this API. grempe-amazon-ec2-043f1b4/wsdl/2008-02-01.ec2.wsdl000066400000000000000000001622401147233247500206270ustar00rootroot00000000000000 This API call should be treated as under development. The current API specification supports a richer set of semantics than we intend to retain in future releases, and the details for this call are still under review. Semantically, clients can depend on fine grained CIDR based access control (as currently exposed) but for group based access control clients should only depend on the ability to control access for an entire (user,group) tuple. Fine grained group based access control at the protocol and port or icmp code:type level are not guaranteed to be supported in future releases of this API. This API call should be treated as under development. The current API specification supports a richer set of semantics than we intend to retain in future releases, and the details for this call are still under review. Semantically, clients can depend on fine grained CIDR based access control (as currently exposed) but for group based access control clients should only depend on the ability to control access for an entire (user,group) tuple. Fine grained group based access control at the protocol and port or icmp code:type level are not guaranteed to be supported in future releases of this API. grempe-amazon-ec2-043f1b4/wsdl/2008-05-05.ec2.wsdl000066400000000000000000002140151147233247500206340ustar00rootroot00000000000000 This API call should be treated as under development. The current API specification supports a richer set of semantics than we intend to retain in future releases, and the details for this call are still under review. Semantically, clients can depend on fine grained CIDR based access control (as currently exposed) but for group based access control clients should only depend on the ability to control access for an entire (user,group) tuple. Fine grained group based access control at the protocol and port or icmp code:type level are not guaranteed to be supported in future releases of this API. This API call should be treated as under development. The current API specification supports a richer set of semantics than we intend to retain in future releases, and the details for this call are still under review. Semantically, clients can depend on fine grained CIDR based access control (as currently exposed) but for group based access control clients should only depend on the ability to control access for an entire (user,group) tuple. Fine grained group based access control at the protocol and port or icmp code:type level are not guaranteed to be supported in future releases of this API. grempe-amazon-ec2-043f1b4/wsdl/2008-12-01.ec2.wsdl000066400000000000000000002423271147233247500206350ustar00rootroot00000000000000 This API call should be treated as under development. The current API specification supports a richer set of semantics than we intend to retain in future releases, and the details for this call are still under review. Semantically, clients can depend on fine grained CIDR based access control (as currently exposed) but for group based access control clients should only depend on the ability to control access for an entire (user,group) tuple. Fine grained group based access control at the protocol and port or icmp code:type level are not guaranteed to be supported in future releases of this API. This API call should be treated as under development. The current API specification supports a richer set of semantics than we intend to retain in future releases, and the details for this call are still under review. Semantically, clients can depend on fine grained CIDR based access control (as currently exposed) but for group based access control clients should only depend on the ability to control access for an entire (user,group) tuple. Fine grained group based access control at the protocol and port or icmp code:type level are not guaranteed to be supported in future releases of this API. grempe-amazon-ec2-043f1b4/wsdl/2009-10-31.ec2.wsdl000066400000000000000000004625071147233247500206430ustar00rootroot00000000000000 grempe-amazon-ec2-043f1b4/wsdl/2009-11-30.ec2.wsdl000066400000000000000000005254721147233247500206440ustar00rootroot00000000000000