Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EC2 ELB listeners now support InstanceProtocol without breaking existing syntax #1048

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
117 changes: 92 additions & 25 deletions boto/ec2/elb/__init__.py
Expand Up @@ -132,8 +132,8 @@ def get_all_load_balancers(self, load_balancer_names=None):
return self.get_list('DescribeLoadBalancers', params,
[('member', LoadBalancer)])

def create_load_balancer(self, name, zones, listeners, subnets=None,
security_groups=None, scheme='internet-facing'):
def create_load_balancer(self, name, zones, listeners=None, subnets=None,
security_groups=None, scheme='internet-facing', complex_listeners=None):
"""
Create a new load balancer for your account. By default the load
balancer will be created in EC2. To create a load balancer inside a
Expand All @@ -152,7 +152,7 @@ def create_load_balancer(self, name, zones, listeners, subnets=None,
(LoadBalancerPortNumber, InstancePortNumber, Protocol,
[SSLCertificateId]) where LoadBalancerPortNumber and
InstancePortNumber are integer values between 1 and 65535,
Protocol is a string containing either 'TCP', 'HTTP' or
Protocol is a string containing either 'TCP', 'SSL', HTTP', or
'HTTPS'; SSLCertificateID is the ARN of a AWS AIM
certificate, and must be specified when doing HTTPS.

Expand All @@ -177,18 +177,52 @@ def create_load_balancer(self, name, zones, listeners, subnets=None,
This option is only available for LoadBalancers attached
to an Amazon VPC.

:type complex_listeners: List of tuples
:param complex_listeners: Each tuple contains four or five values,
(LoadBalancerPortNumber, InstancePortNumber, Protocol, InstanceProtocol,
SSLCertificateId).

Where;
- LoadBalancerPortNumber and InstancePortNumber are integer
values between 1 and 65535.
- Protocol and InstanceProtocol is a string containing either 'TCP',
'SSL', 'HTTP', or 'HTTPS'
- SSLCertificateId is the ARN of an SSL certificate loaded into
AWS IAM

:rtype: :class:`boto.ec2.elb.loadbalancer.LoadBalancer`
:return: The newly created :class:`boto.ec2.elb.loadbalancer.LoadBalancer`
"""
if not listeners and not complex_listeners:
# Must specify one of the two options
return None

params = {'LoadBalancerName': name}
for index, listener in enumerate(listeners):
i = index + 1
protocol = listener[2].upper()
params['Listeners.member.%d.LoadBalancerPort' % i] = listener[0]
params['Listeners.member.%d.InstancePort' % i] = listener[1]
params['Listeners.member.%d.Protocol' % i] = listener[2]
if protocol == 'HTTPS' or protocol == 'SSL':
params['Listeners.member.%d.SSLCertificateId' % i] = listener[3]

# Handle legacy listeners
if listeners:
for index, listener in enumerate(listeners):
i = index + 1
protocol = listener[2].upper()
params['Listeners.member.%d.LoadBalancerPort' % i] = listener[0]
params['Listeners.member.%d.InstancePort' % i] = listener[1]
params['Listeners.member.%d.Protocol' % i] = listener[2]
if protocol == 'HTTPS' or protocol == 'SSL':
params['Listeners.member.%d.SSLCertificateId' % i] = listener[3]

# Handle the full listeners
if complex_listeners:
for index, listener in enumerate(complex_listeners):
i = index + 1
protocol = listener[2].upper()
InstanceProtocol = listener[3].upper()
params['Listeners.member.%d.LoadBalancerPort' % i] = listener[0]
params['Listeners.member.%d.InstancePort' % i] = listener[1]
params['Listeners.member.%d.Protocol' % i] = listener[2]
params['Listeners.member.%d.InstanceProtocol' % i] = listener[3]
if protocol == 'HTTPS' or protocol == 'SSL':
params['Listeners.member.%d.SSLCertificateId' % i] = listener[4]

if zones:
self.build_list_params(params, zones, 'AvailabilityZones.member.%d')

