diff --git a/moto/__init__.py b/moto/__init__.py
index 49f121a3c..302156efe 100644
--- a/moto/__init__.py
+++ b/moto/__init__.py
@@ -3,6 +3,7 @@ logging.getLogger('boto').setLevel(logging.CRITICAL)
from .dynamodb import mock_dynamodb
from .ec2 import mock_ec2
+from .elb import mock_elb
from .s3 import mock_s3
from .ses import mock_ses
from .sqs import mock_sqs
diff --git a/moto/elb/__init__.py b/moto/elb/__init__.py
new file mode 100644
index 000000000..fcadac99e
--- /dev/null
+++ b/moto/elb/__init__.py
@@ -0,0 +1,2 @@
+from .models import elb_backend
+mock_elb = elb_backend.decorator
diff --git a/moto/elb/models.py b/moto/elb/models.py
new file mode 100644
index 000000000..aff7f082b
--- /dev/null
+++ b/moto/elb/models.py
@@ -0,0 +1,80 @@
+from moto.core import BaseBackend
+
+
+class FakeHealthCheck(object):
+ def __init__(self, timeout, healthy_threshold, unhealthy_threshold,
+ interval, target):
+ self.timeout = timeout
+ self.healthy_threshold = healthy_threshold
+ self.unhealthy_threshold = unhealthy_threshold
+ self.interval = interval
+ self.target = target
+
+
+class FakeListener(object):
+ def __init__(self, load_balancer_port, instance_port, protocol):
+ self.load_balancer_port = load_balancer_port
+ self.instance_port = instance_port
+ self.protocol = protocol.upper()
+
+
+class FakeLoadBalancer(object):
+ def __init__(self, name, zones, ports):
+ self.name = name
+ self.health_check = None
+ self.instance_ids = []
+ self.zones = zones
+ self.listeners = []
+ for protocol, lb_port, instance_port in ports:
+ listener = FakeListener(
+ protocol=protocol,
+ load_balancer_port=lb_port,
+ instance_port=instance_port,
+ )
+ self.listeners.append(listener)
+
+
+class ELBBackend(BaseBackend):
+
+ def __init__(self):
+ self.load_balancers = {}
+
+ def create_load_balancer(self, name, zones, ports):
+ new_load_balancer = FakeLoadBalancer(name=name, zones=zones, ports=ports)
+ self.load_balancers[name] = new_load_balancer
+ return new_load_balancer
+
+ def describe_load_balancers(self, names):
+ balancers = self.load_balancers.values()
+ if names:
+ return [balancer for balancer in balancers if balancer.name in names]
+ else:
+ return balancers
+
+ def delete_load_balancer(self, load_balancer_name):
+ self.load_balancers.pop(load_balancer_name, None)
+
+ def get_load_balancer(self, load_balancer_name):
+ return self.load_balancers.get(load_balancer_name)
+
+ def configure_health_check(self, load_balancer_name, timeout,
+ healthy_threshold, unhealthy_threshold, interval,
+ target):
+ check = FakeHealthCheck(timeout, healthy_threshold, unhealthy_threshold,
+ interval, target)
+ load_balancer = self.get_load_balancer(load_balancer_name)
+ load_balancer.health_check = check
+ return check
+
+ def register_instances(self, load_balancer_name, instance_ids):
+ load_balancer = self.get_load_balancer(load_balancer_name)
+ load_balancer.instance_ids.extend(instance_ids)
+ return load_balancer
+
+ def deregister_instances(self, load_balancer_name, instance_ids):
+ load_balancer = self.get_load_balancer(load_balancer_name)
+ new_instance_ids = [instance_id for instance_id in load_balancer.instance_ids if instance_id not in instance_ids]
+ load_balancer.instance_ids = new_instance_ids
+ return load_balancer
+
+elb_backend = ELBBackend()
diff --git a/moto/elb/responses.py b/moto/elb/responses.py
new file mode 100644
index 000000000..4fcf055df
--- /dev/null
+++ b/moto/elb/responses.py
@@ -0,0 +1,179 @@
+from jinja2 import Template
+
+from moto.core.responses import BaseResponse
+from .models import elb_backend
+
+
+class ELBResponse(BaseResponse):
+
+ def create_load_balancer(self):
+ """
+ u'Scheme': [u'internet-facing'],
+ """
+ load_balancer_name = self.querystring.get('LoadBalancerName')[0]
+ availability_zones = [value[0] for key, value in self.querystring.items() if "AvailabilityZones.member" in key]
+ ports = []
+ port_index = 1
+ while True:
+ try:
+ protocol = self.querystring['Listeners.member.{}.Protocol'.format(port_index)][0]
+ except KeyError:
+ break
+ lb_port = self.querystring['Listeners.member.{}.LoadBalancerPort'.format(port_index)][0]
+ instance_port = self.querystring['Listeners.member.{}.InstancePort'.format(port_index)][0]
+ ports.append([protocol, lb_port, instance_port])
+ port_index += 1
+ elb_backend.create_load_balancer(
+ name=load_balancer_name,
+ zones=availability_zones,
+ ports=ports,
+ )
+ template = Template(CREATE_LOAD_BALANCER_TEMPLATE)
+ return template.render()
+
+ def describe_load_balancers(self):
+ names = [value[0] for key, value in self.querystring.items() if "LoadBalancerNames.member" in key]
+ load_balancers = elb_backend.describe_load_balancers(names)
+ template = Template(DESCRIBE_LOAD_BALANCERS_TEMPLATE)
+ return template.render(load_balancers=load_balancers)
+
+ def delete_load_balancer(self):
+ load_balancer_name = self.querystring.get('LoadBalancerName')[0]
+ elb_backend.delete_load_balancer(load_balancer_name)
+ template = Template(DELETE_LOAD_BALANCER_TEMPLATE)
+ return template.render()
+
+ def configure_health_check(self):
+ check = elb_backend.configure_health_check(
+ load_balancer_name=self.querystring.get('LoadBalancerName')[0],
+ timeout=self.querystring.get('HealthCheck.Timeout')[0],
+ healthy_threshold=self.querystring.get('HealthCheck.HealthyThreshold')[0],
+ unhealthy_threshold=self.querystring.get('HealthCheck.UnhealthyThreshold')[0],
+ interval=self.querystring.get('HealthCheck.Interval')[0],
+ target=self.querystring.get('HealthCheck.Target')[0],
+ )
+ template = Template(CONFIGURE_HEALTH_CHECK_TEMPLATE)
+ return template.render(check=check)
+
+ def register_instances_with_load_balancer(self):
+ load_balancer_name = self.querystring.get('LoadBalancerName')[0]
+ instance_ids = [value[0] for key, value in self.querystring.items() if "Instances.member" in key]
+ template = Template(REGISTER_INSTANCES_TEMPLATE)
+ load_balancer = elb_backend.register_instances(load_balancer_name, instance_ids)
+ return template.render(load_balancer=load_balancer)
+
+ def deregister_instances_from_load_balancer(self):
+ load_balancer_name = self.querystring.get('LoadBalancerName')[0]
+ instance_ids = [value[0] for key, value in self.querystring.items() if "Instances.member" in key]
+ template = Template(DEREGISTER_INSTANCES_TEMPLATE)
+ load_balancer = elb_backend.deregister_instances(load_balancer_name, instance_ids)
+ return template.render(load_balancer=load_balancer)
+
+CREATE_LOAD_BALANCER_TEMPLATE = """
+ tests.us-east-1.elb.amazonaws.com
+"""
+
+DELETE_LOAD_BALANCER_TEMPLATE = """
+"""
+
+DESCRIBE_LOAD_BALANCERS_TEMPLATE = """
+
+
+ {% for load_balancer in load_balancers %}
+
+
+
+ {{ load_balancer.name }}
+ 2013-01-01T00:00:00.19000Z
+
+ {% if load_balancer.health_check %}
+ {{ load_balancer.health_check.interval }}
+ {{ load_balancer.health_check.target }}
+ {{ load_balancer.health_check.healthy_threshold }}
+ {{ load_balancer.health_check.timeout }}
+ {{ load_balancer.health_check.unhealthy_threshold }}
+ {% endif %}
+
+ vpc-56e10e3d
+
+ {% for listener in load_balancer.listeners %}
+
+
+ AWSConsolePolicy-1
+
+
+ {{ listener.protocol }}
+ {{ listener.load_balancer_port }}
+ {{ listener.protocol }}
+ {{ listener.instance_port }}
+
+
+ {% endfor %}
+
+
+ {% for instance_id in load_balancer.instance_ids %}
+
+ {{ instance_id }}
+
+ {% endfor %}
+
+
+
+
+
+
+ AWSConsolePolicy-1
+ 30
+
+
+
+
+ {% for zone in load_balancer.zones %}
+ {{ zone }}
+ {% endfor %}
+
+ tests.us-east-1.elb.amazonaws.com
+ Z3ZONEID
+ internet-facing
+ tests.us-east-1.elb.amazonaws.com
+
+
+
+
+ {% endfor %}
+
+
+
+ f9880f01-7852-629d-a6c3-3ae2-666a409287e6dc0c
+
+"""
+
+CONFIGURE_HEALTH_CHECK_TEMPLATE = """
+
+ {{ check.interval }}
+ {{ check.target }}
+ {{ check.healthy_threshold }}
+ {{ check.timeout }}
+ {{ check.unhealthy_threshold }}
+
+"""
+
+REGISTER_INSTANCES_TEMPLATE = """
+
+ {% for instance_id in load_balancer.instance_ids %}
+
+ {{ instance_id }}
+
+ {% endfor %}
+
+"""
+
+DEREGISTER_INSTANCES_TEMPLATE = """
+
+ {% for instance_id in load_balancer.instance_ids %}
+
+ {{ instance_id }}
+
+ {% endfor %}
+
+"""
diff --git a/moto/elb/urls.py b/moto/elb/urls.py
new file mode 100644
index 000000000..e41ed2921
--- /dev/null
+++ b/moto/elb/urls.py
@@ -0,0 +1,9 @@
+from .responses import ELBResponse
+
+url_bases = [
+ "https?://elasticloadbalancing.(.+).amazonaws.com",
+]
+
+url_paths = {
+ '{0}/$': ELBResponse().dispatch,
+}
diff --git a/tests/test_elb/test_elb.py b/tests/test_elb/test_elb.py
new file mode 100644
index 000000000..11ddc0ced
--- /dev/null
+++ b/tests/test_elb/test_elb.py
@@ -0,0 +1,121 @@
+import boto
+from boto.ec2.elb import HealthCheck
+import sure # flake8: noqa
+
+from moto import mock_elb, mock_ec2
+
+
+@mock_elb
+def test_create_load_balancer():
+ conn = boto.connect_elb()
+
+ zones = ['us-east-1a', 'us-east-1b']
+ ports = [(80, 8080, 'http'), (443, 8443, 'tcp')]
+ lb = conn.create_load_balancer('my-lb', zones, ports)
+
+ balancers = conn.get_all_load_balancers()
+ balancer = balancers[0]
+ balancer.name.should.equal("my-lb")
+ set(balancer.availability_zones).should.equal(set(['us-east-1a', 'us-east-1b']))
+ listener1 = balancer.listeners[0]
+ listener1.load_balancer_port.should.equal(80)
+ listener1.instance_port.should.equal(8080)
+ listener1.protocol.should.equal("HTTP")
+ listener2 = balancer.listeners[1]
+ listener2.load_balancer_port.should.equal(443)
+ listener2.instance_port.should.equal(8443)
+ listener2.protocol.should.equal("TCP")
+
+
+@mock_elb
+def test_get_load_balancers_by_name():
+ conn = boto.connect_elb()
+
+ zones = ['us-east-1a', 'us-east-1b']
+ ports = [(80, 8080, 'http'), (443, 8443, 'tcp')]
+ lb = conn.create_load_balancer('my-lb1', zones, ports)
+ lb = conn.create_load_balancer('my-lb2', zones, ports)
+ lb = conn.create_load_balancer('my-lb3', zones, ports)
+
+ conn.get_all_load_balancers().should.have.length_of(3)
+ conn.get_all_load_balancers(load_balancer_names=['my-lb1']).should.have.length_of(1)
+ conn.get_all_load_balancers(load_balancer_names=['my-lb1', 'my-lb2']).should.have.length_of(2)
+
+
+@mock_elb
+def test_delete_load_balancer():
+ conn = boto.connect_elb()
+
+ zones = ['us-east-1a']
+ ports = [(80, 8080, 'http'), (443, 8443, 'tcp')]
+ lb = conn.create_load_balancer('my-lb', zones, ports)
+
+ balancers = conn.get_all_load_balancers()
+ balancers.should.have.length_of(1)
+
+ conn.delete_load_balancer("my-lb")
+ balancers = conn.get_all_load_balancers()
+ balancers.should.have.length_of(0)
+
+
+@mock_elb
+def test_create_health_check():
+ conn = boto.connect_elb()
+
+ hc = HealthCheck(
+ interval=20,
+ healthy_threshold=3,
+ unhealthy_threshold=5,
+ target='HTTP:8080/health',
+ timeout=23,
+ )
+
+ lb = conn.create_load_balancer('my-lb', [], [])
+ lb.configure_health_check(hc)
+
+ balancer = conn.get_all_load_balancers()[0]
+ health_check = balancer.health_check
+ health_check.interval.should.equal(20)
+ health_check.healthy_threshold.should.equal(3)
+ health_check.unhealthy_threshold.should.equal(5)
+ health_check.target.should.equal('HTTP:8080/health')
+ health_check.timeout.should.equal(23)
+
+
+@mock_ec2
+@mock_elb
+def test_register_instances():
+ ec2_conn = boto.connect_ec2()
+ reservation = ec2_conn.run_instances('ami-1234abcd', 2)
+ instance_id1 = reservation.instances[0].id
+ instance_id2 = reservation.instances[1].id
+
+ conn = boto.connect_elb()
+ lb = conn.create_load_balancer('my-lb', [], [])
+
+ lb.register_instances([instance_id1, instance_id2])
+
+ balancer = conn.get_all_load_balancers()[0]
+ instance_ids = [instance.id for instance in balancer.instances]
+ set(instance_ids).should.equal(set([instance_id1, instance_id2]))
+
+
+@mock_ec2
+@mock_elb
+def test_deregister_instances():
+ ec2_conn = boto.connect_ec2()
+ reservation = ec2_conn.run_instances('ami-1234abcd', 2)
+ instance_id1 = reservation.instances[0].id
+ instance_id2 = reservation.instances[1].id
+
+ conn = boto.connect_elb()
+ lb = conn.create_load_balancer('my-lb', [], [])
+
+ lb.register_instances([instance_id1, instance_id2])
+
+ balancer = conn.get_all_load_balancers()[0]
+ balancer.instances.should.have.length_of(2)
+ balancer.deregister_instances([instance_id1])
+
+ balancer.instances.should.have.length_of(1)
+ balancer.instances[0].id.should.equal(instance_id2)
diff --git a/tests/test_elb/test_server.py b/tests/test_elb/test_server.py
new file mode 100644
index 000000000..e69de29bb