Merge pull request #139 from kouk/backendaccess

general support for access to backend models
This commit is contained in:
Steve Pulec 2014-08-02 10:43:35 -04:00
commit d2fc7bb7f9
5 changed files with 102 additions and 40 deletions

View File

@ -25,3 +25,10 @@ BACKENDS = {
'sts': sts_backend,
'route53': route53_backend
}
def get_model(name):
for backend in BACKENDS.values():
models = getattr(backend.__class__, '__models__', {})
if name in models:
return getattr(backend, models[name])()

View File

@ -65,8 +65,28 @@ class MockAWS(object):
return wrapper
class BaseBackend(object):
class Model(type):
def __new__(self, clsname, bases, namespace):
cls = super(Model, self).__new__(self, clsname, bases, namespace)
cls.__models__ = {}
for name, value in namespace.iteritems():
model = getattr(value, "__returns_model__", False)
if model is not False:
cls.__models__[model] = name
for base in bases:
cls.__models__.update(getattr(base, "__models__", {}))
return cls
@staticmethod
def prop(model_name):
""" decorator to mark a class method as returning model values """
def dec(f):
f.__returns_model__ = model_name
return f
return dec
class BaseBackend(object):
def reset(self):
self.__dict__ = {}
self.__init__()

View File

@ -3,8 +3,11 @@ import itertools
from collections import defaultdict
from boto.ec2.instance import Instance as BotoInstance, Reservation
from boto.ec2.spotinstancerequest import SpotInstanceRequest as BotoSpotRequest
from boto.ec2.launchspecification import LaunchSpecification
from moto.core import BaseBackend
from moto.core.models import Model
from .exceptions import (
InvalidIdError,
DependencyViolationError,
@ -937,42 +940,46 @@ class VPCGatewayAttachmentBackend(object):
return attachment
class SpotInstanceRequest(object):
class SpotInstanceRequest(BotoSpotRequest):
def __init__(self, spot_request_id, price, image_id, type, valid_from,
valid_until, launch_group, availability_zone_group, key_name,
security_groups, user_data, instance_type, placement, kernel_id,
ramdisk_id, monitoring_enabled, subnet_id):
ramdisk_id, monitoring_enabled, subnet_id, **kwargs):
super(SpotInstanceRequest, self).__init__(**kwargs)
ls = LaunchSpecification()
self.launch_specification = ls
self.id = spot_request_id
self.state = "open"
self.price = price
self.image_id = image_id
self.type = type
self.valid_from = valid_from
self.valid_until = valid_until
self.launch_group = launch_group
self.availability_zone_group = availability_zone_group
self.key_name = key_name
self.user_data = user_data
self.instance_type = instance_type
self.placement = placement
self.kernel_id = kernel_id
self.ramdisk_id = ramdisk_id
self.monitoring_enabled = monitoring_enabled
self.subnet_id = subnet_id
self.user_data = user_data # NOT
ls.kernel = kernel_id
ls.ramdisk = ramdisk_id
ls.image_id = image_id
ls.key_name = key_name
ls.instance_type = instance_type
ls.placement = placement
ls.monitored = monitoring_enabled
ls.subnet_id = subnet_id
self.security_groups = []
if security_groups:
for group_name in security_groups:
group = ec2_backend.get_security_group_from_name(group_name)
if group:
self.security_groups.append(group)
ls.groups.append(group)
else:
# If not security groups, add the default
default_group = ec2_backend.get_security_group_from_name("default")
self.security_groups.append(default_group)
ls.groups.append(default_group)
class SpotRequestBackend(object):
__metaclass__ = Model
def __init__(self):
self.spot_instance_requests = {}
super(SpotRequestBackend, self).__init__()
@ -995,6 +1002,7 @@ class SpotRequestBackend(object):
requests.append(request)
return requests
@Model.prop('SpotInstanceRequest')
def describe_spot_instance_requests(self):
return self.spot_instance_requests.values()

View File