Expand All @@ -208,7 +242,7 @@ def create_load_balancer(self, name, zones, listeners, subnets=None,
load_balancer.security_groups = security_groups
return load_balancer

def create_load_balancer_listeners(self, name, listeners):
def create_load_balancer_listeners(self, name, listeners=None, complex_listeners=None):
"""
Creates a Listener (or group of listeners) for an existing
Load Balancer
Expand All @@ -217,26 +251,59 @@ def create_load_balancer_listeners(self, name, listeners):
:param name: The name of the load balancer to create the listeners for

:type listeners: List of tuples
:param listeners: Each tuple contains three values,
:param listeners: Each tuple contains three or four values,
(LoadBalancerPortNumber, InstancePortNumber, Protocol,
[SSLCertificateId]) where LoadBalancerPortNumber and
InstancePortNumber are integer values between 1 and 65535,
Protocol is a string containing either 'TCP', 'HTTP',
'HTTPS', or 'SSL'; SSLCertificateID is the ARN of a AWS
AIM certificate, and must be specified when doing HTTPS or
SSL.
Protocol is a string containing either 'TCP', 'SSL', HTTP', or
'HTTPS'; SSLCertificateID is the ARN of a AWS AIM
certificate, and must be specified when doing HTTPS.

:type complex_listeners: List of tuples
:param complex_listeners: Each tuple contains four or five values,
(LoadBalancerPortNumber, InstancePortNumber, Protocol, InstanceProtocol,
SSLCertificateId).

Where;
- LoadBalancerPortNumber and InstancePortNumber are integer
values between 1 and 65535.
- Protocol and InstanceProtocol is a string containing either 'TCP',
'SSL', 'HTTP', or 'HTTPS'
- SSLCertificateId is the ARN of an SSL certificate loaded into
AWS IAM

:return: The status of the request
"""
if not listeners and not complex_listeners:
# Must specify one of the two options
return None

params = {'LoadBalancerName': name}
for index, listener in enumerate(listeners):
i = index + 1
protocol = listener[2].upper()
params['Listeners.member.%d.LoadBalancerPort' % i] = listener[0]
params['Listeners.member.%d.InstancePort' % i] = listener[1]
params['Listeners.member.%d.Protocol' % i] = listener[2]
if protocol == 'HTTPS' or protocol == 'SSL':
params['Listeners.member.%d.SSLCertificateId' % i] = listener[3]

# Handle the simple listeners
if listeners:
for index, listener in enumerate(listeners):
i = index + 1
protocol = listener[2].upper()
params['Listeners.member.%d.LoadBalancerPort' % i] = listener[0]
params['Listeners.member.%d.InstancePort' % i] = listener[1]
params['Listeners.member.%d.Protocol' % i] = listener[2]
if protocol == 'HTTPS' or protocol == 'SSL':
params['Listeners.member.%d.SSLCertificateId' % i] = listener[3]

# Handle the full listeners
if complex_listeners:
for index, listener in enumerate(complex_listeners):
i = index + 1
protocol = listener[2].upper()
InstanceProtocol = listener[3].upper()
params['Listeners.member.%d.LoadBalancerPort' % i] = listener[0]
params['Listeners.member.%d.InstancePort' % i] = listener[1]
params['Listeners.member.%d.Protocol' % i] = listener[2]
params['Listeners.member.%d.InstanceProtocol' % i] = listener[3]
if protocol == 'HTTPS' or protocol == 'SSL':
params['Listeners.member.%d.SSLCertificateId' % i] = listener[4]

return self.get_status('CreateLoadBalancerListeners', params)

def delete_load_balancer(self, name):
Expand Down
11 changes: 10 additions & 1 deletion boto/ec2/elb/listener.py
Expand Up @@ -27,16 +27,19 @@ class Listener(object):
"""

def __init__(self, load_balancer=None, load_balancer_port=0,
instance_port=0, protocol='', ssl_certificate_id=None):
instance_port=0, protocol='', ssl_certificate_id=None, instance_protocol=None):
self.load_balancer = load_balancer
self.load_balancer_port = load_balancer_port
self.instance_port = instance_port
self.protocol = protocol
self.instance_protocol = instance_protocol
self.ssl_certificate_id = ssl_certificate_id
self.policy_names = ListElement()

def __repr__(self):
r = "(%d, %d, '%s'" % (self.load_balancer_port, self.instance_port, self.protocol)
if self.instance_protocol:
r += ", '%s'" % self.instance_protocol
if self.ssl_certificate_id:
r += ', %s' % (self.ssl_certificate_id)
r += ')'
Expand All @@ -52,6 +55,8 @@ def endElement(self, name, value, connection):
self.load_balancer_port = int(value)
elif name == 'InstancePort':
self.instance_port = int(value)
elif name == 'InstanceProtocol':
self.instance_protocol = value
elif name == 'Protocol':
self.protocol = value
elif name == 'SSLCertificateId':
Expand All @@ -62,13 +67,17 @@ def endElement(self, name, value, connection):
def get_tuple(self):
return self.load_balancer_port, self.instance_port, self.protocol

def get_complex_tuple(self):
return self.load_balancer_port, self.instance_port, self.protocol, self.instance_protocol

def __getitem__(self, key):
if key == 0:
return self.load_balancer_port
if key == 1:
return self.instance_port
if key == 2:
return self.protocol
# @todo: Not sure how to extend safely without breaking backward compatibility
raise KeyError


Expand Down