diff --git a/moto/elb/exceptions.py b/moto/elb/exceptions.py new file mode 100644 index 000000000..e2707b60a --- /dev/null +++ b/moto/elb/exceptions.py @@ -0,0 +1,29 @@ +from __future__ import unicode_literals +from moto.core.exceptions import RESTError + + +class ELBClientError(RESTError): + code = 400 + + +class DuplicateTagKeysError(ELBClientError): + def __init__(self, cidr): + super(DuplicateTagKeysError, self).__init__( + "DuplicateTagKeys", + "Tag key was specified more than once: {0}" + .format(cidr)) + + +class LoadBalancerNotFoundError(ELBClientError): + def __init__(self, cidr): + super(LoadBalancerNotFoundError, self).__init__( + "LoadBalancerNotFound", + "The specified load balancer does not exist: {0}" + .format(cidr)) + + +class TooManyTagsError(ELBClientError): + def __init__(self): + super(TooManyTagsError, self).__init__( + "LoadBalancerNotFound", + "The quota for the number of tags that can be assigned to a load balancer has been reached") diff --git a/moto/elb/models.py b/moto/elb/models.py index 85c5ff11b..1f50c3aca 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 .exceptions import TooManyTagsError class FakeHealthCheck(object): @@ -57,6 +58,7 @@ class FakeLoadBalancer(object): self.policies.other_policies = [] self.policies.app_cookie_stickiness_policies = [] self.policies.lb_cookie_stickiness_policies = [] + self.tags = {} for port in ports: listener = FakeListener( @@ -130,6 +132,18 @@ class FakeLoadBalancer(object): return attributes + def add_tag(self, key, value): + if len(self.tags) >= 10 and key not in self.tags: + raise TooManyTagsError() + self.tags[key] = value + + def list_tags(self): + return self.tags + + def remove_tag(self, key): + if key in self.tags: + del self.tags[key] + class ELBBackend(BaseBackend): diff --git a/moto/elb/responses.py b/moto/elb/responses.py index a0187f160..3455ef38e 100644 --- a/moto/elb/responses.py +++ b/moto/elb/responses.py @@ -12,6 +12,10 @@ from boto.ec2.elb.policies import ( from moto.core.responses import BaseResponse from .models import elb_backends +from .exceptions import DuplicateTagKeysError, LoadBalancerNotFoundError, \ + TooManyTagsError + +from collections import Counter class ELBResponse(BaseResponse): @@ -218,6 +222,104 @@ class ELBResponse(BaseResponse): template = self.response_template(DESCRIBE_INSTANCE_HEALTH_TEMPLATE) return template.render(instance_ids=instance_ids) + def add_tags(self): + for key, value in self.querystring.items(): + if "LoadBalancerNames.member" in key: + number = key.split('.')[2] + load_balancer_name = value[0] + elb = self.elb_backend.get_load_balancer(load_balancer_name) + if not elb: + raise LoadBalancerNotFoundError(load_balancer_name) + + value = 'Tags.member.{}.Value'.format(number) + key = 'Tags.member.{}.Key'.format(number) + tag_values = [] + tag_keys = [] + + for t_key, t_val in 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 = Counter(tag_keys).most_common(1) + + 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) + + + template = self.response_template(ADD_TAGS_TEMPLATE) + return template.render() + + def remove_tags(self): + for key, value in self.querystring.items(): + if "LoadBalancerNames.member" in key: + number = key.split('.')[2] + load_balancer_name = self._get_param('LoadBalancerNames.member.{}'.format(number)) + elb = self.elb_backend.get_load_balancer(load_balancer_name) + if not elb: + raise LoadBalancerNotFound(load_balancer_name) + + key = 'Tag.member.{}.Key'.format(number) + for t_key, t_val in self.querystring.items(): + if t_key.startswith('Tags.member.'): + if t_key.split('.')[3] == 'Key': + elb.remove_tag(t_val[0]) + + template = self.response_template(REMOVE_TAGS_TEMPLATE) + return template.render() + + def describe_tags(self): + for key, value in self.querystring.items(): + if "LoadBalancerNames.member" in key: + number = key.split('.')[2] + load_balancer_name = self._get_param('LoadBalancerNames.member.{}'.format(number)) + elb = self.elb_backend.get_load_balancer(load_balancer_name) + if not elb: + raise LoadBalancerNotFound(load_balancer_name) + + template = self.response_template(DESCRIBE_TAGS_TEMPLATE) + return template.render(tags=elb.tags) + +ADD_TAGS_TEMPLATE = """ + + + 360e81f7-1100-11e4-b6ed-0f30EXAMPLE + +""" + +REMOVE_TAGS_TEMPLATE = """ + + + 360e81f7-1100-11e4-b6ed-0f30EXAMPLE + +""" + +DESCRIBE_TAGS_TEMPLATE = """ + + + + + {% for key, value in tags.items() %} + + {{ value }} + {{ key }} + + {% endfor %} + + + + + + 360e81f7-1100-11e4-b6ed-0f30EXAMPLE + +""" + CREATE_LOAD_BALANCER_TEMPLATE = """