Fix ec2 tags in instance create. Closes #938.

This commit is contained in:
Steve Pulec 2017-05-12 19:48:14 -04:00
parent 0fe824277b
commit 97b920f6cf
4 changed files with 80 additions and 1 deletions

View File

@ -1,4 +1,6 @@
from __future__ import unicode_literals
from collections import defaultdict
import datetime
import json
import logging
@ -330,6 +332,26 @@ class BaseResponse(_TemplateEnvironmentMixin):
return results
def _parse_tag_specification(self, param_prefix):
tags = self._get_list_prefix(param_prefix)
results = defaultdict(dict)
for tag in tags:
resource_type = tag.pop("resource_type")
param_index = 1
while True:
key_name = 'tag.{0}._key'.format(param_index)
value_name = 'tag.{0}._value'.format(param_index)
try:
results[resource_type][tag[key_name]] = tag[value_name]
except KeyError:
break
param_index += 1
return results
@property
def request_json(self):
return 'JSON' in self.querystring.get('ContentType', [])

View File

@ -141,6 +141,10 @@ class TaggedEC2Resource(BaseModel):
def add_tag(self, key, value):
self.ec2_backend.create_tags([self.id], {key: value})
def add_tags(self, tag_map):
for key, value in tag_map.items():
self.ec2_backend.create_tags([self.id], {key: value})
def get_filter_value(self, filter_name):
tags = self.get_tags()
@ -638,6 +642,10 @@ class InstanceBackend(object):
security_groups.extend(self.get_security_group_from_id(sg_id)
for sg_id in kwargs.pop("security_group_ids", []))
self.reservations[new_reservation.id] = new_reservation
tags = kwargs.pop("tags", {})
instance_tags = tags.get('instance', {})
for index in range(count):
new_instance = Instance(
self,
@ -647,6 +655,7 @@ class InstanceBackend(object):
**kwargs
)
new_reservation.instances.append(new_instance)
new_instance.add_tags(instance_tags)
new_instance.setup_defaults()
return new_reservation

View File

@ -47,13 +47,15 @@ class InstanceResponse(BaseResponse):
associate_public_ip = self.querystring.get(
"AssociatePublicIpAddress", [None])[0]
key_name = self.querystring.get("KeyName", [None])[0]
tags = self._parse_tag_specification("TagSpecification")
if self.is_not_dryrun('RunInstance'):
new_reservation = self.ec2_backend.add_instances(
image_id, min_count, user_data, security_group_names,
instance_type=instance_type, placement=placement, subnet_id=subnet_id,
key_name=key_name, security_group_ids=security_group_ids,
nics=nics, private_ip=private_ip, associate_public_ip=associate_public_ip)
nics=nics, private_ip=private_ip, associate_public_ip=associate_public_ip,
tags=tags)
template = self.response_template(EC2_RUN_INSTANCES)
return template.render(reservation=new_reservation)
@ -282,6 +284,14 @@ EC2_RUN_INSTANCES = """<RunInstancesResponse xmlns="http://ec2.amazonaws.com/doc
<clientToken/>
<hypervisor>xen</hypervisor>
<ebsOptimized>false</ebsOptimized>
<tagSet>
{% for tag in instance.get_tags() %}
<item>
<key>{{ tag.key }}</key>
<value>{{ tag.value }}</value>
</item>
{% endfor %}
</tagSet>
<networkInterfaceSet>
{% for nic in instance.nics.values() %}
<item>

View File

@ -178,6 +178,44 @@ def test_get_paginated_instances():
assert 'NextToken' not in resp2.keys()
@mock_ec2
def test_create_with_tags():
ec2 = boto3.client('ec2', region_name='us-west-2')
instances = ec2.run_instances(
ImageId='ami-123',
MinCount=1,
MaxCount=1,
InstanceType='t2.micro',
TagSpecifications=[
{
'ResourceType': 'instance',
'Tags': [
{
'Key': 'MY_TAG1',
'Value': 'MY_VALUE1',
},
{
'Key': 'MY_TAG2',
'Value': 'MY_VALUE2',
},
],
},
{
'ResourceType': 'instance',
'Tags': [
{
'Key': 'MY_TAG3',
'Value': 'MY_VALUE3',
},
]
},
],
)
assert 'Tags' in instances['Instances'][0]
len(instances['Instances'][0]['Tags']).should.equal(3)
@mock_ec2_deprecated
def test_get_instances_filtering_by_state():
conn = boto.connect_ec2()