Add ability to launch instances with security groups.

This commit is contained in:
Steve Pulec 2014-03-22 14:02:47 -04:00
parent fc8fd79cd8
commit 140f1c2000
4 changed files with 38 additions and 21 deletions

View File

@ -106,7 +106,8 @@ class FakeAutoScalingGroup(object):
reservation = ec2_backend.add_instances(
self.launch_config.image_id,
count_needed,
self.launch_config.user_data
self.launch_config.user_data,
self.launch_config.security_groups,
)
for instance in reservation.instances:
instance.autoscaling_group = self

View File

@ -30,12 +30,13 @@ class InstanceState(object):
class Instance(BotoInstance):
def __init__(self, image_id, user_data):
def __init__(self, image_id, user_data, security_groups):
super(Instance, self).__init__()
self.id = random_instance_id()
self.image_id = image_id
self._state = InstanceState("running", 16)
self.user_data = user_data
self.security_groups = security_groups
def start(self, *args, **kwargs):
self._state.name = "running"
@ -69,13 +70,16 @@ class InstanceBackend(object):
if instance.id == instance_id:
return instance
def add_instances(self, image_id, count, user_data):
def add_instances(self, image_id, count, user_data, security_group_names):
new_reservation = Reservation()
new_reservation.id = random_reservation_id()
security_groups = [self.get_security_group_from_name(name) for name in security_group_names]
for index in range(count):
new_instance = Instance(
image_id,
user_data,
security_groups,
)
new_reservation.instances.append(new_instance)
self.reservations[new_reservation.id] = new_reservation
@ -369,7 +373,7 @@ class SecurityGroupBackend(object):
return vpc.pop(group_id)
elif name:
# Group Name. Has to be in standard EC2, VPC needs to be identified by group_id
group = self.get_security_group_from_name(name, None)
group = self.get_security_group_from_name(name)
if group:
return self.groups[None].pop(group.id)
@ -381,9 +385,7 @@ class SecurityGroupBackend(object):
if group.id == group_id:
return group
def get_security_group_from_name(self, name, vpc_id):
def get_security_group_from_name(self, name, vpc_id=None):
for group_id, group in self.groups[vpc_id].iteritems():
if group.name == name:
return group
@ -441,7 +443,6 @@ class SecurityGroupBackend(object):
elif group_id:
group = self.get_security_group_from_id(group_id)
source_groups = []
for source_group_name in source_group_names:
source_group = self.get_security_group_from_name(source_group_name, vpc_id)
@ -627,12 +628,12 @@ class SpotInstanceRequest(object):
self.security_groups = []
if security_groups:
for group_name in security_groups:
group = ec2_backend.get_security_group_from_name(group_name, None)
group = ec2_backend.get_security_group_from_name(group_name)
if group:
self.security_groups.append(group)
else:
# If not security groups, add the default
default_group = ec2_backend.get_security_group_from_name("default", None)
default_group = ec2_backend.get_security_group_from_name("default")
self.security_groups.append(default_group)

View File

@ -8,6 +8,9 @@ from moto.ec2.exceptions import InvalidIdError
class InstanceResponse(BaseResponse):
def _get_multi_param(self, param_prefix):
return [value[0] for key, value in self.querystring.items() if key.startswith(param_prefix)]
def describe_instances(self):
instance_ids = instance_ids_from_querystring(self.querystring)
if instance_ids:
@ -29,7 +32,8 @@ class InstanceResponse(BaseResponse):
min_count = int(self.querystring.get('MinCount', ['1'])[0])
image_id = self.querystring.get('ImageId')[0]
user_data = self.querystring.get('UserData')
new_reservation = ec2_backend.add_instances(image_id, min_count, user_data)
security_group_names = self._get_multi_param('SecurityGroup')
new_reservation = ec2_backend.add_instances(image_id, min_count, user_data, security_group_names)
template = Template(EC2_RUN_INSTANCES)
return template.render(reservation=new_reservation)
@ -119,10 +123,12 @@ EC2_RUN_INSTANCES = """<RunInstancesResponse xmlns="http://ec2.amazonaws.com/doc
</monitoring>
<sourceDestCheck>true</sourceDestCheck>
<groupSet>
{% for group in instance.security_groups %}
<item>
<groupId>sg-245f6a01</groupId>
<groupName>default</groupName>
<groupId>{{ group.id }}</groupId>
<groupName>{{ group.name }}</groupName>
</item>
{% endfor %}
</groupSet>
<virtualizationType>paravirtual</virtualizationType>
<clientToken/>
@ -140,12 +146,7 @@ EC2_DESCRIBE_INSTANCES = """<DescribeInstancesResponse xmlns='http://ec2.amazona
<item>
<reservationId>{{ reservation.id }}</reservationId>
<ownerId>111122223333</ownerId>
<groupSet>
<item>
<groupId>sg-1a2b3c4d</groupId>
<groupName>my-security-group</groupName>
</item>
</groupSet>
<groupSet></groupSet>
<instancesSet>
{% for instance in reservation.instances %}
<item>
@ -178,10 +179,12 @@ EC2_DESCRIBE_INSTANCES = """<DescribeInstancesResponse xmlns='http://ec2.amazona
<ipAddress>46.51.219.63</ipAddress>
<sourceDestCheck>true</sourceDestCheck>
<groupSet>
{% for group in instance.security_groups %}
<item>
<groupId>sg-1a2b3c4d</groupId>
<groupName>my-security-group</groupName>
<groupId>{{ group.id }}</groupId>
<groupName>{{ group.name }}</groupName>
</item>
{% endfor %}
</groupSet>
<architecture>x86_64</architecture>
<rootDeviceType>ebs</rootDeviceType>

View File

@ -170,3 +170,15 @@ def test_user_data_with_run_instance():
instance_attribute.should.be.a(InstanceAttribute)
decoded_user_data = base64.decodestring(instance_attribute.get("userData"))
decoded_user_data.should.equal("some user data")
@mock_ec2
def test_run_instance_with_security_group():
conn = boto.connect_ec2('the_key', 'the_secret')
group = conn.create_security_group('group1', "some description")
reservation = conn.run_instances('ami-1234abcd', security_groups=['group1'])
instance = reservation.instances[0]
instance.groups[0].id.should.equal(group.id)
instance.groups[0].name.should.equal("group1")