diff --git a/moto/ec2/models.py b/moto/ec2/models.py index f69919aec..368d27bb6 100644 --- a/moto/ec2/models.py +++ b/moto/ec2/models.py @@ -1,3 +1,4 @@ +import copy from collections import defaultdict from boto.ec2.instance import Instance as BotoInstance, Reservation @@ -117,6 +118,22 @@ class InstanceBackend(object): instances.append(instance) return instances + def get_reservations_by_instance_ids(self, instance_ids): + """ Go through all of the reservations and filter to only return those + associated with the given instance_ids. + """ + reservations = [] + for reservation in self.reservations.values(): + reservation_instance_ids = [instance.id for instance in reservation.instances] + matching_reservation = any(instance_id in reservation_instance_ids for instance_id in instance_ids) + if matching_reservation: + # We need to make a copy of the reservation because we have to modify the + # instances to limit to those requested + reservation_copy = copy.deepcopy(reservation) + reservation_copy.instances = [instance for instance in reservation_copy.instances if instance.id in instance_ids] + reservations.append(reservation_copy) + return reservations + def all_reservations(self): return self.reservations.values() diff --git a/moto/ec2/responses/instances.py b/moto/ec2/responses/instances.py index d752bf0f6..d0f044e50 100644 --- a/moto/ec2/responses/instances.py +++ b/moto/ec2/responses/instances.py @@ -7,8 +7,13 @@ from moto.ec2.utils import instance_ids_from_querystring class InstanceResponse(object): def describe_instances(self): + instance_ids = instance_ids_from_querystring(self.querystring) template = Template(EC2_DESCRIBE_INSTANCES) - return template.render(reservations=ec2_backend.all_reservations()) + if instance_ids: + reservations = ec2_backend.get_reservations_by_instance_ids(instance_ids) + else: + reservations = ec2_backend.all_reservations() + return template.render(reservations=reservations) def run_instances(self): min_count = int(self.querystring.get('MinCount', ['1'])[0]) diff --git a/tests/test_ec2/test_instances.py b/tests/test_ec2/test_instances.py index 11c2cc00e..941c2c42a 100644 --- a/tests/test_ec2/test_instances.py +++ b/tests/test_ec2/test_instances.py @@ -50,6 +50,26 @@ def test_instance_launch_and_terminate(): instance.state.should.equal('shutting-down') +@mock_ec2 +def test_get_instances_by_id(): + conn = boto.connect_ec2() + reservation = conn.run_instances('ami-1234abcd', min_count=2) + instance1, instance2 = reservation.instances + + reservations = conn.get_all_instances(instance_ids=[instance1.id]) + reservations.should.have.length_of(1) + reservation = reservations[0] + reservation.instances.should.have.length_of(1) + reservation.instances[0].id.should.equal(instance1.id) + + reservations = conn.get_all_instances(instance_ids=[instance1.id, instance2.id]) + reservations.should.have.length_of(1) + reservation = reservations[0] + reservation.instances.should.have.length_of(2) + instance_ids = [instance.id for instance in reservation.instances] + instance_ids.should.equal([instance1.id, instance2.id]) + + @mock_ec2 def test_instance_start_and_stop(): conn = boto.connect_ec2('the_key', 'the_secret')