From ce3fdaa0127df73254998496bd005c4050ea62fa Mon Sep 17 00:00:00 2001 From: Daniel Hepper Date: Thu, 14 Apr 2016 14:43:03 +0200 Subject: [PATCH 1/5] Implemented subnet handling in ELB backend The ELB backend now honors the Subnets parameter in CreateLoadBalancer calls. When a load balancer is created with subnets, the VPC is also set to the VPC of the subnets. --- moto/elb/models.py | 24 +++++++++++++++++++----- moto/elb/responses.py | 15 +++++++++++++-- tests/test_elb/test_elb.py | 25 +++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 7 deletions(-) diff --git a/moto/elb/models.py b/moto/elb/models.py index 8954f5e3c..e4b817f32 100644 --- a/moto/elb/models.py +++ b/moto/elb/models.py @@ -10,6 +10,7 @@ from boto.ec2.elb.attributes import ( ) from boto.ec2.elb.policies import Policies from moto.core import BaseBackend +from moto.ec2.models import ec2_backends from .exceptions import LoadBalancerNotFoundError, TooManyTagsError, BadHealthCheckDefinition @@ -47,7 +48,7 @@ class FakeBackend(object): class FakeLoadBalancer(object): - def __init__(self, name, zones, ports, scheme='internet-facing',): + def __init__(self, name, zones, ports, scheme='internet-facing', vpc_id=None, subnets=None): self.name = name self.health_check = None self.instance_ids = [] @@ -60,6 +61,8 @@ class FakeLoadBalancer(object): self.policies.other_policies = [] self.policies.app_cookie_stickiness_policies = [] self.policies.lb_cookie_stickiness_policies = [] + self.subnets = subnets or [] + self.vpc_id = vpc_id self.tags = {} for port in ports: @@ -149,11 +152,22 @@ class FakeLoadBalancer(object): class ELBBackend(BaseBackend): - def __init__(self): + def __init__(self, region_name=None): + self.region_name = region_name self.load_balancers = {} - def create_load_balancer(self, name, zones, ports, scheme='internet-facing'): - new_load_balancer = FakeLoadBalancer(name=name, zones=zones, ports=ports, scheme=scheme) + def reset(self): + region_name = self.region_name + self.__dict__ = {} + self.__init__(region_name) + + def create_load_balancer(self, name, zones, ports, scheme='internet-facing', subnets=None): + vpc_id = None + ec2_backend = ec2_backends[self.region_name] + if subnets: + subnet = ec2_backend.get_subnet(subnets[0]) + vpc_id = subnet.vpc_id + new_load_balancer = FakeLoadBalancer(name=name, zones=zones, ports=ports, scheme=scheme, subnets=subnets, vpc_id=vpc_id) self.load_balancers[name] = new_load_balancer return new_load_balancer @@ -286,4 +300,4 @@ class ELBBackend(BaseBackend): elb_backends = {} for region in boto.ec2.elb.regions(): - elb_backends[region.name] = ELBBackend() + elb_backends[region.name] = ELBBackend(region.name) diff --git a/moto/elb/responses.py b/moto/elb/responses.py index a55ba5382..9e98dcfbb 100644 --- a/moto/elb/responses.py +++ b/moto/elb/responses.py @@ -27,12 +27,14 @@ class ELBResponse(BaseResponse): availability_zones = self._get_multi_param("AvailabilityZones.member") ports = self._get_list_prefix("Listeners.member") scheme = self._get_param('Scheme') + subnets = self._get_multi_param("Subnets.member") self.elb_backend.create_load_balancer( name=load_balancer_name, zones=availability_zones, ports=ports, - scheme=scheme + scheme=scheme, + subnets=subnets ) template = self.response_template(CREATE_LOAD_BALANCER_TEMPLATE) return template.render() @@ -369,7 +371,11 @@ DESCRIBE_LOAD_BALANCERS_TEMPLATE = """ 1: - # We have dupes... - raise DuplicateTagKeysError(counts[0]) - - for tag_key, tag_value in zip(tag_keys, tag_values): - elb.add_tag(tag_key, tag_value) - + self._add_tags(elb) template = self.response_template(ADD_TAGS_TEMPLATE) return template.render() @@ -292,6 +269,31 @@ class ELBResponse(BaseResponse): template = self.response_template(DESCRIBE_TAGS_TEMPLATE) return template.render(load_balancers=elbs) + def _add_tags(self, elb): + tag_values = [] + tag_keys = [] + + for t_key, t_val in sorted(self.querystring.items()): + if t_key.startswith('Tags.member.'): + if t_key.split('.')[3] == 'Key': + tag_keys.extend(t_val) + elif t_key.split('.')[3] == 'Value': + tag_values.extend(t_val) + + counts = {} + for i in tag_keys: + counts[i] = tag_keys.count(i) + + counts = sorted(counts.items(), key=lambda i:i[1], reverse=True) + + if counts and counts[0][1] > 1: + # We have dupes... + raise DuplicateTagKeysError(counts[0]) + + for tag_key, tag_value in zip(tag_keys, tag_values): + elb.add_tag(tag_key, tag_value) + + ADD_TAGS_TEMPLATE = """ diff --git a/tests/test_elb/test_elb.py b/tests/test_elb/test_elb.py index 7ec0a34b0..828b8b04d 100644 --- a/tests/test_elb/test_elb.py +++ b/tests/test_elb/test_elb.py @@ -721,6 +721,24 @@ def test_add_remove_tags(): lb_tags['other-lb'].should.have.key('other').which.should.equal('something') +@mock_elb +def test_create_with_tags(): + client = boto3.client('elb', region_name='us-east-1') + + client.create_load_balancer( + LoadBalancerName='my-lb', + Listeners=[{'Protocol':'tcp', 'LoadBalancerPort':80, 'InstancePort':8080}], + AvailabilityZones=['us-east-1a', 'us-east-1b'], + Tags=[{ + 'Key': 'k', + 'Value': 'v' + }] + ) + + tags = dict((d['Key'], d['Value']) for d in client.describe_tags(LoadBalancerNames=['my-lb'])['TagDescriptions'][0]['Tags']) + tags.should.have.key('k').which.should.equal('v') + + @mock_ec2 @mock_elb def test_subnets(): From 105ba838353b4f8588d46c3188420bf6e48a9625 Mon Sep 17 00:00:00 2001 From: Daniel Hepper Date: Thu, 14 Apr 2016 15:51:32 +0200 Subject: [PATCH 5/5] Fix an assertion that was always true --- tests/test_elb/test_elb.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/test_elb/test_elb.py b/tests/test_elb/test_elb.py index 828b8b04d..ee135a9e5 100644 --- a/tests/test_elb/test_elb.py +++ b/tests/test_elb/test_elb.py @@ -614,11 +614,11 @@ def test_add_remove_tags(): client.add_tags(LoadBalancerNames=['my-lb'], Tags=[{ 'Key': 'a', - 'Value': 'a' + 'Value': 'b' }]) tags = dict([(d['Key'], d['Value']) for d in client.describe_tags(LoadBalancerNames=['my-lb'])['TagDescriptions'][0]['Tags']]) - tags.should.have('a').should.equal('a') + tags.should.have.key('a').which.should.equal('b') client.add_tags(LoadBalancerNames=['my-lb'], Tags=[{