From 41a277a9bd8bd8e4feab87909c75ec8be77ca295 Mon Sep 17 00:00:00 2001 From: Benton Roberts Date: Sun, 28 Oct 2012 22:17:01 -0400 Subject: [PATCH 1/7] [aws|rds] add region and owner_id as RDS connection attributes --- lib/fog/aws/rds.rb | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/fog/aws/rds.rb b/lib/fog/aws/rds.rb index 0d8a1503f..603fead9b 100644 --- a/lib/fog/aws/rds.rb +++ b/lib/fog/aws/rds.rb @@ -118,6 +118,8 @@ module Fog end class Real + attr_reader :region + include Fog::AWS::CredentialFetcher::ConnectionMethods # Initialize connection to ELB # @@ -142,8 +144,8 @@ module Fog setup_credentials(options) @connection_options = options[:connection_options] || {} - options[:region] ||= 'us-east-1' - @host = options[:host] || "rds.#{options[:region]}.amazonaws.com" + @region = options[:region] || 'us-east-1' + @host = options[:host] || "rds.#{@region}.amazonaws.com" @path = options[:path] || '/' @persistent = options[:persistent] || false @port = options[:port] || 443 @@ -151,6 +153,10 @@ module Fog @connection = Fog::Connection.new("#{@scheme}://#{@host}:#{@port}#{@path}", @persistent, @connection_options) end + def owner_id + @owner_id ||= Fog::AWS[:rds].security_groups.get('default').owner_id + end + def reload @connection.reset end From 3ba4af532f09432cd81802b188fab2f52b3517d9 Mon Sep 17 00:00:00 2001 From: Benton Roberts Date: Sun, 28 Oct 2012 22:19:30 -0400 Subject: [PATCH 2/7] [aws|rds] add request definitions for RDS tagging and increment RDS API version --- lib/fog/aws/rds.rb | 6 ++- .../aws/requests/rds/add_tags_to_resource.rb | 46 +++++++++++++++++++ .../requests/rds/list_tags_for_resource.rb | 43 +++++++++++++++++ .../requests/rds/remove_tags_from_resource.rb | 44 ++++++++++++++++++ 4 files changed, 138 insertions(+), 1 deletion(-) create mode 100644 lib/fog/aws/requests/rds/add_tags_to_resource.rb create mode 100644 lib/fog/aws/requests/rds/list_tags_for_resource.rb create mode 100644 lib/fog/aws/requests/rds/remove_tags_from_resource.rb diff --git a/lib/fog/aws/rds.rb b/lib/fog/aws/rds.rb index 603fead9b..b6a7a0759 100644 --- a/lib/fog/aws/rds.rb +++ b/lib/fog/aws/rds.rb @@ -23,6 +23,10 @@ module Fog request :describe_db_engine_versions request :describe_db_reserved_instances + request :add_tags_to_resource + request :list_tags_for_resource + request :remove_tags_from_resource + request :describe_db_snapshots request :create_db_snapshot request :delete_db_snapshot @@ -187,7 +191,7 @@ module Fog :host => @host, :path => @path, :port => @port, - :version => '2012-01-15' #'2011-04-01' + :version => '2012-09-17' #'2011-04-01' } ) diff --git a/lib/fog/aws/requests/rds/add_tags_to_resource.rb b/lib/fog/aws/requests/rds/add_tags_to_resource.rb new file mode 100644 index 000000000..fc54ad0ff --- /dev/null +++ b/lib/fog/aws/requests/rds/add_tags_to_resource.rb @@ -0,0 +1,46 @@ +module Fog + module AWS + class RDS + class Real + + # adds tags to a database instance + # http://docs.amazonwebservices.com/AmazonRDS/latest/APIReference/API_AddTagsToResource.html + # ==== Parameters + # * rds_id <~String> - name of the RDS instance whose tags are to be retrieved + # * tags <~Hash> A Hash of (String) key-value pairs + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + def add_tags_to_resource(rds_id, tags) + keys = tags.keys.sort + values = keys.map {|key| tags[key]} + request({ + 'Action' => 'AddTagsToResource', + 'ResourceName' => "arn:aws:rds:#{@region}:#{owner_id}:db:#{rds_id}", + :parser => Fog::Parsers::AWS::RDS::Base.new, + }.merge(Fog::AWS.indexed_param('Tags.member.%d.Key', keys)). + merge(Fog::AWS.indexed_param('Tags.member.%d.Value', values))) + end + + end + + class Mock + + def add_tags_to_resource(rds_id, tags) + response = Excon::Response.new + if server = self.data[:servers][rds_id] + server['Tags'].merge! tags + response.status = 200 + response.body = { + "ResponseMetadata"=>{ "RequestId"=> Fog::AWS::Mock.request_id } + } + response + else + raise Fog::AWS::RDS::NotFound.new("DBInstance #{rds_id} not found") + end + end + + end + end + end +end diff --git a/lib/fog/aws/requests/rds/list_tags_for_resource.rb b/lib/fog/aws/requests/rds/list_tags_for_resource.rb new file mode 100644 index 000000000..b7d829765 --- /dev/null +++ b/lib/fog/aws/requests/rds/list_tags_for_resource.rb @@ -0,0 +1,43 @@ +module Fog + module AWS + class RDS + class Real + + require 'fog/aws/parsers/rds/tag_list_parser' + + # returns a Hash of tags for a database instance + # http://docs.amazonwebservices.com/AmazonRDS/latest/APIReference/API_ListTagsForResource.html + # ==== Parameters + # * rds_id <~String> - name of the RDS instance whose tags are to be retrieved + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + def list_tags_for_resource(rds_id) + request( + 'Action' => 'ListTagsForResource', + 'ResourceName' => "arn:aws:rds:#{@region}:#{owner_id}:db:#{rds_id}", + :parser => Fog::Parsers::AWS::RDS::TagListParser.new, + ) + end + + end + + class Mock + + def list_tags_for_resource(rds_id) + response = Excon::Response.new + if server = self.data[:servers][rds_id] + response.status = 200 + response.body = { + "ListTagsForResourceResult" => { "TagList" => server['Tags'] } + } + response + else + raise Fog::AWS::RDS::NotFound.new("DBInstance #{rds_id} not found") + end + end + + end + end + end +end diff --git a/lib/fog/aws/requests/rds/remove_tags_from_resource.rb b/lib/fog/aws/requests/rds/remove_tags_from_resource.rb new file mode 100644 index 000000000..055fe6299 --- /dev/null +++ b/lib/fog/aws/requests/rds/remove_tags_from_resource.rb @@ -0,0 +1,44 @@ +module Fog + module AWS + class RDS + class Real + + # removes tags from a database instance + # http://docs.amazonwebservices.com/AmazonRDS/latest/APIReference/API_RemoveTagsFromResource.html + # ==== Parameters + # * rds_id <~String> - name of the RDS instance whose tags are to be retrieved + # * keys <~Array> A list of String keys for the tags to remove + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + def remove_tags_from_resource(rds_id, keys) + request( + { 'Action' => 'RemoveTagsFromResource', + 'ResourceName' => "arn:aws:rds:#{@region}:#{owner_id}:db:#{rds_id}", + :parser => Fog::Parsers::AWS::RDS::Base.new, + }.merge(Fog::AWS.indexed_param('TagKeys.member.%d', keys)) + ) + end + + end + + class Mock + + def remove_tags_from_resource(rds_id, keys) + response = Excon::Response.new + if server = self.data[:servers][rds_id] + keys.each {|key| server['Tags'].delete key} + response.status = 200 + response.body = { + "ResponseMetadata"=>{ "RequestId"=> Fog::AWS::Mock.request_id } + } + response + else + raise Fog::AWS::RDS::NotFound.new("DBInstance #{rds_id} not found") + end + end + + end + end + end +end From 9bb8a2702d8998042da60251cadb0bc822158016 Mon Sep 17 00:00:00 2001 From: Benton Roberts Date: Sun, 28 Oct 2012 22:19:50 -0400 Subject: [PATCH 3/7] [aws|rds] add tests for RDS tagging requests --- lib/fog/aws/parsers/rds/tag_list_parser.rb | 35 +++++++++ .../aws/requests/rds/create_db_instance.rb | 3 +- tests/aws/requests/rds/helper.rb | 6 ++ tests/aws/requests/rds/tagging_tests.rb | 78 +++++++++++++++++++ 4 files changed, 121 insertions(+), 1 deletion(-) create mode 100644 lib/fog/aws/parsers/rds/tag_list_parser.rb create mode 100644 tests/aws/requests/rds/tagging_tests.rb diff --git a/lib/fog/aws/parsers/rds/tag_list_parser.rb b/lib/fog/aws/parsers/rds/tag_list_parser.rb new file mode 100644 index 000000000..2441f46fd --- /dev/null +++ b/lib/fog/aws/parsers/rds/tag_list_parser.rb @@ -0,0 +1,35 @@ +module Fog + module Parsers + module AWS + module RDS + # parses an XML-formatted list of resource tags from AWS + class TagListParser < Fog::Parsers::Base + + # each tag is modeled as a String pair (2-element Array) + def reset + @this_key = nil + @this_value = nil + @tags = Hash.new + @response = {'ListTagsForResourceResult' => {'TagList' => {}}} + end + + def end_element(name) + super + case name + when 'Tag' + @tags[@this_key] = @this_value + @this_key, @this_value = nil, nil + when 'Key' + @this_key = value + when 'Value' + @this_value = value + when 'TagList' + @response['ListTagsForResourceResult']['TagList'] = @tags + end + end + + end + end + end + end +end diff --git a/lib/fog/aws/requests/rds/create_db_instance.rb b/lib/fog/aws/requests/rds/create_db_instance.rb index e3f19867b..88f516a9a 100644 --- a/lib/fog/aws/requests/rds/create_db_instance.rb +++ b/lib/fog/aws/requests/rds/create_db_instance.rb @@ -103,7 +103,8 @@ module Fog # "ReadReplicaSourceDBInstanceIdentifier" => nil, # "LatestRestorableTime" => nil, "AvailabilityZone" => options["AvailabilityZone"], - "DBSubnetGroupName" => options["DBSubnetGroupName"] + "DBSubnetGroupName" => options["DBSubnetGroupName"], + "Tags" => {} } diff --git a/tests/aws/requests/rds/helper.rb b/tests/aws/requests/rds/helper.rb index f106af490..73ad10ae7 100644 --- a/tests/aws/requests/rds/helper.rb +++ b/tests/aws/requests/rds/helper.rb @@ -223,6 +223,12 @@ class AWS } }) + LIST_TAGS_FOR_RESOURCE = { + 'ListTagsForResourceResult' => { + 'TagList' => Fog::Nullable::Hash + } + } + end end diff --git a/tests/aws/requests/rds/tagging_tests.rb b/tests/aws/requests/rds/tagging_tests.rb new file mode 100644 index 000000000..883a4fb48 --- /dev/null +++ b/tests/aws/requests/rds/tagging_tests.rb @@ -0,0 +1,78 @@ +Shindo.tests('AWS::RDS | tagging requests', ['aws', 'rds']) do + @rds = Fog::AWS[:rds] + @db_instance_id = "fog-test-#{rand(65536).to_s(16)}" + Formatador.display_line "Creating RDS instance #{@db_instance_id}" + @rds.create_db_instance(@db_instance_id, 'AllocatedStorage' => 5, + 'DBInstanceClass' => 'db.t1.micro', 'Engine' => 'mysql', + 'MasterUsername' => 'foguser', 'MasterUserPassword' => 'fogpassword') + Formatador.display_line "Waiting for instance #{@db_instance_id} to be ready" + @db = @rds.servers.get(@db_instance_id) + @db.wait_for { ready? } + + tests('success') do + + single_tag = {'key1' => 'value1'} + two_tags = {'key2' => 'value2', 'key3' => 'value3'} + + tests("#add_tags_to_resource with a single tag"). + formats(AWS::RDS::Formats::BASIC) do + result = @rds.add_tags_to_resource(@db_instance_id, single_tag).body + returns(single_tag) do + @rds.list_tags_for_resource(@db_instance_id). + body['ListTagsForResourceResult']['TagList'] + end + result + end + + tests("#add_tags_to_resource with a multiple tags"). + formats(AWS::RDS::Formats::BASIC) do + result = @rds.add_tags_to_resource(@db_instance_id, two_tags).body + returns(single_tag.merge(two_tags)) do + @rds.list_tags_for_resource(@db_instance_id). + body['ListTagsForResourceResult']['TagList'] + end + result + end + + tests("#remove_tags_from_resource").formats(AWS::RDS::Formats::BASIC) do + result = @rds.remove_tags_from_resource( + @db_instance_id, [single_tag.keys.first]).body + returns(two_tags) do + @rds.list_tags_for_resource(@db_instance_id). + body['ListTagsForResourceResult']['TagList'] + end + result + end + + tests("#list_tags_for_resource"). + formats(AWS::RDS::Formats::LIST_TAGS_FOR_RESOURCE) do + result = @rds.list_tags_for_resource(@db_instance_id).body + returns(two_tags) do + result['ListTagsForResourceResult']['TagList'] + end + result + end + + end + + tests('failure') do + tests "tagging a nonexisting instance" do + raises(Fog::AWS::RDS::NotFound) do + @rds.add_tags_to_resource('doesnexist', {'key1' => 'value1'}) + end + end + tests "listing tags for a nonexisting instance" do + raises(Fog::AWS::RDS::NotFound) do + @rds.list_tags_for_resource('doesnexist') + end + end + tests "removing tags for a nonexisting instance" do + raises(Fog::AWS::RDS::NotFound) do + @rds.remove_tags_from_resource('doesnexist', ['key1']) + end + end + end + + Formatador.display_line "Destroying DB instance #{@db_instance_id}" + @db.destroy +end From 28216278eb32dea437239adfd9f9cd468c628dd7 Mon Sep 17 00:00:00 2001 From: Benton Roberts Date: Sun, 28 Oct 2012 23:18:21 -0400 Subject: [PATCH 4/7] [aws|rds] add tagging methods to RDS server model --- lib/fog/aws/models/rds/server.rb | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/lib/fog/aws/models/rds/server.rb b/lib/fog/aws/models/rds/server.rb index 33f8ee8d3..5ca7383ab 100644 --- a/lib/fog/aws/models/rds/server.rb +++ b/lib/fog/aws/models/rds/server.rb @@ -60,6 +60,24 @@ module Fog connection.snapshots(:server => self) end + def tags + requires :id + connection.list_tags_for_resource(id). + body['ListTagsForResourceResult']['TagList'] + end + + def add_tags(new_tags) + requires :id + connection.add_tags_to_resource(id, new_tags) + tags + end + + def remove_tags(tag_keys) + requires :id + connection.remove_tags_from_resource(id, tag_keys) + tags + end + def modify(immediately, options) options[:security_group_names] ||= options['DBSecurityGroups'] params = self.class.new(options).attributes_to_params From eb96e320b973e4799d319578f2ff25124ab3cb6c Mon Sep 17 00:00:00 2001 From: Benton Roberts Date: Sun, 28 Oct 2012 23:18:43 -0400 Subject: [PATCH 5/7] [aws|rds] add tagging tests for RDS server model --- tests/aws/models/rds/tagging_tests.rb | 20 ++++++++++++++++++++ tests/aws/requests/rds/tagging_tests.rb | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100644 tests/aws/models/rds/tagging_tests.rb diff --git a/tests/aws/models/rds/tagging_tests.rb b/tests/aws/models/rds/tagging_tests.rb new file mode 100644 index 000000000..62d711646 --- /dev/null +++ b/tests/aws/models/rds/tagging_tests.rb @@ -0,0 +1,20 @@ +Shindo.tests("AWS::RDS | tagging", ['aws', 'rds']) do + + @server = Fog::AWS[:rds].servers.create(rds_default_server_params) + Formatador.display_line "Creating RDS instance #{@server.id}" + Formatador.display_line "Waiting for instance #{@server.id} to be ready" + @server.wait_for { ready? } + + tags1 = {'key1' => 'val1'} + tags2 = {'key2' => 'val2'} + + tests "add and remove tags from a running RDS model" do + returns({}) { @server.tags } + returns(tags1) { @server.add_tags tags1 } + returns(tags1.merge tags2) { @server.add_tags tags2 } + returns(tags2) { @server.remove_tags tags1.keys } + returns(tags2) { @server.tags } + end + + @server.destroy +end diff --git a/tests/aws/requests/rds/tagging_tests.rb b/tests/aws/requests/rds/tagging_tests.rb index 883a4fb48..413b592ff 100644 --- a/tests/aws/requests/rds/tagging_tests.rb +++ b/tests/aws/requests/rds/tagging_tests.rb @@ -36,7 +36,7 @@ Shindo.tests('AWS::RDS | tagging requests', ['aws', 'rds']) do tests("#remove_tags_from_resource").formats(AWS::RDS::Formats::BASIC) do result = @rds.remove_tags_from_resource( - @db_instance_id, [single_tag.keys.first]).body + @db_instance_id, single_tag.keys).body returns(two_tags) do @rds.list_tags_for_resource(@db_instance_id). body['ListTagsForResourceResult']['TagList'] From bfd0ade19ea6da51d6e3fff730503abcf127c502 Mon Sep 17 00:00:00 2001 From: Benton Roberts Date: Mon, 29 Oct 2012 10:17:19 -0400 Subject: [PATCH 6/7] [aws|rds] store mocked RDS instance tags in connection object --- lib/fog/aws/requests/rds/add_tags_to_resource.rb | 2 +- lib/fog/aws/requests/rds/create_db_instance.rb | 5 +++-- lib/fog/aws/requests/rds/list_tags_for_resource.rb | 3 ++- lib/fog/aws/requests/rds/remove_tags_from_resource.rb | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/fog/aws/requests/rds/add_tags_to_resource.rb b/lib/fog/aws/requests/rds/add_tags_to_resource.rb index fc54ad0ff..07bba85b9 100644 --- a/lib/fog/aws/requests/rds/add_tags_to_resource.rb +++ b/lib/fog/aws/requests/rds/add_tags_to_resource.rb @@ -29,7 +29,7 @@ module Fog def add_tags_to_resource(rds_id, tags) response = Excon::Response.new if server = self.data[:servers][rds_id] - server['Tags'].merge! tags + self.data[:tags][rds_id].merge! tags response.status = 200 response.body = { "ResponseMetadata"=>{ "RequestId"=> Fog::AWS::Mock.request_id } diff --git a/lib/fog/aws/requests/rds/create_db_instance.rb b/lib/fog/aws/requests/rds/create_db_instance.rb index 88f516a9a..1cd81ea37 100644 --- a/lib/fog/aws/requests/rds/create_db_instance.rb +++ b/lib/fog/aws/requests/rds/create_db_instance.rb @@ -103,8 +103,7 @@ module Fog # "ReadReplicaSourceDBInstanceIdentifier" => nil, # "LatestRestorableTime" => nil, "AvailabilityZone" => options["AvailabilityZone"], - "DBSubnetGroupName" => options["DBSubnetGroupName"], - "Tags" => {} + "DBSubnetGroupName" => options["DBSubnetGroupName"] } @@ -116,6 +115,8 @@ module Fog response.status = 200 # This values aren't showed at creating time but at available time self.data[:servers][db_name]["InstanceCreateTime"] = Time.now + self.data[:tags] ||= {} + self.data[:tags][db_name] = {} response end diff --git a/lib/fog/aws/requests/rds/list_tags_for_resource.rb b/lib/fog/aws/requests/rds/list_tags_for_resource.rb index b7d829765..5361de1aa 100644 --- a/lib/fog/aws/requests/rds/list_tags_for_resource.rb +++ b/lib/fog/aws/requests/rds/list_tags_for_resource.rb @@ -29,7 +29,8 @@ module Fog if server = self.data[:servers][rds_id] response.status = 200 response.body = { - "ListTagsForResourceResult" => { "TagList" => server['Tags'] } + "ListTagsForResourceResult" => + {"TagList" => self.data[:tags][rds_id]} } response else diff --git a/lib/fog/aws/requests/rds/remove_tags_from_resource.rb b/lib/fog/aws/requests/rds/remove_tags_from_resource.rb index 055fe6299..19b297f69 100644 --- a/lib/fog/aws/requests/rds/remove_tags_from_resource.rb +++ b/lib/fog/aws/requests/rds/remove_tags_from_resource.rb @@ -27,7 +27,7 @@ module Fog def remove_tags_from_resource(rds_id, keys) response = Excon::Response.new if server = self.data[:servers][rds_id] - keys.each {|key| server['Tags'].delete key} + keys.each {|key| self.data[:tags][rds_id].delete key} response.status = 200 response.body = { "ResponseMetadata"=>{ "RequestId"=> Fog::AWS::Mock.request_id } From d46c6d068ab55e906660d937e58d13c3f7b9b9fd Mon Sep 17 00:00:00 2001 From: Benton Roberts Date: Tue, 30 Oct 2012 08:45:00 -0400 Subject: [PATCH 7/7] [aws|rds] FIX non-1.8-compliant syntax bug --- lib/fog/aws/requests/rds/list_tags_for_resource.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/fog/aws/requests/rds/list_tags_for_resource.rb b/lib/fog/aws/requests/rds/list_tags_for_resource.rb index 5361de1aa..6c37a5ce3 100644 --- a/lib/fog/aws/requests/rds/list_tags_for_resource.rb +++ b/lib/fog/aws/requests/rds/list_tags_for_resource.rb @@ -16,7 +16,7 @@ module Fog request( 'Action' => 'ListTagsForResource', 'ResourceName' => "arn:aws:rds:#{@region}:#{owner_id}:db:#{rds_id}", - :parser => Fog::Parsers::AWS::RDS::TagListParser.new, + :parser => Fog::Parsers::AWS::RDS::TagListParser.new ) end