diff --git a/lib/fog/aws/elbv2.rb b/lib/fog/aws/elbv2.rb index 1a3885ae5..1b0726780 100644 --- a/lib/fog/aws/elbv2.rb +++ b/lib/fog/aws/elbv2.rb @@ -5,7 +5,10 @@ module Fog recognizes :region, :host, :path, :port, :scheme, :persistent, :use_iam_profile, :aws_session_token, :aws_credentials_expire_at, :version, :instrumentor, :instrumentor_name request_path 'fog/aws/requests/elbv2' + request :add_tags request :create_load_balancer + request :describe_tags + request :remove_tags request :describe_load_balancers request :describe_listeners diff --git a/lib/fog/aws/parsers/elbv2/describe_tags.rb b/lib/fog/aws/parsers/elbv2/describe_tags.rb new file mode 100644 index 000000000..dd09041df --- /dev/null +++ b/lib/fog/aws/parsers/elbv2/describe_tags.rb @@ -0,0 +1,53 @@ +module Fog + module Parsers + module AWS + module ELBV2 + class DescribeTags < Fog::Parsers::Base + def reset + @this_key = nil + @this_value = nil + @tags = Hash.new + @response = { 'DescribeTagsResult' => { 'TagDescriptions' => [] }, 'ResponseMetadata' => {} } + @in_tags = false + end + + def start_element(name, attrs = []) + super + case name + when 'member' + unless @in_tags + @resource_arn = nil + @tags = {} + end + when 'Tags' + @in_tags = true + end + end + + def end_element(name) + super + case name + when 'member' + if @in_tags + @tags[@this_key] = @this_value + @this_key, @this_value = nil, nil + else + @response['DescribeTagsResult']['TagDescriptions'] << { 'Tags' => @tags, 'ResourceArn' => @resource_arn } + end + when 'Key' + @this_key = value + when 'Value' + @this_value = value + when 'ResourceArn' + @resource_arn = value + when 'RequestId' + @response['ResponseMetadata'][name] = value + when 'Tags' + @in_tags = false + end + end + end + end + end + end +end diff --git a/lib/fog/aws/parsers/elbv2/empty.rb b/lib/fog/aws/parsers/elbv2/empty.rb new file mode 100644 index 000000000..94305b937 --- /dev/null +++ b/lib/fog/aws/parsers/elbv2/empty.rb @@ -0,0 +1,10 @@ +module Fog + module Parsers + module AWS + module ELBV2 + class Empty < ELB::Empty + end + end + end + end +end diff --git a/lib/fog/aws/requests/elbv2/add_tags.rb b/lib/fog/aws/requests/elbv2/add_tags.rb new file mode 100644 index 000000000..199af4c75 --- /dev/null +++ b/lib/fog/aws/requests/elbv2/add_tags.rb @@ -0,0 +1,45 @@ +module Fog + module AWS + class ELBV2 + class Real + require 'fog/aws/parsers/elbv2/empty' + + # adds tags to a load balancer instance + # http://docs.aws.amazon.com/ElasticLoadBalancing/latest/APIReference/API_AddTags.html + # ==== Parameters + # * resource_arn <~String> - The Amazon Resource Name (ARN) of the resource + # * tags <~Hash> A Hash of (String) key-value pairs + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + def add_tags(resource_arn, tags) + keys = tags.keys.sort + values = keys.map {|key| tags[key]} + request({ + 'Action' => 'AddTags', + 'ResourceArns.member.1' => resource_arn, + :parser => Fog::Parsers::AWS::ELBV2::Empty.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(resource_arn, tags) + response = Excon::Response.new + if self.data[:load_balancers_v2][resource_arn] + self.data[:tags][resource_arn].merge! tags + response.status = 200 + response.body = { + "ResponseMetadata"=>{ "RequestId"=> Fog::AWS::Mock.request_id } + } + response + else + raise Fog::AWS::ELBV2::NotFound.new("Elastic load balancer #{resource_arn} not found") + end + end + end + end + end +end diff --git a/lib/fog/aws/requests/elbv2/create_load_balancer.rb b/lib/fog/aws/requests/elbv2/create_load_balancer.rb index 064940953..7aacdcfbc 100644 --- a/lib/fog/aws/requests/elbv2/create_load_balancer.rb +++ b/lib/fog/aws/requests/elbv2/create_load_balancer.rb @@ -102,6 +102,7 @@ module Fog dns_name = Fog::AWS::ELBV2::Mock.dns_name(name, @region) type = options[:type] || 'application' + load_balancer_arn = Fog::AWS::Mock.arn('elasticloadbalancing', self.data[:owner_id], "loadbalancer/#{type[0..2]}/#{name}/#{Fog::AWS::Mock.key_id}") subnet_ids = options[:subnets] || [] region = if subnet_ids.any? @@ -126,7 +127,7 @@ module Fog vpc_id = subnets.first['vpcId'] self.data[:tags] ||= {} - self.data[:tags][name] = options[:tags] || {} + self.data[:tags][load_balancer_arn] = options[:tags] || {} load_balancer = { 'AvailabilityZones' => availability_zones || [], @@ -138,10 +139,10 @@ module Fog 'VpcId' => vpc_id, 'Type' => type, 'State' => {'Code' => 'provisioning'}, - 'LoadBalancerArn' => Fog::AWS::Mock.arn('elasticloadbalancing', self.data[:owner_id], "loadbalancer/#{type[0..2]}/#{name}/#{Fog::AWS::Mock.key_id}"), + 'LoadBalancerArn' => load_balancer_arn, 'LoadBalancerName' => name } - self.data[:load_balancers_v2][name] = load_balancer + self.data[:load_balancers_v2][load_balancer_arn] = load_balancer response.body = { 'ResponseMetadata' => { 'RequestId' => Fog::AWS::Mock.request_id diff --git a/lib/fog/aws/requests/elbv2/describe_tags.rb b/lib/fog/aws/requests/elbv2/describe_tags.rb new file mode 100644 index 000000000..c4b3144da --- /dev/null +++ b/lib/fog/aws/requests/elbv2/describe_tags.rb @@ -0,0 +1,50 @@ +module Fog + module AWS + class ELBV2 + class Real + require 'fog/aws/parsers/elbv2/describe_tags' + + # returns a Hash of tags for a load balancer + # http://docs.aws.amazon.com/ElasticLoadBalancing/latest/APIReference/API_DescribeTags.html + # ==== Parameters + # * resource_arns <~Array> - ARN(s) of the ELB instance whose tags are to be retrieved + # ==== Returns + # * response<~Excon::Response>: + # * body<~Hash>: + def describe_tags(resource_arns) + request({ + 'Action' => 'DescribeTags', + :parser => Fog::Parsers::AWS::ELBV2::DescribeTags.new + }.merge!(Fog::AWS.indexed_param('ResourceArns.member.%d', [*resource_arns])) + ) + end + end + + class Mock + def describe_tags(resource_arns) + response = Excon::Response.new + resource_arns = [*resource_arns] + + tag_describtions = resource_arns.map do |resource_arn| + if self.data[:load_balancers_v2][resource_arn] + { + "Tags"=>self.data[:tags][resource_arn], + "ResourceArn"=>resource_arn + } + else + raise Fog::AWS::ELBV2::NotFound.new("Elastic load balancer #{resource_arns} not found") + end + end + + response.status = 200 + response.body = { + "ResponseMetadata"=>{"RequestId"=> Fog::AWS::Mock.request_id }, + "DescribeTagsResult"=>{"TagDescriptions"=> tag_describtions} + } + + response + end + end + end + end +end diff --git a/lib/fog/aws/requests/elbv2/remove_tags.rb b/lib/fog/aws/requests/elbv2/remove_tags.rb new file mode 100644 index 000000000..fb4b442f9 --- /dev/null +++ b/lib/fog/aws/requests/elbv2/remove_tags.rb @@ -0,0 +1,45 @@ +module Fog + module AWS + class ELBV2 + class Real + require 'fog/aws/parsers/elbv2/empty' + + # removes tags from an elastic load balancer instance + # http://docs.aws.amazon.com/ElasticLoadBalancing/latest/APIReference/API_RemoveTags.html + # ==== Parameters + # * resource_arn <~String> - ARN of the ELB 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(resource_arn, keys) + request( + { 'Action' => 'RemoveTags', + 'ResourceArns.member.1' => resource_arn, + :parser => Fog::Parsers::AWS::ELBV2::Empty.new, + }.merge(Fog::AWS.indexed_param('TagKeys.member.%d', keys)) + ) + end + + end + + class Mock + + def remove_tags(resource_arn, keys) + response = Excon::Response.new + if self.data[:load_balancers_v2][resource_arn] + keys.each {|key| self.data[:tags][resource_arn].delete key} + response.status = 200 + response.body = { + "ResponseMetadata"=>{ "RequestId"=> Fog::AWS::Mock.request_id } + } + response + else + raise Fog::AWS::ELBV2::NotFound.new("Elastic load balancer #{resource_arn} not found") + end + end + + end + end + end +end diff --git a/tests/parsers/elbv2/describe_tags_tests.rb b/tests/parsers/elbv2/describe_tags_tests.rb new file mode 100644 index 000000000..82b183602 --- /dev/null +++ b/tests/parsers/elbv2/describe_tags_tests.rb @@ -0,0 +1,35 @@ +require 'fog/xml' +require 'fog/aws/parsers/elbv2/describe_tags' + +DESCRIBE_TAGS_RESULT = <<-EOF + + + + + arn:aws:elasticloadbalancing:us-west-2:123456789012:loadbalancer/app/my-load-balancer/50dc6c495c0c9188 + + + lima + project + + + digital-media + department + + + + + + + 34f144db-f2d9-11e5-a53c-67205c0d10fd + + +EOF + +Shindo.tests('AWS::ELBV2 | parsers | describe_tags', %w[aws elb parser]) do + tests('parses the xml').formats(AWS::ELBV2::Formats::DESCRIBE_TAGS) do + parser = Nokogiri::XML::SAX::Parser.new(Fog::Parsers::AWS::ELBV2::DescribeTags.new) + parser.parse(DESCRIBE_TAGS_RESULT) + parser.document.response + end +end diff --git a/tests/requests/elbv2/helper.rb b/tests/requests/elbv2/helper.rb index b86bb2a99..506427441 100644 --- a/tests/requests/elbv2/helper.rb +++ b/tests/requests/elbv2/helper.rb @@ -52,6 +52,15 @@ class AWS DESCRIBE_LISTENERS = BASIC.merge({ 'DescribeListenersResult' => {'Listeners' => [LISTENER], 'NextMarker' => Fog::Nullable::String} }) + + TAG_DESCRIPTIONS = [{ + "Tags" => Hash, + "ResourceArn" => String + }] + + DESCRIBE_TAGS = BASIC.merge({ + 'DescribeTagsResult' => {'TagDescriptions' => TAG_DESCRIPTIONS} + }) end end end diff --git a/tests/requests/elbv2/load_balancer_tests.rb b/tests/requests/elbv2/load_balancer_tests.rb index 4230d68e5..0a8e46443 100644 --- a/tests/requests/elbv2/load_balancer_tests.rb +++ b/tests/requests/elbv2/load_balancer_tests.rb @@ -3,21 +3,48 @@ Shindo.tests('AWS::ELBV2 | load_balancer_tests', ['aws', 'elb']) do @key_name = 'fog-test' vpc = Fog::Compute[:aws].create_vpc('10.255.254.64/28').body['vpcSet'].first @subnet_id = Fog::Compute[:aws].create_subnet(vpc['vpcId'], vpc['cidrBlock']).body['subnet']['subnetId'] + @tags = { 'test1' => 'Value1', 'test2' => 'Value2' } tests('success') do - tests("#create_load_balancer").formats(AWS::ELBV2::Formats::CREATE_LOAD_BALANCER) do + tests('#create_load_balancer').formats(AWS::ELBV2::Formats::CREATE_LOAD_BALANCER) do options = { subnets: [@subnet_id] } - Fog::AWS[:elbv2].create_load_balancer(@load_balancer_id, options).body + load_balancer = Fog::AWS[:elbv2].create_load_balancer(@load_balancer_id, options).body + @load_balancer_arn = load_balancer['CreateLoadBalancerResult']['LoadBalancers'].first['LoadBalancerArn'] + load_balancer end - tests("#describe_load_balancers").formats(AWS::ELBV2::Formats::DESCRIBE_LOAD_BALANCERS) do + tests('#describe_load_balancers').formats(AWS::ELBV2::Formats::DESCRIBE_LOAD_BALANCERS) do Fog::AWS[:elbv2].describe_load_balancers.body end tests('#describe_load_balancers with bad name') do raises(Fog::AWS::ELBV2::NotFound) { Fog::AWS[:elbv2].describe_load_balancers('LoadBalancerNames' => 'none-such-lb') } end + + tests("#add_tags('#{@load_balancer_arn}', #{@tags})").formats(AWS::ELBV2::Formats::BASIC) do + Fog::AWS[:elbv2].add_tags(@load_balancer_arn, @tags).body + end + + tests('#describe_tags').formats(AWS::ELBV2::Formats::DESCRIBE_TAGS) do + Fog::AWS[:elbv2].describe_tags(@load_balancer_arn).body + end + + tests('#describe_tags with at least one wrong arn') do + raises(Fog::AWS::ELBV2::NotFound) { Fog::AWS[:elbv2].describe_tags([@load_balancer_arn, 'wrong_arn']) } + end + + tests("#describe_tags(#{@load_balancer_arn})").returns(@tags) do + Fog::AWS[:elbv2].describe_tags(@load_balancer_arn).body['DescribeTagsResult']['TagDescriptions'].first['Tags'] + end + + tests("#remove_tags('#{@load_balancer_arn}', #{@tags.keys})").formats(AWS::ELBV2::Formats::BASIC) do + Fog::AWS[:elbv2].remove_tags(@load_balancer_arn, @tags.keys).body + end + + tests("#describe_tags(#{@load_balancer_arn})").returns({}) do + Fog::AWS[:elbv2].describe_tags(@load_balancer_arn).body['DescribeTagsResult']['TagDescriptions'].first['Tags'] + end end end