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 = """