From 9f106afcd34a477b2c2e87c45171e61e700dcd9a Mon Sep 17 00:00:00 2001 From: Benton Roberts Date: Tue, 27 Sep 2011 10:52:46 -0400 Subject: [PATCH] [aws|acs] Added security group methods --- lib/fog/aws/acs.rb | 106 +++++++++--------- .../authorize_cache_security_group_ingress.rb | 26 +++++ .../parsers/acs/describe_security_groups.rb | 27 +++++ ...rity_group.rb => single_security_group.rb} | 10 +- .../authorize_cache_security_group_ingress.rb | 36 ++++++ .../acs/create_cache_security_group.rb | 4 +- .../acs/describe_cache_security_groups.rb | 34 ++++++ .../revoke_cache_security_group_ingress.rb | 37 ++++++ tests/aws/requests/acs/helper.rb | 4 +- .../aws/requests/acs/security_group_tests.rb | 75 +++++++++++++ 10 files changed, 296 insertions(+), 63 deletions(-) create mode 100644 lib/fog/aws/parsers/acs/authorize_cache_security_group_ingress.rb create mode 100644 lib/fog/aws/parsers/acs/describe_security_groups.rb rename lib/fog/aws/parsers/acs/{create_cache_security_group.rb => single_security_group.rb} (75%) create mode 100644 lib/fog/aws/requests/acs/authorize_cache_security_group_ingress.rb create mode 100644 lib/fog/aws/requests/acs/describe_cache_security_groups.rb create mode 100644 lib/fog/aws/requests/acs/revoke_cache_security_group_ingress.rb create mode 100644 tests/aws/requests/acs/security_group_tests.rb diff --git a/lib/fog/aws/acs.rb b/lib/fog/aws/acs.rb index 9d3d1a0b3..849cf46be 100644 --- a/lib/fog/aws/acs.rb +++ b/lib/fog/aws/acs.rb @@ -7,9 +7,6 @@ module Fog request_path 'fog/aws/requests/acs' - #request :authorize_cache_security_group_ingress - #request :revoke_cache_security_group_ingress - #request :create_cache_cluster #request :delete_cache_cluster #request :describe_cache_clusters @@ -23,8 +20,10 @@ module Fog #request :reset_cache_parameter_group request :create_cache_security_group - #request :delete_cache_security_group - #request :describe_cache_security_groups + request :delete_cache_security_group + request :describe_cache_security_groups + request :authorize_cache_security_group_ingress + request :revoke_cache_security_group_ingress #request :describe_engine_default_parameters @@ -53,57 +52,58 @@ module Fog options[:region] ||= 'us-east-1' @host = options[:host] || case options[:region] - when 'us-east-1' - 'acsvc.us-east-1.amazonaws.com' - else - raise ArgumentError, "Unknown region: #{options[:region].inspect}" - end - @path = options[:path] || '/' - @port = options[:port] || 443 - @scheme = options[:scheme] || 'https' - @connection = Fog::Connection.new("#{@scheme}://#{@host}:#{@port}#{@path}", options[:persistent]) - end - - def reload - @connection.reset - end - - private - def request(params) - idempotent = params.delete(:idempotent) - parser = params.delete(:parser) - - body = Fog::AWS.signed_params( - params, - { - :aws_access_key_id => @aws_access_key_id, - :hmac => @hmac, - :host => @host, - :path => @path, - :port => @port, - :version => '2011-07-15' - } - ) - - begin - response = @connection.request({ - :body => body, - :expects => 200, - :headers => { 'Content-Type' => 'application/x-www-form-urlencoded' }, - :idempotent => idempotent, - :host => @host, - :method => 'POST', - :parser => parser - }) - rescue Excon::Errors::HTTPStatusError => error - # TODO: handle not found errors - raise + when 'us-east-1' + 'acsvc.us-east-1.amazonaws.com' + #TODO: Support other regions + else + raise ArgumentError, "Unknown region: #{options[:region].inspect}" + end + @path = options[:path] || '/' + @port = options[:port] || 443 + @scheme = options[:scheme] || 'https' + @connection = Fog::Connection.new("#{@scheme}://#{@host}:#{@port}#{@path}", options[:persistent]) end - response - end + def reload + @connection.reset + end + private + def request(params) + idempotent = params.delete(:idempotent) + parser = params.delete(:parser) + + body = Fog::AWS.signed_params( + params, + { + :aws_access_key_id => @aws_access_key_id, + :hmac => @hmac, + :host => @host, + :path => @path, + :port => @port, + :version => '2011-07-15' + } + ) + + begin + response = @connection.request({ + :body => body, + :expects => 200, + :headers => { 'Content-Type' => 'application/x-www-form-urlencoded' }, + :idempotent => idempotent, + :host => @host, + :method => 'POST', + :parser => parser + }) + rescue Excon::Errors::HTTPStatusError => error + # TODO: handle not found errors + raise + end + + response + end + + end end end end -end diff --git a/lib/fog/aws/parsers/acs/authorize_cache_security_group_ingress.rb b/lib/fog/aws/parsers/acs/authorize_cache_security_group_ingress.rb new file mode 100644 index 000000000..51113c7ce --- /dev/null +++ b/lib/fog/aws/parsers/acs/authorize_cache_security_group_ingress.rb @@ -0,0 +1,26 @@ +module Fog + module Parsers + module AWS + module ACS + + require 'fog/aws/parsers/acs/security_group_parser' + + class AuthorizeCacheSecurityGroupIngress < Fog::Parsers::AWS::ACS::SecurityGroupParser + + def end_element(name) + case name + when 'CacheSecurityGroup' then + @response['CacheSecurityGroup'] = @security_group + reset_security_group + else + super + end + + end + + end + + end + end + end +end diff --git a/lib/fog/aws/parsers/acs/describe_security_groups.rb b/lib/fog/aws/parsers/acs/describe_security_groups.rb new file mode 100644 index 000000000..8ccd3488a --- /dev/null +++ b/lib/fog/aws/parsers/acs/describe_security_groups.rb @@ -0,0 +1,27 @@ +module Fog + module Parsers + module AWS + module ACS + require 'fog/aws/parsers/acs/security_group_parser' + + class DescribeSecurityGroups < SecurityGroupParser + + def reset + super + @response['CacheSecurityGroups'] = [] + end + + def end_element(name) + case name + when 'CacheSecurityGroup' + @response["#{name}s"] << @security_group + reset_security_group + else + super + end + end + end + end + end + end +end diff --git a/lib/fog/aws/parsers/acs/create_cache_security_group.rb b/lib/fog/aws/parsers/acs/single_security_group.rb similarity index 75% rename from lib/fog/aws/parsers/acs/create_cache_security_group.rb rename to lib/fog/aws/parsers/acs/single_security_group.rb index 6be43cdb8..8e7b638a1 100644 --- a/lib/fog/aws/parsers/acs/create_cache_security_group.rb +++ b/lib/fog/aws/parsers/acs/single_security_group.rb @@ -2,10 +2,9 @@ module Fog module Parsers module AWS module ACS - require 'fog/aws/parsers/acs/security_group_parser' - class CreateCacheSecurityGroup < Fog::Parsers::AWS::ACS::SecurityGroupParser + class SingleSecurityGroup < SecurityGroupParser def reset super @@ -18,8 +17,8 @@ module Fog def end_element(name) case name - when 'CacheSecurityGroup' then - @response['CacheSecurityGroup'] = @security_group + when 'CacheSecurityGroup' + @response[name] = @security_group reset_security_group when 'RequestId' @@ -27,11 +26,8 @@ module Fog else super end - end - end - end end end diff --git a/lib/fog/aws/requests/acs/authorize_cache_security_group_ingress.rb b/lib/fog/aws/requests/acs/authorize_cache_security_group_ingress.rb new file mode 100644 index 000000000..a3a4b4185 --- /dev/null +++ b/lib/fog/aws/requests/acs/authorize_cache_security_group_ingress.rb @@ -0,0 +1,36 @@ +module Fog + module AWS + class ACS + class Real + + require 'fog/aws/parsers/acs/single_security_group' + + # Authorize ingress to a CacheSecurityGroup using EC2 Security Groups + # + # === Parameters + # * name <~String> - The name of the cache security group + # * ec2_name <~String> - The name of the EC2 security group to authorize + # * ec2_owner_id <~String> - The AWS Account Number of the EC2 security group + # === Returns + # * response <~Excon::Response>: + # * body <~Hash> + def authorize_cache_security_group_ingress(name, ec2_name, ec2_owner_id) + request({ + 'Action' => 'AuthorizeCacheSecurityGroupIngress', + 'CacheSecurityGroupName' => name, + 'EC2SecurityGroupName' => ec2_name, + 'EC2SecurityGroupOwnerId' => ec2_owner_id, + :parser => Fog::Parsers::AWS::ACS::SingleSecurityGroup.new + }) + end + + end + + class Mock + def authorize_cache_security_group_ingress + Fog::Mock.not_implemented + end + end + end + end +end diff --git a/lib/fog/aws/requests/acs/create_cache_security_group.rb b/lib/fog/aws/requests/acs/create_cache_security_group.rb index 64f12a65c..24e2723cf 100644 --- a/lib/fog/aws/requests/acs/create_cache_security_group.rb +++ b/lib/fog/aws/requests/acs/create_cache_security_group.rb @@ -3,7 +3,7 @@ module Fog class ACS class Real - require 'fog/aws/parsers/acs/create_cache_security_group' + require 'fog/aws/parsers/acs/single_security_group' # creates a cache security group # @@ -18,7 +18,7 @@ module Fog 'Action' => 'CreateCacheSecurityGroup', 'CacheSecurityGroupName' => name, 'CacheSecurityGroupDescription' => description, - :parser => Fog::Parsers::AWS::ACS::CreateCacheSecurityGroup.new + :parser => Fog::Parsers::AWS::ACS::SingleSecurityGroup.new }) end end diff --git a/lib/fog/aws/requests/acs/describe_cache_security_groups.rb b/lib/fog/aws/requests/acs/describe_cache_security_groups.rb new file mode 100644 index 000000000..a71e94ee5 --- /dev/null +++ b/lib/fog/aws/requests/acs/describe_cache_security_groups.rb @@ -0,0 +1,34 @@ +module Fog + module AWS + class ACS + class Real + + require 'fog/aws/parsers/acs/describe_security_groups' + + # Returns a list of CacheSecurityGroup descriptions + # + # === Parameters + # * options <~Hash> (optional): + # * CacheSecurityGroupName<~String> - The name of the cache security group + # * Marker <~String> - marker provided in the previous request + # * MaxRecords <~String> - the maximum number of records to include + # === Returns + # * response <~Excon::Response>: + # * body <~Hash> + def describe_cache_security_groups(options = {}) + request({ + 'Action' => 'DescribeCacheSecurityGroups', + :parser => Fog::Parsers::AWS::ACS::DescribeSecurityGroups.new + }.merge(options)) + end + + end + + class Mock + def describe_cache_security_groups + Fog::Mock.not_implemented + end + end + end + end +end diff --git a/lib/fog/aws/requests/acs/revoke_cache_security_group_ingress.rb b/lib/fog/aws/requests/acs/revoke_cache_security_group_ingress.rb new file mode 100644 index 000000000..5f87667f2 --- /dev/null +++ b/lib/fog/aws/requests/acs/revoke_cache_security_group_ingress.rb @@ -0,0 +1,37 @@ + +module Fog + module AWS + class ACS + class Real + + require 'fog/aws/parsers/acs/single_security_group' + + # Revoke ingress to a CacheSecurityGroup using EC2 Security Groups + # + # === Parameters + # * name <~String> - The name of the cache security group + # * ec2_name <~String> - The name of the EC2 security group to revoke + # * ec2_owner_id <~String> - The AWS Account Number of the EC2 security group + # === Returns + # * response <~Excon::Response>: + # * body <~Hash> + def revoke_cache_security_group_ingress(name, ec2_name, ec2_owner_id) + request({ + 'Action' => 'RevokeCacheSecurityGroupIngress', + 'CacheSecurityGroupName' => name, + 'EC2SecurityGroupName' => ec2_name, + 'EC2SecurityGroupOwnerId' => ec2_owner_id, + :parser => Fog::Parsers::AWS::ACS::SingleSecurityGroup.new + }) + end + + end + + class Mock + def revoke_cache_security_group_ingress + Fog::Mock.not_implemented + end + end + end + end +end diff --git a/tests/aws/requests/acs/helper.rb b/tests/aws/requests/acs/helper.rb index 60e1f608a..3c4d9758e 100644 --- a/tests/aws/requests/acs/helper.rb +++ b/tests/aws/requests/acs/helper.rb @@ -13,7 +13,9 @@ class AWS 'OwnerId' => String } - CREATE_SECURITY_GROUP = BASIC.merge('CacheSecurityGroup' => SECURITY_GROUP) + SINGLE_SECURITY_GROUP = BASIC.merge('CacheSecurityGroup' => SECURITY_GROUP) + DESCRIBE_SECURITY_GROUPS = BASIC.merge('CacheSecurityGroups' => [SECURITY_GROUP]) + end end diff --git a/tests/aws/requests/acs/security_group_tests.rb b/tests/aws/requests/acs/security_group_tests.rb new file mode 100644 index 000000000..4a7b9880c --- /dev/null +++ b/tests/aws/requests/acs/security_group_tests.rb @@ -0,0 +1,75 @@ +Shindo.tests('AWS::ACS | security group requests', ['aws', 'acs']) do + + tests('success') do + pending if Fog.mocking? + + name = 'fog-test' + description = 'Fog Test Group' + + tests('#create_cache_security_group').formats(AWS::ACS::Formats::SINGLE_SECURITY_GROUP) do + body = AWS[:acs].create_cache_security_group(name, description).body + group = body['CacheSecurityGroup'] + returns(name) { group['CacheSecurityGroupName'] } + returns(description) { group['CacheSecurityGroupDescription'] } + returns([], "no authorized security group") { group['EC2SecurityGroups'] } + body + end + + tests('#describe_cache_security_groups without options').formats(AWS::ACS::Formats::DESCRIBE_SECURITY_GROUPS) do + body = AWS[:acs].describe_cache_security_groups.body + returns(true, "has #{name}") do + body['CacheSecurityGroups'].any? {|group| group['CacheSecurityGroupName'] == name } + end + body + end + + tests('#describe_cache_security_groups with name').formats(AWS::ACS::Formats::DESCRIBE_SECURITY_GROUPS) do + body = AWS[:acs].describe_cache_security_groups('CacheSecurityGroupName' => name).body + returns(1, "size of 1") { body['CacheSecurityGroups'].size } + returns(name, "has #{name}") { body['CacheSecurityGroups'].first['CacheSecurityGroupName'] } + body + end + + tests('authorization') do + ec2_group = Fog::Compute.new(:provider => 'AWS').security_groups.create(:name => 'fog-test-acs', :description => 'Fog Test ACS') + # Reload to get the owner_id + ec2_group.reload + + tests('#authorize_cache_security_group_ingress').formats(AWS::ACS::Formats::SINGLE_SECURITY_GROUP) do + body = AWS[:acs].authorize_cache_security_group_ingress(name, ec2_group.name, ec2_group.owner_id).body + group = body['CacheSecurityGroup'] + expected_ec2_groups = [{'Status' => 'authorizing', 'EC2SecurityGroupName' => ec2_group.name, 'EC2SecurityGroupOwnerId' => ec2_group.owner_id}] + returns(expected_ec2_groups, 'has correct EC2 groups') { group['EC2SecurityGroups'] } + body + end + + # Wait for the state to be active + Fog.wait_for do + group = AWS[:acs].describe_cache_security_groups('CacheSecurityGroupName' => name).body['CacheSecurityGroups'].first + group['EC2SecurityGroups'].all? {|ec2| ec2['Status'] == 'authorized'} + end + + tests('#revoke_cache_security_group_ingress').formats(AWS::ACS::Formats::SINGLE_SECURITY_GROUP) do + body = AWS[:acs].revoke_cache_security_group_ingress(name, ec2_group.name, ec2_group.owner_id).body + group = body['CacheSecurityGroup'] + expected_ec2_groups = [{'Status' => 'revoking', 'EC2SecurityGroupName' => ec2_group.name, 'EC2SecurityGroupOwnerId' => ec2_group.owner_id}] + returns(expected_ec2_groups, 'has correct EC2 groups') { group['EC2SecurityGroups'] } + body + end + + + ec2_group.destroy + end + + tests('#delete_cache_security_group').formats(AWS::ACS::Formats::BASIC) do + body = AWS[:acs].delete_cache_security_group(name).body + end + end + + tests('failure') do + # TODO: + # Create a duplicate security group + # List a missing security group + # Delete a missing security group + end +end