diff --git a/moto/cloudformation/models.py b/moto/cloudformation/models.py index d8793b8ea..bf11bc7ce 100644 --- a/moto/cloudformation/models.py +++ b/moto/cloudformation/models.py @@ -26,7 +26,7 @@ class FakeStack(object): self.output_map = self._create_output_map() def _create_resource_map(self): - resource_map = ResourceMap(self.stack_id, self.name, self.parameters, self.region_name, self.template_dict) + resource_map = ResourceMap(self.stack_id, self.name, self.parameters, self.tags, self.region_name, self.template_dict) resource_map.create() return resource_map diff --git a/moto/cloudformation/parsing.py b/moto/cloudformation/parsing.py index 26eab6e87..126cf7991 100644 --- a/moto/cloudformation/parsing.py +++ b/moto/cloudformation/parsing.py @@ -2,6 +2,7 @@ from __future__ import unicode_literals import collections import functools import logging +import copy from moto.autoscaling import models as autoscaling_models from moto.awslambda import models as lambda_models @@ -264,11 +265,12 @@ class ResourceMap(collections.Mapping): each resources is passed this lazy map that it can grab dependencies from. """ - def __init__(self, stack_id, stack_name, parameters, region_name, template): + def __init__(self, stack_id, stack_name, parameters, tags, region_name, template): self._template = template self._resource_json_map = template['Resources'] self._region_name = region_name self.input_parameters = parameters + self.tags = copy.deepcopy(tags) self.resolved_parameters = {} # Create the default resources @@ -339,13 +341,12 @@ class ResourceMap(collections.Mapping): # Since this is a lazy map, to create every object we just need to # iterate through self. - tags = {'aws:cloudformation:stack-name': self.get('AWS::StackName'), - 'aws:cloudformation:stack-id': self.get('AWS::StackId')} + self.tags.update({'aws:cloudformation:stack-name': self.get('AWS::StackName'), + 'aws:cloudformation:stack-id': self.get('AWS::StackId')}) for resource in self.resources: - self[resource] if isinstance(self[resource], ec2_models.TaggedEC2Resource): - tags['aws:cloudformation:logical-id'] = resource - ec2_models.ec2_backends[self._region_name].create_tags([self[resource].physical_resource_id], tags) + self.tags['aws:cloudformation:logical-id'] = resource + ec2_models.ec2_backends[self._region_name].create_tags([self[resource].physical_resource_id], self.tags) def update(self, template): self.load_mapping() diff --git a/moto/ec2/models.py b/moto/ec2/models.py index db2b71bcb..9707eb973 100644 --- a/moto/ec2/models.py +++ b/moto/ec2/models.py @@ -774,9 +774,9 @@ class TagBackend(object): raise InvalidParameterValueErrorTagNull() for resource_id in resource_ids: if resource_id in self.tags: - if len(self.tags[resource_id]) + len(tags) > 10: + if len(self.tags[resource_id]) + len([tag for tag in tags if not tag.startswith("aws:")]) > 10: raise TagLimitExceeded() - elif len(tags) > 10: + elif len([tag for tag in tags if not tag.startswith("aws:")]) > 10: raise TagLimitExceeded() for resource_id in resource_ids: for tag in tags: diff --git a/tests/test_cloudformation/test_cloudformation_stack_integration.py b/tests/test_cloudformation/test_cloudformation_stack_integration.py index 5f52bb9a9..609ab4a21 100644 --- a/tests/test_cloudformation/test_cloudformation_stack_integration.py +++ b/tests/test_cloudformation/test_cloudformation_stack_integration.py @@ -363,6 +363,12 @@ def test_stack_security_groups(): "Type": "AWS::EC2::SecurityGroup", "Properties": { "GroupDescription": "My security group", + "Tags": [ + { + "Key": "bar", + "Value": "baz" + } + ], "SecurityGroupIngress": [{ "IpProtocol": "tcp", "FromPort": "22", @@ -384,6 +390,7 @@ def test_stack_security_groups(): conn.create_stack( "security_group_stack", template_body=security_group_template_json, + tags={"foo":"bar"} ) ec2_conn = boto.ec2.connect_to_region("us-west-1") @@ -395,6 +402,8 @@ def test_stack_security_groups(): ec2_instance.groups[0].id.should.equal(instance_group.id) instance_group.description.should.equal("My security group") + instance_group.tags.should.have.key('foo').which.should.equal('bar') + instance_group.tags.should.have.key('bar').which.should.equal('baz') rule1, rule2 = instance_group.rules int(rule1.to_port).should.equal(22) int(rule1.from_port).should.equal(22)