Merge pull request #335 from mrucci/elb-attributes-support

Add support for ELB attributes.
This commit is contained in:
Steve Pulec 2015-03-22 15:55:26 -04:00
commit f2bfcfb803
3 changed files with 271 additions and 0 deletions

View File

@ -1,6 +1,13 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import boto.ec2.elb import boto.ec2.elb
from boto.ec2.elb.attributes import (
LbAttributes,
ConnectionSettingAttribute,
ConnectionDrainingAttribute,
AccessLogAttribute,
CrossZoneLoadBalancingAttribute,
)
from moto.core import BaseBackend from moto.core import BaseBackend
@ -29,6 +36,7 @@ class FakeLoadBalancer(object):
self.instance_ids = [] self.instance_ids = []
self.zones = zones self.zones = zones
self.listeners = [] self.listeners = []
self.attributes = FakeLoadBalancer.get_default_attributes()
for protocol, lb_port, instance_port, ssl_certificate_id in ports: for protocol, lb_port, instance_port, ssl_certificate_id in ports:
listener = FakeListener( listener = FakeListener(
@ -73,6 +81,28 @@ class FakeLoadBalancer(object):
raise NotImplementedError('"Fn::GetAtt" : [ "{0}" , "SourceSecurityGroup.OwnerAlias" ]"') raise NotImplementedError('"Fn::GetAtt" : [ "{0}" , "SourceSecurityGroup.OwnerAlias" ]"')
raise UnformattedGetAttTemplateException() raise UnformattedGetAttTemplateException()
@classmethod
def get_default_attributes(cls):
attributes = LbAttributes()
cross_zone_load_balancing = CrossZoneLoadBalancingAttribute()
cross_zone_load_balancing.enabled = False
attributes.cross_zone_load_balancing = cross_zone_load_balancing
connection_draining = ConnectionDrainingAttribute()
connection_draining.enabled = False
attributes.connection_draining = connection_draining
access_log = AccessLogAttribute()
access_log.enabled = False
attributes.access_log = access_log
connection_settings = ConnectionSettingAttribute()
connection_settings.idle_timeout = 60
attributes.connecting_settings = connection_settings
return attributes
class ELBBackend(BaseBackend): class ELBBackend(BaseBackend):
@ -151,6 +181,26 @@ class ELBBackend(BaseBackend):
load_balancer.instance_ids = new_instance_ids load_balancer.instance_ids = new_instance_ids
return load_balancer return load_balancer
def set_cross_zone_load_balancing_attribute(self, load_balancer_name, attribute):
load_balancer = self.get_load_balancer(load_balancer_name)
load_balancer.attributes.cross_zone_load_balancing = attribute
return load_balancer
def set_access_log_attribute(self, load_balancer_name, attribute):
load_balancer = self.get_load_balancer(load_balancer_name)
load_balancer.attributes.access_log = attribute
return load_balancer
def set_connection_draining_attribute(self, load_balancer_name, attribute):
load_balancer = self.get_load_balancer(load_balancer_name)
load_balancer.attributes.connection_draining = attribute
return load_balancer
def set_connection_settings_attribute(self, load_balancer_name, attribute):
load_balancer = self.get_load_balancer(load_balancer_name)
load_balancer.attributes.connecting_settings = attribute
return load_balancer
elb_backends = {} elb_backends = {}
for region in boto.ec2.elb.regions(): for region in boto.ec2.elb.regions():

View File

@ -1,4 +1,10 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from boto.ec2.elb.attributes import (
ConnectionSettingAttribute,
ConnectionDrainingAttribute,
AccessLogAttribute,
CrossZoneLoadBalancingAttribute,
)
from moto.core.responses import BaseResponse from moto.core.responses import BaseResponse
from .models import elb_backends from .models import elb_backends
@ -122,6 +128,56 @@ class ELBResponse(BaseResponse):
load_balancer = self.elb_backend.deregister_instances(load_balancer_name, instance_ids) load_balancer = self.elb_backend.deregister_instances(load_balancer_name, instance_ids)
return template.render(load_balancer=load_balancer) return template.render(load_balancer=load_balancer)
def describe_load_balancer_attributes(self):
load_balancer_name = self.querystring.get('LoadBalancerName')[0]
load_balancer = self.elb_backend.describe_load_balancers(load_balancer_name)[0]
template = self.response_template(DESCRIBE_ATTRIBUTES_TEMPLATE)
return template.render(attributes=load_balancer.attributes)
def modify_load_balancer_attributes(self):
load_balancer_name = self.querystring.get('LoadBalancerName')[0]
load_balancer = self.elb_backend.describe_load_balancers(load_balancer_name)[0]
def parse_attribute(attribute_name):
"""
Transform self.querystring parameters matching `LoadBalancerAttributes.attribute_name.attribute_key`
into a dictionary of (attribute_name, attribute_key)` pairs.
"""
attribute_prefix = "LoadBalancerAttributes." + attribute_name
return dict((key.lstrip(attribute_prefix), value[0]) for key, value in self.querystring.items() if key.startswith(attribute_prefix))
cross_zone = parse_attribute("CrossZoneLoadBalancing")
if cross_zone:
attribute = CrossZoneLoadBalancingAttribute()
attribute.enabled = cross_zone["Enabled"] == "true"
self.elb_backend.set_cross_zone_load_balancing_attribute(load_balancer_name, attribute)
access_log = parse_attribute("AccessLog")
if access_log:
attribute = AccessLogAttribute()
attribute.enabled = access_log["Enabled"] == "true"
attribute.s3_bucket_name = access_log["S3BucketName"]
attribute.s3_bucket_prefix = access_log["S3BucketPrefix"]
attribute.emit_interval = access_log["EmitInterval"]
self.elb_backend.set_access_log_attribute(load_balancer_name, attribute)
connection_draining = parse_attribute("ConnectionDraining")
if connection_draining:
attribute = ConnectionDrainingAttribute()
attribute.enabled = connection_draining["Enabled"] == "true"
attribute.timeout = connection_draining["Timeout"]
self.elb_backend.set_connection_draining_attribute(load_balancer_name, attribute)
connection_settings = parse_attribute("ConnectionSettings")
if connection_settings:
attribute = ConnectionSettingAttribute()
attribute.idle_timeout = connection_settings["IdleTimeout"]
self.elb_backend.set_connection_settings_attribute(load_balancer_name, attribute)
template = self.response_template(MODIFY_ATTRIBUTES_TEMPLATE)
return template.render(attributes=load_balancer.attributes)
CREATE_LOAD_BALANCER_TEMPLATE = """<CreateLoadBalancerResult xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/"> CREATE_LOAD_BALANCER_TEMPLATE = """<CreateLoadBalancerResult xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/">
<DNSName>tests.us-east-1.elb.amazonaws.com</DNSName> <DNSName>tests.us-east-1.elb.amazonaws.com</DNSName>
</CreateLoadBalancerResult>""" </CreateLoadBalancerResult>"""
@ -253,3 +309,67 @@ DELETE_LOAD_BALANCER_LISTENERS = """<DeleteLoadBalancerListenersResponse xmlns="
<RequestId>83c88b9d-12b7-11e3-8b82-87b12EXAMPLE</RequestId> <RequestId>83c88b9d-12b7-11e3-8b82-87b12EXAMPLE</RequestId>
</ResponseMetadata> </ResponseMetadata>
</DeleteLoadBalancerListenersResponse>""" </DeleteLoadBalancerListenersResponse>"""
DESCRIBE_ATTRIBUTES_TEMPLATE = """<DescribeLoadBalancerAttributesResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/">
<DescribeLoadBalancerAttributesResult>
<LoadBalancerAttributes>
<AccessLog>
<Enabled>{{ attributes.access_log.enabled }}</Enabled>
{% if attributes.access_log.enabled %}
<S3BucketName>{{ attributes.access_log.s3_bucket_name }}</S3BucketName>
<S3BucketPrefix>{{ attributes.access_log.s3_bucket_prefix }}</S3BucketPrefix>
<EmitInterval>{{ attributes.access_log.emit_interval }}</EmitInterval>
{% endif %}
</AccessLog>
<ConnectionSettings>
<IdleTimeout>{{ attributes.connecting_settings.idle_timeout }}</IdleTimeout>
</ConnectionSettings>
<CrossZoneLoadBalancing>
<Enabled>{{ attributes.cross_zone_load_balancing.enabled }}</Enabled>
</CrossZoneLoadBalancing>
<ConnectionDraining>
<Enabled>{{ attributes.connection_draining.enabled }}</Enabled>
{% if attributes.connection_draining.enabled %}
<Timeout>{{ attributes.connection_draining.timeout }}</Timeout>
{% endif %}
</ConnectionDraining>
</LoadBalancerAttributes>
</DescribeLoadBalancerAttributesResult>
<ResponseMetadata>
<RequestId>83c88b9d-12b7-11e3-8b82-87b12EXAMPLE</RequestId>
</ResponseMetadata>
</DescribeLoadBalancerAttributesResponse>
"""
MODIFY_ATTRIBUTES_TEMPLATE = """<ModifyLoadBalancerAttributesResponse xmlns="http://elasticloadbalancing.amazonaws.com/doc/2012-06-01/">
<ModifyLoadBalancerAttributesResult>
<LoadBalancerName>my-loadbalancer</LoadBalancerName>
<LoadBalancerAttributes>
<AccessLog>
<Enabled>{{ attributes.access_log.enabled }}</Enabled>
{% if attributes.access_log.enabled %}
<S3BucketName>{{ attributes.access_log.s3_bucket_name }}</S3BucketName>
<S3BucketPrefix>{{ attributes.access_log.s3_bucket_prefix }}</S3BucketPrefix>
<EmitInterval>{{ attributes.access_log.emit_interval }}</EmitInterval>
{% endif %}
</AccessLog>
<ConnectionSettings>
<IdleTimeout>{{ attributes.connecting_settings.idle_timeout }}</IdleTimeout>
</ConnectionSettings>
<CrossZoneLoadBalancing>
<Enabled>{{ attributes.cross_zone_load_balancing.enabled }}</Enabled>
</CrossZoneLoadBalancing>
<ConnectionDraining>
<Enabled>{{ attributes.connection_draining.enabled }}</Enabled>
{% if attributes.connection_draining.enabled %}
<Timeout>{{ attributes.connection_draining.timeout }}</Timeout>
{% endif %}
</ConnectionDraining>
</LoadBalancerAttributes>
</ModifyLoadBalancerAttributesResult>
<ResponseMetadata>
<RequestId>83c88b9d-12b7-11e3-8b82-87b12EXAMPLE</RequestId>
</ResponseMetadata>
</ModifyLoadBalancerAttributesResponse>
"""

View File

@ -2,6 +2,11 @@ from __future__ import unicode_literals
import boto import boto
import boto.ec2.elb import boto.ec2.elb
from boto.ec2.elb import HealthCheck from boto.ec2.elb import HealthCheck
from boto.ec2.elb.attributes import (
ConnectionSettingAttribute,
ConnectionDrainingAttribute,
AccessLogAttribute,
)
import sure # noqa import sure # noqa
from moto import mock_elb, mock_ec2 from moto import mock_elb, mock_ec2
@ -193,3 +198,99 @@ def test_deregister_instances():
balancer.instances.should.have.length_of(1) balancer.instances.should.have.length_of(1)
balancer.instances[0].id.should.equal(instance_id2) balancer.instances[0].id.should.equal(instance_id2)
@mock_elb
def test_default_attributes():
conn = boto.connect_elb()
ports = [(80, 8080, 'http'), (443, 8443, 'tcp')]
lb = conn.create_load_balancer('my-lb', [], ports)
attributes = lb.get_attributes()
attributes.cross_zone_load_balancing.enabled.should.be.false
attributes.connection_draining.enabled.should.be.false
attributes.access_log.enabled.should.be.false
attributes.connecting_settings.idle_timeout.should.equal(60)
@mock_elb
def test_cross_zone_load_balancing_attribute():
conn = boto.connect_elb()
ports = [(80, 8080, 'http'), (443, 8443, 'tcp')]
lb = conn.create_load_balancer('my-lb', [], ports)
conn.modify_lb_attribute("my-lb", "CrossZoneLoadBalancing", True)
attributes = lb.get_attributes(force=True)
attributes.cross_zone_load_balancing.enabled.should.be.true
conn.modify_lb_attribute("my-lb", "CrossZoneLoadBalancing", False)
attributes = lb.get_attributes(force=True)
attributes.cross_zone_load_balancing.enabled.should.be.false
@mock_elb
def test_connection_draining_attribute():
conn = boto.connect_elb()
ports = [(80, 8080, 'http'), (443, 8443, 'tcp')]
lb = conn.create_load_balancer('my-lb', [], ports)
connection_draining = ConnectionDrainingAttribute()
connection_draining.enabled = True
connection_draining.timeout = 60
conn.modify_lb_attribute("my-lb", "ConnectionDraining", connection_draining)
attributes = lb.get_attributes(force=True)
attributes.connection_draining.enabled.should.be.true
attributes.connection_draining.timeout.should.equal(60)
connection_draining.timeout = 30
conn.modify_lb_attribute("my-lb", "ConnectionDraining", connection_draining)
attributes = lb.get_attributes(force=True)
attributes.connection_draining.timeout.should.equal(30)
connection_draining.enabled = False
conn.modify_lb_attribute("my-lb", "ConnectionDraining", connection_draining)
attributes = lb.get_attributes(force=True)
attributes.connection_draining.enabled.should.be.false
@mock_elb
def test_access_log_attribute():
conn = boto.connect_elb()
ports = [(80, 8080, 'http'), (443, 8443, 'tcp')]
lb = conn.create_load_balancer('my-lb', [], ports)
access_log = AccessLogAttribute()
access_log.enabled = True
access_log.s3_bucket_name = 'bucket'
access_log.s3_bucket_prefix = 'prefix'
access_log.emit_interval = 60
conn.modify_lb_attribute("my-lb", "AccessLog", access_log)
attributes = lb.get_attributes(force=True)
attributes.access_log.enabled.should.be.true
attributes.access_log.s3_bucket_name.should.equal("bucket")
attributes.access_log.s3_bucket_prefix.should.equal("prefix")
attributes.access_log.emit_interval.should.equal(60)
access_log.enabled = False
conn.modify_lb_attribute("my-lb", "AccessLog", access_log)
attributes = lb.get_attributes(force=True)
attributes.access_log.enabled.should.be.false
@mock_elb
def test_connection_settings_attribute():
conn = boto.connect_elb()
ports = [(80, 8080, 'http'), (443, 8443, 'tcp')]
lb = conn.create_load_balancer('my-lb', [], ports)
connection_settings = ConnectionSettingAttribute(conn)
connection_settings.idle_timeout = 120
conn.modify_lb_attribute("my-lb", "ConnectingSettings", connection_settings)
attributes = lb.get_attributes(force=True)
attributes.connecting_settings.idle_timeout.should.equal(120)
connection_settings.idle_timeout = 60
conn.modify_lb_attribute("my-lb", "ConnectingSettings", connection_settings)
attributes = lb.get_attributes(force=True)
attributes.connecting_settings.idle_timeout.should.equal(60)