diff --git a/moto/elb/models.py b/moto/elb/models.py
index 94914a8e7..e1487f5aa 100644
--- a/moto/elb/models.py
+++ b/moto/elb/models.py
@@ -1,6 +1,13 @@
from __future__ import unicode_literals
import boto.ec2.elb
+from boto.ec2.elb.attributes import (
+ LbAttributes,
+ ConnectionSettingAttribute,
+ ConnectionDrainingAttribute,
+ AccessLogAttribute,
+ CrossZoneLoadBalancingAttribute,
+)
from moto.core import BaseBackend
@@ -29,6 +36,7 @@ class FakeLoadBalancer(object):
self.instance_ids = []
self.zones = zones
self.listeners = []
+ self.attributes = FakeLoadBalancer.get_default_attributes()
for protocol, lb_port, instance_port, ssl_certificate_id in ports:
listener = FakeListener(
@@ -73,6 +81,28 @@ class FakeLoadBalancer(object):
raise NotImplementedError('"Fn::GetAtt" : [ "{0}" , "SourceSecurityGroup.OwnerAlias" ]"')
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):
@@ -151,6 +181,26 @@ class ELBBackend(BaseBackend):
load_balancer.instance_ids = new_instance_ids
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 = {}
for region in boto.ec2.elb.regions():
diff --git a/moto/elb/responses.py b/moto/elb/responses.py
index fb114fb22..be9c8ad8b 100644
--- a/moto/elb/responses.py
+++ b/moto/elb/responses.py
@@ -1,4 +1,10 @@
from __future__ import unicode_literals
+from boto.ec2.elb.attributes import (
+ ConnectionSettingAttribute,
+ ConnectionDrainingAttribute,
+ AccessLogAttribute,
+ CrossZoneLoadBalancingAttribute,
+)
from moto.core.responses import BaseResponse
from .models import elb_backends
@@ -122,6 +128,56 @@ class ELBResponse(BaseResponse):
load_balancer = self.elb_backend.deregister_instances(load_balancer_name, instance_ids)
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 = """
tests.us-east-1.elb.amazonaws.com
"""
@@ -253,3 +309,67 @@ DELETE_LOAD_BALANCER_LISTENERS = """
+
+
+
+ {{ attributes.access_log.enabled }}
+ {% if attributes.access_log.enabled %}
+ {{ attributes.access_log.s3_bucket_name }}
+ {{ attributes.access_log.s3_bucket_prefix }}
+ {{ attributes.access_log.emit_interval }}
+ {% endif %}
+
+
+ {{ attributes.connecting_settings.idle_timeout }}
+
+
+ {{ attributes.cross_zone_load_balancing.enabled }}
+
+
+ {{ attributes.connection_draining.enabled }}
+ {% if attributes.connection_draining.enabled %}
+ {{ attributes.connection_draining.timeout }}
+ {% endif %}
+
+
+
+
+ 83c88b9d-12b7-11e3-8b82-87b12EXAMPLE
+
+
+"""
+
+MODIFY_ATTRIBUTES_TEMPLATE = """
+
+ my-loadbalancer
+
+
+ {{ attributes.access_log.enabled }}
+ {% if attributes.access_log.enabled %}
+ {{ attributes.access_log.s3_bucket_name }}
+ {{ attributes.access_log.s3_bucket_prefix }}
+ {{ attributes.access_log.emit_interval }}
+ {% endif %}
+
+
+ {{ attributes.connecting_settings.idle_timeout }}
+
+
+ {{ attributes.cross_zone_load_balancing.enabled }}
+
+
+ {{ attributes.connection_draining.enabled }}
+ {% if attributes.connection_draining.enabled %}
+ {{ attributes.connection_draining.timeout }}
+ {% endif %}
+
+
+
+
+ 83c88b9d-12b7-11e3-8b82-87b12EXAMPLE
+
+
+"""
+
diff --git a/tests/test_elb/test_elb.py b/tests/test_elb/test_elb.py
index abfa38e5c..3f31e9d49 100644
--- a/tests/test_elb/test_elb.py
+++ b/tests/test_elb/test_elb.py
@@ -2,6 +2,11 @@ from __future__ import unicode_literals
import boto
import boto.ec2.elb
from boto.ec2.elb import HealthCheck
+from boto.ec2.elb.attributes import (
+ ConnectionSettingAttribute,
+ ConnectionDrainingAttribute,
+ AccessLogAttribute,
+)
import sure # noqa
from moto import mock_elb, mock_ec2
@@ -193,3 +198,99 @@ def test_deregister_instances():
balancer.instances.should.have.length_of(1)
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)
+
+