Fix ami tests

- missing and malformed image ids
- test_ami_filters

- test_ami_copy tests

- test_ami_create_and_delete test

- test_ami_filter_wildcard test

- the rest of the tests by using the non-deprecated mock_ec2
This commit is contained in:
William Richard 2017-12-05 16:53:30 -05:00
parent 00a4249b74
commit e0d4728c5d
No known key found for this signature in database
GPG Key ID: F7F8BA4DDBE1ABED
3 changed files with 102 additions and 83 deletions

View File

@ -48,7 +48,6 @@ from .exceptions import (
InvalidRouteError, InvalidRouteError,
InvalidInstanceIdError, InvalidInstanceIdError,
InvalidAMIIdError, InvalidAMIIdError,
MalformedAMIIdError,
InvalidAMIAttributeItemValueError, InvalidAMIAttributeItemValueError,
InvalidSnapshotIdError, InvalidSnapshotIdError,
InvalidVolumeIdError, InvalidVolumeIdError,
@ -68,8 +67,8 @@ from .exceptions import (
InvalidCustomerGatewayIdError, InvalidCustomerGatewayIdError,
RulesPerSecurityGroupLimitExceededError, RulesPerSecurityGroupLimitExceededError,
MotoNotImplementedError, MotoNotImplementedError,
FilterNotImplementedError FilterNotImplementedError,
) MalformedAMIIdError)
from .utils import ( from .utils import (
EC2_RESOURCE_TO_PREFIX, EC2_RESOURCE_TO_PREFIX,
EC2_PREFIX_TO_RESOURCE, EC2_PREFIX_TO_RESOURCE,
@ -1032,11 +1031,11 @@ class TagBackend(object):
class Ami(TaggedEC2Resource): class Ami(TaggedEC2Resource):
def __init__(self, ec2_backend, ami_id, instance=None, source_ami=None, def __init__(self, ec2_backend, ami_id, instance=None, source_ami=None,
name=None, description=None, owner_id=None, name=None, description=None, owner_id=111122223333,
public=False, virtualization_type=None, architecture=None, public=False, virtualization_type=None, architecture=None,
state='available', creation_date=None, platform=None, state='available', creation_date=None, platform=None,
image_type='machine', image_location=None, hypervisor=None, image_type='machine', image_location=None, hypervisor=None,
root_device_type=None, root_device_name=None, sriov='simple', root_device_type='standard', root_device_name='/dev/sda1', sriov='simple',
region_name='us-east-1a' region_name='us-east-1a'
): ):
self.ec2_backend = ec2_backend self.ec2_backend = ec2_backend
@ -1137,14 +1136,13 @@ class AmiBackend(object):
ami_id = ami['ami_id'] ami_id = ami['ami_id']
self.amis[ami_id] = Ami(self, **ami) self.amis[ami_id] = Ami(self, **ami)
def create_image(self, instance_id, name=None, description=None, def create_image(self, instance_id, name=None, description=None, context=None):
context=None):
# TODO: check that instance exists and pull info from it. # TODO: check that instance exists and pull info from it.
ami_id = random_ami_id() ami_id = random_ami_id()
instance = self.get_instance(instance_id) instance = self.get_instance(instance_id)
ami = Ami(self, ami_id, instance=instance, source_ami=None, ami = Ami(self, ami_id, instance=instance, source_ami=None,
name=name, description=description, name=name, description=description,
owner_id=context.get_current_user() if context else None) owner_id=context.get_current_user() if context else '111122223333')
self.amis[ami_id] = ami self.amis[ami_id] = ami
return ami return ami
@ -1161,6 +1159,17 @@ class AmiBackend(object):
context=None): context=None):
images = self.amis.values() images = self.amis.values()
if len(ami_ids):
# boto3 seems to default to just searching based on ami ids if that parameter is passed
# and if no images are found, it raises an errors
malformed_ami_ids = [ami_id for ami_id in ami_ids if not ami_id.startswith('ami-')]
if malformed_ami_ids:
raise MalformedAMIIdError(malformed_ami_ids)
images = [ami for ami in images if ami.id in ami_ids]
if len(images) == 0:
raise InvalidAMIIdError(ami_ids)
else:
# Limit images by launch permissions # Limit images by launch permissions
if exec_users: if exec_users:
tmp_images = [] tmp_images = []
@ -1179,18 +1188,10 @@ class AmiBackend(object):
owners)) owners))
images = [ami for ami in images if ami.owner_id in owners] images = [ami for ami in images if ami.owner_id in owners]
if ami_ids:
images = [ami for ami in images if ami.id in ami_ids]
if len(ami_ids) > len(images):
unknown_ids = set(ami_ids) - set(images)
for id in unknown_ids:
if not self.AMI_REGEX.match(id):
raise MalformedAMIIdError(id)
raise InvalidAMIIdError(unknown_ids)
# Generic filters # Generic filters
if filters: if filters:
return generic_filter(filters, images) return generic_filter(filters, images)
return images return images
def deregister_image(self, ami_id): def deregister_image(self, ami_id):

