From af568153523c5db2e6f0d86713937fc33375bcf7 Mon Sep 17 00:00:00 2001 From: Thomas Dudziak Date: Fri, 15 Oct 2010 14:05:18 -0700 Subject: [PATCH 1/6] Updated API version --- amazon-ec2.gemspec | 37 +++++++++++++++++++------------------ lib/AWS/EC2.rb | 2 +- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/amazon-ec2.gemspec b/amazon-ec2.gemspec index 71f02d9..20e710f 100644 --- a/amazon-ec2.gemspec +++ b/amazon-ec2.gemspec @@ -9,10 +9,10 @@ Gem::Specification.new do |s| s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version= s.authors = ["Glenn Rempe"] - s.date = %q{2010-06-10} + s.date = %q{2010-10-15} s.description = %q{A Ruby library for accessing the Amazon Web Services EC2, ELB, RDS, Cloudwatch, and Autoscaling APIs.} s.email = %q{glenn@rempe.us} - s.executables = ["ec2-gem-example.rb", "ec2-gem-profile.rb", "ec2sh", "setup.rb"] + s.executables = ["awshell", "ec2sh", "ec2-gem-profile.rb", "setup.rb", "ec2-gem-example.rb"] s.extra_rdoc_files = [ "ChangeLog", "LICENSE", @@ -29,6 +29,7 @@ Gem::Specification.new do |s| "Rakefile", "VERSION", "amazon-ec2.gemspec", + "bin/awshell", "bin/ec2-gem-example.rb", "bin/ec2-gem-profile.rb", "bin/ec2sh", @@ -97,37 +98,37 @@ Gem::Specification.new do |s| s.rdoc_options = ["--title", "amazon-ec2 documentation", "--line-numbers", "--main", "README.rdoc"] s.require_paths = ["lib"] s.rubyforge_project = %q{amazon-ec2} - s.rubygems_version = %q{1.3.7} + s.rubygems_version = %q{1.3.5} s.summary = %q{Amazon EC2 Ruby Gem} s.test_files = [ - "test/test_Autoscaling_groups.rb", - "test/test_EC2.rb", - "test/test_EC2_availability_zones.rb", - "test/test_EC2_console.rb", - "test/test_EC2_elastic_ips.rb", - "test/test_EC2_image_attributes.rb", - "test/test_EC2_images.rb", - "test/test_EC2_instances.rb", + "test/test_EC2_console.rb", "test/test_EC2_keypairs.rb", + "test/test_EC2_volumes.rb", + "test/test_EC2_image_attributes.rb", + "test/test_EC2_snapshots.rb", "test/test_EC2_products.rb", - "test/test_EC2_responses.rb", + "test/test_RDS.rb", + "test/test_EC2_images.rb", "test/test_EC2_s3_xmlsimple.rb", + "test/test_ELB_load_balancers.rb", + "test/test_EC2_instances.rb", + "test/test_Autoscaling_groups.rb", "test/test_EC2_security_groups.rb", - "test/test_EC2_snapshots.rb", + "test/test_EC2.rb", + "test/test_EC2_availability_zones.rb", "test/test_EC2_spot_instance_requests.rb", + "test/test_EC2_responses.rb", "test/test_EC2_spot_prices.rb", - "test/test_EC2_subnets.rb", - "test/test_EC2_volumes.rb", - "test/test_ELB_load_balancers.rb", "test/test_helper.rb", - "test/test_RDS.rb" + "test/test_EC2_subnets.rb", + "test/test_EC2_elastic_ips.rb" ] if s.respond_to? :specification_version then current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION s.specification_version = 3 - if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then + if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then s.add_runtime_dependency(%q, [">= 1.0.12"]) s.add_development_dependency(%q, [">= 0.9.8"]) s.add_development_dependency(%q, [">= 0.10.0"]) diff --git a/lib/AWS/EC2.rb b/lib/AWS/EC2.rb index 6dc1fc5..5850b28 100644 --- a/lib/AWS/EC2.rb +++ b/lib/AWS/EC2.rb @@ -14,7 +14,7 @@ module EC2 DEFAULT_HOST = 'ec2.amazonaws.com' end - API_VERSION = '2009-11-30' + API_VERSION = '2010-08-31' class Base < AWS::Base def api_version From a5eb3b55989ae492da4a0d482da9373debd3c238 Mon Sep 17 00:00:00 2001 From: Thomas Dudziak Date: Fri, 15 Oct 2010 16:05:51 -0700 Subject: [PATCH 2/6] First version of describe_tags --- amazon-ec2.gemspec | 33 +++++++++++++++++---------------- lib/AWS.rb | 11 ++++++++++- lib/AWS/EC2/tags.rb | 19 +++++++++++++++++++ 3 files changed, 46 insertions(+), 17 deletions(-) create mode 100644 lib/AWS/EC2/tags.rb diff --git a/amazon-ec2.gemspec b/amazon-ec2.gemspec index 20e710f..bdb21f5 100644 --- a/amazon-ec2.gemspec +++ b/amazon-ec2.gemspec @@ -1,6 +1,6 @@ # Generated by jeweler # DO NOT EDIT THIS FILE DIRECTLY -# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command +# Instead, edit Jeweler::Tasks in rakefile, and run the gemspec command # -*- encoding: utf-8 -*- Gem::Specification.new do |s| @@ -12,7 +12,7 @@ Gem::Specification.new do |s| s.date = %q{2010-10-15} s.description = %q{A Ruby library for accessing the Amazon Web Services EC2, ELB, RDS, Cloudwatch, and Autoscaling APIs.} s.email = %q{glenn@rempe.us} - s.executables = ["awshell", "ec2sh", "ec2-gem-profile.rb", "setup.rb", "ec2-gem-example.rb"] + s.executables = ["awshell", "ec2-gem-example.rb", "ec2-gem-profile.rb", "ec2sh", "setup.rb"] s.extra_rdoc_files = [ "ChangeLog", "LICENSE", @@ -55,6 +55,7 @@ Gem::Specification.new do |s| "lib/AWS/EC2/spot_instance_requests.rb", "lib/AWS/EC2/spot_prices.rb", "lib/AWS/EC2/subnets.rb", + "lib/AWS/EC2/tags.rb", "lib/AWS/EC2/volumes.rb", "lib/AWS/ELB.rb", "lib/AWS/ELB/load_balancers.rb", @@ -101,27 +102,27 @@ Gem::Specification.new do |s| s.rubygems_version = %q{1.3.5} s.summary = %q{Amazon EC2 Ruby Gem} s.test_files = [ - "test/test_EC2_console.rb", - "test/test_EC2_keypairs.rb", - "test/test_EC2_volumes.rb", + "test/test_Autoscaling_groups.rb", + "test/test_EC2.rb", + "test/test_EC2_availability_zones.rb", + "test/test_EC2_console.rb", + "test/test_EC2_elastic_ips.rb", "test/test_EC2_image_attributes.rb", - "test/test_EC2_snapshots.rb", - "test/test_EC2_products.rb", - "test/test_RDS.rb", "test/test_EC2_images.rb", - "test/test_EC2_s3_xmlsimple.rb", - "test/test_ELB_load_balancers.rb", "test/test_EC2_instances.rb", - "test/test_Autoscaling_groups.rb", + "test/test_EC2_keypairs.rb", + "test/test_EC2_products.rb", + "test/test_EC2_responses.rb", + "test/test_EC2_s3_xmlsimple.rb", "test/test_EC2_security_groups.rb", - "test/test_EC2.rb", - "test/test_EC2_availability_zones.rb", + "test/test_EC2_snapshots.rb", "test/test_EC2_spot_instance_requests.rb", - "test/test_EC2_responses.rb", "test/test_EC2_spot_prices.rb", - "test/test_helper.rb", "test/test_EC2_subnets.rb", - "test/test_EC2_elastic_ips.rb" + "test/test_EC2_volumes.rb", + "test/test_ELB_load_balancers.rb", + "test/test_helper.rb", + "test/test_RDS.rb" ] if s.respond_to? :specification_version then diff --git a/lib/AWS.rb b/lib/AWS.rb index 0474018..da20c99 100644 --- a/lib/AWS.rb +++ b/lib/AWS.rb @@ -219,7 +219,14 @@ def pathhashlist(key, arr_of_hashes, mappings) params = {} arr_of_hashes.each_with_index do |hash, i| hash.each do |attribute, value| - params["#{key}.#{i+1}.#{mappings[attribute]}"] = value.to_s + 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 @@ -248,6 +255,8 @@ def make_request(action, params, data='') CGI::escape(param[0]) + "=" + CGI::escape(param[1]) end.join("&") + "&Signature=" + sig +puts(query); + req = Net::HTTP::Post.new("/") req.content_type = 'application/x-www-form-urlencoded' req['User-Agent'] = "github-amazon-ec2-ruby-gem" diff --git a/lib/AWS/EC2/tags.rb b/lib/AWS/EC2/tags.rb new file mode 100644 index 0000000..c3f1840 --- /dev/null +++ b/lib/AWS/EC2/tags.rb @@ -0,0 +1,19 @@ +module AWS + module EC2 + class Base < AWS::Base + + # The DescribeTags operation lists the tags, If you do not specify any filters, all tags will be returned. + # + # @option options [optional, Array] :filters ([]) An array of Hashes representing the filters. e.g. [{:key => 'name'}, {:resource_type => 'instance'},...] + # + def describe_tags( options = {} ) + params = {} + if options[:filters] + params.merge!(pathhashlist('Filter', options[:filters], {:key => 'key', :resource_id => 'resource-id', :resource_type => 'resource-type', :value => 'value' })) + end + return response_generator(:action => "DescribeTags", :params => params) + end + end + end +end + From 6e1d8e22f1c917326e8d81064e2d830b4c0b8b42 Mon Sep 17 00:00:00 2001 From: Thomas Dudziak Date: Fri, 15 Oct 2010 16:14:50 -0700 Subject: [PATCH 3/6] Removed debug output --- amazon-ec2.gemspec | 32 ++++++++++++++++---------------- lib/AWS.rb | 3 +-- 2 files changed, 17 insertions(+), 18 deletions(-) diff --git a/amazon-ec2.gemspec b/amazon-ec2.gemspec index bdb21f5..4789c64 100644 --- a/amazon-ec2.gemspec +++ b/amazon-ec2.gemspec @@ -1,6 +1,6 @@ # Generated by jeweler # DO NOT EDIT THIS FILE DIRECTLY -# Instead, edit Jeweler::Tasks in rakefile, and run the gemspec command +# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command # -*- encoding: utf-8 -*- Gem::Specification.new do |s| @@ -12,7 +12,7 @@ Gem::Specification.new do |s| s.date = %q{2010-10-15} s.description = %q{A Ruby library for accessing the Amazon Web Services EC2, ELB, RDS, Cloudwatch, and Autoscaling APIs.} s.email = %q{glenn@rempe.us} - s.executables = ["awshell", "ec2-gem-example.rb", "ec2-gem-profile.rb", "ec2sh", "setup.rb"] + s.executables = ["awshell", "ec2sh", "ec2-gem-profile.rb", "setup.rb", "ec2-gem-example.rb"] s.extra_rdoc_files = [ "ChangeLog", "LICENSE", @@ -102,27 +102,27 @@ Gem::Specification.new do |s| s.rubygems_version = %q{1.3.5} s.summary = %q{Amazon EC2 Ruby Gem} s.test_files = [ - "test/test_Autoscaling_groups.rb", - "test/test_EC2.rb", - "test/test_EC2_availability_zones.rb", - "test/test_EC2_console.rb", - "test/test_EC2_elastic_ips.rb", - "test/test_EC2_image_attributes.rb", - "test/test_EC2_images.rb", - "test/test_EC2_instances.rb", + "test/test_EC2_console.rb", "test/test_EC2_keypairs.rb", + "test/test_EC2_volumes.rb", + "test/test_EC2_image_attributes.rb", + "test/test_EC2_snapshots.rb", "test/test_EC2_products.rb", - "test/test_EC2_responses.rb", + "test/test_RDS.rb", + "test/test_EC2_images.rb", "test/test_EC2_s3_xmlsimple.rb", + "test/test_ELB_load_balancers.rb", + "test/test_EC2_instances.rb", + "test/test_Autoscaling_groups.rb", "test/test_EC2_security_groups.rb", - "test/test_EC2_snapshots.rb", + "test/test_EC2.rb", + "test/test_EC2_availability_zones.rb", "test/test_EC2_spot_instance_requests.rb", + "test/test_EC2_responses.rb", "test/test_EC2_spot_prices.rb", - "test/test_EC2_subnets.rb", - "test/test_EC2_volumes.rb", - "test/test_ELB_load_balancers.rb", "test/test_helper.rb", - "test/test_RDS.rb" + "test/test_EC2_subnets.rb", + "test/test_EC2_elastic_ips.rb" ] if s.respond_to? :specification_version then diff --git a/lib/AWS.rb b/lib/AWS.rb index da20c99..d2173da 100644 --- a/lib/AWS.rb +++ b/lib/AWS.rb @@ -255,8 +255,6 @@ def make_request(action, params, data='') CGI::escape(param[0]) + "=" + CGI::escape(param[1]) end.join("&") + "&Signature=" + sig -puts(query); - req = Net::HTTP::Post.new("/") req.content_type = 'application/x-www-form-urlencoded' req['User-Agent'] = "github-amazon-ec2-ruby-gem" @@ -291,6 +289,7 @@ def response_generator( options = {} ) http_response = make_request(options[:action], options[:params]) http_xml = http_response.body + return Response.parse(:xml => http_xml) end From 8cd676b1261f257963a94ba6f419007f0164c0c1 Mon Sep 17 00:00:00 2001 From: Thomas Dudziak Date: Fri, 15 Oct 2010 17:48:30 -0700 Subject: [PATCH 4/6] Created separate function for the key-value parameter structure that tags need; added create_tags method --- lib/AWS.rb | 33 +++++++++++++++++++++++++++++++++ lib/AWS/EC2/tags.rb | 20 +++++++++++++++++--- 2 files changed, 50 insertions(+), 3 deletions(-) diff --git a/lib/AWS.rb b/lib/AWS.rb index d2173da..0340968 100644 --- a/lib/AWS.rb +++ b/lib/AWS.rb @@ -232,6 +232,38 @@ def pathhashlist(key, arr_of_hashes, mappings) 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 @@ -259,6 +291,7 @@ def make_request(action, params, data='') req.content_type = 'application/x-www-form-urlencoded' req['User-Agent'] = "github-amazon-ec2-ruby-gem" +puts(query) response = @http.request(req, query) # Make a call to see if we need to throw an error based on the response given by EC2 diff --git a/lib/AWS/EC2/tags.rb b/lib/AWS/EC2/tags.rb index c3f1840..bf025ca 100644 --- a/lib/AWS/EC2/tags.rb +++ b/lib/AWS/EC2/tags.rb @@ -2,14 +2,28 @@ module 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] :filters ([]) An array of Hashes representing the filters. e.g. [{:key => 'name'}, {:resource_type => 'instance'},...] + # @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[:filters] - params.merge!(pathhashlist('Filter', options[:filters], {:key => 'key', :resource_id => 'resource-id', :resource_type => 'resource-type', :value => 'value' })) + 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 From 5a5aab3d0560017940004d690966946ad9d70c2c Mon Sep 17 00:00:00 2001 From: Thomas Dudziak Date: Fri, 15 Oct 2010 17:57:13 -0700 Subject: [PATCH 5/6] Added delete_tags --- lib/AWS/EC2/tags.rb | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/lib/AWS/EC2/tags.rb b/lib/AWS/EC2/tags.rb index bf025ca..df37dab 100644 --- a/lib/AWS/EC2/tags.rb +++ b/lib/AWS/EC2/tags.rb @@ -27,6 +27,20 @@ def describe_tags( options = {} ) 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 From 1b7f6c23fe6c8f0b6452488588d5c9c44fb423e7 Mon Sep 17 00:00:00 2001 From: Thomas Dudziak Date: Fri, 15 Oct 2010 18:24:32 -0700 Subject: [PATCH 6/6] Forgot debug statement --- lib/AWS.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/AWS.rb b/lib/AWS.rb index 0340968..41e75df 100644 --- a/lib/AWS.rb +++ b/lib/AWS.rb @@ -291,7 +291,6 @@ def make_request(action, params, data='') req.content_type = 'application/x-www-form-urlencoded' req['User-Agent'] = "github-amazon-ec2-ruby-gem" -puts(query) response = @http.request(req, query) # Make a call to see if we need to throw an error based on the response given by EC2