adding owner id to amis v2 (#1331)

* Adding owner-id/OwnerId to the AMI classes to allow the value to be specified to test filtering images based on owner.

* Added default AMIs and filtering by owner-id

* Fixed some tests

* Fixed more random tests

* Updated MANIFEST

* .
This commit is contained in:
Terry Cain 2017-11-12 11:18:25 +00:00 committed by GitHub
parent 123f369e6e
commit bd8c1e4567
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 758 additions and 110 deletions

View File

@ -1,5 +1,6 @@
include README.md LICENSE AUTHORS.md
include requirements.txt requirements-dev.txt tox.ini
include moto/ec2/resources/instance_types.json
include moto/ec2/resources/amis.json
recursive-include moto/templates *
recursive-include tests *

View File

@ -19,10 +19,19 @@ class CloudFormationResponse(BaseResponse):
template_url_parts = urlparse(template_url)
if "localhost" in template_url:
bucket_name, key_name = template_url_parts.path.lstrip(
"/").split("/")
"/").split("/", 1)
else:
bucket_name = template_url_parts.netloc.split(".")[0]
key_name = template_url_parts.path.lstrip("/")
if template_url_parts.netloc.endswith('amazonaws.com') \
and template_url_parts.netloc.startswith('s3'):
# Handle when S3 url uses amazon url with bucket in path
# Also handles getting region as technically s3 is region'd
# region = template_url.netloc.split('.')[1]
bucket_name, key_name = template_url_parts.path.lstrip(
"/").split("/", 1)
else:
bucket_name = template_url_parts.netloc.split(".")[0]
key_name = template_url_parts.path.lstrip("/")
key = s3_backend.get_key(bucket_name, key_name)
return key.value.decode("utf-8")
@ -227,13 +236,13 @@ CREATE_STACK_RESPONSE_TEMPLATE = """<CreateStackResponse>
</CreateStackResponse>
"""
UPDATE_STACK_RESPONSE_TEMPLATE = """<UpdateStackResponse>
UPDATE_STACK_RESPONSE_TEMPLATE = """<UpdateStackResponse xmlns="http://cloudformation.amazonaws.com/doc/2010-05-15/">
<UpdateStackResult>
<StackId>{{ stack.stack_id }}</StackId>
</UpdateStackResult>
<ResponseMetadata>
<RequestId>b9b5b068-3a41-11e5-94eb-example</RequestId>
</ResponseMetadata>
<RequestId>b9b4b068-3a41-11e5-94eb-example</RequestId>
</ResponseMetadata>
</UpdateStackResponse>
"""
@ -399,16 +408,6 @@ GET_TEMPLATE_RESPONSE_TEMPLATE = """<GetTemplateResponse>
</GetTemplateResponse>"""
UPDATE_STACK_RESPONSE_TEMPLATE = """<UpdateStackResponse xmlns="http://cloudformation.amazonaws.com/doc/2010-05-15/">
<UpdateStackResult>
<StackId>{{ stack.stack_id }}</StackId>
</UpdateStackResult>
<ResponseMetadata>
<RequestId>b9b4b068-3a41-11e5-94eb-example</RequestId>
</ResponseMetadata>
</UpdateStackResponse>
"""
DELETE_STACK_RESPONSE_TEMPLATE = """<DeleteStackResponse>
<ResponseMetadata>
<RequestId>5ccc7dcd-744c-11e5-be70-example</RequestId>
@ -416,6 +415,7 @@ DELETE_STACK_RESPONSE_TEMPLATE = """<DeleteStackResponse>
</DeleteStackResponse>
"""
LIST_EXPORTS_RESPONSE = """<ListExportsResponse xmlns="http://cloudformation.amazonaws.com/doc/2010-05-15/">
<ListExportsResult>
<Exports>

View File

@ -6,6 +6,7 @@ import ipaddress
import json
import re
import six
import warnings
from pkg_resources import resource_filename
import boto.ec2
@ -45,7 +46,6 @@ from .exceptions import (
InvalidRouteTableIdError,
InvalidRouteError,
InvalidInstanceIdError,
MalformedAMIIdError,
InvalidAMIIdError,
InvalidAMIAttributeItemValueError,
InvalidSnapshotIdError,
@ -113,8 +113,12 @@ from .utils import (
tag_filter_matches,
)
RES_FILE = resource_filename(__name__, 'resources/instance_types.json')
INSTANCE_TYPES = json.load(open(RES_FILE, 'r'))
INSTANCE_TYPES = json.load(
open(resource_filename(__name__, 'resources/instance_types.json'), 'r')
)
AMIS = json.load(
open(resource_filename(__name__, 'resources/amis.json'), 'r')
)
def utc_date_and_time():
@ -384,6 +388,11 @@ class Instance(TaggedEC2Resource, BotoInstance):
amis = self.ec2_backend.describe_images(filters={'image-id': image_id})
ami = amis[0] if amis else None
if ami is None:
warnings.warn('Could not find AMI with image-id:{0}, '
'in the near future this will '
'cause an error'.format(image_id),
PendingDeprecationWarning)
self.platform = ami.platform if ami else None
self.virtualization_type = ami.virtualization_type if ami else 'paravirtual'
@ -1001,17 +1010,31 @@ class TagBackend(object):
class Ami(TaggedEC2Resource):
def __init__(self, ec2_backend, ami_id, instance=None, source_ami=None,
name=None, description=None):
name=None, description=None, owner_id=None,
public=False, virtualization_type=None, architecture=None,
state='available', creation_date=None, platform=None,
image_type='machine', image_location=None, hypervisor=None,
root_device_type=None, root_device_name=None, sriov='simple',
region_name='us-east-1a'
):
self.ec2_backend = ec2_backend
self.id = ami_id
self.state = "available"
self.state = state
self.name = name
self.image_type = image_type
self.image_location = image_location
self.owner_id = owner_id
self.description = description
self.virtualization_type = None
self.architecture = None
self.virtualization_type = virtualization_type
self.architecture = architecture
self.kernel_id = None
self.platform = None
self.creation_date = utc_date_and_time()
self.platform = platform
self.hypervisor = hypervisor
self.root_device_name = root_device_name
self.root_device_type = root_device_type
self.sriov = sriov
self.creation_date = utc_date_and_time() if creation_date is None else creation_date
if instance:
self.instance = instance
@ -1039,8 +1062,11 @@ class Ami(TaggedEC2Resource):
self.launch_permission_groups = set()
self.launch_permission_users = set()
if public:
self.launch_permission_groups.add('all')
# AWS auto-creates these, we should reflect the same.
volume = self.ec2_backend.create_volume(15, "us-east-1a")
volume = self.ec2_backend.create_volume(15, region_name)
self.ebs_snapshot = self.ec2_backend.create_snapshot(
volume.id, "Auto-created snapshot for AMI %s" % self.id)
@ -1067,6 +1093,8 @@ class Ami(TaggedEC2Resource):
return self.state
elif filter_name == 'name':
return self.name
elif filter_name == 'owner-id':
return self.owner_id
else:
return super(Ami, self).get_filter_value(
filter_name, 'DescribeImages')
@ -1075,14 +1103,22 @@ class Ami(TaggedEC2Resource):
class AmiBackend(object):
def __init__(self):
self.amis = {}
self._load_amis()
super(AmiBackend, self).__init__()
def create_image(self, instance_id, name=None, description=None):
def _load_amis(self):
for ami in AMIS:
ami_id = ami['ami_id']
self.amis[ami_id] = Ami(self, **ami)
def create_image(self, instance_id, name=None, description=None, owner_id=None):
# TODO: check that instance exists and pull info from it.
ami_id = random_ami_id()
instance = self.get_instance(instance_id)
ami = Ami(self, ami_id, instance=instance, source_ami=None,
name=name, description=description)
name=name, description=description, owner_id=owner_id)
self.amis[ami_id] = ami
return ami
@ -1095,30 +1131,29 @@ class AmiBackend(object):
self.amis[ami_id] = ami
return ami
def describe_images(self, ami_ids=(), filters=None, exec_users=None):
images = []
def describe_images(self, ami_ids=(), filters=None, exec_users=None, owners=None):
images = self.amis.values()
# Limit images by launch permissions
if exec_users:
for ami_id in self.amis:
found = False
tmp_images = []
for ami in images:
for user_id in exec_users:
if user_id in self.amis[ami_id].launch_permission_users:
found = True
if found:
images.append(self.amis[ami_id])
if images == []:
return images
if user_id in ami.launch_permission_users:
tmp_images.append(ami)
images = tmp_images
# Limit by owner ids
if 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]
# Generic filters
if filters:
images = images or self.amis.values()
return generic_filter(filters, images)
else:
for ami_id in ami_ids:
if ami_id in self.amis:
images.append(self.amis[ami_id])
elif not ami_id.startswith("ami-"):
raise MalformedAMIIdError(ami_id)
else:
raise InvalidAMIIdError(ami_id)
return images or self.amis.values()
return images
def deregister_image(self, ami_id):
if ami_id in self.amis:
@ -3679,8 +3714,8 @@ class NatGatewayBackend(object):
return self.nat_gateways.pop(nat_gateway_id)
class EC2Backend(BaseBackend, InstanceBackend, TagBackend, AmiBackend,
RegionsAndZonesBackend, SecurityGroupBackend, EBSBackend,
class EC2Backend(BaseBackend, InstanceBackend, TagBackend, EBSBackend,
RegionsAndZonesBackend, SecurityGroupBackend, AmiBackend,
VPCBackend, SubnetBackend, SubnetRouteTableAssociationBackend,
NetworkInterfaceBackend, VPNConnectionBackend,
VPCPeeringConnectionBackend,

View File

@ -0,0 +1,546 @@
[
{
"ami_id": "ami-03cf127a",
"state": "available",
"public": true,
"owner_id": "801119661308",
"sriov": "simple",
"root_device_type": "ebs",
"root_device_name": "/dev/sda1",
"description": "Microsoft Windows Server 2016 Nano Locale English AMI provided by Amazon",
"image_type": "machine",
"platform": "windows",
"architecture": "x86_64",
"name": "Windows_Server-2016-English-Nano-Base-2017.10.13",
"virtualization_type": "hvm",
"hypervisor": "xen"
},
{
"ami_id": "ami-12c6146b",
"state": "available",
"public": true,
"owner_id": "801119661308",
"sriov": "simple",
"root_device_type": "ebs",
"root_device_name": "/dev/sda1",
"description": "Microsoft Windows Server 2008 R2 SP1 Datacenter 64-bit Locale English Base AMI provided by Amazon",
"image_type": "machine",
"platform": "windows",
"architecture": "x86_64",
"name": "Windows_Server-2008-R2_SP1-English-64Bit-Base-2017.10.13",
"virtualization_type": "hvm",
"hypervisor": "xen"
},
{
"ami_id": "ami-1812c061",
"state": "available",
"public": true,
"owner_id": "801119661308",
"sriov": "simple",
"root_device_type": "ebs",
"root_device_name": "/dev/sda1",
"description": "Microsoft Windows Server 2016 Locale English with SQL Standard 2016 AMI provided by Amazon",
"image_type": "machine",
"platform": "windows",
"architecture": "x86_64",
"name": "Windows_Server-2016-English-Full-SQL_2016_SP1_Standard-2017.10.13",
"virtualization_type": "hvm",
"hypervisor": "xen"
},
{
"ami_id": "ami-1e749f67",
"state": "available",
"public": true,
"owner_id": "099720109477",
"sriov": "simple",
"root_device_type": "ebs",
"root_device_name": "/dev/sda1",
"description": "Canonical, Ubuntu, 14.04 LTS, amd64 trusty image build on 2017-07-27",
"image_type": "machine",
"platform": null,
"architecture": "x86_64",
"name": "ubuntu/images/hvm-ssd/ubuntu-trusty-14.04-amd64-server-20170727",
"virtualization_type": "hvm",
"hypervisor": "xen"
},
{
"ami_id": "ami-1ecc1e67",
"state": "available",
"public": true,
"owner_id": "801119661308",
"sriov": "simple",
"root_device_type": "ebs",
"root_device_name": "/dev/sda1",
"description": "Microsoft Windows Server 2012 R2 RTM 64-bit Locale English AMI provided by Amazon",
"image_type": "machine",
"platform": "windows",
"architecture": "x86_64",
"name": "Windows_Server-2012-R2_RTM-English-64Bit-Base-2017.10.13",
"virtualization_type": "hvm",
"hypervisor": "xen"
},
{
"ami_id": "ami-1f12c066",
"state": "available",
"public": true,
"owner_id": "801119661308",
"sriov": "simple",
"root_device_type": "ebs",
"root_device_name": "/dev/sda1",
"description": "Microsoft Windows Server 2016 Locale English with SQL Express 2016 AMI provided by Amazon",
"image_type": "machine",
"platform": "windows",
"architecture": "x86_64",
"name": "Windows_Server-2016-English-Full-SQL_2016_SP1_Express-2017.10.13",
"virtualization_type": "hvm",
"hypervisor": "xen"
},
{
"ami_id": "ami-24f3215d",
"state": "available",
"public": true,
"owner_id": "801119661308",
"sriov": "simple",
"root_device_type": "ebs",
"root_device_name": "/dev/sda1",
"description": "Microsoft Windows Server 2012 R2 RTM 64-bit Locale English with SQL Web 2014 AMI provided by Amazon",
"image_type": "machine",
"platform": "windows",
"architecture": "x86_64",
"name": "Windows_Server-2012-R2_RTM-English-64Bit-SQL_2014_SP2_Web-2017.10.13",
"virtualization_type": "hvm",
"hypervisor": "xen"
},
{
"ami_id": "ami-35e92e4c",
"state": "available",
"public": true,
"owner_id": "013907871322",
"sriov": "simple",
"root_device_type": "ebs",
"root_device_name": "/dev/sda1",
"description": "SUSE Linux Enterprise Server 12 SP3 (HVM, 64-bit, SSD-Backed)",
"image_type": "machine",
"platform": null,
"architecture": "x86_64",
"name": "suse-sles-12-sp3-v20170907-hvm-ssd-x86_64",
"virtualization_type": "hvm",
"hypervisor": "xen"
},
{
"ami_id": "ami-3bf32142",
"state": "available",
"public": true,
"owner_id": "801119661308",
"sriov": "simple",
"root_device_type": "ebs",
"root_device_name": "/dev/sda1",
"description": "Microsoft Windows Server 2012 R2 RTM 64-bit Locale English with SQL Express 2016 AMI provided by Amazon",
"image_type": "machine",
"platform": "windows",
"architecture": "x86_64",
"name": "Windows_Server-2012-R2_RTM-English-64Bit-SQL_2016_SP1_Express-2017.10.13",
"virtualization_type": "hvm",
"hypervisor": "xen"
},
{
"ami_id": "ami-3df32144",
"state": "available",
"public": true,
"owner_id": "801119661308",
"sriov": "simple",
"root_device_type": "ebs",
"root_device_name": "/dev/sda1",
"description": "Microsoft Windows Server 2012 R2 RTM 64-bit Locale English with SQL Enterprise 2016 AMI provided by Amazon",
"image_type": "machine",
"platform": "windows",
"architecture": "x86_64",
"name": "Windows_Server-2012-R2_RTM-English-64Bit-SQL_2016_SP1_Enterprise-2017.10.13",
"virtualization_type": "hvm",
"hypervisor": "xen"
},
{
"ami_id": "ami-56ec3e2f",
"state": "available",
"public": true,
"owner_id": "801119661308",
"sriov": "simple",
"root_device_type": "ebs",
"root_device_name": "/dev/sda1",
"description": "Microsoft Windows Server 2016 Locale English with SQL Express 2017 AMI provided by Amazon",
"image_type": "machine",
"platform": "windows",
"architecture": "x86_64",
"name": "Windows_Server-2016-English-Full-SQL_2017_Express-2017.10.13",
"virtualization_type": "hvm",
"hypervisor": "xen"
},
{
"ami_id": "ami-61db0918",
"state": "available",
"public": true,
"owner_id": "801119661308",
"sriov": "simple",
"root_device_type": "ebs",
"root_device_name": "/dev/sda1",
"description": "Microsoft Windows Server 2003 R2 SP2 Datacenter 64-bit Locale English Base AMI provided by Amazon",
"image_type": "machine",
"platform": "windows",
"architecture": "x86_64",
"name": "Windows_Server-2003-R2_SP2-English-64Bit-Base-2017.10.13",
"virtualization_type": "hvm",
"hypervisor": "xen"
},
{
"ami_id": "ami-6ef02217",
"state": "available",
"public": true,
"owner_id": "801119661308",
"sriov": "simple",
"root_device_type": "ebs",
"root_device_name": "/dev/sda1",
"description": "Microsoft Windows Server 2012 R2 RTM 64-bit Locale English with SQL Web 2016 AMI provided by Amazon",
"image_type": "machine",
"platform": "windows",
"architecture": "x86_64",
"name": "Windows_Server-2012-R2_RTM-English-64Bit-SQL_2016_SP1_Web-2017.10.13",
"virtualization_type": "hvm",
"hypervisor": "xen"
},
{
"ami_id": "ami-760aaa0f",
"state": "available",
"public": true,
"owner_id": "137112412989",
"sriov": "simple",
"root_device_type": "ebs",
"root_device_name": "/dev/xvda",
"description": "Amazon Linux AMI 2017.09.1.20171103 x86_64 HVM GP2",
"image_type": "machine",
"platform": null,
"architecture": "x86_64",
"name": "amzn-ami-hvm-2017.09.1.20171103-x86_64-gp2",
"virtualization_type": "hvm",
"hypervisor": "xen"
},
{
"ami_id": "ami-77ed3f0e",
"state": "available",
"public": true,
"owner_id": "801119661308",
"sriov": "simple",
"root_device_type": "ebs",
"root_device_name": "/dev/sda1",
"description": "Microsoft Windows Server 2016 Full Locale English with SQL Enterprise 2016 SP1 AMI provided by Amazon",
"image_type": "machine",
"platform": "windows",
"architecture": "x86_64",
"name": "Windows_Server-2016-English-Full-SQL_2016_SP1_Enterprise-2017.10.13",
"virtualization_type": "hvm",
"hypervisor": "xen"
},
{
"ami_id": "ami-785db401",
"state": "available",
"public": true,
"owner_id": "099720109477",
"sriov": "simple",
"root_device_type": "ebs",
"root_device_name": "/dev/sda1",
"description": "Canonical, Ubuntu, 16.04 LTS, amd64 xenial image build on 2017-07-21",
"image_type": "machine",
"platform": null,
"architecture": "x86_64",
"name": "ubuntu/images/hvm-ssd/ubuntu-xenial-16.04-amd64-server-20170721",
"virtualization_type": "hvm",
"hypervisor": "xen"
},
{
"ami_id": "ami-8104a4f8",
"state": "available",
"public": true,
"owner_id": "137112412989",
"sriov": "simple",
"root_device_type": "ebs",
"root_device_name": "/dev/sda1",
"description": "Amazon Linux AMI 2017.09.1.20171103 x86_64 PV EBS",
"image_type": "machine",
"platform": null,
"architecture": "x86_64",
"name": "amzn-ami-pv-2017.09.1.20171103-x86_64-ebs",
"virtualization_type": "paravirtual",
"hypervisor": "xen"
},
{
"ami_id": "ami-84ee3cfd",
"state": "available",
"public": true,
"owner_id": "801119661308",
"sriov": "simple",
"root_device_type": "ebs",
"root_device_name": "/dev/sda1",
"description": "Microsoft Windows Server 2016 Locale English with SQL Web 2017 AMI provided by Amazon",
"image_type": "machine",
"platform": "windows",
"architecture": "x86_64",
"name": "Windows_Server-2016-English-Full-SQL_2017_Web-2017.10.13",
"virtualization_type": "hvm",
"hypervisor": "xen"
},
{
"ami_id": "ami-86ee3cff",
"state": "available",
"public": true,
"owner_id": "801119661308",
"sriov": "simple",
"root_device_type": "ebs",
"root_device_name": "/dev/sda1",
"description": "Microsoft Windows Server 2016 Locale English with SQL Standard 2017 AMI provided by Amazon",
"image_type": "machine",
"platform": "windows",
"architecture": "x86_64",
"name": "Windows_Server-2016-English-Full-SQL_2017_Standard-2017.10.13",
"virtualization_type": "hvm",
"hypervisor": "xen"
},
{
"ami_id": "ami-999844e0",
"state": "available",
"public": true,
"owner_id": "898082745236",
"sriov": "simple",
"root_device_type": "ebs",
"root_device_name": "/dev/xvda",
"description": "Deep Learning on Amazon Linux with MXNet, Tensorflow, Caffe, Theano, Torch, CNTK and Keras",
"image_type": "machine",
"platform": null,
"architecture": "x86_64",
"name": "Deep Learning AMI Amazon Linux - 3.3_Oct2017",
"virtualization_type": "hvm",
"hypervisor": "xen"
},
{
"ami_id": "ami-9b32e8e2",
"state": "available",
"public": true,
"owner_id": "898082745236",
"sriov": "simple",
"root_device_type": "ebs",
"root_device_name": "/dev/sda1",
"description": "CUDA9 Classic Ubuntu DLAMI 1508914531",
"image_type": "machine",
"platform": null,
"architecture": "x86_64",
"name": "Ubuntu CUDA9 DLAMI with MXNet/TF/Caffe2",
"virtualization_type": "hvm",
"hypervisor": "xen"
},
{
"ami_id": "ami-a9cc1ed0",
"state": "available",
"public": true,
"owner_id": "801119661308",
"sriov": "simple",
"root_device_type": "ebs",
"root_device_name": "/dev/sda1",
"description": "Microsoft Windows Server 2012 R2 RTM 64-bit Locale English with SQL Standard 2014 AMI provided by Amazon",
"image_type": "machine",
"platform": "windows",
"architecture": "x86_64",
"name": "Windows_Server-2012-R2_RTM-English-64Bit-SQL_2014_SP2_Standard-2017.10.13",
"virtualization_type": "hvm",
"hypervisor": "xen"
},
{
"ami_id": "ami-afee3cd6",
"state": "available",
"public": true,
"owner_id": "801119661308",
"sriov": "simple",
"root_device_type": "ebs",
"root_device_name": "/dev/sda1",
"description": "Microsoft Windows Server 2016 Locale English with SQL Web 2016 SP1 AMI provided by Amazon",
"image_type": "machine",
"platform": "windows",
"architecture": "x86_64",
"name": "Windows_Server-2016-English-Full-SQL_2016_SP1_Web-2017.10.13",
"virtualization_type": "hvm",
"hypervisor": "xen"
},
{
"ami_id": "ami-b7e93bce",
"state": "available",
"public": true,
"owner_id": "801119661308",
"sriov": "simple",
"root_device_type": "ebs",
"root_device_name": "/dev/sda1",
"description": "Microsoft Windows Server 2016 with Desktop Experience Locale English AMI provided by Amazon",
"image_type": "machine",
"platform": "windows",
"architecture": "x86_64",
"name": "Windows_Server-2016-English-Full-Base-2017.10.13",
"virtualization_type": "hvm",
"hypervisor": "xen"
},
{
"ami_id": "ami-bb9a6bc2",
"state": "available",
"public": true,
"owner_id": "309956199498",
"sriov": "simple",
"root_device_type": "ebs",
"root_device_name": "/dev/sda1",
"description": "Provided by Red Hat, Inc.",
"image_type": "machine",
"platform": null,
"architecture": "x86_64",
"name": "RHEL-7.4_HVM_GA-20170808-x86_64-2-Hourly2-GP2",
"virtualization_type": "hvm",
"hypervisor": "xen"
},
{
"ami_id": "ami-bceb39c5",
"state": "available",
"public": true,
"owner_id": "801119661308",
"sriov": "simple",
"root_device_type": "ebs",
"root_device_name": "/dev/sda1",
"description": "Microsoft Windows Server 2016 with Containers Locale English AMI provided by Amazon",
"image_type": "machine",
"platform": "windows",
"architecture": "x86_64",
"name": "Windows_Server-2016-English-Full-Containers-2017.10.13",
"virtualization_type": "hvm",
"hypervisor": "xen"
},
{
"ami_id": "ami-c2ff2dbb",
"state": "available",
"public": true,
"owner_id": "801119661308",
"sriov": "simple",
"root_device_type": "ebs",
"root_device_name": "/dev/sda1",
"description": "Microsoft Windows Server 2012 RTM 64-bit Locale English Base AMI provided by Amazon",
"image_type": "machine",
"platform": "windows",
"architecture": "x86_64",
"name": "Windows_Server-2012-RTM-English-64Bit-Base-2017.10.13",
"virtualization_type": "hvm",
"hypervisor": "xen"
},
{
"ami_id": "ami-c6f321bf",
"state": "available",
"public": true,
"owner_id": "801119661308",
"sriov": "simple",
"root_device_type": "ebs",
"root_device_name": "/dev/sda1",
"description": "Microsoft Windows Server 2012 R2 RTM 64-bit Locale English with SQL Express 2014 AMI provided by Amazon",
"image_type": "machine",
"platform": "windows",
"architecture": "x86_64",
"name": "Windows_Server-2012-R2_RTM-English-64Bit-SQL_2014_SP2_Express-2017.10.13",
"virtualization_type": "hvm",
"hypervisor": "xen"
},
{
"ami_id": "ami-d1cb19a8",
"state": "available",
"public": true,
"owner_id": "801119661308",
"sriov": "simple",
"root_device_type": "ebs",
"root_device_name": "/dev/sda1",
"description": "Microsoft Windows Server 2008 SP2 Datacenter 64-bit Locale English Base AMI provided by Amazon",
"image_type": "machine",
"platform": "windows",
"architecture": "x86_64",
"name": "Windows_Server-2008-SP2-English-64Bit-Base-2017.10.13",
"virtualization_type": "hvm",
"hypervisor": "xen"
},
{
"ami_id": "ami-dca37ea5",
"state": "available",
"public": true,
"owner_id": "898082745236",
"sriov": "simple",
"root_device_type": "ebs",
"root_device_name": "/dev/sda1",
"description": "Deep Learning on Ubuntu Linux with MXNet, Tensorflow, Caffe, Theano, Torch, CNTK and Keras",
"image_type": "machine",
"platform": null,
"architecture": "x86_64",
"name": "Deep Learning AMI Ubuntu Linux - 2.4_Oct2017",
"virtualization_type": "hvm",
"hypervisor": "xen"
},
{
"ami_id": "ami-f0e83a89",
"state": "available",
"public": true,
"owner_id": "801119661308",
"sriov": "simple",
"root_device_type": "ebs",
"root_device_name": "/dev/sda1",
"description": "Microsoft Windows Server 2016 Locale English with SQL Enterprise 2017 AMI provided by Amazon",
"image_type": "machine",
"platform": "windows",
"architecture": "x86_64",
"name": "Windows_Server-2016-English-Full-SQL_2017_Enterprise-2017.10.13",
"virtualization_type": "hvm",
"hypervisor": "xen"
},
{
"ami_id": "ami-f4cf1d8d",
"state": "available",
"public": true,
"owner_id": "801119661308",
"sriov": "simple",
"root_device_type": "ebs",
"root_device_name": "/dev/sda1",
"description": "Microsoft Windows Server 2012 R2 RTM 64-bit Locale English with SQL Standard 2016 AMI provided by Amazon",
"image_type": "machine",
"platform": "windows",
"architecture": "x86_64",
"name": "Windows_Server-2012-R2_RTM-English-64Bit-SQL_2016_SP1_Standard-2017.10.13",
"virtualization_type": "hvm",
"hypervisor": "xen"
},
{
"ami_id": "ami-f8e54081",
"state": "available",
"public": true,
"owner_id": "898082745236",
"sriov": "simple",
"root_device_type": "ebs",
"root_device_name": "/dev/xvda",
"description": "CUDA9 Classic Amazon Linux DLAMI 1508914924",
"image_type": "machine",
"platform": null,
"architecture": "x86_64",
"name": "CUDA9ClassicAmazonLinuxDLAMIwithMXNetTensorflowandCaffe2 ",
"virtualization_type": "hvm",
"hypervisor": "xen"
},
{
"ami_id": "ami-fa7cdd89",
"state": "available",
"public": true,
"owner_id": "013907871322",
"sriov": "simple",
"root_device_type": "ebs",
"root_device_name": "/dev/sda",
"description": "SUSE Linux Enterprise Server 11 Service Pack 4 ((PV, 64-bit, SSD-Backed)",
"image_type": "machine",
"platform": null,
"architecture": "x86_64",
"name": "suse-sles-11-sp4-v20151207-pv-ssd-x86_64",
"virtualization_type": "paravirtual",
"hypervisor": "xen"
}
]

View File

@ -36,9 +36,10 @@ class AmisResponse(BaseResponse):
def describe_images(self):
ami_ids = self._get_multi_param('ImageId')
filters = filters_from_querystring(self.querystring)
owners = self._get_multi_param('Owner')
exec_users = self._get_multi_param('ExecutableBy')
images = self.ec2_backend.describe_images(
ami_ids=ami_ids, filters=filters, exec_users=exec_users)
ami_ids=ami_ids, filters=filters, exec_users=exec_users, owners=owners)
template = self.response_template(DESCRIBE_IMAGES_RESPONSE)
return template.render(images=images)
@ -92,12 +93,12 @@ DESCRIBE_IMAGES_RESPONSE = """<DescribeImagesResponse xmlns="http://ec2.amazonaw
{% for image in images %}
<item>
<imageId>{{ image.id }}</imageId>
<imageLocation>amazon/getting-started</imageLocation>
<imageLocation>{{ image.image_location }}</imageLocation>
<imageState>{{ image.state }}</imageState>
<imageOwnerId>123456789012</imageOwnerId>
<imageOwnerId>{{ image.owner_id }}</imageOwnerId>
<isPublic>{{ image.is_public_string }}</isPublic>
<architecture>{{ image.architecture }}</architecture>
<imageType>machine</imageType>
<imageType>{{ image.image_type }}</imageType>
<kernelId>{{ image.kernel_id }}</kernelId>
<ramdiskId>ari-1a2b3c4d</ramdiskId>
<imageOwnerAlias>amazon</imageOwnerAlias>
@ -107,8 +108,8 @@ DESCRIBE_IMAGES_RESPONSE = """<DescribeImagesResponse xmlns="http://ec2.amazonaw
<platform>{{ image.platform }}</platform>
{% endif %}
<description>{{ image.description }}</description>
<rootDeviceType>ebs</rootDeviceType>
<rootDeviceName>/dev/sda1</rootDeviceName>
<rootDeviceType>{{ image.root_device_type }}</rootDeviceType>
<rootDeviceName>{{ image.root_device_name }}</rootDeviceName>
<blockDeviceMapping>
<item>
<deviceName>/dev/sda1</deviceName>

View File

@ -34,6 +34,7 @@ class InstanceResponse(BaseResponse):
def run_instances(self):
min_count = int(self._get_param('MinCount', if_none='1'))
image_id = self._get_param('ImageId')
owner_id = self._get_param('OwnerId')
user_data = self._get_param('UserData')
security_group_names = self._get_multi_param('SecurityGroup')
security_group_ids = self._get_multi_param('SecurityGroupId')
@ -51,7 +52,7 @@ class InstanceResponse(BaseResponse):
new_reservation = self.ec2_backend.add_instances(
image_id, min_count, user_data, security_group_names,
instance_type=instance_type, placement=placement, region_name=region_name, subnet_id=subnet_id,
key_name=key_name, security_group_ids=security_group_ids,
owner_id=owner_id, key_name=key_name, security_group_ids=security_group_ids,
nics=nics, private_ip=private_ip, associate_public_ip=associate_public_ip,
tags=tags)

40
scripts/get_amis.py Normal file
View File

@ -0,0 +1,40 @@
import boto3
import json
# Taken from free tear list when creating an instance
instances = [
'ami-760aaa0f', 'ami-bb9a6bc2', 'ami-35e92e4c', 'ami-785db401', 'ami-b7e93bce', 'ami-dca37ea5', 'ami-999844e0',
'ami-9b32e8e2', 'ami-f8e54081', 'ami-bceb39c5', 'ami-03cf127a', 'ami-1ecc1e67', 'ami-c2ff2dbb', 'ami-12c6146b',
'ami-d1cb19a8', 'ami-61db0918', 'ami-56ec3e2f', 'ami-84ee3cfd', 'ami-86ee3cff', 'ami-f0e83a89', 'ami-1f12c066',
'ami-afee3cd6', 'ami-1812c061', 'ami-77ed3f0e', 'ami-3bf32142', 'ami-6ef02217', 'ami-f4cf1d8d', 'ami-3df32144',
'ami-c6f321bf', 'ami-24f3215d', 'ami-fa7cdd89', 'ami-1e749f67', 'ami-a9cc1ed0', 'ami-8104a4f8'
]
client = boto3.client('ec2', region_name='eu-west-1')
test = client.describe_images(ImageIds=instances)
result = []
for image in test['Images']:
try:
tmp = {
'ami_id': image['ImageId'],
'name': image['Name'],
'description': image['Description'],
'owner_id': image['OwnerId'],
'public': image['Public'],
'virtualization_type': image['VirtualizationType'],
'architecture': image['Architecture'],
'state': image['State'],
'platform': image.get('Platform'),
'image_type': image['ImageType'],
'hypervisor': image['Hypervisor'],
'root_device_name': image['RootDeviceName'],
'root_device_type': image['RootDeviceType'],
'sriov': image.get('SriovNetSupport', 'simple')
}
result.append(tmp)
except Exception as err:
pass
print(json.dumps(result, indent=2))

View File

@ -2260,7 +2260,9 @@ def test_stack_elbv2_resources_integration():
# test outputs
stacks = cfn_conn.describe_stacks(StackName='elb_stack')['Stacks']
len(stacks).should.equal(1)
stacks[0]['Outputs'].should.equal([
{'OutputKey': 'albdns', 'OutputValue': load_balancers[0]['DNSName']},
{'OutputKey': 'albname', 'OutputValue': load_balancers[0]['LoadBalancerName']},
])
dns = list(filter(lambda item: item['OutputKey'] == 'albdns', stacks[0]['Outputs']))[0]
name = list(filter(lambda item: item['OutputKey'] == 'albname', stacks[0]['Outputs']))[0]
dns['OutputValue'].should.equal(load_balancers[0]['DNSName'])
name['OutputValue'].should.equal(load_balancers[0]['LoadBalancerName'])

View File

@ -666,10 +666,6 @@ def test_ami_attribute_error_cases():
cm.exception.request_id.should_not.be.none
"""
Boto3
"""
@mock_ec2
def test_ami_filter_wildcard():
ec2 = boto3.resource('ec2', region_name='us-west-1')
@ -678,3 +674,20 @@ def test_ami_filter_wildcard():
filter_result = list(ec2.images.filter(Owners=['111122223333'], Filters=[{'Name':'name', 'Values':['test*']}]))
assert filter_result == [image]
@mock_ec2
def test_ami_filter_by_owner_id():
client = boto3.client('ec2', region_name='us-east-1')
ubuntu_id = '099720109477'
ubuntu_images = client.describe_images(Owners=[ubuntu_id])
all_images = client.describe_images()
ubuntu_ids = [ami['OwnerId'] for ami in ubuntu_images['Images']]
all_ids = [ami['OwnerId'] for ami in all_images['Images']]
# Assert all ubuntu_ids are the same and one equals ubuntu_id
assert all(ubuntu_ids) and ubuntu_ids[0] == ubuntu_id
# Check we actually have a subset of images
assert len(ubuntu_ids) < len(all_ids)

View File

@ -17,12 +17,14 @@ def test_create_and_delete_volume():
volume = conn.create_volume(80, "us-east-1a")
all_volumes = conn.get_all_volumes()
all_volumes.should.have.length_of(1)
all_volumes[0].size.should.equal(80)
all_volumes[0].zone.should.equal("us-east-1a")
all_volumes[0].encrypted.should.be(False)
volume = all_volumes[0]
current_volume = [item for item in all_volumes if item.id == volume.id]
current_volume.should.have.length_of(1)
current_volume[0].size.should.equal(80)
current_volume[0].zone.should.equal("us-east-1a")
current_volume[0].encrypted.should.be(False)
volume = current_volume[0]
with assert_raises(EC2ResponseError) as ex:
volume.delete(dry_run=True)
@ -33,7 +35,9 @@ def test_create_and_delete_volume():
volume.delete()
conn.get_all_volumes().should.have.length_of(0)
all_volumes = conn.get_all_volumes()
my_volume = [item for item in all_volumes if item.id == volume.id]
my_volume.should.have.length_of(0)
# Deleting something that was already deleted should throw an error
with assert_raises(EC2ResponseError) as cm:
@ -57,7 +61,7 @@ def test_create_encrypted_volume_dryrun():
@mock_ec2_deprecated
def test_create_encrypted_volume():
conn = boto.connect_ec2('the_key', 'the_secret')
conn.create_volume(80, "us-east-1a", encrypted=True)
volume = conn.create_volume(80, "us-east-1a", encrypted=True)
with assert_raises(EC2ResponseError) as ex:
conn.create_volume(80, "us-east-1a", encrypted=True, dry_run=True)
@ -66,7 +70,7 @@ def test_create_encrypted_volume():
ex.exception.message.should.equal(
'An error occurred (DryRunOperation) when calling the CreateVolume operation: Request would have succeeded, but DryRun flag is set')
all_volumes = conn.get_all_volumes()
all_volumes = [vol for vol in conn.get_all_volumes() if vol.id == volume.id]
all_volumes[0].encrypted.should.be(True)
@ -116,67 +120,69 @@ def test_volume_filters():
block_mapping = instance.block_device_mapping['/dev/sda1']
volume_ids = (volume1.id, volume2.id, volume3.id, volume4.id, block_mapping.volume_id)
volumes_by_attach_time = conn.get_all_volumes(
filters={'attachment.attach-time': block_mapping.attach_time})
set([vol.id for vol in volumes_by_attach_time]
).should.equal(set([block_mapping.volume_id]))
).should.equal({block_mapping.volume_id})
volumes_by_attach_device = conn.get_all_volumes(
filters={'attachment.device': '/dev/sda1'})
set([vol.id for vol in volumes_by_attach_device]
).should.equal(set([block_mapping.volume_id]))
).should.equal({block_mapping.volume_id})
volumes_by_attach_instance_id = conn.get_all_volumes(
filters={'attachment.instance-id': instance.id})
set([vol.id for vol in volumes_by_attach_instance_id]
).should.equal(set([block_mapping.volume_id]))
).should.equal({block_mapping.volume_id})
volumes_by_attach_status = conn.get_all_volumes(
filters={'attachment.status': 'attached'})
set([vol.id for vol in volumes_by_attach_status]
).should.equal(set([block_mapping.volume_id]))
).should.equal({block_mapping.volume_id})
volumes_by_create_time = conn.get_all_volumes(
filters={'create-time': volume4.create_time})
set([vol.create_time for vol in volumes_by_create_time]
).should.equal(set([volume4.create_time]))
).should.equal({volume4.create_time})
volumes_by_size = conn.get_all_volumes(filters={'size': volume2.size})
set([vol.id for vol in volumes_by_size]).should.equal(set([volume2.id]))
set([vol.id for vol in volumes_by_size]).should.equal({volume2.id})
volumes_by_snapshot_id = conn.get_all_volumes(
filters={'snapshot-id': snapshot.id})
set([vol.id for vol in volumes_by_snapshot_id]
).should.equal(set([volume4.id]))
).should.equal({volume4.id})
volumes_by_status = conn.get_all_volumes(filters={'status': 'in-use'})
set([vol.id for vol in volumes_by_status]).should.equal(
set([block_mapping.volume_id]))
{block_mapping.volume_id})
volumes_by_id = conn.get_all_volumes(filters={'volume-id': volume1.id})
set([vol.id for vol in volumes_by_id]).should.equal(set([volume1.id]))
set([vol.id for vol in volumes_by_id]).should.equal({volume1.id})
volumes_by_tag_key = conn.get_all_volumes(filters={'tag-key': 'testkey1'})
set([vol.id for vol in volumes_by_tag_key]).should.equal(set([volume1.id]))
set([vol.id for vol in volumes_by_tag_key]).should.equal({volume1.id})
volumes_by_tag_value = conn.get_all_volumes(
filters={'tag-value': 'testvalue1'})
set([vol.id for vol in volumes_by_tag_value]
).should.equal(set([volume1.id]))
).should.equal({volume1.id})
volumes_by_tag = conn.get_all_volumes(
filters={'tag:testkey1': 'testvalue1'})
set([vol.id for vol in volumes_by_tag]).should.equal(set([volume1.id]))
set([vol.id for vol in volumes_by_tag]).should.equal({volume1.id})
volumes_by_unencrypted = conn.get_all_volumes(
filters={'encrypted': 'false'})
set([vol.id for vol in volumes_by_unencrypted]).should.equal(
set([block_mapping.volume_id, volume2.id])
set([vol.id for vol in volumes_by_unencrypted if vol.id in volume_ids]).should.equal(
{block_mapping.volume_id, volume2.id}
)
volumes_by_encrypted = conn.get_all_volumes(filters={'encrypted': 'true'})
set([vol.id for vol in volumes_by_encrypted]).should.equal(
set([volume1.id, volume3.id, volume4.id])
set([vol.id for vol in volumes_by_encrypted if vol.id in volume_ids]).should.equal(
{volume1.id, volume3.id, volume4.id}
)
@ -252,18 +258,20 @@ def test_create_snapshot():
snapshot.update()
snapshot.status.should.equal('completed')
snapshots = conn.get_all_snapshots()
snapshots = [snap for snap in conn.get_all_snapshots() if snap.id == snapshot.id]
snapshots.should.have.length_of(1)
snapshots[0].description.should.equal('a test snapshot')
snapshots[0].start_time.should_not.be.none
snapshots[0].encrypted.should.be(False)
# Create snapshot without description
num_snapshots = len(conn.get_all_snapshots())
snapshot = volume.create_snapshot()
conn.get_all_snapshots().should.have.length_of(2)
conn.get_all_snapshots().should.have.length_of(num_snapshots + 1)
snapshot.delete()
conn.get_all_snapshots().should.have.length_of(1)
conn.get_all_snapshots().should.have.length_of(num_snapshots)
# Deleting something that was already deleted should throw an error
with assert_raises(EC2ResponseError) as cm:
@ -281,7 +289,7 @@ def test_create_encrypted_snapshot():
snapshot.update()
snapshot.status.should.equal('completed')
snapshots = conn.get_all_snapshots()
snapshots = [snap for snap in conn.get_all_snapshots() if snap.id == snapshot.id]
snapshots.should.have.length_of(1)
snapshots[0].description.should.equal('a test snapshot')
snapshots[0].start_time.should_not.be.none
@ -331,52 +339,52 @@ def test_snapshot_filters():
snapshots_by_description = conn.get_all_snapshots(
filters={'description': 'testsnapshot1'})
set([snap.id for snap in snapshots_by_description]
).should.equal(set([snapshot1.id]))
).should.equal({snapshot1.id})
snapshots_by_id = conn.get_all_snapshots(
filters={'snapshot-id': snapshot1.id})
set([snap.id for snap in snapshots_by_id]
).should.equal(set([snapshot1.id]))
).should.equal({snapshot1.id})
snapshots_by_start_time = conn.get_all_snapshots(
filters={'start-time': snapshot1.start_time})
set([snap.start_time for snap in snapshots_by_start_time]
).should.equal(set([snapshot1.start_time]))
).should.equal({snapshot1.start_time})
snapshots_by_volume_id = conn.get_all_snapshots(
filters={'volume-id': volume1.id})
set([snap.id for snap in snapshots_by_volume_id]
).should.equal(set([snapshot1.id, snapshot2.id]))
).should.equal({snapshot1.id, snapshot2.id})
snapshots_by_status = conn.get_all_snapshots(
filters={'status': 'completed'})
set([snap.id for snap in snapshots_by_status]
).should.equal(set([snapshot1.id, snapshot2.id, snapshot3.id]))
({snapshot1.id, snapshot2.id, snapshot3.id} -
{snap.id for snap in snapshots_by_status}).should.have.length_of(0)
snapshots_by_volume_size = conn.get_all_snapshots(
filters={'volume-size': volume1.size})
set([snap.id for snap in snapshots_by_volume_size]
).should.equal(set([snapshot1.id, snapshot2.id]))
).should.equal({snapshot1.id, snapshot2.id})
snapshots_by_tag_key = conn.get_all_snapshots(
filters={'tag-key': 'testkey1'})
set([snap.id for snap in snapshots_by_tag_key]
).should.equal(set([snapshot1.id]))
).should.equal({snapshot1.id})
snapshots_by_tag_value = conn.get_all_snapshots(
filters={'tag-value': 'testvalue1'})
set([snap.id for snap in snapshots_by_tag_value]
).should.equal(set([snapshot1.id]))
).should.equal({snapshot1.id})
snapshots_by_tag = conn.get_all_snapshots(
filters={'tag:testkey1': 'testvalue1'})
set([snap.id for snap in snapshots_by_tag]
).should.equal(set([snapshot1.id]))
).should.equal({snapshot1.id})
snapshots_by_encrypted = conn.get_all_snapshots(
filters={'encrypted': 'true'})
set([snap.id for snap in snapshots_by_encrypted]
).should.equal(set([snapshot3.id]))
).should.equal({snapshot3.id})
@mock_ec2_deprecated
@ -563,9 +571,11 @@ def test_volume_tag_escaping():
ex.exception.status.should.equal(400)
ex.exception.message.should.equal(
'An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set')
dict(conn.get_all_snapshots()[0].tags).should_not.be.equal(
snaps = [snap for snap in conn.get_all_snapshots() if snap.id == snapshot.id]
dict(snaps[0].tags).should_not.be.equal(
{'key': '</closed>'})
snapshot.add_tags({'key': '</closed>'})
dict(conn.get_all_snapshots()[0].tags).should.equal({'key': '</closed>'})
snaps = [snap for snap in conn.get_all_snapshots() if snap.id == snapshot.id]
dict(snaps[0].tags).should.equal({'key': '</closed>'})

View File

@ -217,7 +217,6 @@ def test_create_with_tags():
len(instances['Instances'][0]['Tags']).should.equal(3)
@mock_ec2_deprecated
def test_get_instances_filtering_by_state():
conn = boto.connect_ec2()

View File

@ -356,7 +356,7 @@ def test_retrieved_snapshots_must_contain_their_tags():
# Fetch the snapshot again
all_snapshots = conn.get_all_snapshots()
snapshot = all_snapshots[0]
snapshot = [item for item in all_snapshots if item.id == snapshot.id][0]
retrieved_tags = snapshot.tags
conn.delete_snapshot(snapshot.id)

View File

@ -19,4 +19,4 @@ def test_describe_clusters():
res = test_client.get('/?Action=DescribeClusters')
result = res.data.decode("utf-8")
result.should.contain("<DescribeClustersResponse><DescribeClustersResult><Clusters></Clusters></DescribeClustersResult")
result.should.contain("<Clusters></Clusters>")

View File

@ -1,5 +1,5 @@
[tox]
envlist = py26, py27, py33, py34
envlist = py27, py36
[testenv]
deps =