View File

@ -113,12 +113,12 @@ DESCRIBE_IMAGES_RESPONSE = """<DescribeImagesResponse xmlns="http://ec2.amazonaw
<rootDeviceName>{{ image.root_device_name }}</rootDeviceName> <rootDeviceName>{{ image.root_device_name }}</rootDeviceName>
<blockDeviceMapping> <blockDeviceMapping>
<item> <item>
<deviceName>/dev/sda1</deviceName> <deviceName>{{ image.root_device_name }}</deviceName>
<ebs> <ebs>
<snapshotId>{{ image.ebs_snapshot.id }}</snapshotId> <snapshotId>{{ image.ebs_snapshot.id }}</snapshotId>
<volumeSize>15</volumeSize> <volumeSize>15</volumeSize>
<deleteOnTermination>false</deleteOnTermination> <deleteOnTermination>false</deleteOnTermination>
<volumeType>standard</volumeType> <volumeType>{{ image.root_device_type }}</volumeType>
</ebs> </ebs>
</item> </item>
</blockDeviceMapping> </blockDeviceMapping>

View File

@ -1,16 +1,12 @@
from __future__ import unicode_literals from __future__ import unicode_literals
# Ensure 'assert_raises' context manager support for Python 2.6
import tests.backport_assert_raises # noqa
from nose.tools import assert_raises
import boto import boto
import boto3
import boto.ec2 import boto.ec2
import boto3 import boto3
from boto.exception import EC2ResponseError, EC2ResponseError from boto.exception import EC2ResponseError
from botocore.exceptions import ClientError from botocore.exceptions import ClientError
# Ensure 'assert_raises' context manager support for Python 2.6
import sure # noqa from nose.tools import assert_raises
from moto import mock_ec2_deprecated, mock_ec2 from moto import mock_ec2_deprecated, mock_ec2
from tests.helpers import requires_boto_gte from tests.helpers import requires_boto_gte
@ -19,6 +15,11 @@ from tests.helpers import requires_boto_gte
@mock_ec2_deprecated @mock_ec2_deprecated
def test_ami_create_and_delete(): def test_ami_create_and_delete():
conn = boto.connect_ec2('the_key', 'the_secret') conn = boto.connect_ec2('the_key', 'the_secret')
initial_volume_count = 34
conn.get_all_volumes().should.have.length_of(initial_volume_count)
conn.get_all_snapshots().should.have.length_of(initial_volume_count)
reservation = conn.run_instances('ami-1234abcd') reservation = conn.run_instances('ami-1234abcd')
instance = reservation.instances[0] instance = reservation.instances[0]
@ -33,33 +34,34 @@ def test_ami_create_and_delete():
image_id = conn.create_image(instance.id, "test-ami", "this is a test ami") image_id = conn.create_image(instance.id, "test-ami", "this is a test ami")
all_images = conn.get_all_images() all_images = conn.get_all_images()
image = all_images[0] set([i.id for i in all_images]).should.contain(image_id)
image.id.should.equal(image_id) retrieved_image = [i for i in all_images if i.id == image_id][0]
image.virtualization_type.should.equal(instance.virtualization_type)
image.architecture.should.equal(instance.architecture) retrieved_image.id.should.equal(image_id)
image.kernel_id.should.equal(instance.kernel) retrieved_image.virtualization_type.should.equal(instance.virtualization_type)
image.platform.should.equal(instance.platform) retrieved_image.architecture.should.equal(instance.architecture)
image.creationDate.should_not.be.none retrieved_image.kernel_id.should.equal(instance.kernel)
retrieved_image.platform.should.equal(instance.platform)
retrieved_image.creationDate.should_not.be.none
instance.terminate() instance.terminate()
# Validate auto-created volume and snapshot # Validate auto-created volume and snapshot
volumes = conn.get_all_volumes() volumes = conn.get_all_volumes()
volumes.should.have.length_of(1) volumes.should.have.length_of(initial_volume_count + 1)
volume = volumes[0]
snapshots = conn.get_all_snapshots() snapshots = conn.get_all_snapshots()
snapshots.should.have.length_of(1) snapshots.should.have.length_of(initial_volume_count + 1)
snapshot = snapshots[0]
image.block_device_mapping.current_value.snapshot_id.should.equal( retrieved_image_snapshot_id = retrieved_image.block_device_mapping.current_value.snapshot_id
snapshot.id) [s.id for s in snapshots].should.contain(retrieved_image_snapshot_id)
snapshot = [s for s in snapshots if s.id == retrieved_image_snapshot_id][0]
snapshot.description.should.equal( snapshot.description.should.equal(
"Auto-created snapshot for AMI {0}".format(image.id)) "Auto-created snapshot for AMI {0}".format(retrieved_image.id))
snapshot.volume_id.should.equal(volume.id) [v.id for v in volumes].should.contain(snapshot.volume_id)
# root device should be in AMI's block device mappings # root device should be in AMI's block device mappings
root_mapping = image.block_device_mapping.get(image.root_device_name) root_mapping = retrieved_image.block_device_mapping.get(retrieved_image.root_device_name)
root_mapping.should_not.be.none root_mapping.should_not.be.none
# Deregister # Deregister
@ -84,6 +86,11 @@ def test_ami_create_and_delete():
@mock_ec2_deprecated @mock_ec2_deprecated
def test_ami_copy(): def test_ami_copy():
conn = boto.ec2.connect_to_region("us-west-1") conn = boto.ec2.connect_to_region("us-west-1")
initial_volume_count = 34
conn.get_all_volumes().should.have.length_of(initial_volume_count)
conn.get_all_snapshots().should.have.length_of(initial_volume_count)
reservation = conn.run_instances('ami-1234abcd') reservation = conn.run_instances('ami-1234abcd')
instance = reservation.instances[0] instance = reservation.instances[0]
@ -96,7 +103,8 @@ def test_ami_copy():
# the image_id to fetch the full info. # the image_id to fetch the full info.
with assert_raises(EC2ResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
copy_image_ref = conn.copy_image( copy_image_ref = conn.copy_image(
source_image.region.name, source_image.id, "test-copy-ami", "this is a test copy ami", dry_run=True) source_image.region.name, source_image.id, "test-copy-ami", "this is a test copy ami",
dry_run=True)
ex.exception.error_code.should.equal('DryRunOperation') ex.exception.error_code.should.equal('DryRunOperation')
ex.exception.status.should.equal(400) ex.exception.status.should.equal(400)
ex.exception.message.should.equal( ex.exception.message.should.equal(
@ -115,8 +123,8 @@ def test_ami_copy():
copy_image.platform.should.equal(source_image.platform) copy_image.platform.should.equal(source_image.platform)
# Validate auto-created volume and snapshot # Validate auto-created volume and snapshot
conn.get_all_volumes().should.have.length_of(2) conn.get_all_volumes().should.have.length_of(initial_volume_count + 2)
conn.get_all_snapshots().should.have.length_of(2) conn.get_all_snapshots().should.have.length_of(initial_volume_count + 2)
copy_image.block_device_mapping.current_value.snapshot_id.should_not.equal( copy_image.block_device_mapping.current_value.snapshot_id.should_not.equal(
source_image.block_device_mapping.current_value.snapshot_id) source_image.block_device_mapping.current_value.snapshot_id)
@ -218,7 +226,8 @@ def test_ami_filters():
amis_by_architecture = conn.get_all_images( amis_by_architecture = conn.get_all_images(
filters={'architecture': 'x86_64'}) filters={'architecture': 'x86_64'})
set([ami.id for ami in amis_by_architecture]).should.equal(set([imageB.id])) set([ami.id for ami in amis_by_architecture]).should.contain(imageB.id)
len(amis_by_architecture).should.equal(35)
amis_by_kernel = conn.get_all_images(filters={'kernel-id': 'k-abcd1234'}) amis_by_kernel = conn.get_all_images(filters={'kernel-id': 'k-abcd1234'})
set([ami.id for ami in amis_by_kernel]).should.equal(set([imageB.id])) set([ami.id for ami in amis_by_kernel]).should.equal(set([imageB.id]))
@ -226,26 +235,32 @@ def test_ami_filters():
amis_by_virtualization = conn.get_all_images( amis_by_virtualization = conn.get_all_images(
filters={'virtualization-type': 'paravirtual'}) filters={'virtualization-type': 'paravirtual'})
set([ami.id for ami in amis_by_virtualization] set([ami.id for ami in amis_by_virtualization]
).should.equal(set([imageB.id])) ).should.contain(imageB.id)
len(amis_by_virtualization).should.equal(3)
amis_by_platform = conn.get_all_images(filters={'platform': 'windows'}) amis_by_platform = conn.get_all_images(filters={'platform': 'windows'})
set([ami.id for ami in amis_by_platform]).should.equal(set([imageA.id])) set([ami.id for ami in amis_by_platform]).should.contain(imageA.id)
len(amis_by_platform).should.equal(24)
amis_by_id = conn.get_all_images(filters={'image-id': imageA.id}) amis_by_id = conn.get_all_images(filters={'image-id': imageA.id})
set([ami.id for ami in amis_by_id]).should.equal(set([imageA.id])) set([ami.id for ami in amis_by_id]).should.equal(set([imageA.id]))
amis_by_state = conn.get_all_images(filters={'state': 'available'}) amis_by_state = conn.get_all_images(filters={'state': 'available'})
set([ami.id for ami in amis_by_state]).should.equal( ami_ids_by_state = [ami.id for ami in amis_by_state]
set([imageA.id, imageB.id])) ami_ids_by_state.should.contain(imageA.id)
ami_ids_by_state.should.contain(imageB.id)
len(amis_by_state).should.equal(36)
amis_by_name = conn.get_all_images(filters={'name': imageA.name}) amis_by_name = conn.get_all_images(filters={'name': imageA.name})
set([ami.id for ami in amis_by_name]).should.equal(set([imageA.id])) set([ami.id for ami in amis_by_name]).should.equal(set([imageA.id]))
amis_by_public = conn.get_all_images(filters={'is-public': True}) amis_by_public = conn.get_all_images(filters={'is-public': True})
set([ami.id for ami in amis_by_public]).should.equal(set([imageB.id])) set([ami.id for ami in amis_by_public]).should.contain(imageB.id)
len(amis_by_public).should.equal(35)
amis_by_nonpublic = conn.get_all_images(filters={'is-public': False}) amis_by_nonpublic = conn.get_all_images(filters={'is-public': False})
set([ami.id for ami in amis_by_nonpublic]).should.equal(set([imageA.id])) set([ami.id for ami in amis_by_nonpublic]).should.contain(imageA.id)
len(amis_by_nonpublic).should.equal(1)
@mock_ec2_deprecated @mock_ec2_deprecated
@ -428,7 +443,7 @@ def test_ami_attribute_user_permissions():
**REMOVE_USERS_ARGS).should_not.throw(EC2ResponseError) **REMOVE_USERS_ARGS).should_not.throw(EC2ResponseError)
@mock_ec2_deprecated @mock_ec2
def test_ami_describe_executable_users(): def test_ami_describe_executable_users():
conn = boto3.client('ec2', region_name='us-east-1') conn = boto3.client('ec2', region_name='us-east-1')
ec2 = boto3.resource('ec2', 'us-east-1') ec2 = boto3.resource('ec2', 'us-east-1')
@ -440,7 +455,6 @@ def test_ami_describe_executable_users():
image_id = conn.create_image(InstanceId=instance_id, image_id = conn.create_image(InstanceId=instance_id,
Name='TestImage', )['ImageId'] Name='TestImage', )['ImageId']
USER1 = '123456789011' USER1 = '123456789011'
ADD_USER_ARGS = {'ImageId': image_id, ADD_USER_ARGS = {'ImageId': image_id,
@ -461,7 +475,7 @@ def test_ami_describe_executable_users():
images[0]['ImageId'].should.equal(image_id) images[0]['ImageId'].should.equal(image_id)
@mock_ec2_deprecated @mock_ec2
def test_ami_describe_executable_users_negative(): def test_ami_describe_executable_users_negative():
conn = boto3.client('ec2', region_name='us-east-1') conn = boto3.client('ec2', region_name='us-east-1')
ec2 = boto3.resource('ec2', 'us-east-1') ec2 = boto3.resource('ec2', 'us-east-1')
@ -473,7 +487,6 @@ def test_ami_describe_executable_users_negative():
image_id = conn.create_image(InstanceId=instance_id, image_id = conn.create_image(InstanceId=instance_id,
Name='TestImage')['ImageId'] Name='TestImage')['ImageId']
USER1 = '123456789011' USER1 = '123456789011'
USER2 = '113355789012' USER2 = '113355789012'
@ -482,6 +495,7 @@ def test_ami_describe_executable_users_negative():
'OperationType': 'add', 'OperationType': 'add',
'UserIds': [USER1]} 'UserIds': [USER1]}
# Add users and get no images
# Add users and get no images # Add users and get no images
conn.modify_image_attribute(**ADD_USER_ARGS) conn.modify_image_attribute(**ADD_USER_ARGS)
@ -494,7 +508,7 @@ def test_ami_describe_executable_users_negative():
images.should.have.length_of(0) images.should.have.length_of(0)
@mock_ec2_deprecated @mock_ec2
def test_ami_describe_executable_users_and_filter(): def test_ami_describe_executable_users_and_filter():
conn = boto3.client('ec2', region_name='us-east-1') conn = boto3.client('ec2', region_name='us-east-1')
ec2 = boto3.resource('ec2', 'us-east-1') ec2 = boto3.resource('ec2', 'us-east-1')
@ -506,7 +520,6 @@ def test_ami_describe_executable_users_and_filter():
image_id = conn.create_image(InstanceId=instance_id, image_id = conn.create_image(InstanceId=instance_id,
Name='ImageToDelete', )['ImageId'] Name='ImageToDelete', )['ImageId']
USER1 = '123456789011' USER1 = '123456789011'
ADD_USER_ARGS = {'ImageId': image_id, ADD_USER_ARGS = {'ImageId': image_id,
@ -685,8 +698,13 @@ def test_ami_filter_wildcard():
ec2 = boto3.resource('ec2', region_name='us-west-1') ec2 = boto3.resource('ec2', region_name='us-west-1')
instance = ec2.create_instances(ImageId='ami-1234abcd', MinCount=1, MaxCount=1)[0] instance = ec2.create_instances(ImageId='ami-1234abcd', MinCount=1, MaxCount=1)[0]
image = instance.create_image(Name='test-image') image = instance.create_image(Name='test-image')
filter_result = list(ec2.images.filter(Owners=['111122223333'], Filters=[{'Name':'name', 'Values':['test*']}]))
assert filter_result == [image] # create an image with the same owner but will not match the filter
instance.create_image(Name='not-matching-image')
filter_result = list(
ec2.images.filter(Owners=['111122223333'], Filters=[{'Name': 'name', 'Values': ['test*']}]))
filter_result.should.equal([image])
@mock_ec2 @mock_ec2