@ -95,27 +95,27 @@ REQUEST_SPOT_INSTANCES_TEMPLATE = """<RequestSpotInstancesResponse xmlns="http:/
</status>
<availabilityZoneGroup>{{ request.availability_zone_group }}</availabilityZoneGroup>
<launchSpecification>
<imageId>{{ request.image_id }}</imageId>
<keyName>{{ request.key_name }}</keyName>
<imageId>{{ request.launch_specification.image_id }}</imageId>
<keyName>{{ request.launch_specification.key_name }}</keyName>
<groupSet>
{% for group in request.security_groups %}
{% for group in request.launch_specification.groups %}
<item>
<groupId>{{ group.id }}</groupId>
<groupName>{{ group.name }}</groupName>
</item>
{% endfor %}
</groupSet>
<kernelId>{{ request.kernel_id }}</kernelId>
<ramdiskId>{{ request.ramdisk_id }}</ramdiskId>
<subnetId>{{ request.subnet_id }}</subnetId>
<instanceType>{{ request.instance_type }}</instanceType>
<kernelId>{{ request.launch_specification.kernel }}</kernelId>
<ramdiskId>{{ request.launch_specification.ramdisk }}</ramdiskId>
<subnetId>{{ request.launch_specification.subnet_id }}</subnetId>
<instanceType>{{ request.launch_specification.instance_type }}</instanceType>
<blockDeviceMapping/>
<monitoring>
<enabled>{{ request.monitoring_enabled }}</enabled>
<enabled>{{ request.launch_specification.monitored }}</enabled>
</monitoring>
<ebsOptimized>{{ request.ebs_optimized }}</ebsOptimized>
<ebsOptimized>{{ request.launch_specification.ebs_optimized }}</ebsOptimized>
<PlacementRequestType>
<availabilityZone>{{ request.placement }}</availabilityZone>
<availabilityZone>{{ request.launch_specification.placement }}</availabilityZone>
<groupName></groupName>
</PlacementRequestType>
</launchSpecification>
@ -151,36 +151,36 @@ DESCRIBE_SPOT_INSTANCES_TEMPLATE = """<DescribeSpotInstanceRequestsResponse xmln
<availabilityZoneGroup>{{ request.availability_zone_group }}</availabilityZoneGroup>
{% endif %}
<launchSpecification>
<imageId>{{ request.image_id }}</imageId>
{% if request.key_name %}
<keyName>{{ request.key_name }}</keyName>
<imageId>{{ request.launch_specification.image_id }}</imageId>
{% if request.launch_specification.key_name %}
<keyName>{{ request.launch_specification.key_name }}</keyName>
{% endif %}
<groupSet>
{% for group in request.security_groups %}
{% for group in request.launch_specification.groups %}
<item>
<groupId>{{ group.id }}</groupId>
<groupName>{{ group.name }}</groupName>
</item>
{% endfor %}
</groupSet>
{% if request.kernel_id %}
<kernelId>{{ request.kernel_id }}</kernelId>
{% if request.launch_specification.kernel %}
<kernelId>{{ request.launch_specification.kernel }}</kernelId>
{% endif %}
{% if request.ramdisk_id %}
<ramdiskId>{{ request.ramdisk_id }}</ramdiskId>
{% if request.launch_specification.ramdisk %}
<ramdiskId>{{ request.launch_specification.ramdisk }}</ramdiskId>
{% endif %}
{% if request.subnet_id %}
<subnetId>{{ request.subnet_id }}</subnetId>
{% if request.launch_specification.subnet_id %}
<subnetId>{{ request.launch_specification.subnet_id }}</subnetId>
{% endif %}
<instanceType>{{ request.instance_type }}</instanceType>
<instanceType>{{ request.launch_specification.instance_type }}</instanceType>
<blockDeviceMapping/>
<monitoring>
<enabled>{{ request.monitoring_enabled }}</enabled>
<enabled>{{ request.launch_specification.monitored }}</enabled>
</monitoring>
<ebsOptimized>{{ request.ebs_optimized }}</ebsOptimized>
{% if request.placement %}
<ebsOptimized>{{ request.launch_specification.ebs_optimized }}</ebsOptimized>
{% if request.launch_specification.placement %}
<PlacementRequestType>
<availabilityZone>{{ request.placement }}</availabilityZone>
<availabilityZone>{{ request.launch_specification.placement }}</availabilityZone>
<groupName></groupName>
</PlacementRequestType>
{% endif %}

View File

@ -4,6 +4,7 @@ import boto
import sure # noqa
from moto import mock_ec2
from moto.backends import get_model
from moto.core.utils import iso_8601_datetime
@ -97,3 +98,29 @@ def test_cancel_spot_instance_request():
requests = conn.get_all_spot_instance_requests()
requests.should.have.length_of(0)
@mock_ec2
def test_request_spot_instances_fulfilled():
"""
Test that moto correctly fullfills a spot instance request
"""
conn = boto.connect_ec2()
request = conn.request_spot_instances(
price=0.5, image_id='ami-abcd1234',
)
requests = conn.get_all_spot_instance_requests()
requests.should.have.length_of(1)
request = requests[0]
request.state.should.equal("open")
get_model('SpotInstanceRequest')[0].state = 'active'
requests = conn.get_all_spot_instance_requests()
requests.should.have.length_of(1)
request = requests[0]
request.state.should.equal("active")