mirror of
https://github.com/fog/fog-aws.git
synced 2022-11-09 13:50:52 -05:00
Merge pull request #542 from KevinLoiseau/feature/elbv2_creation_endpoint
Feature/elbv2 creation endpoint
This commit is contained in:
commit
beb3199492
7 changed files with 419 additions and 1 deletions
|
@ -1,7 +1,11 @@
|
|||
module Fog
|
||||
module AWS
|
||||
class ELBV2 < ELB
|
||||
requires :aws_access_key_id, :aws_secret_access_key
|
||||
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 :create_load_balancer
|
||||
request :describe_load_balancers
|
||||
request :describe_listeners
|
||||
|
||||
|
@ -12,6 +16,54 @@ module Fog
|
|||
super(options)
|
||||
end
|
||||
end
|
||||
|
||||
class Mock
|
||||
def self.data
|
||||
@data ||= Hash.new do |hash, region|
|
||||
owner_id = Fog::AWS::Mock.owner_id
|
||||
hash[region] = Hash.new do |region_hash, key|
|
||||
region_hash[key] = {
|
||||
:owner_id => owner_id,
|
||||
:load_balancers_v2 => {}
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.dns_name(name, region)
|
||||
"#{name}-#{Fog::Mock.random_hex(8)}.#{region}.elb.amazonaws.com"
|
||||
end
|
||||
|
||||
def self.reset
|
||||
@data = nil
|
||||
end
|
||||
|
||||
attr_reader :region
|
||||
|
||||
def initialize(options={})
|
||||
@use_iam_profile = options[:use_iam_profile]
|
||||
|
||||
@region = options[:region] || 'us-east-1'
|
||||
setup_credentials(options)
|
||||
|
||||
Fog::AWS.validate_region!(@region)
|
||||
end
|
||||
|
||||
def setup_credentials(options)
|
||||
@aws_access_key_id = options[:aws_access_key_id]
|
||||
@aws_secret_access_key = options[:aws_secret_access_key]
|
||||
|
||||
@signer = Fog::AWS::SignatureV4.new(@aws_access_key_id, @aws_secret_access_key,@region,'elasticloadbalancing')
|
||||
end
|
||||
|
||||
def data
|
||||
self.class.data[@region][@aws_access_key_id]
|
||||
end
|
||||
|
||||
def reset_data
|
||||
self.class.data[@region].delete(@aws_access_key_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
88
lib/fog/aws/parsers/elbv2/create_load_balancer.rb
Normal file
88
lib/fog/aws/parsers/elbv2/create_load_balancer.rb
Normal file
|
@ -0,0 +1,88 @@
|
|||
module Fog
|
||||
module Parsers
|
||||
module AWS
|
||||
module ELBV2
|
||||
class CreateLoadBalancer < Fog::Parsers::Base
|
||||
def reset
|
||||
reset_load_balancer
|
||||
reset_availability_zone
|
||||
@load_balancer_addresses = {}
|
||||
@state = {}
|
||||
@results = { 'LoadBalancers' => [] }
|
||||
@response = { 'CreateLoadBalancerResult' => {}, 'ResponseMetadata' => {} }
|
||||
end
|
||||
|
||||
def reset_load_balancer
|
||||
@load_balancer = { 'SecurityGroups' => [], 'AvailabilityZones' => [] }
|
||||
end
|
||||
|
||||
def reset_availability_zone
|
||||
@availability_zone = { 'LoadBalancerAddresses' => [] }
|
||||
end
|
||||
|
||||
def start_element(name, attrs = [])
|
||||
super
|
||||
case name
|
||||
when 'AvailabilityZones'
|
||||
@in_availability_zones = true
|
||||
when 'LoadBalancerAddresses'
|
||||
@in_load_balancer_addresses = true
|
||||
when 'SecurityGroups'
|
||||
@in_security_groups = true
|
||||
when 'State'
|
||||
@in_state = true
|
||||
end
|
||||
end
|
||||
|
||||
def end_element(name)
|
||||
case name
|
||||
when 'member'
|
||||
if @in_availability_zones && @in_load_balancer_addresses
|
||||
@availability_zone['LoadBalancerAddresses'] << @load_balancer_addresses
|
||||
elsif @in_availability_zones
|
||||
@load_balancer['AvailabilityZones'] << @availability_zone
|
||||
reset_availability_zone
|
||||
elsif @in_security_groups
|
||||
@load_balancer['SecurityGroups'] << value
|
||||
else
|
||||
@results['LoadBalancers'] << @load_balancer
|
||||
reset_load_balancer
|
||||
end
|
||||
when 'SubnetId', 'ZoneName'
|
||||
@availability_zone[name] = value
|
||||
when 'IpAddress', 'AllocationId'
|
||||
@load_balancer_addresses[name] = value
|
||||
|
||||
when 'CanonicalHostedZoneName', 'CanonicalHostedZoneNameID', 'LoadBalancerName', 'DNSName', 'Scheme', 'Type',
|
||||
'LoadBalancerArn', 'IpAddressType', 'CanonicalHostedZoneId', 'VpcId'
|
||||
@load_balancer[name] = value
|
||||
when 'CreatedTime'
|
||||
@load_balancer[name] = Time.parse(value)
|
||||
|
||||
when 'LoadBalancerAddresses'
|
||||
@in_load_balancer_addresses = false
|
||||
when 'AvailabilityZones'
|
||||
@in_availability_zones = false
|
||||
when 'SecurityGroups'
|
||||
@in_security_groups = false
|
||||
when 'State'
|
||||
@in_state = false
|
||||
@load_balancer[name] = @state
|
||||
@state = {}
|
||||
when 'Code'
|
||||
@state[name] = value
|
||||
|
||||
when 'RequestId'
|
||||
@response['ResponseMetadata'][name] = value
|
||||
|
||||
when 'NextMarker'
|
||||
@results['NextMarker'] = value
|
||||
when 'CreateLoadBalancerResponse'
|
||||
@response['CreateLoadBalancerResult'] = @results
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
159
lib/fog/aws/requests/elbv2/create_load_balancer.rb
Normal file
159
lib/fog/aws/requests/elbv2/create_load_balancer.rb
Normal file
|
@ -0,0 +1,159 @@
|
|||
module Fog
|
||||
module AWS
|
||||
class ELBV2
|
||||
class Real
|
||||
require 'fog/aws/parsers/elbv2/create_load_balancer'
|
||||
|
||||
# Create a new Elastic Load Balancer
|
||||
#
|
||||
# ==== Parameters
|
||||
# * name<~String> - The name of the load balancer.
|
||||
# This name must be unique per region per account, can have a maximum of 32 characters, must contain only alphanumeric characters or hyphens,
|
||||
# must not begin or end with a hyphen, and must not begin with "internal-".
|
||||
# - Required: Yes
|
||||
# * options<~Hash>:
|
||||
# * ip_address_type<~String> - [Application Load Balancers] The type of IP addresses used by the subnets for your load balancer.
|
||||
# The possible values are ipv4 (for IPv4 addresses) and dualstack (for IPv4 and IPv6 addresses).
|
||||
# Internal load balancers must use ipv4.
|
||||
# - Required: No
|
||||
# * scheme<~String> - The default is an Internet-facing load balancer. Valid Values: internet-facing | internal
|
||||
# - Required: No
|
||||
# * security_groups<~Array> - The IDs of the security groups for the load balancer.
|
||||
# - Required: No
|
||||
# * subnet_mappings<~Array> - The IDs of the public subnets. You can specify only one subnet per Availability Zone. You must specify either subnets or subnet mappings.
|
||||
# - [Application Load Balancers] You must specify subnets from at least two Availability Zones.
|
||||
# You cannot specify Elastic IP addresses for your subnets.
|
||||
# - [Network Load Balancers] You can specify subnets from one or more Availability Zones.
|
||||
# You can specify one Elastic IP address per subnet if you need static IP addresses for your internet-facing load balancer.
|
||||
# For internal load balancers, you can specify one private IP address per subnet from the IPv4 range of the subnet.
|
||||
# - Required: No
|
||||
# * subnets<~Array> - The IDs of the public subnets. You can specify only one subnet per Availability Zone. You must specify either subnets or subnet mappings.
|
||||
# - [Application Load Balancers] You must specify subnets from at least two Availability Zones.
|
||||
# - [Network Load Balancers] You can specify subnets from one or more Availability Zones.
|
||||
# - Required: No
|
||||
# * tags<~Hash> - One or more tags to assign to the load balancer.
|
||||
# - Required: No
|
||||
# * type<~String> - The type of load balancer. The default is application. Valid Values: application | network
|
||||
# - Required: No
|
||||
# ==== Returns
|
||||
# * response<~Excon::Response>:
|
||||
# * body<~Hash>:
|
||||
# * 'ResponseMetadata'<~Hash>:
|
||||
# * 'RequestId'<~String> - Id of request
|
||||
# * 'CreateLoadBalancerResult'<~Hash>:
|
||||
# * 'LoadBalancers'<~Array>
|
||||
# * 'AvailabilityZones'<~Array>:
|
||||
# * 'SubnetId'<~String> - ID of the subnet
|
||||
# * 'ZoneName'<~String> - Name of the Availability Zone
|
||||
# * 'LoadBalancerAddresses'<~Array>:
|
||||
# * 'IpAddress'<~String> - IP address
|
||||
# * 'AllocationId'<~String> - ID of the AWS allocation
|
||||
# * 'CanonicalHostedZoneName'<~String> - name of the Route 53 hosted zone associated with the load balancer
|
||||
# * 'CanonicalHostedZoneNameID'<~String> - ID of the Route 53 hosted zone associated with the load balancer
|
||||
# * 'CreatedTime'<~Time> - time load balancer was created
|
||||
# * 'DNSName'<~String> - external DNS name of load balancer
|
||||
# * 'LoadBalancerName'<~String> - name of load balancer
|
||||
# * 'SecurityGroups'<~Array> - array of security group id
|
||||
def create_load_balancer(name, options = {})
|
||||
params = {}
|
||||
params.merge!(Fog::AWS.indexed_param('Subnets.member.%d', options[:subnets]))
|
||||
params.merge!(Fog::AWS.indexed_param('SecurityGroups.member.%d', options[:security_groups]))
|
||||
params.merge!(Fog::AWS.serialize_keys('Scheme', options[:scheme]))
|
||||
params.merge!(Fog::AWS.serialize_keys('Type', options[:type]))
|
||||
params.merge!(Fog::AWS.serialize_keys('IpAddressType', options[:ip_address_type]))
|
||||
|
||||
|
||||
unless options[:tags].nil?
|
||||
tag_keys = options[:tags].keys.sort
|
||||
tag_values = tag_keys.map { |key| options[:tags][key] }
|
||||
params.merge!(Fog::AWS.indexed_param('Tags.member.%d.Key', tag_keys))
|
||||
params.merge!(Fog::AWS.indexed_param('Tags.member.%d.Value', tag_values))
|
||||
end
|
||||
|
||||
unless options[:subnet_mappings].nil?
|
||||
subnet_ids = []
|
||||
allocation_ids = []
|
||||
private_ipv4_address = []
|
||||
options[:subnet_mappings].each do |subnet_mapping|
|
||||
subnet_ids.push(subnet_mapping[:subnet_id])
|
||||
allocation_ids.push(subnet_mapping[:allocation_id])
|
||||
private_ipv4_address.push(subnet_mapping[:private_ipv4_address])
|
||||
end
|
||||
params.merge!(Fog::AWS.indexed_param('SubnetMappings.member.%d.SubnetId', subnet_ids))
|
||||
params.merge!(Fog::AWS.indexed_param('SubnetMappings.member.%d.AllocationId', allocation_ids))
|
||||
params.merge!(Fog::AWS.indexed_param('SubnetMappings.member.%d.PrivateIPv4Address', private_ipv4_address))
|
||||
end
|
||||
|
||||
|
||||
request({
|
||||
'Action' => 'CreateLoadBalancer',
|
||||
'Name' => name,
|
||||
:parser => Fog::Parsers::AWS::ELBV2::CreateLoadBalancer.new
|
||||
}.merge!(params))
|
||||
end
|
||||
end
|
||||
|
||||
class Mock
|
||||
def create_load_balancer(name, options = {})
|
||||
response = Excon::Response.new
|
||||
response.status = 200
|
||||
|
||||
raise Fog::AWS::ELBV2::IdentifierTaken if self.data[:load_balancers_v2].key? name
|
||||
|
||||
dns_name = Fog::AWS::ELBV2::Mock.dns_name(name, @region)
|
||||
type = options[:type] || 'application'
|
||||
|
||||
subnet_ids = options[:subnets] || []
|
||||
region = if subnet_ids.any?
|
||||
# using Hash here for Rubt 1.8.7 support.
|
||||
Hash[
|
||||
Fog::AWS::Compute::Mock.data.select do |_, region_data|
|
||||
unless region_data[@aws_access_key_id].nil?
|
||||
region_data[@aws_access_key_id][:subnets].any? do |region_subnets|
|
||||
subnet_ids.include? region_subnets['subnetId']
|
||||
end
|
||||
end
|
||||
end
|
||||
].keys[0]
|
||||
else
|
||||
'us-east-1'
|
||||
end
|
||||
|
||||
subnets = Fog::AWS::Compute::Mock.data[region][@aws_access_key_id][:subnets].select {|e| subnet_ids.include?(e["subnetId"]) }
|
||||
availability_zones = subnets.map do |subnet|
|
||||
{ "LoadBalancerAddresses"=>[], "SubnetId"=>subnet["subnetId"], "ZoneName"=>subnet["availabilityZone"]}
|
||||
end
|
||||
vpc_id = subnets.first['vpcId']
|
||||
|
||||
self.data[:tags] ||= {}
|
||||
self.data[:tags][name] = options[:tags] || {}
|
||||
|
||||
load_balancer = {
|
||||
'AvailabilityZones' => availability_zones || [],
|
||||
'Scheme' => options[:scheme] || 'internet-facing',
|
||||
'SecurityGroups' => options[:security_groups] || [],
|
||||
'CanonicalHostedZoneId' => '',
|
||||
'CreatedTime' => Time.now,
|
||||
'DNSName' => dns_name,
|
||||
'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}"),
|
||||
'LoadBalancerName' => name
|
||||
}
|
||||
self.data[:load_balancers_v2][name] = load_balancer
|
||||
response.body = {
|
||||
'ResponseMetadata' => {
|
||||
'RequestId' => Fog::AWS::Mock.request_id
|
||||
},
|
||||
'CreateLoadBalancerResult' => {
|
||||
'LoadBalancers' => [load_balancer]
|
||||
}
|
||||
}
|
||||
|
||||
response
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -47,6 +47,54 @@ module Fog
|
|||
}.merge!(options))
|
||||
end
|
||||
end
|
||||
|
||||
class Mock
|
||||
def describe_load_balancers(options = {})
|
||||
unless options.is_a?(Hash)
|
||||
Fog::Logger.deprecation("describe_load_balancers with #{options.class} is deprecated, use all('LoadBalancerNames' => []) instead [light_black](#{caller.first})[/]")
|
||||
options = { 'LoadBalancerNames' => [options].flatten }
|
||||
end
|
||||
|
||||
lb_names = options['LoadBalancerNames'] || []
|
||||
|
||||
lb_names = [*lb_names]
|
||||
load_balancers = if lb_names.any?
|
||||
lb_names.map do |lb_name|
|
||||
lb = self.data[:load_balancers_v2].find { |name, data| name == lb_name }
|
||||
raise Fog::AWS::ELBV2::NotFound unless lb
|
||||
lb[1].dup
|
||||
end.compact
|
||||
else
|
||||
self.data[:load_balancers_v2].map { |lb, values| values.dup }
|
||||
end
|
||||
|
||||
marker = options.fetch('Marker', 0).to_i
|
||||
if load_balancers.count - marker > 400
|
||||
next_marker = marker + 400
|
||||
load_balancers = load_balancers[marker...next_marker]
|
||||
else
|
||||
next_marker = nil
|
||||
end
|
||||
|
||||
response = Excon::Response.new
|
||||
response.status = 200
|
||||
|
||||
response.body = {
|
||||
'ResponseMetadata' => {
|
||||
'RequestId' => Fog::AWS::Mock.request_id
|
||||
},
|
||||
'DescribeLoadBalancersResult' => {
|
||||
'LoadBalancers' => load_balancers
|
||||
}
|
||||
}
|
||||
|
||||
if next_marker
|
||||
response.body['DescribeLoadBalancersResult']['NextMarker'] = next_marker.to_s
|
||||
end
|
||||
|
||||
response
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
48
tests/parsers/elbv2/create_load_balancer_tests.rb
Normal file
48
tests/parsers/elbv2/create_load_balancer_tests.rb
Normal file
|
@ -0,0 +1,48 @@
|
|||
require 'fog/xml'
|
||||
require 'fog/aws/parsers/elbv2/create_load_balancer'
|
||||
|
||||
CREATE_LOAD_BALANCER_RESULT = <<-EOF
|
||||
<CreateLoadBalancerResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2015-12-01/">
|
||||
<CreateLoadBalancerResult>
|
||||
<LoadBalancers>
|
||||
<member>
|
||||
<LoadBalancerArn>arn:aws:elasticloadbalancing:us-west-2:123456789012:loadbalancer/app/my-internal-load-balancer/50dc6c495c0c9188</LoadBalancerArn>
|
||||
<Scheme>internet-facing</Scheme>
|
||||
<LoadBalancerName>my-load-balancer</LoadBalancerName>
|
||||
<VpcId>vpc-3ac0fb5f</VpcId>
|
||||
<CanonicalHostedZoneId>Z2P70J7EXAMPLE</CanonicalHostedZoneId>
|
||||
<CreatedTime>2016-03-25T21:29:48.850Z</CreatedTime>
|
||||
<AvailabilityZones>
|
||||
<member>
|
||||
<SubnetId>subnet-8360a9e7</SubnetId>
|
||||
<ZoneName>us-west-2a</ZoneName>
|
||||
</member>
|
||||
<member>
|
||||
<SubnetId>subnet-b7d581c0</SubnetId>
|
||||
<ZoneName>us-west-2b</ZoneName>
|
||||
</member>
|
||||
</AvailabilityZones>
|
||||
<SecurityGroups>
|
||||
<member>sg-5943793c</member>
|
||||
</SecurityGroups>
|
||||
<DNSName>my-load-balancer-424835706.us-west-2.elb.amazonaws.com</DNSName>
|
||||
<State>
|
||||
<Code>provisioning</Code>
|
||||
</State>
|
||||
<Type>application</Type>
|
||||
</member>
|
||||
</LoadBalancers>
|
||||
</CreateLoadBalancerResult>
|
||||
<ResponseMetadata>
|
||||
<RequestId>32d531b2-f2d0-11e5-9192-3fff33344cfa</RequestId>
|
||||
</ResponseMetadata>
|
||||
</CreateLoadBalancerResponse>
|
||||
EOF
|
||||
|
||||
Shindo.tests('AWS::ELBV2 | parsers | create_load_balancer', %w[aws elb parser]) do
|
||||
tests('parses the xml').formats(AWS::ELBV2::Formats::CREATE_LOAD_BALANCER) do
|
||||
parser = Nokogiri::XML::SAX::Parser.new(Fog::Parsers::AWS::ELBV2::CreateLoadBalancer.new)
|
||||
parser.parse(CREATE_LOAD_BALANCER_RESULT)
|
||||
parser.document.response
|
||||
end
|
||||
end
|
|
@ -27,7 +27,7 @@ class AWS
|
|||
})
|
||||
|
||||
CREATE_LOAD_BALANCER = BASIC.merge({
|
||||
'CreateLoadBalancerResult' => {'LoadBalancers' => [LOAD_BALANCER], 'NextMarker' => Fog::Nullable::String}
|
||||
'CreateLoadBalancerResult' => {'LoadBalancers' => [LOAD_BALANCER]}
|
||||
})
|
||||
|
||||
LISTENER_DEFAULT_ACTIONS = [{
|
||||
|
|
23
tests/requests/elbv2/load_balancer_tests.rb
Normal file
23
tests/requests/elbv2/load_balancer_tests.rb
Normal file
|
@ -0,0 +1,23 @@
|
|||
Shindo.tests('AWS::ELBV2 | load_balancer_tests', ['aws', 'elb']) do
|
||||
@load_balancer_id = 'fog-test-elb'
|
||||
@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']
|
||||
|
||||
tests('success') 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
|
||||
end
|
||||
|
||||
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
|
||||
end
|
||||
end
|
Loading…
Reference in a new issue