Merge pull request #270 from tsanders/instance_modify_security_groups

Add support for instance "groupSet" attribute modification and description.  Support for Route Table tagging.
This commit is contained in:
Steve Pulec 2014-11-29 20:52:38 -05:00
commit 345b15f383
5 changed files with 94 additions and 4 deletions

View File

@ -543,7 +543,14 @@ class InstanceBackend(object):
setattr(instance, key, value)
return instance
def modify_instance_security_groups(self, instance_id, new_group_list):
instance = self.get_instance(instance_id)
setattr(instance, 'security_groups', new_group_list)
return instance
def describe_instance_attribute(self, instance_id, key):
if key == 'group_set':
key = 'security_groups'
instance = self.get_instance(instance_id)
value = getattr(instance, key)
return instance, value
@ -2484,7 +2491,7 @@ class EC2Backend(BaseBackend, InstanceBackend, TagBackend, AmiBackend,
elif resource_prefix == EC2_RESOURCE_TO_PREFIX['reserved-instance']:
self.raise_not_implemented_error('DescribeReservedInstances')
elif resource_prefix == EC2_RESOURCE_TO_PREFIX['route-table']:
self.raise_not_implemented_error('DescribeRouteTables')
self.get_route_table(route_table_id=resource_id)
elif resource_prefix == EC2_RESOURCE_TO_PREFIX['security-group']:
self.describe_security_groups(group_ids=[resource_id])
elif resource_prefix == EC2_RESOURCE_TO_PREFIX['snapshot']:

View File

@ -88,12 +88,18 @@ class InstanceResponse(BaseResponse):
instance_ids = instance_ids_from_querystring(self.querystring)
instance_id = instance_ids[0]
instance, value = self.ec2_backend.describe_instance_attribute(instance_id, key)
template = Template(EC2_DESCRIBE_INSTANCE_ATTRIBUTE)
if key == "group_set":
template = Template(EC2_DESCRIBE_INSTANCE_GROUPSET_ATTRIBUTE)
else:
template = Template(EC2_DESCRIBE_INSTANCE_ATTRIBUTE)
return template.render(instance=instance, attribute=attribute, value=value)
def modify_instance_attribute(self):
handlers = [self._dot_value_instance_attribute_handler,
self._block_device_mapping_handler]
self._block_device_mapping_handler,
self._security_grp_instance_attribute_handler]
for handler in handlers:
success = handler()
@ -163,6 +169,17 @@ class InstanceResponse(BaseResponse):
self.ec2_backend.modify_instance_attribute(instance_id, normalized_attribute, value)
return EC2_MODIFY_INSTANCE_ATTRIBUTE
def _security_grp_instance_attribute_handler(self):
new_security_grp_list = []
for key, value in self.querystring.items():
if 'GroupId.' in key:
new_security_grp_list.append(self.querystring.get(key)[0])
instance_ids = instance_ids_from_querystring(self.querystring)
instance_id = instance_ids[0]
self.ec2_backend.modify_instance_security_groups(instance_id, new_security_grp_list)
return EC2_MODIFY_INSTANCE_ATTRIBUTE
EC2_RUN_INSTANCES = """<RunInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2012-12-01/">
<requestId>59dbff89-35bd-4eac-99ed-be587EXAMPLE</requestId>
@ -500,6 +517,18 @@ EC2_DESCRIBE_INSTANCE_ATTRIBUTE = """<DescribeInstanceAttributeResponse xmlns="h
</{{ attribute }}>
</DescribeInstanceAttributeResponse>"""
EC2_DESCRIBE_INSTANCE_GROUPSET_ATTRIBUTE = """<DescribeInstanceAttributeResponse xmlns="http://ec2.amazonaws.com/doc/2012-12-01/">
<requestId>59dbff89-35bd-4eac-99ed-be587EXAMPLE</requestId>
<instanceId>{{ instance.id }}</instanceId>
<{{ attribute }}>
{% for sg_id in value %}
<item>
<groupId>{{ sg_id }}</groupId>
</item>
{% endfor %}
</{{ attribute }}>
</DescribeInstanceAttributeResponse>"""
EC2_MODIFY_INSTANCE_ATTRIBUTE = """<ModifyInstanceAttributeResponse xmlns="http://ec2.amazonaws.com/doc/2012-12-01/">
<requestId>59dbff89-35bd-4eac-99ed-be587EXAMPLE</requestId>
<return>true</return>

View File

@ -121,7 +121,16 @@ CREATE_ROUTE_TABLE_RESPONSE = """
{% endfor %}
</routeSet>
<associationSet/>
<tagSet/>
<tagSet>
{% for tag in route_table.get_tags() %}
<item>
<resourceId>{{ tag.resource_id }}</resourceId>
<resourceType>{{ tag.resource_type }}</resourceType>
<key>{{ tag.key }}</key>
<value>{{ tag.value }}</value>
</item>
{% endfor %}
</tagSet>
</routeTable>
</CreateRouteTableResponse>
"""
@ -172,6 +181,16 @@ DESCRIBE_ROUTE_TABLES_RESPONSE = """
{% endfor %}
</associationSet>
<tagSet/>
<tagSet>
{% for tag in route_table.get_tags() %}
<item>
<resourceId>{{ tag.resource_id }}</resourceId>
<resourceType>{{ tag.resource_type }}</resourceType>
<key>{{ tag.key }}</key>
<value>{{ tag.value }}</value>
</item>
{% endfor %}
</tagSet>
</item>
{% endfor %}
</routeTableSet>

View File

@ -274,6 +274,22 @@ def test_instance_attribute_instance_type():
instance_attribute.should.be.a(InstanceAttribute)
instance_attribute.get('instanceType').should.equal("m1.small")
@mock_ec2
def test_modify_instance_attribute_security_groups():
conn = boto.connect_ec2('the_key', 'the_secret')
reservation = conn.run_instances('ami-1234abcd')
instance = reservation.instances[0]
sg_id = 'sg-1234abcd'
sg_id2 = 'sg-abcd4321'
instance.modify_attribute("groupSet", [sg_id, sg_id2])
instance_attribute = instance.get_attribute("groupSet")
instance_attribute.should.be.a(InstanceAttribute)
group_list = instance_attribute.get('groupSet')
any(g.id == sg_id for g in group_list).should.be.ok
any(g.id == sg_id2 for g in group_list).should.be.ok
@mock_ec2
def test_instance_attribute_user_data():

View File

@ -418,3 +418,22 @@ def test_routes_vpc_peering_connection():
new_route.state.should.equal('blackhole')
new_route.destination_cidr_block.should.equal(ROUTE_CIDR)
@mock_ec2
def test_network_acl_tagging():
conn = boto.connect_vpc('the_key', 'the secret')
vpc = conn.create_vpc("10.0.0.0/16")
route_table = conn.create_route_table(vpc.id)
route_table.add_tag("a key", "some value")
tag = conn.get_all_tags()[0]
tag.name.should.equal("a key")
tag.value.should.equal("some value")
all_route_tables = conn.get_all_route_tables()
test_route_table = next(na for na in all_route_tables
if na.id == route_table.id)
test_route_table.tags.should.have.length_of(1)
test_route_table.tags["a key"].should.equal("some value")