Get standalone server mode working for all tests.

This commit is contained in:
Steve Pulec 2017-02-23 19:43:48 -05:00
parent cb28eeefbb
commit 81836b6981
78 changed files with 934 additions and 760 deletions

View File

@ -8,6 +8,9 @@ Latest
* The normal @mock_<service> decorators will no longer work with boto. It is suggested that you upgrade to boto3 or use the standalone-server mode. If you would still like to use boto, you must use the @mock_<service>_deprecated decorators which will be removed in a future release. * The normal @mock_<service> decorators will no longer work with boto. It is suggested that you upgrade to boto3 or use the standalone-server mode. If you would still like to use boto, you must use the @mock_<service>_deprecated decorators which will be removed in a future release.
* The @mock_s3bucket_path decorator is now deprecated. Use the @mock_s3 decorator instead. * The @mock_s3bucket_path decorator is now deprecated. Use the @mock_s3 decorator instead.
Added
* Reset API: a reset API has been added to flush all of the current data ex: `requests.post("http://motoapi.amazonaws.com/moto-api/reset")`
0.4.31 0.4.31
------ ------

View File

@ -9,5 +9,8 @@ test:
rm -rf cover rm -rf cover
@nosetests -sv --with-coverage --cover-html ./tests/ @nosetests -sv --with-coverage --cover-html ./tests/
test_server:
@TEST_SERVER_MODE=true nosetests -sv --with-coverage --cover-html ./tests/
publish: publish:
python setup.py sdist bdist_wheel upload python setup.py sdist bdist_wheel upload

View File

@ -1,17 +1,16 @@
# Moto - Mock Boto # Moto - Mock AWS Services
[![Build Status](https://travis-ci.org/spulec/moto.png?branch=master)](https://travis-ci.org/spulec/moto) [![Build Status](https://travis-ci.org/spulec/moto.png?branch=master)](https://travis-ci.org/spulec/moto)
[![Coverage Status](https://coveralls.io/repos/spulec/moto/badge.png?branch=master)](https://coveralls.io/r/spulec/moto) [![Coverage Status](https://coveralls.io/repos/spulec/moto/badge.png?branch=master)](https://coveralls.io/r/spulec/moto)
# In a nutshell # In a nutshell
Moto is a library that allows your python tests to easily mock out the boto library. Moto is a library that allows your tests to easily mock out AWS Services.
Imagine you have the following code that you want to test: Imagine you have the following python code that you want to test:
```python ```python
import boto import boto3
from boto.s3.key import Key
class MyModel(object): class MyModel(object):
def __init__(self, name, value): def __init__(self, name, value):
@ -19,11 +18,9 @@ class MyModel(object):
self.value = value self.value = value
def save(self): def save(self):
conn = boto.connect_s3() s3 = boto3.client('s3', region_name='us-east-1')
bucket = conn.get_bucket('mybucket') s3.put_object(Bucket='mybucket', Key=self.name, Body=self.value)
k = Key(bucket)
k.key = self.name
k.set_contents_from_string(self.value)
``` ```
Take a minute to think how you would have tested that in the past. Take a minute to think how you would have tested that in the past.
@ -31,25 +28,28 @@ Take a minute to think how you would have tested that in the past.
Now see how you could test it with Moto: Now see how you could test it with Moto:
```python ```python
import boto import boto3
from moto import mock_s3 from moto import mock_s3
from mymodule import MyModel from mymodule import MyModel
@mock_s3 @mock_s3
def test_my_model_save(): def test_my_model_save():
conn = boto.connect_s3() conn = boto3.resource('s3', region_name='us-east-1')
# We need to create the bucket since this is all in Moto's 'virtual' AWS account # We need to create the bucket since this is all in Moto's 'virtual' AWS account
conn.create_bucket('mybucket') conn.create_bucket(Bucket='mybucket')
model_instance = MyModel('steve', 'is awesome') model_instance = MyModel('steve', 'is awesome')
model_instance.save() model_instance.save()
assert conn.get_bucket('mybucket').get_key('steve').get_contents_as_string() == 'is awesome' body = conn.Object('mybucket', 'steve').get()['Body'].read().decode("utf-8")
assert body == b'is awesome'
``` ```
With the decorator wrapping the test, all the calls to s3 are automatically mocked out. The mock keeps the state of the buckets and keys. With the decorator wrapping the test, all the calls to s3 are automatically mocked out. The mock keeps the state of the buckets and keys.
It gets even better! Moto isn't just S3. Here's the status of the other AWS services implemented. It gets even better! Moto isn't just for Python code and it isn't just for S3. Look at the [standalone server mode](https://github.com/spulec/moto#stand-alone-server-mode) for more information about running Moto with other languages. Here's the status of the other AWS services implemented:
```gherkin ```gherkin
|------------------------------------------------------------------------------| |------------------------------------------------------------------------------|
@ -193,11 +193,6 @@ def test_my_model_save():
mock.stop() mock.stop()
``` ```
## Use with other libraries (boto3) or languages
In general, Moto doesn't rely on anything specific to Boto. It only mocks AWS endpoints, so there should be no issue with boto3 or using other languages. Feel free to open an issue if something isn't working though. If you are using another language, you will need to either use the stand-alone server mode (more below) or monkey patch the HTTP calls yourself.
## Stand-alone Server Mode ## Stand-alone Server Mode
Moto also has a stand-alone server mode. This allows you to utilize Moto also has a stand-alone server mode. This allows you to utilize

View File

@ -326,8 +326,8 @@ class RestAPI(object):
return status_code, {}, response return status_code, {}, response
def update_integration_mocks(self, stage_name): def update_integration_mocks(self, stage_name):
stage_url = STAGE_URL.format(api_id=self.id, region_name=self.region_name, stage_name=stage_name) stage_url = STAGE_URL.format(api_id=self.id.upper(), region_name=self.region_name, stage_name=stage_name)
responses.add_callback(responses.GET, stage_url.lower(), callback=self.resource_callback) responses.add_callback(responses.GET, stage_url, callback=self.resource_callback)
def create_stage(self, name, deployment_id,variables=None,description='',cacheClusterEnabled=None,cacheClusterSize=None): def create_stage(self, name, deployment_id,variables=None,description='',cacheClusterEnabled=None,cacheClusterSize=None):
if variables is None: if variables is None:

View File

@ -154,15 +154,15 @@ class LambdaFunction(object):
sys.stderr = sys.__stderr__ sys.stderr = sys.__stderr__
return self.convert(result) return self.convert(result)
def invoke(self, request, headers): def invoke(self, body, request_headers, response_headers):
payload = dict() payload = dict()
# Get the invocation type: # Get the invocation type:
r = self._invoke_lambda(code=self.code, event=request.body) r = self._invoke_lambda(code=self.code, event=body)
if request.headers.get("x-amz-invocation-type") == "RequestResponse": if request_headers.get("x-amz-invocation-type") == "RequestResponse":
encoded = base64.b64encode(r.encode('utf-8')) encoded = base64.b64encode(r.encode('utf-8'))
headers["x-amz-log-result"] = encoded.decode('utf-8') response_headers["x-amz-log-result"] = encoded.decode('utf-8')
payload['result'] = headers["x-amz-log-result"] payload['result'] = response_headers["x-amz-log-result"]
result = r.encode('utf-8') result = r.encode('utf-8')
else: else:
result = json.dumps(payload) result = json.dumps(payload)

View File

@ -10,32 +10,32 @@ from .models import lambda_backends
class LambdaResponse(BaseResponse): class LambdaResponse(BaseResponse):
@classmethod def root(self, request, full_url, headers):
def root(cls, request, full_url, headers): self.setup_class(request, full_url, headers)
if request.method == 'GET': if request.method == 'GET':
return cls()._list_functions(request, full_url, headers) return self._list_functions(request, full_url, headers)
elif request.method == 'POST': elif request.method == 'POST':
return cls()._create_function(request, full_url, headers) return self._create_function(request, full_url, headers)
else: else:
raise ValueError("Cannot handle request") raise ValueError("Cannot handle request")
@classmethod def function(self, request, full_url, headers):
def function(cls, request, full_url, headers): self.setup_class(request, full_url, headers)
if request.method == 'GET': if request.method == 'GET':
return cls()._get_function(request, full_url, headers) return self._get_function(request, full_url, headers)
elif request.method == 'DELETE': elif request.method == 'DELETE':
return cls()._delete_function(request, full_url, headers) return self._delete_function(request, full_url, headers)
else: else:
raise ValueError("Cannot handle request") raise ValueError("Cannot handle request")
@classmethod def invoke(self, request, full_url, headers):
def invoke(cls, request, full_url, headers): self.setup_class(request, full_url, headers)
if request.method == 'POST': if request.method == 'POST':
return cls()._invoke(request, full_url, headers) return self._invoke(request, full_url)
else: else:
raise ValueError("Cannot handle request") raise ValueError("Cannot handle request")
def _invoke(self, request, full_url, headers): def _invoke(self, request, full_url):
response_headers = {} response_headers = {}
lambda_backend = self.get_lambda_backend(full_url) lambda_backend = self.get_lambda_backend(full_url)
@ -44,7 +44,7 @@ class LambdaResponse(BaseResponse):
if lambda_backend.has_function(function_name): if lambda_backend.has_function(function_name):
fn = lambda_backend.get_function(function_name) fn = lambda_backend.get_function(function_name)
payload = fn.invoke(request, response_headers) payload = fn.invoke(self.body, self.headers, response_headers)
response_headers['Content-Length'] = str(len(payload)) response_headers['Content-Length'] = str(len(payload))
return 202, response_headers, payload return 202, response_headers, payload
else: else:
@ -59,7 +59,7 @@ class LambdaResponse(BaseResponse):
def _create_function(self, request, full_url, headers): def _create_function(self, request, full_url, headers):
lambda_backend = self.get_lambda_backend(full_url) lambda_backend = self.get_lambda_backend(full_url)
spec = json.loads(request.body.decode('utf-8')) spec = json.loads(self.body.decode('utf-8'))
try: try:
fn = lambda_backend.create_function(spec) fn = lambda_backend.create_function(spec)
except ValueError as e: except ValueError as e:

View File

@ -5,9 +5,10 @@ url_bases = [
"https?://lambda.(.+).amazonaws.com", "https?://lambda.(.+).amazonaws.com",
] ]
response = LambdaResponse()
url_paths = { url_paths = {
# double curly braces because the `format()` method is called on the strings '{0}/(?P<api_version>[^/]+)/functions/?$': response.root,
'{0}/\d{{4}}-\d{{2}}-\d{{2}}/functions/?$': LambdaResponse.root, '{0}/(?P<api_version>[^/]+)/functions/(?P<function_name>[\w_-]+)/?$': response.function,
'{0}/\d{{4}}-\d{{2}}-\d{{2}}/functions/(?P<function_name>[\w_-]+)/?$': LambdaResponse.function, '{0}/(?P<api_version>[^/]+)/functions/(?P<function_name>[\w_-]+)/invocations/?$': response.invoke,
'{0}/\d{{4}}-\d{{2}}-\d{{2}}/functions/(?P<function_name>[\w_-]+)/invocations?$': LambdaResponse.invoke,
} }

View File

@ -1,67 +1,71 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from moto.apigateway import apigateway_backend from moto.apigateway import apigateway_backends
from moto.autoscaling import autoscaling_backend from moto.autoscaling import autoscaling_backends
from moto.awslambda import lambda_backend from moto.awslambda import lambda_backends
from moto.cloudformation import cloudformation_backend from moto.cloudformation import cloudformation_backends
from moto.cloudwatch import cloudwatch_backend from moto.cloudwatch import cloudwatch_backends
from moto.core import moto_api_backend from moto.core import moto_api_backends
from moto.datapipeline import datapipeline_backend from moto.datapipeline import datapipeline_backends
from moto.dynamodb import dynamodb_backend from moto.dynamodb import dynamodb_backends
from moto.dynamodb2 import dynamodb_backend2 from moto.dynamodb2 import dynamodb_backends2
from moto.ec2 import ec2_backend from moto.ec2 import ec2_backends
from moto.ecs import ecs_backend from moto.ecs import ecs_backends
from moto.elb import elb_backend from moto.elb import elb_backends
from moto.emr import emr_backend from moto.emr import emr_backends
from moto.events import events_backend from moto.events import events_backends
from moto.glacier import glacier_backend from moto.glacier import glacier_backends
from moto.iam import iam_backend from moto.iam import iam_backends
from moto.kinesis import kinesis_backend from moto.instance_metadata import instance_metadata_backends
from moto.kms import kms_backend from moto.kinesis import kinesis_backends
from moto.opsworks import opsworks_backend from moto.kms import kms_backends
from moto.rds import rds_backend from moto.opsworks import opsworks_backends
from moto.redshift import redshift_backend from moto.rds2 import rds2_backends
from moto.route53 import route53_backend from moto.redshift import redshift_backends
from moto.s3 import s3_backend from moto.route53 import route53_backends
from moto.ses import ses_backend from moto.s3 import s3_backends
from moto.sns import sns_backend from moto.ses import ses_backends
from moto.sqs import sqs_backend from moto.sns import sns_backends
from moto.sts import sts_backend from moto.sqs import sqs_backends
from moto.sts import sts_backends
BACKENDS = { BACKENDS = {
'apigateway': apigateway_backend, 'apigateway': apigateway_backends,
'autoscaling': autoscaling_backend, 'autoscaling': autoscaling_backends,
'cloudformation': cloudformation_backend, 'cloudformation': cloudformation_backends,
'cloudwatch': cloudwatch_backend, 'cloudwatch': cloudwatch_backends,
'datapipeline': datapipeline_backend, 'datapipeline': datapipeline_backends,
'dynamodb': dynamodb_backend, 'dynamodb': dynamodb_backends,
'dynamodb2': dynamodb_backend2, 'dynamodb2': dynamodb_backends2,
'ec2': ec2_backend, 'ec2': ec2_backends,
'ecs': ecs_backend, 'ecs': ecs_backends,
'elb': elb_backend, 'elb': elb_backends,
'events': events_backend, 'events': events_backends,
'emr': emr_backend, 'emr': emr_backends,
'glacier': glacier_backend, 'glacier': glacier_backends,
'iam': iam_backend, 'iam': iam_backends,
'moto_api': moto_api_backend, 'moto_api': moto_api_backends,
'opsworks': opsworks_backend, 'instance_metadata': instance_metadata_backends,
'kinesis': kinesis_backend, 'opsworks': opsworks_backends,
'kms': kms_backend, 'kinesis': kinesis_backends,
'redshift': redshift_backend, 'kms': kms_backends,
'rds': rds_backend, 'redshift': redshift_backends,
's3': s3_backend, 'rds': rds2_backends,
's3bucket_path': s3_backend, 's3': s3_backends,
'ses': ses_backend, 's3bucket_path': s3_backends,
'sns': sns_backend, 'ses': ses_backends,
'sqs': sqs_backend, 'sns': sns_backends,
'sts': sts_backend, 'sqs': sqs_backends,
'route53': route53_backend, 'sts': sts_backends,
'lambda': lambda_backend, 'route53': route53_backends,
'lambda': lambda_backends,
} }
def get_model(name): def get_model(name, region):
for backend in BACKENDS.values(): for backends in BACKENDS.values():
for region, backend in backends.items():
if region == region:
models = getattr(backend.__class__, '__models__', {}) models = getattr(backend.__class__, '__models__', {})
if name in models: if name in models:
return list(getattr(backend, models[name])()) return list(getattr(backend, models[name])())

View File

@ -17,6 +17,9 @@ class CloudFormationResponse(BaseResponse):
def _get_stack_from_s3_url(self, template_url): def _get_stack_from_s3_url(self, template_url):
template_url_parts = urlparse(template_url) template_url_parts = urlparse(template_url)
if "localhost" in template_url:
bucket_name, key_name = template_url_parts.path.lstrip("/").split("/")
else:
bucket_name = template_url_parts.netloc.split(".")[0] bucket_name = template_url_parts.netloc.split(".")[0]
key_name = template_url_parts.path.lstrip("/") key_name = template_url_parts.path.lstrip("/")

View File

@ -1,2 +1,4 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from .models import BaseBackend, moto_api_backend # flake8: noqa from .models import BaseBackend, moto_api_backend # flake8: noqa
moto_api_backends = {"global": moto_api_backend}

View File

@ -1,3 +1,5 @@
from __future__ import unicode_literals
from werkzeug.exceptions import HTTPException from werkzeug.exceptions import HTTPException
from jinja2 import DictLoader, Environment from jinja2 import DictLoader, Environment
from six import text_type from six import text_type
@ -47,6 +49,10 @@ class RESTError(HTTPException):
error_type=error_type, message=message, **kwargs) error_type=error_type, message=message, **kwargs)
class DryRunClientError(RESTError):
code = 400
class JsonRESTError(RESTError): class JsonRESTError(RESTError):
def __init__(self, error_type, message, template='error_json', **kwargs): def __init__(self, error_type, message, template='error_json', **kwargs):
super(JsonRESTError, self).__init__(error_type, message, template, **kwargs) super(JsonRESTError, self).__init__(error_type, message, template, **kwargs)

View File

@ -6,9 +6,9 @@ import inspect
import os import os
import re import re
from moto import settings
from moto.packages.responses import responses from moto.packages.responses import responses
from moto.packages.httpretty import HTTPretty from moto.packages.httpretty import HTTPretty
from .responses import metadata_response
from .utils import ( from .utils import (
convert_httpretty_response, convert_httpretty_response,
convert_regex_to_flask_path, convert_regex_to_flask_path,
@ -21,6 +21,15 @@ class BaseMockAWS(object):
def __init__(self, backends): def __init__(self, backends):
self.backends = backends self.backends = backends
self.backends_for_urls = {}
from moto.backends import BACKENDS
default_backends = {
"instance_metadata": BACKENDS['instance_metadata']['global'],
"moto_api": BACKENDS['moto_api']['global'],
}
self.backends_for_urls.update(self.backends)
self.backends_for_urls.update(default_backends)
if self.__class__.nested_count == 0: if self.__class__.nested_count == 0:
self.reset() self.reset()
@ -95,7 +104,7 @@ class HttprettyMockAWS(BaseMockAWS):
HTTPretty.enable() HTTPretty.enable()
for method in HTTPretty.METHODS: for method in HTTPretty.METHODS:
backend = list(self.backends.values())[0] for backend in self.backends_for_urls.values():
for key, value in backend.urls.items(): for key, value in backend.urls.items():
HTTPretty.register_uri( HTTPretty.register_uri(
method=method, method=method,
@ -103,13 +112,6 @@ class HttprettyMockAWS(BaseMockAWS):
body=convert_httpretty_response(value), body=convert_httpretty_response(value),
) )
# Mock out localhost instance metadata
HTTPretty.register_uri(
method=method,
uri=re.compile('http://169.254.169.254/latest/meta-data/.*'),
body=convert_httpretty_response(metadata_response),
)
def disable_patching(self): def disable_patching(self):
HTTPretty.disable() HTTPretty.disable()
HTTPretty.reset() HTTPretty.reset()
@ -126,7 +128,7 @@ class ResponsesMockAWS(BaseMockAWS):
def enable_patching(self): def enable_patching(self):
responses.start() responses.start()
for method in RESPONSES_METHODS: for method in RESPONSES_METHODS:
backend = list(self.backends.values())[0] for backend in self.backends_for_urls.values():
for key, value in backend.urls.items(): for key, value in backend.urls.items():
responses.add_callback( responses.add_callback(
method=method, method=method,
@ -134,12 +136,6 @@ class ResponsesMockAWS(BaseMockAWS):
callback=convert_flask_to_responses_response(value), callback=convert_flask_to_responses_response(value),
) )
# Mock out localhost instance metadata
responses.add_callback(
method=method,
url=re.compile('http://169.254.169.254/latest/meta-data/.*'),
callback=convert_flask_to_responses_response(metadata_response),
)
for pattern in responses.mock._urls: for pattern in responses.mock._urls:
pattern['stream'] = True pattern['stream'] = True
@ -270,10 +266,15 @@ class BaseBackend(object):
return paths return paths
def decorator(self, func=None): def decorator(self, func=None):
if func: if settings.TEST_SERVER_MODE:
return MockAWS({'global': self})(func) mocked_backend = ServerModeMockAWS({'global': self})
else: else:
return MockAWS({'global': self}) mocked_backend = MockAWS({'global': self})
if func:
return mocked_backend(func)
else:
return mocked_backend
def deprecated_decorator(self, func=None): def deprecated_decorator(self, func=None):
if func: if func:
@ -289,13 +290,15 @@ class base_decorator(object):
self.backends = backends self.backends = backends
def __call__(self, func=None): def __call__(self, func=None):
if self.mock_backend == MockAWS and os.environ.get('TEST_SERVER_MODE', '0').lower() == 'true': if self.mock_backend != HttprettyMockAWS and settings.TEST_SERVER_MODE:
self.mock_backend = ServerModeMockAWS mocked_backend = ServerModeMockAWS(self.backends)
else:
mocked_backend = self.mock_backend(self.backends)
if func: if func:
return self.mock_backend(self.backends)(func) return mocked_backend(func)
else: else:
return self.mock_backend(self.backends) return mocked_backend
class deprecated_base_decorator(base_decorator): class deprecated_base_decorator(base_decorator):
@ -303,14 +306,12 @@ class deprecated_base_decorator(base_decorator):
class MotoAPIBackend(BaseBackend): class MotoAPIBackend(BaseBackend):
def __init__(self):
super(MotoAPIBackend, self).__init__()
def reset(self): def reset(self):
from moto.backends import BACKENDS from moto.backends import BACKENDS
for name, backend in BACKENDS.items(): for name, backends in BACKENDS.items():
if name == "moto_api": if name == "moto_api":
continue continue
for region_name, backend in backends.items():
backend.reset() backend.reset()
self.__init__() self.__init__()

View File

@ -5,7 +5,7 @@ import logging
import re import re
import pytz import pytz
from boto.exception import JSONResponseError from moto.core.exceptions import DryRunClientError
from jinja2 import Environment, DictLoader, TemplateNotFound from jinja2 import Environment, DictLoader, TemplateNotFound
@ -149,17 +149,19 @@ class BaseResponse(_TemplateEnvironmentMixin):
self.path = urlparse(full_url).path self.path = urlparse(full_url).path
self.querystring = querystring self.querystring = querystring
self.method = request.method self.method = request.method
self.region = self.get_region_from_url(full_url) self.region = self.get_region_from_url(request, full_url)
self.headers = request.headers self.headers = request.headers
if 'host' not in self.headers: if 'host' not in self.headers:
self.headers['host'] = urlparse(full_url).netloc self.headers['host'] = urlparse(full_url).netloc
self.response_headers = {"server": "amazon.com"} self.response_headers = {"server": "amazon.com"}
def get_region_from_url(self, full_url): def get_region_from_url(self, request, full_url):
match = re.search(self.region_regex, full_url) match = re.search(self.region_regex, full_url)
if match: if match:
region = match.group(1) region = match.group(1)
elif 'Authorization' in request.headers:
region = request.headers['Authorization'].split(",")[0].split("/")[2]
else: else:
region = self.default_region region = self.default_region
return region return region
@ -195,6 +197,7 @@ class BaseResponse(_TemplateEnvironmentMixin):
if "status" in headers: if "status" in headers:
headers['status'] = str(headers['status']) headers['status'] = str(headers['status'])
return status, headers, body return status, headers, body
raise NotImplementedError("The {0} action has not been implemented".format(action)) raise NotImplementedError("The {0} action has not been implemented".format(action))
def _get_param(self, param_name, if_none=None): def _get_param(self, param_name, if_none=None):
@ -323,55 +326,19 @@ class BaseResponse(_TemplateEnvironmentMixin):
def is_not_dryrun(self, action): def is_not_dryrun(self, action):
if 'true' in self.querystring.get('DryRun', ['false']): if 'true' in self.querystring.get('DryRun', ['false']):
raise JSONResponseError(400, 'DryRunOperation', body={'message': 'An error occurred (DryRunOperation) when calling the %s operation: Request would have succeeded, but DryRun flag is set' % action}) message = 'An error occurred (DryRunOperation) when calling the %s operation: Request would have succeeded, but DryRun flag is set' % action
raise DryRunClientError(error_type="DryRunOperation", message=message)
return True return True
def metadata_response(request, full_url, headers):
"""
Mock response for localhost metadata
http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AESDG-chapter-instancedata.html
"""
parsed_url = urlparse(full_url)
tomorrow = datetime.datetime.utcnow() + datetime.timedelta(days=1)
credentials = dict(
AccessKeyId="test-key",
SecretAccessKey="test-secret-key",
Token="test-session-token",
Expiration=tomorrow.strftime("%Y-%m-%dT%H:%M:%SZ")
)
path = parsed_url.path
meta_data_prefix = "/latest/meta-data/"
# Strip prefix if it is there
if path.startswith(meta_data_prefix):
path = path[len(meta_data_prefix):]
if path == '':
result = 'iam'
elif path == 'iam':
result = json.dumps({
'security-credentials': {
'default-role': credentials
}
})
elif path == 'iam/security-credentials/':
result = 'default-role'
elif path == 'iam/security-credentials/default-role':
result = json.dumps(credentials)
else:
raise NotImplementedError("The {0} metadata path has not been implemented".format(path))
return 200, headers, result
class MotoAPIResponse(BaseResponse): class MotoAPIResponse(BaseResponse):
def reset_response(self, request, full_url, headers): def reset_response(self, request, full_url, headers):
if request.method == "POST":
from .models import moto_api_backend from .models import moto_api_backend
moto_api_backend.reset() moto_api_backend.reset()
return 200, {}, json.dumps({"status": "ok"}) return 200, {}, json.dumps({"status": "ok"})
return 400, {}, json.dumps({"Error": "Need to POST to reset Moto"})
class _RecursiveDictRef(object): class _RecursiveDictRef(object):

View File

@ -118,12 +118,16 @@ class convert_flask_to_httpretty_response(object):
return "{0}.{1}".format(outer, self.callback.__name__) return "{0}.{1}".format(outer, self.callback.__name__)
def __call__(self, args=None, **kwargs): def __call__(self, args=None, **kwargs):
from flask import request from flask import request, Response
result = self.callback(request, request.url, {}) result = self.callback(request, request.url, {})
# result is a status, headers, response tuple # result is a status, headers, response tuple
status, headers, response = result status, headers, content = result
return response, status, headers
response = Response(response=content, status=status, headers=headers)
if request.method == "HEAD" and 'content-length' in headers:
response.headers['Content-Length'] = headers['content-length']
return response
class convert_flask_to_responses_response(object): class convert_flask_to_responses_response(object):

View File

@ -1,4 +1,6 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from .models import dynamodb_backend from .models import dynamodb_backend
dynamodb_backends = {"global": dynamodb_backend}
mock_dynamodb = dynamodb_backend.decorator mock_dynamodb = dynamodb_backend.decorator
mock_dynamodb_deprecated = dynamodb_backend.deprecated_decorator mock_dynamodb_deprecated = dynamodb_backend.deprecated_decorator

View File

@ -1,4 +1,6 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from .models import dynamodb_backend2 from .models import dynamodb_backend2
dynamodb_backends2 = {"global": dynamodb_backend2}
mock_dynamodb2 = dynamodb_backend2.decorator mock_dynamodb2 = dynamodb_backend2.decorator
mock_dynamodb2_deprecated = dynamodb_backend2.deprecated_decorator mock_dynamodb2_deprecated = dynamodb_backend2.deprecated_decorator

View File

@ -1,6 +1,5 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from boto.ec2.instancetype import InstanceType from boto.ec2.instancetype import InstanceType
from boto.exception import JSONResponseError
from moto.core.responses import BaseResponse from moto.core.responses import BaseResponse
from moto.core.utils import camelcase_to_underscores from moto.core.utils import camelcase_to_underscores
from moto.ec2.utils import instance_ids_from_querystring, filters_from_querystring, \ from moto.ec2.utils import instance_ids_from_querystring, filters_from_querystring, \

View File

@ -1,6 +1,5 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from boto.exception import JSONResponseError
from moto.core.responses import BaseResponse from moto.core.responses import BaseResponse

View File

@ -35,8 +35,8 @@ class SpotInstances(BaseResponse):
def request_spot_instances(self): def request_spot_instances(self):
price = self._get_param('SpotPrice') price = self._get_param('SpotPrice')
image_id = self._get_param('LaunchSpecification.ImageId') image_id = self._get_param('LaunchSpecification.ImageId')
count = self._get_int_param('InstanceCount') count = self._get_int_param('InstanceCount', 1)
type = self._get_param('Type') type = self._get_param('Type', 'one-time')
valid_from = self._get_param('ValidFrom') valid_from = self._get_param('ValidFrom')
valid_until = self._get_param('ValidUntil') valid_until = self._get_param('ValidUntil')
launch_group = self._get_param('LaunchGroup') launch_group = self._get_param('LaunchGroup')
@ -44,7 +44,7 @@ class SpotInstances(BaseResponse):
key_name = self._get_param('LaunchSpecification.KeyName') key_name = self._get_param('LaunchSpecification.KeyName')
security_groups = self._get_multi_param('LaunchSpecification.SecurityGroup') security_groups = self._get_multi_param('LaunchSpecification.SecurityGroup')
user_data = self._get_param('LaunchSpecification.UserData') user_data = self._get_param('LaunchSpecification.UserData')
instance_type = self._get_param('LaunchSpecification.InstanceType') instance_type = self._get_param('LaunchSpecification.InstanceType', 'm1.small')
placement = self._get_param('LaunchSpecification.Placement.AvailabilityZone') placement = self._get_param('LaunchSpecification.Placement.AvailabilityZone')
kernel_id = self._get_param('LaunchSpecification.KernelId') kernel_id = self._get_param('LaunchSpecification.KernelId')
ramdisk_id = self._get_param('LaunchSpecification.RamdiskId') ramdisk_id = self._get_param('LaunchSpecification.RamdiskId')

7
moto/emr/exceptions.py Normal file
View File

@ -0,0 +1,7 @@
from __future__ import unicode_literals
from moto.core.exceptions import RESTError
class EmrError(RESTError):
code = 400

View File

@ -299,6 +299,7 @@ class ElasticMapReduceBackend(BaseBackend):
created_before = dtparse(created_before) created_before = dtparse(created_before)
clusters = [c for c in clusters if c.creation_datetime < created_before] clusters = [c for c in clusters if c.creation_datetime < created_before]
# Amazon EMR can return a maximum of 512 job flow descriptions
return sorted(clusters, key=lambda x: x.id)[:512] return sorted(clusters, key=lambda x: x.id)[:512]
def describe_step(self, cluster_id, step_id): def describe_step(self, cluster_id, step_id):

View File

@ -5,15 +5,14 @@ from datetime import datetime
from functools import wraps from functools import wraps
import pytz import pytz
from botocore.exceptions import ClientError
from moto.compat import urlparse from moto.compat import urlparse
from moto.core.responses import AWSServiceSpec from moto.core.responses import AWSServiceSpec
from moto.core.responses import BaseResponse from moto.core.responses import BaseResponse
from moto.core.responses import xml_to_json_response from moto.core.responses import xml_to_json_response
from .exceptions import EmrError
from .models import emr_backends from .models import emr_backends
from .utils import steps_from_query_string from .utils import steps_from_query_string, tags_from_query_string
from .utils import tags_from_query_string
def generate_boto3_response(operation): def generate_boto3_response(operation):
@ -46,7 +45,7 @@ class ElasticMapReduceResponse(BaseResponse):
aws_service_spec = AWSServiceSpec('data/emr/2009-03-31/service-2.json') aws_service_spec = AWSServiceSpec('data/emr/2009-03-31/service-2.json')
def get_region_from_url(self, full_url): def get_region_from_url(self, request, full_url):
parsed = urlparse(full_url) parsed = urlparse(full_url)
for regex in self.region_regex: for regex in self.region_regex:
match = regex.search(parsed.netloc) match = regex.search(parsed.netloc)
@ -240,9 +239,7 @@ class ElasticMapReduceResponse(BaseResponse):
'Only one AMI version and release label may be specified. ' 'Only one AMI version and release label may be specified. '
'Provided AMI: {0}, release label: {1}.').format( 'Provided AMI: {0}, release label: {1}.').format(
ami_version, release_label) ami_version, release_label)
raise ClientError( raise EmrError(error_type="ValidationException", message=message, template='single_error')
{'Error': {'Code': 'ValidationException',
'Message': message}}, 'RunJobFlow')
else: else:
if ami_version: if ami_version:
kwargs['requested_ami_version'] = ami_version kwargs['requested_ami_version'] = ami_version

View File

@ -2,4 +2,5 @@ from __future__ import unicode_literals
from .models import events_backend from .models import events_backend
events_backends = {"global": events_backend}
mock_events = events_backend.decorator mock_events = events_backend.decorator

View File

@ -3,7 +3,7 @@ from __future__ import unicode_literals
from .responses import EventsHandler from .responses import EventsHandler
url_bases = [ url_bases = [
"https://events.(.+).amazonaws.com" "https?://events.(.+).amazonaws.com"
] ]
url_paths = { url_paths = {

View File

@ -1,4 +1,6 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from .models import iam_backend from .models import iam_backend
iam_backends = {"global": iam_backend}
mock_iam = iam_backend.decorator mock_iam = iam_backend.decorator
mock_iam_deprecated = iam_backend.deprecated_decorator mock_iam_deprecated = iam_backend.deprecated_decorator

View File

@ -2,7 +2,7 @@ from __future__ import unicode_literals
from .responses import IamResponse from .responses import IamResponse
url_bases = [ url_bases = [
"https?://iam.amazonaws.com", "https?://iam(.*).amazonaws.com",
] ]
url_paths = { url_paths = {

View File

@ -0,0 +1,4 @@
from __future__ import unicode_literals
from .models import instance_metadata_backend
instance_metadata_backends = {"global": instance_metadata_backend}

View File

@ -0,0 +1,7 @@
from moto.core.models import BaseBackend
class InstanceMetadataBackend(BaseBackend):
pass
instance_metadata_backend = InstanceMetadataBackend()

View File

@ -0,0 +1,47 @@
from __future__ import unicode_literals
import datetime
import json
from urlparse import urlparse
from moto.core.responses import BaseResponse
class InstanceMetadataResponse(BaseResponse):
def metadata_response(self, request, full_url, headers):
"""
Mock response for localhost metadata
http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AESDG-chapter-instancedata.html
"""
parsed_url = urlparse(full_url)
tomorrow = datetime.datetime.utcnow() + datetime.timedelta(days=1)
credentials = dict(
AccessKeyId="test-key",
SecretAccessKey="test-secret-key",
Token="test-session-token",
Expiration=tomorrow.strftime("%Y-%m-%dT%H:%M:%SZ")
)
path = parsed_url.path
meta_data_prefix = "/latest/meta-data/"
# Strip prefix if it is there
if path.startswith(meta_data_prefix):
path = path[len(meta_data_prefix):]
if path == '':
result = 'iam'
elif path == 'iam':
result = json.dumps({
'security-credentials': {
'default-role': credentials
}
})
elif path == 'iam/security-credentials/':
result = 'default-role'
elif path == 'iam/security-credentials/default-role':
result = json.dumps(credentials)
else:
raise NotImplementedError("The {0} metadata path has not been implemented".format(path))
return 200, headers, result

View File

@ -0,0 +1,12 @@
from __future__ import unicode_literals
from .responses import InstanceMetadataResponse
url_bases = [
"http://169.254.169.254"
]
instance_metadata = InstanceMetadataResponse()
url_paths = {
'{0}/(?P<path>.+)': instance_metadata.metadata_response,
}

View File

@ -20,7 +20,7 @@ class KinesisResponse(BaseResponse):
@property @property
def is_firehose(self): def is_firehose(self):
host = self.headers.get('host') or self.headers['Host'] host = self.headers.get('host') or self.headers['Host']
return host.startswith('firehose') return host.startswith('firehose') or 'firehose' in self.headers.get('Authorization', '')
def create_stream(self): def create_stream(self):
stream_name = self.parameters.get('StreamName') stream_name = self.parameters.get('StreamName')

View File

@ -1,4 +1,6 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from .models import route53_backend from .models import route53_backend
route53_backends = {"global": route53_backend}
mock_route53 = route53_backend.decorator mock_route53 = route53_backend.decorator
mock_route53_deprecated = route53_backend.deprecated_decorator mock_route53_deprecated = route53_backend.deprecated_decorator

View File

@ -1,14 +1,18 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from jinja2 import Template from jinja2 import Template
from six.moves.urllib.parse import parse_qs, urlparse from six.moves.urllib.parse import parse_qs, urlparse
from moto.core.responses import BaseResponse
from .models import route53_backend from .models import route53_backend
import xmltodict import xmltodict
def list_or_create_hostzone_response(request, full_url, headers): class Route53 (BaseResponse):
def list_or_create_hostzone_response(self, request, full_url, headers):
self.setup_class(request, full_url, headers)
if request.method == "POST": if request.method == "POST":
elements = xmltodict.parse(request.body) elements = xmltodict.parse(self.body)
if "HostedZoneConfig" in elements["CreateHostedZoneRequest"]: if "HostedZoneConfig" in elements["CreateHostedZoneRequest"]:
comment = elements["CreateHostedZoneRequest"]["HostedZoneConfig"]["Comment"] comment = elements["CreateHostedZoneRequest"]["HostedZoneConfig"]["Comment"]
try: try:
@ -22,7 +26,6 @@ def list_or_create_hostzone_response(request, full_url, headers):
comment = None comment = None
private_zone = False private_zone = False
name = elements["CreateHostedZoneRequest"]["Name"] name = elements["CreateHostedZoneRequest"]["Name"]
if name[-1] != ".": if name[-1] != ".":
@ -42,7 +45,8 @@ def list_or_create_hostzone_response(request, full_url, headers):
return 200, headers, template.render(zones=all_zones) return 200, headers, template.render(zones=all_zones)
def get_or_delete_hostzone_response(request, full_url, headers): def get_or_delete_hostzone_response(self, request, full_url, headers):
self.setup_class(request, full_url, headers)
parsed_url = urlparse(full_url) parsed_url = urlparse(full_url)
zoneid = parsed_url.path.rstrip('/').rsplit('/', 1)[1] zoneid = parsed_url.path.rstrip('/').rsplit('/', 1)[1]
the_zone = route53_backend.get_hosted_zone(zoneid) the_zone = route53_backend.get_hosted_zone(zoneid)
@ -58,7 +62,9 @@ def get_or_delete_hostzone_response(request, full_url, headers):
return 200, headers, DELETE_HOSTED_ZONE_RESPONSE return 200, headers, DELETE_HOSTED_ZONE_RESPONSE
def rrset_response(request, full_url, headers): def rrset_response(self, request, full_url, headers):
self.setup_class(request, full_url, headers)
parsed_url = urlparse(full_url) parsed_url = urlparse(full_url)
method = request.method method = request.method
@ -68,7 +74,7 @@ def rrset_response(request, full_url, headers):
return 404, headers, "Zone %s Not Found" % zoneid return 404, headers, "Zone %s Not Found" % zoneid
if method == "POST": if method == "POST":
elements = xmltodict.parse(request.body) elements = xmltodict.parse(self.body)
change_list = elements['ChangeResourceRecordSetsRequest']['ChangeBatch']['Changes']['Change'] change_list = elements['ChangeResourceRecordSetsRequest']['ChangeBatch']['Changes']['Change']
if not isinstance(change_list, list): if not isinstance(change_list, list):
@ -108,12 +114,14 @@ def rrset_response(request, full_url, headers):
return 200, headers, template.render(record_sets=record_sets) return 200, headers, template.render(record_sets=record_sets)
def health_check_response(request, full_url, headers): def health_check_response(self, request, full_url, headers):
self.setup_class(request, full_url, headers)
parsed_url = urlparse(full_url) parsed_url = urlparse(full_url)
method = request.method method = request.method
if method == "POST": if method == "POST":
properties = xmltodict.parse(request.body)['CreateHealthCheckRequest']['HealthCheckConfig'] properties = xmltodict.parse(self.body)['CreateHealthCheckRequest']['HealthCheckConfig']
health_check_args = { health_check_args = {
"ip_address": properties.get('IPAddress'), "ip_address": properties.get('IPAddress'),
"port": properties.get('Port'), "port": properties.get('Port'),
@ -136,7 +144,9 @@ def health_check_response(request, full_url, headers):
health_checks = route53_backend.get_health_checks() health_checks = route53_backend.get_health_checks()
return 200, headers, template.render(health_checks=health_checks) return 200, headers, template.render(health_checks=health_checks)
def not_implemented_response(request, full_url, headers): def not_implemented_response(self, request, full_url, headers):
self.setup_class(request, full_url, headers)
action = '' action = ''
if 'tags' in full_url: if 'tags' in full_url:
action = 'tags' action = 'tags'
@ -145,7 +155,9 @@ def not_implemented_response(request, full_url, headers):
raise NotImplementedError("The action for {0} has not been implemented for route 53".format(action)) raise NotImplementedError("The action for {0} has not been implemented for route 53".format(action))
def list_or_change_tags_for_resource_request(request, full_url, headers): def list_or_change_tags_for_resource_request(self, request, full_url, headers):
self.setup_class(request, full_url, headers)
parsed_url = urlparse(full_url) parsed_url = urlparse(full_url)
id_ = parsed_url.path.split("/")[-1] id_ = parsed_url.path.split("/")[-1]
type_ = parsed_url.path.split("/")[-2] type_ = parsed_url.path.split("/")[-2]
@ -158,7 +170,7 @@ def list_or_change_tags_for_resource_request(request, full_url, headers):
if request.method == "POST": if request.method == "POST":
tags = xmltodict.parse( tags = xmltodict.parse(
request.body)['ChangeTagsForResourceRequest'] self.body)['ChangeTagsForResourceRequest']
if 'AddTags' in tags: if 'AddTags' in tags:
tags = tags['AddTags'] tags = tags['AddTags']

View File

@ -1,15 +1,25 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from . import responses from .responses import Route53
url_bases = [ url_bases = [
"https://route53.amazonaws.com/201.-..-../", "https?://route53(.*).amazonaws.com",
] ]
def tag_response1(*args, **kwargs):
return Route53().list_or_change_tags_for_resource_request(*args, **kwargs)
def tag_response2(*args, **kwargs):
return Route53().list_or_change_tags_for_resource_request(*args, **kwargs)
url_paths = { url_paths = {
'{0}hostedzone$': responses.list_or_create_hostzone_response, '{0}/(?P<api_version>[\d_-]+)/hostedzone$': Route53().list_or_create_hostzone_response,
'{0}hostedzone/[^/]+$': responses.get_or_delete_hostzone_response, '{0}/(?P<api_version>[\d_-]+)/hostedzone/(?P<zone_id>[^/]+)$': Route53().get_or_delete_hostzone_response,
'{0}hostedzone/[^/]+/rrset/?$': responses.rrset_response, '{0}/(?P<api_version>[\d_-]+)/hostedzone/(?P<zone_id>[^/]+)/rrset/?$': Route53().rrset_response,
'{0}healthcheck': responses.health_check_response, '{0}/(?P<api_version>[\d_-]+)/healthcheck': Route53().health_check_response,
'{0}tags/(healthcheck|hostedzone)/*': responses.list_or_change_tags_for_resource_request, '{0}/(?P<api_version>[\d_-]+)/tags/healthcheck/(?P<zone_id>[^/]+)$': tag_response1,
'{0}trafficpolicyinstances/*': responses.not_implemented_response '{0}/(?P<api_version>[\d_-]+)/tags/hostedzone/(?P<zone_id>[^/]+)$': tag_response2,
'{0}/(?P<api_version>[\d_-]+)/trafficpolicyinstances/*': Route53().not_implemented_response
} }

View File

@ -1,4 +1,6 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from .models import s3_backend from .models import s3_backend
s3_backends = {"global": s3_backend}
mock_s3 = s3_backend.decorator mock_s3 = s3_backend.decorator
mock_s3_deprecated = s3_backend.deprecated_decorator mock_s3_deprecated = s3_backend.deprecated_decorator

View File

@ -89,21 +89,21 @@ class FakeKey(object):
@property @property
def response_dict(self): def response_dict(self):
r = { res = {
'etag': self.etag, 'etag': self.etag,
'last-modified': self.last_modified_RFC1123, 'last-modified': self.last_modified_RFC1123,
'content-length': str(len(self.value)), 'content-length': str(len(self.value)),
} }
if self._storage_class != 'STANDARD': if self._storage_class != 'STANDARD':
r['x-amz-storage-class'] = self._storage_class res['x-amz-storage-class'] = self._storage_class
if self._expiry is not None: if self._expiry is not None:
rhdr = 'ongoing-request="false", expiry-date="{0}"' rhdr = 'ongoing-request="false", expiry-date="{0}"'
r['x-amz-restore'] = rhdr.format(self.expiry_date) res['x-amz-restore'] = rhdr.format(self.expiry_date)
if self._is_versioned: if self._is_versioned:
r['x-amz-version-id'] = str(self._version_id) res['x-amz-version-id'] = str(self._version_id)
return r return res
@property @property
def size(self): def size(self):

View File

@ -39,21 +39,28 @@ class DomainDispatcherApplication(object):
return host return host
for backend_name, backend in BACKENDS.items(): for backend_name, backend in BACKENDS.items():
for url_base in backend.url_bases: for url_base in backend.values()[0].url_bases:
if re.match(url_base, 'http://%s' % host): if re.match(url_base, 'http://%s' % host):
return backend_name return backend_name
raise RuntimeError('Invalid host: "%s"' % host) raise RuntimeError('Invalid host: "%s"' % host)
def get_application(self, environ): def get_application(self, environ):
if environ.get('PATH_INFO', '').startswith("/moto-api"): path_info = environ.get('PATH_INFO', '')
if path_info.startswith("/moto-api"):
host = "moto_api" host = "moto_api"
elif path_info.startswith("/latest/meta-data/"):
host = "instance_metadata"
else: else:
host = environ['HTTP_HOST'].split(':')[0] host = environ['HTTP_HOST'].split(':')[0]
if host == "localhost": if host == "localhost":
# Fall back to parsing auth header to find service # Fall back to parsing auth header to find service
# ['Credential=sdffdsa', '20170220', 'us-east-1', 'sns', 'aws4_request'] # ['Credential=sdffdsa', '20170220', 'us-east-1', 'sns', 'aws4_request']
try:
_, _, region, service, _ = environ['HTTP_AUTHORIZATION'].split(",")[0].split()[1].split("/") _, _, region, service, _ = environ['HTTP_AUTHORIZATION'].split(",")[0].split()[1].split("/")
except ValueError:
region = 'us-east-1'
service = 's3'
host = "{service}.{region}.amazonaws.com".format(service=service, region=region) host = "{service}.{region}.amazonaws.com".format(service=service, region=region)
with self.lock: with self.lock:
@ -108,7 +115,7 @@ def create_backend_app(service):
backend_app.view_functions = {} backend_app.view_functions = {}
backend_app.url_map = Map() backend_app.url_map = Map()
backend_app.url_map.converters['regex'] = RegexConverter backend_app.url_map.converters['regex'] = RegexConverter
backend = BACKENDS[service] backend = BACKENDS[service].values()[0]
for url_path, handler in backend.flask_paths.items(): for url_path, handler in backend.flask_paths.items():
if handler.__name__ == 'dispatch': if handler.__name__ == 'dispatch':
endpoint = '{0}.dispatch'.format(handler.__self__.__name__) endpoint = '{0}.dispatch'.format(handler.__self__.__name__)

View File

@ -1,4 +1,6 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from .models import ses_backend from .models import ses_backend
ses_backends = {"global": ses_backend}
mock_ses = ses_backend.decorator mock_ses = ses_backend.decorator
mock_ses_deprecated = ses_backend.deprecated_decorator mock_ses_deprecated = ses_backend.deprecated_decorator

View File

@ -2,7 +2,8 @@ from __future__ import unicode_literals
from .responses import EmailResponse from .responses import EmailResponse
url_bases = [ url_bases = [
"https?://email.(.+).amazonaws.com" "https?://email.(.+).amazonaws.com",
"https?://ses.(.+).amazonaws.com",
] ]
url_paths = { url_paths = {

3
moto/settings.py Normal file
View File

@ -0,0 +1,3 @@
import os
TEST_SERVER_MODE = os.environ.get('TEST_SERVER_MODE', '0').lower() == 'true'

View File

@ -1,4 +1,6 @@
from __future__ import unicode_literals from __future__ import unicode_literals
from .models import sts_backend from .models import sts_backend
sts_backends = {"global": sts_backend}
mock_sts = sts_backend.decorator mock_sts = sts_backend.decorator
mock_sts_deprecated = sts_backend.deprecated_decorator mock_sts_deprecated = sts_backend.deprecated_decorator

View File

@ -2,7 +2,7 @@ from __future__ import unicode_literals
from .responses import TokenResponse from .responses import TokenResponse
url_bases = [ url_bases = [
"https?://sts.amazonaws.com" "https?://sts(.*).amazonaws.com"
] ]
url_paths = { url_paths = {

View File

@ -0,0 +1,52 @@
/*
* Copyright 2010-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file is distributed
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
* express or implied. See the License for the specific language governing
* permissions and limitations under the License.
*/
package com.amazonaws.samples;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import com.amazonaws.AmazonClientException;
import com.amazonaws.AmazonServiceException;
import com.amazonaws.regions.Region;
import com.amazonaws.regions.Regions;
import com.amazonaws.services.sqs.AmazonSQS;
import com.amazonaws.services.sqs.AmazonSQSClient;
public class S3Sample {
public static void main(String[] args) throws IOException {
AmazonSQS sqs = new AmazonSQSClient();
Region usWest2 = Region.getRegion(Regions.US_WEST_2);
sqs.setRegion(usWest2);
sqs.setEndpoint("http://localhost:8086");
String queueName = "my-first-queue";
sqs.createQueue(queueName);
System.out.println("Listing queues");
for (String queue_url: sqs.listQueues().getQueueUrls()) {
System.out.println(" - " + queue_url);
}
System.out.println();
}
}

26
other_langs/test.js Normal file
View File

@ -0,0 +1,26 @@
var AWS = require('aws-sdk');
var s3 = new AWS.S3({endpoint: "http://localhost:8086"});
var myBucket = 'my.unique.bucket.name';
var myKey = 'myBucketKey';
s3.createBucket({Bucket: myBucket}, function(err, data) {
if (err) {
console.log(err);
} else {
params = {Bucket: myBucket, Key: myKey, Body: 'Hello!'};
s3.putObject(params, function(err, data) {
if (err) {
console.log(err)
} else {
console.log("Successfully uploaded data to myBucket/myKey");
}
});
}
});
s3.listBuckets(function(err, data) {
if (err) console.log(err, err.stack); // an error occurred
else console.log(data); // successful response
});

6
other_langs/test.rb Normal file
View File

@ -0,0 +1,6 @@
require 'aws-sdk'
sqs = Aws::SQS::Resource.new(region: 'us-west-2', endpoint: 'http://localhost:8086')
my_queue = sqs.create_queue(queue_name: 'my-bucket')
puts sqs.client.list_queues()

View File

@ -10,7 +10,7 @@ import sure # noqa
from botocore.exceptions import ClientError from botocore.exceptions import ClientError
from moto.packages.responses import responses from moto.packages.responses import responses
from moto import mock_apigateway from moto import mock_apigateway, settings
@freeze_time("2015-01-01") @freeze_time("2015-01-01")
@ -29,11 +29,11 @@ def test_create_and_get_rest_api():
) )
response.pop('ResponseMetadata') response.pop('ResponseMetadata')
response.pop('createdDate')
response.should.equal({ response.should.equal({
'id': api_id, 'id': api_id,
'name': 'my_api', 'name': 'my_api',
'description': 'this is my api', 'description': 'this is my api',
'createdDate': datetime(2015, 1, 1, tzinfo=tzutc())
}) })
@ -930,4 +930,5 @@ def test_http_proxying_integration():
deploy_url = "https://{api_id}.execute-api.{region_name}.amazonaws.com/{stage_name}".format(api_id=api_id, region_name=region_name, stage_name=stage_name) deploy_url = "https://{api_id}.execute-api.{region_name}.amazonaws.com/{stage_name}".format(api_id=api_id, region_name=region_name, stage_name=stage_name)
if not settings.TEST_SERVER_MODE:
requests.get(deploy_url).content.should.equal(b"a fake response") requests.get(deploy_url).content.should.equal(b"a fake response")

View File

@ -10,7 +10,7 @@ import zipfile
import sure # noqa import sure # noqa
from freezegun import freeze_time from freezegun import freeze_time
from moto import mock_lambda, mock_s3, mock_ec2 from moto import mock_lambda, mock_s3, mock_ec2, settings
def _process_lamda(pfunc): def _process_lamda(pfunc):
@ -36,16 +36,15 @@ def lambda_handler(event, context):
volume_id = event.get('volume_id') volume_id = event.get('volume_id')
print('get volume details for %s' % volume_id) print('get volume details for %s' % volume_id)
import boto3 import boto3
ec2 = boto3.resource('ec2', region_name='us-west-2') ec2 = boto3.resource('ec2', region_name='us-west-2', endpoint_url="http://{base_url}")
vol = ec2.Volume(volume_id) vol = ec2.Volume(volume_id)
print('Volume - %s state=%s, size=%s' % (volume_id, vol.state, vol.size)) print('Volume - %s state=%s, size=%s' % (volume_id, vol.state, vol.size))
return event return event
""" """.format(base_url="localhost:8086" if settings.TEST_SERVER_MODE else "ec2.us-west-2.amazonaws.com")
return _process_lamda(pfunc) return _process_lamda(pfunc)
@mock_lambda @mock_lambda
@mock_s3
def test_list_functions(): def test_list_functions():
conn = boto3.client('lambda', 'us-west-2') conn = boto3.client('lambda', 'us-west-2')
result = conn.list_functions() result = conn.list_functions()
@ -53,7 +52,6 @@ def test_list_functions():
@mock_lambda @mock_lambda
@freeze_time('2015-01-01 00:00:00')
def test_invoke_requestresponse_function(): def test_invoke_requestresponse_function():
conn = boto3.client('lambda', 'us-west-2') conn = boto3.client('lambda', 'us-west-2')
conn.create_function( conn.create_function(
@ -80,7 +78,6 @@ def test_invoke_requestresponse_function():
@mock_lambda @mock_lambda
@freeze_time('2015-01-01 00:00:00')
def test_invoke_event_function(): def test_invoke_event_function():
conn = boto3.client('lambda', 'us-west-2') conn = boto3.client('lambda', 'us-west-2')
conn.create_function( conn.create_function(
@ -111,7 +108,6 @@ def test_invoke_event_function():
@mock_ec2 @mock_ec2
@mock_lambda @mock_lambda
@freeze_time('2015-01-01 00:00:00')
def test_invoke_function_get_ec2_volume(): def test_invoke_function_get_ec2_volume():
conn = boto3.resource("ec2", "us-west-2") conn = boto3.resource("ec2", "us-west-2")
vol = conn.create_volume(Size=99, AvailabilityZone='us-west-2') vol = conn.create_volume(Size=99, AvailabilityZone='us-west-2')
@ -141,7 +137,6 @@ def test_invoke_function_get_ec2_volume():
@mock_lambda @mock_lambda
@freeze_time('2015-01-01 00:00:00')
def test_create_based_on_s3_with_missing_bucket(): def test_create_based_on_s3_with_missing_bucket():
conn = boto3.client('lambda', 'us-west-2') conn = boto3.client('lambda', 'us-west-2')
@ -196,6 +191,7 @@ def test_create_function_from_aws_bucket():
) )
result['ResponseMetadata'].pop('HTTPHeaders', None) # this is hard to match against, so remove it result['ResponseMetadata'].pop('HTTPHeaders', None) # this is hard to match against, so remove it
result['ResponseMetadata'].pop('RetryAttempts', None) # Botocore inserts retry attempts not seen in Python27 result['ResponseMetadata'].pop('RetryAttempts', None) # Botocore inserts retry attempts not seen in Python27
result.pop('LastModified')
result.should.equal({ result.should.equal({
'FunctionName': 'testFunction', 'FunctionName': 'testFunction',
'FunctionArn': 'arn:aws:lambda:123456789012:function:testFunction', 'FunctionArn': 'arn:aws:lambda:123456789012:function:testFunction',
@ -207,7 +203,6 @@ def test_create_function_from_aws_bucket():
'Description': 'test lambda function', 'Description': 'test lambda function',
'Timeout': 3, 'Timeout': 3,
'MemorySize': 128, 'MemorySize': 128,
'LastModified': '2015-01-01 00:00:00',
'Version': '$LATEST', 'Version': '$LATEST',
'VpcConfig': { 'VpcConfig': {
"SecurityGroupIds": ["sg-123abc"], "SecurityGroupIds": ["sg-123abc"],
@ -238,6 +233,7 @@ def test_create_function_from_zipfile():
) )
result['ResponseMetadata'].pop('HTTPHeaders', None) # this is hard to match against, so remove it result['ResponseMetadata'].pop('HTTPHeaders', None) # this is hard to match against, so remove it
result['ResponseMetadata'].pop('RetryAttempts', None) # Botocore inserts retry attempts not seen in Python27 result['ResponseMetadata'].pop('RetryAttempts', None) # Botocore inserts retry attempts not seen in Python27
result.pop('LastModified')
result.should.equal({ result.should.equal({
'FunctionName': 'testFunction', 'FunctionName': 'testFunction',
@ -249,7 +245,6 @@ def test_create_function_from_zipfile():
'Description': 'test lambda function', 'Description': 'test lambda function',
'Timeout': 3, 'Timeout': 3,
'MemorySize': 128, 'MemorySize': 128,
'LastModified': '2015-01-01 00:00:00',
'CodeSha256': hashlib.sha256(zip_content).hexdigest(), 'CodeSha256': hashlib.sha256(zip_content).hexdigest(),
'Version': '$LATEST', 'Version': '$LATEST',
'VpcConfig': { 'VpcConfig': {
@ -290,6 +285,7 @@ def test_get_function():
result = conn.get_function(FunctionName='testFunction') result = conn.get_function(FunctionName='testFunction')
result['ResponseMetadata'].pop('HTTPHeaders', None) # this is hard to match against, so remove it result['ResponseMetadata'].pop('HTTPHeaders', None) # this is hard to match against, so remove it
result['ResponseMetadata'].pop('RetryAttempts', None) # Botocore inserts retry attempts not seen in Python27 result['ResponseMetadata'].pop('RetryAttempts', None) # Botocore inserts retry attempts not seen in Python27
result['Configuration'].pop('LastModified')
result.should.equal({ result.should.equal({
"Code": { "Code": {
@ -303,7 +299,6 @@ def test_get_function():
"FunctionArn": "arn:aws:lambda:123456789012:function:testFunction", "FunctionArn": "arn:aws:lambda:123456789012:function:testFunction",
"FunctionName": "testFunction", "FunctionName": "testFunction",
"Handler": "lambda_function.handler", "Handler": "lambda_function.handler",
"LastModified": "2015-01-01 00:00:00",
"MemorySize": 128, "MemorySize": 128,
"Role": "test-iam-role", "Role": "test-iam-role",
"Runtime": "python2.7", "Runtime": "python2.7",
@ -395,7 +390,6 @@ def test_list_create_list_get_delete_list():
"FunctionArn": "arn:aws:lambda:123456789012:function:testFunction", "FunctionArn": "arn:aws:lambda:123456789012:function:testFunction",
"FunctionName": "testFunction", "FunctionName": "testFunction",
"Handler": "lambda_function.handler", "Handler": "lambda_function.handler",
"LastModified": "2015-01-01 00:00:00",
"MemorySize": 128, "MemorySize": 128,
"Role": "test-iam-role", "Role": "test-iam-role",
"Runtime": "python2.7", "Runtime": "python2.7",
@ -408,11 +402,14 @@ def test_list_create_list_get_delete_list():
}, },
'ResponseMetadata': {'HTTPStatusCode': 200}, 'ResponseMetadata': {'HTTPStatusCode': 200},
} }
conn.list_functions()['Functions'].should.equal([expected_function_result['Configuration']]) func = conn.list_functions()['Functions'][0]
func.pop('LastModified')
func.should.equal(expected_function_result['Configuration'])
func = conn.get_function(FunctionName='testFunction') func = conn.get_function(FunctionName='testFunction')
func['ResponseMetadata'].pop('HTTPHeaders', None) # this is hard to match against, so remove it func['ResponseMetadata'].pop('HTTPHeaders', None) # this is hard to match against, so remove it
func['ResponseMetadata'].pop('RetryAttempts', None) # Botocore inserts retry attempts not seen in Python27 func['ResponseMetadata'].pop('RetryAttempts', None) # Botocore inserts retry attempts not seen in Python27
func['Configuration'].pop('LastModified')
func.should.equal(expected_function_result) func.should.equal(expected_function_result)
conn.delete_function(FunctionName='testFunction') conn.delete_function(FunctionName='testFunction')

View File

@ -5,7 +5,7 @@ import boto
import boto.s3 import boto.s3
import boto.s3.key import boto.s3.key
from botocore.exceptions import ClientError from botocore.exceptions import ClientError
from moto import mock_cloudformation, mock_s3_deprecated from moto import mock_cloudformation, mock_s3
import json import json
import sure # noqa import sure # noqa
@ -118,14 +118,20 @@ def test_create_stack_with_role_arn():
@mock_cloudformation @mock_cloudformation
@mock_s3_deprecated @mock_s3
def test_create_stack_from_s3_url(): def test_create_stack_from_s3_url():
s3_conn = boto.s3.connect_to_region('us-west-1') s3 = boto3.client('s3')
bucket = s3_conn.create_bucket("foobar") s3_conn = boto3.resource('s3')
key = boto.s3.key.Key(bucket) bucket = s3_conn.create_bucket(Bucket="foobar")
key.key = "template-key"
key.set_contents_from_string(dummy_template_json) key = s3_conn.Object('foobar', 'template-key').put(Body=dummy_template_json)
key_url = key.generate_url(expires_in=0, query_auth=False) key_url = s3.generate_presigned_url(
ClientMethod='get_object',
Params={
'Bucket': 'foobar',
'Key': 'template-key'
}
)
cf_conn = boto3.client('cloudformation', region_name='us-west-1') cf_conn = boto3.client('cloudformation', region_name='us-west-1')
cf_conn.create_stack( cf_conn.create_stack(

View File

@ -701,19 +701,20 @@ def test_vpc_single_instance_in_subnet():
eip_resource = [resource for resource in resources if resource.resource_type == 'AWS::EC2::EIP'][0] eip_resource = [resource for resource in resources if resource.resource_type == 'AWS::EC2::EIP'][0]
eip_resource.physical_resource_id.should.equal(eip.allocation_id) eip_resource.physical_resource_id.should.equal(eip.allocation_id)
@mock_cloudformation_deprecated() @mock_cloudformation()
@mock_ec2_deprecated() @mock_ec2()
@mock_rds2() @mock_rds2()
def test_rds_db_parameter_groups(): def test_rds_db_parameter_groups():
ec2_conn = boto.ec2.connect_to_region("us-west-1") ec2_conn = boto3.client("ec2", region_name="us-west-1")
ec2_conn.create_security_group('application', 'Our Application Group') ec2_conn.create_security_group(GroupName='application', Description='Our Application Group')
template_json = json.dumps(rds_mysql_with_db_parameter_group.template) template_json = json.dumps(rds_mysql_with_db_parameter_group.template)
conn = boto.cloudformation.connect_to_region("us-west-1") cf_conn = boto3.client('cloudformation', 'us-west-1')
conn.create_stack( cf_conn.create_stack(
"test_stack", StackName="test_stack",
template_body=template_json, TemplateBody=template_json,
parameters=[ Parameters=[{'ParameterKey': key, 'ParameterValue': value} for
key, value in [
("DBInstanceIdentifier", "master_db"), ("DBInstanceIdentifier", "master_db"),
("DBName", "my_db"), ("DBName", "my_db"),
("DBUser", "my_user"), ("DBUser", "my_user"),
@ -722,6 +723,7 @@ def test_rds_db_parameter_groups():
("DBInstanceClass", "db.m1.medium"), ("DBInstanceClass", "db.m1.medium"),
("EC2SecurityGroup", "application"), ("EC2SecurityGroup", "application"),
("MultiAZ", "true"), ("MultiAZ", "true"),
]
], ],
) )
@ -1802,7 +1804,7 @@ def lambda_handler(event, context):
return _process_lamda(pfunc) return _process_lamda(pfunc)
@mock_cloudformation_deprecated @mock_cloudformation
@mock_lambda @mock_lambda
def test_lambda_function(): def test_lambda_function():
# switch this to python as backend lambda only supports python execution. # switch this to python as backend lambda only supports python execution.
@ -1826,10 +1828,10 @@ def test_lambda_function():
} }
template_json = json.dumps(template) template_json = json.dumps(template)
cf_conn = boto.cloudformation.connect_to_region("us-east-1") cf_conn = boto3.client('cloudformation', 'us-east-1')
cf_conn.create_stack( cf_conn.create_stack(
"test_stack", StackName="test_stack",
template_body=template_json, TemplateBody=template_json,
) )
conn = boto3.client('lambda', 'us-east-1') conn = boto3.client('lambda', 'us-east-1')

View File

@ -3,18 +3,23 @@ import sure # noqa
from nose.tools import assert_raises from nose.tools import assert_raises
import requests import requests
from moto import mock_ec2 from moto import mock_ec2, settings
if settings.TEST_SERVER_MODE:
BASE_URL = 'http://localhost:8086'
else:
BASE_URL = 'http://169.254.169.254'
@mock_ec2 @mock_ec2
def test_latest_meta_data(): def test_latest_meta_data():
res = requests.get("http://169.254.169.254/latest/meta-data/") res = requests.get("{0}/latest/meta-data/".format(BASE_URL))
res.content.should.equal(b"iam") res.content.should.equal(b"iam")
@mock_ec2 @mock_ec2
def test_meta_data_iam(): def test_meta_data_iam():
res = requests.get("http://169.254.169.254/latest/meta-data/iam") res = requests.get("{0}/latest/meta-data/iam".format(BASE_URL))
json_response = res.json() json_response = res.json()
default_role = json_response['security-credentials']['default-role'] default_role = json_response['security-credentials']['default-role']
default_role.should.contain('AccessKeyId') default_role.should.contain('AccessKeyId')
@ -25,21 +30,15 @@ def test_meta_data_iam():
@mock_ec2 @mock_ec2
def test_meta_data_security_credentials(): def test_meta_data_security_credentials():
res = requests.get("http://169.254.169.254/latest/meta-data/iam/security-credentials/") res = requests.get("{0}/latest/meta-data/iam/security-credentials/".format(BASE_URL))
res.content.should.equal(b"default-role") res.content.should.equal(b"default-role")
@mock_ec2 @mock_ec2
def test_meta_data_default_role(): def test_meta_data_default_role():
res = requests.get("http://169.254.169.254/latest/meta-data/iam/security-credentials/default-role") res = requests.get("{0}/latest/meta-data/iam/security-credentials/default-role".format(BASE_URL))
json_response = res.json() json_response = res.json()
json_response.should.contain('AccessKeyId') json_response.should.contain('AccessKeyId')
json_response.should.contain('SecretAccessKey') json_response.should.contain('SecretAccessKey')
json_response.should.contain('Token') json_response.should.contain('Token')
json_response.should.contain('Expiration') json_response.should.contain('Expiration')
@mock_ec2
def test_meta_data_unknown_path():
with assert_raises(NotImplementedError):
requests.get("http://169.254.169.254/latest/meta-data/badpath")

View File

@ -0,0 +1,21 @@
from __future__ import unicode_literals
import sure # noqa
from nose.tools import assert_raises
import requests
import boto3
from moto import mock_sqs, settings
base_url = "http://localhost:8086" if settings.TEST_SERVER_MODE else "http://motoapi.amazonaws.com"
@mock_sqs
def test_reset_api():
conn = boto3.client("sqs", region_name='us-west-1')
conn.create_queue(QueueName="queue1")
conn.list_queues()['QueueUrls'].should.have.length_of(1)
res = requests.post("{base_url}/moto-api/reset".format(base_url=base_url))
res.content.should.equal(b'{"status": "ok"}')
conn.list_queues().shouldnt.contain('QueueUrls') # No more queues

View File

@ -42,13 +42,6 @@ def test_describe_missing_table():
conn.describe_table('messages') conn.describe_table('messages')
@mock_dynamodb
def test_sts_handler():
res = requests.post("https://sts.amazonaws.com/", data={"GetSessionToken": ""})
res.ok.should.be.ok
res.text.should.contain("SecretAccessKey")
@mock_dynamodb_deprecated @mock_dynamodb_deprecated
def test_dynamodb_with_connect_to_region(): def test_dynamodb_with_connect_to_region():
# this will work if connected with boto.connect_dynamodb() # this will work if connected with boto.connect_dynamodb()

View File

@ -63,11 +63,3 @@ def test_describe_missing_table():
aws_secret_access_key="sk") aws_secret_access_key="sk")
with assert_raises(JSONResponseError): with assert_raises(JSONResponseError):
conn.describe_table('messages') conn.describe_table('messages')
@requires_boto_gte("2.9")
@mock_dynamodb2
def test_sts_handler():
res = requests.post("https://sts.amazonaws.com/", data={"GetSessionToken": ""})
res.ok.should.be.ok
res.text.should.contain("SecretAccessKey")

View File

@ -5,7 +5,7 @@ from nose.tools import assert_raises
import boto import boto
import boto.ec2 import boto.ec2
from boto.exception import EC2ResponseError, JSONResponseError from boto.exception import EC2ResponseError, EC2ResponseError
import sure # noqa import sure # noqa
@ -19,9 +19,9 @@ def test_ami_create_and_delete():
reservation = conn.run_instances('ami-1234abcd') reservation = conn.run_instances('ami-1234abcd')
instance = reservation.instances[0] instance = reservation.instances[0]
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
image_id = conn.create_image(instance.id, "test-ami", "this is a test ami", dry_run=True) image_id = conn.create_image(instance.id, "test-ami", "this is a test ami", dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the CreateImage operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateImage operation: Request would have succeeded, but DryRun flag is set')
@ -52,9 +52,9 @@ def test_ami_create_and_delete():
snapshot.volume_id.should.equal(volume.id) snapshot.volume_id.should.equal(volume.id)
# Deregister # Deregister
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
success = conn.deregister_image(image_id, dry_run=True) success = conn.deregister_image(image_id, dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the DeregisterImage operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the DeregisterImage operation: Request would have succeeded, but DryRun flag is set')
@ -80,9 +80,9 @@ def test_ami_copy():
source_image = conn.get_all_images(image_ids=[source_image_id])[0] source_image = conn.get_all_images(image_ids=[source_image_id])[0]
# Boto returns a 'CopyImage' object with an image_id attribute here. Use the image_id to fetch the full info. # Boto returns a 'CopyImage' object with an image_id attribute here. Use the image_id to fetch the full info.
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
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) 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)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the CopyImage operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CopyImage operation: Request would have succeeded, but DryRun flag is set')
@ -127,9 +127,9 @@ def test_ami_tagging():
conn.create_image(instance.id, "test-ami", "this is a test ami") conn.create_image(instance.id, "test-ami", "this is a test ami")
image = conn.get_all_images()[0] image = conn.get_all_images()[0]
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
image.add_tag("a key", "some value", dry_run=True) image.add_tag("a key", "some value", dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set')
@ -289,9 +289,9 @@ def test_ami_attribute_group_permissions():
'groups': 'all'} 'groups': 'all'}
# Add 'all' group and confirm # Add 'all' group and confirm
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
conn.modify_image_attribute(**dict(ADD_GROUP_ARGS, **{'dry_run': True})) conn.modify_image_attribute(**dict(ADD_GROUP_ARGS, **{'dry_run': True}))
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the ModifyImageAttribute operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ModifyImageAttribute operation: Request would have succeeded, but DryRun flag is set')

View File

@ -1,11 +1 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import requests
from moto import mock_ec2
@mock_ec2
def test_not_implemented_method():
requests.post.when.called_with(
"https://ec2.us-east-1.amazonaws.com/",
data={'Action': ['foobar']}
).should.throw(NotImplementedError)

View File

@ -5,7 +5,7 @@ from nose.tools import assert_raises
from moto.ec2 import ec2_backends from moto.ec2 import ec2_backends
import boto import boto
from boto.exception import EC2ResponseError, JSONResponseError from boto.exception import EC2ResponseError
import sure # noqa import sure # noqa
from moto import mock_ec2_deprecated from moto import mock_ec2_deprecated
@ -24,9 +24,9 @@ def test_create_and_delete_volume():
volume = all_volumes[0] volume = all_volumes[0]
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
volume.delete(dry_run=True) volume.delete(dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the DeleteVolume operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the DeleteVolume operation: Request would have succeeded, but DryRun flag is set')
@ -46,9 +46,9 @@ def test_create_and_delete_volume():
@mock_ec2_deprecated @mock_ec2_deprecated
def test_create_encrypted_volume_dryrun(): def test_create_encrypted_volume_dryrun():
conn = boto.connect_ec2('the_key', 'the_secret') conn = boto.connect_ec2('the_key', 'the_secret')
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
conn.create_volume(80, "us-east-1a", encrypted=True, dry_run=True) conn.create_volume(80, "us-east-1a", encrypted=True, dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the CreateVolume operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateVolume operation: Request would have succeeded, but DryRun flag is set')
@ -58,9 +58,9 @@ def test_create_encrypted_volume():
conn = boto.connect_ec2('the_key', 'the_secret') conn = boto.connect_ec2('the_key', 'the_secret')
conn.create_volume(80, "us-east-1a", encrypted=True) conn.create_volume(80, "us-east-1a", encrypted=True)
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
conn.create_volume(80, "us-east-1a", encrypted=True, dry_run=True) conn.create_volume(80, "us-east-1a", encrypted=True, dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the CreateVolume operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateVolume operation: Request would have succeeded, but DryRun flag is set')
@ -165,9 +165,9 @@ def test_volume_attach_and_detach():
volume.update() volume.update()
volume.volume_state().should.equal('available') volume.volume_state().should.equal('available')
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
volume.attach(instance.id, "/dev/sdh", dry_run=True) volume.attach(instance.id, "/dev/sdh", dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the AttachVolume operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the AttachVolume operation: Request would have succeeded, but DryRun flag is set')
@ -179,9 +179,9 @@ def test_volume_attach_and_detach():
volume.attach_data.instance_id.should.equal(instance.id) volume.attach_data.instance_id.should.equal(instance.id)
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
volume.detach(dry_run=True) volume.detach(dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the DetachVolume operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the DetachVolume operation: Request would have succeeded, but DryRun flag is set')
@ -214,9 +214,9 @@ def test_create_snapshot():
conn = boto.connect_ec2('the_key', 'the_secret') conn = boto.connect_ec2('the_key', 'the_secret')
volume = conn.create_volume(80, "us-east-1a") volume = conn.create_volume(80, "us-east-1a")
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
snapshot = volume.create_snapshot('a dryrun snapshot', dry_run=True) snapshot = volume.create_snapshot('a dryrun snapshot', dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the CreateSnapshot operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateSnapshot operation: Request would have succeeded, but DryRun flag is set')
@ -347,9 +347,9 @@ def test_snapshot_attribute():
# Add 'all' group and confirm # Add 'all' group and confirm
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
conn.modify_snapshot_attribute(**dict(ADD_GROUP_ARGS, **{'dry_run': True})) conn.modify_snapshot_attribute(**dict(ADD_GROUP_ARGS, **{'dry_run': True}))
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the ModifySnapshotAttribute operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ModifySnapshotAttribute operation: Request would have succeeded, but DryRun flag is set')
@ -363,9 +363,9 @@ def test_snapshot_attribute():
conn.modify_snapshot_attribute.when.called_with(**ADD_GROUP_ARGS).should_not.throw(EC2ResponseError) conn.modify_snapshot_attribute.when.called_with(**ADD_GROUP_ARGS).should_not.throw(EC2ResponseError)
# Remove 'all' group and confirm # Remove 'all' group and confirm
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
conn.modify_snapshot_attribute(**dict(REMOVE_GROUP_ARGS, **{'dry_run': True})) conn.modify_snapshot_attribute(**dict(REMOVE_GROUP_ARGS, **{'dry_run': True}))
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the ModifySnapshotAttribute operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ModifySnapshotAttribute operation: Request would have succeeded, but DryRun flag is set')
@ -424,9 +424,9 @@ def test_create_volume_from_snapshot():
volume = conn.create_volume(80, "us-east-1a") volume = conn.create_volume(80, "us-east-1a")
snapshot = volume.create_snapshot('a test snapshot') snapshot = volume.create_snapshot('a test snapshot')
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
snapshot = volume.create_snapshot('a test snapshot', dry_run=True) snapshot = volume.create_snapshot('a test snapshot', dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the CreateSnapshot operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateSnapshot operation: Request would have succeeded, but DryRun flag is set')
@ -468,9 +468,9 @@ def test_modify_attribute_blockDeviceMapping():
instance = reservation.instances[0] instance = reservation.instances[0]
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
instance.modify_attribute('blockDeviceMapping', {'/dev/sda1': True}, dry_run=True) instance.modify_attribute('blockDeviceMapping', {'/dev/sda1': True}, dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the ModifyInstanceAttribute operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ModifyInstanceAttribute operation: Request would have succeeded, but DryRun flag is set')
@ -487,9 +487,9 @@ def test_volume_tag_escaping():
vol = conn.create_volume(10, 'us-east-1a') vol = conn.create_volume(10, 'us-east-1a')
snapshot = conn.create_snapshot(vol.id, 'Desc') snapshot = conn.create_snapshot(vol.id, 'Desc')
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
snapshot.add_tags({'key': '</closed>'}, dry_run=True) snapshot.add_tags({'key': '</closed>'}, dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set') 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({'key': '</closed>'}) dict(conn.get_all_snapshots()[0].tags).should_not.be.equal({'key': '</closed>'})

View File

@ -5,7 +5,7 @@ from nose.tools import assert_raises
import boto import boto
import boto3 import boto3
from boto.exception import EC2ResponseError, JSONResponseError from boto.exception import EC2ResponseError
import six import six
import sure # noqa import sure # noqa
@ -20,9 +20,9 @@ def test_eip_allocate_classic():
"""Allocate/release Classic EIP""" """Allocate/release Classic EIP"""
conn = boto.connect_ec2('the_key', 'the_secret') conn = boto.connect_ec2('the_key', 'the_secret')
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
standard = conn.allocate_address(dry_run=True) standard = conn.allocate_address(dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the AllocateAddress operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the AllocateAddress operation: Request would have succeeded, but DryRun flag is set')
@ -32,9 +32,9 @@ def test_eip_allocate_classic():
standard.instance_id.should.be.none standard.instance_id.should.be.none
standard.domain.should.be.equal("standard") standard.domain.should.be.equal("standard")
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
standard.release(dry_run=True) standard.release(dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the ReleaseAddress operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ReleaseAddress operation: Request would have succeeded, but DryRun flag is set')
@ -47,9 +47,9 @@ def test_eip_allocate_vpc():
"""Allocate/release VPC EIP""" """Allocate/release VPC EIP"""
conn = boto.connect_ec2('the_key', 'the_secret') conn = boto.connect_ec2('the_key', 'the_secret')
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
vpc = conn.allocate_address(domain="vpc", dry_run=True) vpc = conn.allocate_address(domain="vpc", dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the AllocateAddress operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the AllocateAddress operation: Request would have succeeded, but DryRun flag is set')
@ -89,9 +89,9 @@ def test_eip_associate_classic():
cm.exception.status.should.equal(400) cm.exception.status.should.equal(400)
cm.exception.request_id.should_not.be.none cm.exception.request_id.should_not.be.none
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
conn.associate_address(instance_id=instance.id, public_ip=eip.public_ip, dry_run=True) conn.associate_address(instance_id=instance.id, public_ip=eip.public_ip, dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the AssociateAddress operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the AssociateAddress operation: Request would have succeeded, but DryRun flag is set')
@ -99,9 +99,9 @@ def test_eip_associate_classic():
eip = conn.get_all_addresses(addresses=[eip.public_ip])[0] # no .update() on address ): eip = conn.get_all_addresses(addresses=[eip.public_ip])[0] # no .update() on address ):
eip.instance_id.should.be.equal(instance.id) eip.instance_id.should.be.equal(instance.id)
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
conn.disassociate_address(public_ip=eip.public_ip, dry_run=True) conn.disassociate_address(public_ip=eip.public_ip, dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the DisAssociateAddress operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the DisAssociateAddress operation: Request would have succeeded, but DryRun flag is set')
@ -139,9 +139,9 @@ def test_eip_associate_vpc():
eip.instance_id.should.be.equal(u'') eip.instance_id.should.be.equal(u'')
eip.association_id.should.be.none eip.association_id.should.be.none
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
eip.release(dry_run=True) eip.release(dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the ReleaseAddress operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ReleaseAddress operation: Request would have succeeded, but DryRun flag is set')
@ -153,9 +153,8 @@ def test_eip_associate_vpc():
@mock_ec2 @mock_ec2
def test_eip_boto3_vpc_association(): def test_eip_boto3_vpc_association():
"""Associate EIP to VPC instance in a new subnet with boto3""" """Associate EIP to VPC instance in a new subnet with boto3"""
session = boto3.session.Session(region_name='us-west-1') service = boto3.resource('ec2', region_name='us-west-1')
service = session.resource('ec2') client = boto3.client('ec2', region_name='us-west-1')
client = session.client('ec2')
vpc_res = client.create_vpc(CidrBlock='10.0.0.0/24') vpc_res = client.create_vpc(CidrBlock='10.0.0.0/24')
subnet_res = client.create_subnet( subnet_res = client.create_subnet(
VpcId=vpc_res['Vpc']['VpcId'], CidrBlock='10.0.0.0/24') VpcId=vpc_res['Vpc']['VpcId'], CidrBlock='10.0.0.0/24')

View File

@ -4,10 +4,11 @@ import tests.backport_assert_raises
from nose.tools import assert_raises from nose.tools import assert_raises
import boto3 import boto3
from botocore.exceptions import ClientError
import boto import boto
import boto.cloudformation import boto.cloudformation
import boto.ec2 import boto.ec2
from boto.exception import EC2ResponseError, JSONResponseError from boto.exception import EC2ResponseError
import sure # noqa import sure # noqa
from moto import mock_ec2, mock_cloudformation_deprecated, mock_ec2_deprecated from moto import mock_ec2, mock_cloudformation_deprecated, mock_ec2_deprecated
@ -22,9 +23,9 @@ def test_elastic_network_interfaces():
vpc = conn.create_vpc("10.0.0.0/16") vpc = conn.create_vpc("10.0.0.0/16")
subnet = conn.create_subnet(vpc.id, "10.0.0.0/18") subnet = conn.create_subnet(vpc.id, "10.0.0.0/18")
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
eni = conn.create_network_interface(subnet.id, dry_run=True) eni = conn.create_network_interface(subnet.id, dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the CreateNetworkInterface operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateNetworkInterface operation: Request would have succeeded, but DryRun flag is set')
@ -36,9 +37,9 @@ def test_elastic_network_interfaces():
eni.groups.should.have.length_of(0) eni.groups.should.have.length_of(0)
eni.private_ip_addresses.should.have.length_of(0) eni.private_ip_addresses.should.have.length_of(0)
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
conn.delete_network_interface(eni.id, dry_run=True) conn.delete_network_interface(eni.id, dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the DeleteNetworkInterface operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the DeleteNetworkInterface operation: Request would have succeeded, but DryRun flag is set')
@ -49,7 +50,7 @@ def test_elastic_network_interfaces():
with assert_raises(EC2ResponseError) as cm: with assert_raises(EC2ResponseError) as cm:
conn.delete_network_interface(eni.id) conn.delete_network_interface(eni.id)
cm.exception.code.should.equal('InvalidNetworkInterfaceID.NotFound') cm.exception.error_code.should.equal('InvalidNetworkInterfaceID.NotFound')
cm.exception.status.should.equal(400) cm.exception.status.should.equal(400)
cm.exception.request_id.should_not.be.none cm.exception.request_id.should_not.be.none
@ -60,7 +61,7 @@ def test_elastic_network_interfaces_subnet_validation():
with assert_raises(EC2ResponseError) as cm: with assert_raises(EC2ResponseError) as cm:
conn.create_network_interface("subnet-abcd1234") conn.create_network_interface("subnet-abcd1234")
cm.exception.code.should.equal('InvalidSubnetID.NotFound') cm.exception.error_code.should.equal('InvalidSubnetID.NotFound')
cm.exception.status.should.equal(400) cm.exception.status.should.equal(400)
cm.exception.request_id.should_not.be.none cm.exception.request_id.should_not.be.none
@ -117,9 +118,9 @@ def test_elastic_network_interfaces_modify_attribute():
eni.groups.should.have.length_of(1) eni.groups.should.have.length_of(1)
eni.groups[0].id.should.equal(security_group1.id) eni.groups[0].id.should.equal(security_group1.id)
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
conn.modify_network_interface_attribute(eni.id, 'groupset', [security_group2.id], dry_run=True) conn.modify_network_interface_attribute(eni.id, 'groupset', [security_group2.id], dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the ModifyNetworkInterface operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ModifyNetworkInterface operation: Request would have succeeded, but DryRun flag is set')
@ -183,11 +184,11 @@ def test_elastic_network_interfaces_get_by_tag_name():
eni1 = ec2.create_network_interface(SubnetId=subnet.id, PrivateIpAddress='10.0.10.5') eni1 = ec2.create_network_interface(SubnetId=subnet.id, PrivateIpAddress='10.0.10.5')
with assert_raises(JSONResponseError) as ex: with assert_raises(ClientError) as ex:
eni1.create_tags(Tags=[{'Key': 'Name', 'Value': 'eni1'}], DryRun=True) eni1.create_tags(Tags=[{'Key': 'Name', 'Value': 'eni1'}], DryRun=True)
ex.exception.reason.should.equal('DryRunOperation') ex.exception.response['Error']['Code'].should.equal('DryRunOperation')
ex.exception.status.should.equal(400) ex.exception.response['ResponseMetadata']['HTTPStatusCode'].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') ex.exception.response['Error']['Message'].should.equal('An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set')
eni1.create_tags(Tags=[{'Key': 'Name', 'Value': 'eni1'}]) eni1.create_tags(Tags=[{'Key': 'Name', 'Value': 'eni1'}])

View File

@ -8,7 +8,7 @@ import datetime
import boto import boto
from boto.ec2.instance import Reservation, InstanceAttribute from boto.ec2.instance import Reservation, InstanceAttribute
from boto.exception import EC2ResponseError, JSONResponseError from boto.exception import EC2ResponseError, EC2ResponseError
from freezegun import freeze_time from freezegun import freeze_time
import sure # noqa import sure # noqa
@ -41,9 +41,9 @@ def test_add_servers():
def test_instance_launch_and_terminate(): def test_instance_launch_and_terminate():
conn = boto.connect_ec2('the_key', 'the_secret') conn = boto.connect_ec2('the_key', 'the_secret')
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
reservation = conn.run_instances('ami-1234abcd', dry_run=True) reservation = conn.run_instances('ami-1234abcd', dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the RunInstance operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the RunInstance operation: Request would have succeeded, but DryRun flag is set')
@ -74,9 +74,9 @@ def test_instance_launch_and_terminate():
volume.attach_data.instance_id.should.equal(instance.id) volume.attach_data.instance_id.should.equal(instance.id)
volume.status.should.equal('in-use') volume.status.should.equal('in-use')
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
conn.terminate_instances([instance.id], dry_run=True) conn.terminate_instances([instance.id], dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the TerminateInstance operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the TerminateInstance operation: Request would have succeeded, but DryRun flag is set')
@ -427,9 +427,9 @@ def test_instance_start_and_stop():
instance_ids = [instance.id for instance in instances] instance_ids = [instance.id for instance in instances]
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
stopped_instances = conn.stop_instances(instance_ids, dry_run=True) stopped_instances = conn.stop_instances(instance_ids, dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the StopInstance operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the StopInstance operation: Request would have succeeded, but DryRun flag is set')
@ -438,9 +438,9 @@ def test_instance_start_and_stop():
for instance in stopped_instances: for instance in stopped_instances:
instance.state.should.equal('stopping') instance.state.should.equal('stopping')
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
started_instances = conn.start_instances([instances[0].id], dry_run=True) started_instances = conn.start_instances([instances[0].id], dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the StartInstance operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the StartInstance operation: Request would have succeeded, but DryRun flag is set')
@ -454,9 +454,9 @@ def test_instance_reboot():
reservation = conn.run_instances('ami-1234abcd') reservation = conn.run_instances('ami-1234abcd')
instance = reservation.instances[0] instance = reservation.instances[0]
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
instance.reboot(dry_run=True) instance.reboot(dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the RebootInstance operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the RebootInstance operation: Request would have succeeded, but DryRun flag is set')
@ -470,9 +470,9 @@ def test_instance_attribute_instance_type():
reservation = conn.run_instances('ami-1234abcd') reservation = conn.run_instances('ami-1234abcd')
instance = reservation.instances[0] instance = reservation.instances[0]
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
instance.modify_attribute("instanceType", "m1.small", dry_run=True) instance.modify_attribute("instanceType", "m1.small", dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the ModifyInstanceType operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ModifyInstanceType operation: Request would have succeeded, but DryRun flag is set')
@ -491,9 +491,9 @@ def test_modify_instance_attribute_security_groups():
sg_id = 'sg-1234abcd' sg_id = 'sg-1234abcd'
sg_id2 = 'sg-abcd4321' sg_id2 = 'sg-abcd4321'
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
instance.modify_attribute("groupSet", [sg_id, sg_id2], dry_run=True) instance.modify_attribute("groupSet", [sg_id, sg_id2], dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the ModifyInstanceSecurityGroups operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ModifyInstanceSecurityGroups operation: Request would have succeeded, but DryRun flag is set')
@ -512,9 +512,9 @@ def test_instance_attribute_user_data():
reservation = conn.run_instances('ami-1234abcd') reservation = conn.run_instances('ami-1234abcd')
instance = reservation.instances[0] instance = reservation.instances[0]
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
instance.modify_attribute("userData", "this is my user data", dry_run=True) instance.modify_attribute("userData", "this is my user data", dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the ModifyUserData operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ModifyUserData operation: Request would have succeeded, but DryRun flag is set')
@ -540,9 +540,9 @@ def test_instance_attribute_source_dest_check():
# Set to false (note: Boto converts bool to string, eg 'false') # Set to false (note: Boto converts bool to string, eg 'false')
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
instance.modify_attribute("sourceDestCheck", False, dry_run=True) instance.modify_attribute("sourceDestCheck", False, dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the ModifySourceDestCheck operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ModifySourceDestCheck operation: Request would have succeeded, but DryRun flag is set')
@ -584,9 +584,9 @@ def test_user_data_with_run_instance():
def test_run_instance_with_security_group_name(): def test_run_instance_with_security_group_name():
conn = boto.connect_ec2('the_key', 'the_secret') conn = boto.connect_ec2('the_key', 'the_secret')
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
group = conn.create_security_group('group1', "some description", dry_run=True) group = conn.create_security_group('group1', "some description", dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the CreateSecurityGroup operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateSecurityGroup operation: Request would have succeeded, but DryRun flag is set')
@ -745,9 +745,9 @@ def test_instance_with_nic_attach_detach():
set([group.id for group in eni.groups]).should.equal(set([security_group2.id])) set([group.id for group in eni.groups]).should.equal(set([security_group2.id]))
# Attach # Attach
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
conn.attach_network_interface(eni.id, instance.id, device_index=1, dry_run=True) conn.attach_network_interface(eni.id, instance.id, device_index=1, dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the AttachNetworkInterface operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the AttachNetworkInterface operation: Request would have succeeded, but DryRun flag is set')
@ -766,9 +766,9 @@ def test_instance_with_nic_attach_detach():
set([group.id for group in eni.groups]).should.equal(set([security_group1.id,security_group2.id])) set([group.id for group in eni.groups]).should.equal(set([security_group1.id,security_group2.id]))
# Detach # Detach
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
conn.detach_network_interface(instance_eni.attachment.id, dry_run=True) conn.detach_network_interface(instance_eni.attachment.id, dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the DetachNetworkInterface operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the DetachNetworkInterface operation: Request would have succeeded, but DryRun flag is set')
@ -886,9 +886,9 @@ def test_get_instance_by_security_group():
security_group = conn.create_security_group('test', 'test') security_group = conn.create_security_group('test', 'test')
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
conn.modify_instance_attribute(instance.id, "groupSet", [security_group.id], dry_run=True) conn.modify_instance_attribute(instance.id, "groupSet", [security_group.id], dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the ModifyInstanceSecurityGroups operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ModifyInstanceSecurityGroups operation: Request would have succeeded, but DryRun flag is set')

View File

@ -6,7 +6,7 @@ from nose.tools import assert_raises
import re import re
import boto import boto
from boto.exception import EC2ResponseError, JSONResponseError from boto.exception import EC2ResponseError
import sure # noqa import sure # noqa
@ -24,9 +24,9 @@ def test_igw_create():
conn.get_all_internet_gateways().should.have.length_of(0) conn.get_all_internet_gateways().should.have.length_of(0)
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
igw = conn.create_internet_gateway(dry_run=True) igw = conn.create_internet_gateway(dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the CreateInternetGateway operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateInternetGateway operation: Request would have succeeded, but DryRun flag is set')
@ -44,9 +44,9 @@ def test_igw_attach():
igw = conn.create_internet_gateway() igw = conn.create_internet_gateway()
vpc = conn.create_vpc(VPC_CIDR) vpc = conn.create_vpc(VPC_CIDR)
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
conn.attach_internet_gateway(igw.id, vpc.id, dry_run=True) conn.attach_internet_gateway(igw.id, vpc.id, dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the AttachInternetGateway operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the AttachInternetGateway operation: Request would have succeeded, but DryRun flag is set')
@ -90,9 +90,9 @@ def test_igw_detach():
vpc = conn.create_vpc(VPC_CIDR) vpc = conn.create_vpc(VPC_CIDR)
conn.attach_internet_gateway(igw.id, vpc.id) conn.attach_internet_gateway(igw.id, vpc.id)
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
conn.detach_internet_gateway(igw.id, vpc.id, dry_run=True) conn.detach_internet_gateway(igw.id, vpc.id, dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the DetachInternetGateway operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the DetachInternetGateway operation: Request would have succeeded, but DryRun flag is set')
@ -151,9 +151,9 @@ def test_igw_delete():
igw = conn.create_internet_gateway() igw = conn.create_internet_gateway()
conn.get_all_internet_gateways().should.have.length_of(1) conn.get_all_internet_gateways().should.have.length_of(1)
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
conn.delete_internet_gateway(igw.id, dry_run=True) conn.delete_internet_gateway(igw.id, dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the DeleteInternetGateway operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the DeleteInternetGateway operation: Request would have succeeded, but DryRun flag is set')

View File

@ -7,7 +7,7 @@ import boto
import six import six
import sure # noqa import sure # noqa
from boto.exception import EC2ResponseError, JSONResponseError from boto.exception import EC2ResponseError
from moto import mock_ec2_deprecated from moto import mock_ec2_deprecated
@ -32,9 +32,9 @@ def test_key_pairs_invalid_id():
def test_key_pairs_create(): def test_key_pairs_create():
conn = boto.connect_ec2('the_key', 'the_secret') conn = boto.connect_ec2('the_key', 'the_secret')
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
kp = conn.create_key_pair('foo', dry_run=True) kp = conn.create_key_pair('foo', dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the CreateKeyPair operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateKeyPair operation: Request would have succeeded, but DryRun flag is set')
@ -87,9 +87,9 @@ def test_key_pairs_delete_exist():
conn = boto.connect_ec2('the_key', 'the_secret') conn = boto.connect_ec2('the_key', 'the_secret')
conn.create_key_pair('foo') conn.create_key_pair('foo')
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
r = conn.delete_key_pair('foo', dry_run=True) r = conn.delete_key_pair('foo', dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the DeleteKeyPair operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the DeleteKeyPair operation: Request would have succeeded, but DryRun flag is set')
@ -102,9 +102,9 @@ def test_key_pairs_delete_exist():
def test_key_pairs_import(): def test_key_pairs_import():
conn = boto.connect_ec2('the_key', 'the_secret') conn = boto.connect_ec2('the_key', 'the_secret')
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
kp = conn.import_key_pair('foo', b'content', dry_run=True) kp = conn.import_key_pair('foo', b'content', dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the ImportKeyPair operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ImportKeyPair operation: Request would have succeeded, but DryRun flag is set')

View File

@ -9,7 +9,7 @@ from nose.tools import assert_raises
import boto3 import boto3
import boto import boto
from botocore.exceptions import ClientError from botocore.exceptions import ClientError
from boto.exception import EC2ResponseError, JSONResponseError from boto.exception import EC2ResponseError
import sure # noqa import sure # noqa
from moto import mock_ec2, mock_ec2_deprecated from moto import mock_ec2, mock_ec2_deprecated
@ -19,9 +19,9 @@ from moto import mock_ec2, mock_ec2_deprecated
def test_create_and_describe_security_group(): def test_create_and_describe_security_group():
conn = boto.connect_ec2('the_key', 'the_secret') conn = boto.connect_ec2('the_key', 'the_secret')
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
security_group = conn.create_security_group('test security group', 'this is a test security group', dry_run=True) security_group = conn.create_security_group('test security group', 'this is a test security group', dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the CreateSecurityGroup operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateSecurityGroup operation: Request would have succeeded, but DryRun flag is set')
@ -121,9 +121,9 @@ def test_deleting_security_groups():
cm.exception.request_id.should_not.be.none cm.exception.request_id.should_not.be.none
# Delete by name # Delete by name
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
conn.delete_security_group('test2', dry_run=True) conn.delete_security_group('test2', dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the DeleteSecurityGroup operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the DeleteSecurityGroup operation: Request would have succeeded, but DryRun flag is set')
@ -150,9 +150,9 @@ def test_authorize_ip_range_and_revoke():
conn = boto.connect_ec2('the_key', 'the_secret') conn = boto.connect_ec2('the_key', 'the_secret')
security_group = conn.create_security_group('test', 'test') security_group = conn.create_security_group('test', 'test')
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
success = security_group.authorize(ip_protocol="tcp", from_port="22", to_port="2222", cidr_ip="123.123.123.123/32", dry_run=True) success = security_group.authorize(ip_protocol="tcp", from_port="22", to_port="2222", cidr_ip="123.123.123.123/32", dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the GrantSecurityGroupIngress operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the GrantSecurityGroupIngress operation: Request would have succeeded, but DryRun flag is set')
@ -171,9 +171,9 @@ def test_authorize_ip_range_and_revoke():
cm.exception.request_id.should_not.be.none cm.exception.request_id.should_not.be.none
# Actually revoke # Actually revoke
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
security_group.revoke(ip_protocol="tcp", from_port="22", to_port="2222", cidr_ip="123.123.123.123/32", dry_run=True) security_group.revoke(ip_protocol="tcp", from_port="22", to_port="2222", cidr_ip="123.123.123.123/32", dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the RevokeSecurityGroupIngress operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the RevokeSecurityGroupIngress operation: Request would have succeeded, but DryRun flag is set')
@ -185,9 +185,9 @@ def test_authorize_ip_range_and_revoke():
# Test for egress as well # Test for egress as well
egress_security_group = conn.create_security_group('testegress', 'testegress', vpc_id='vpc-3432589') egress_security_group = conn.create_security_group('testegress', 'testegress', vpc_id='vpc-3432589')
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
success = conn.authorize_security_group_egress(egress_security_group.id, "tcp", from_port="22", to_port="2222", cidr_ip="123.123.123.123/32", dry_run=True) success = conn.authorize_security_group_egress(egress_security_group.id, "tcp", from_port="22", to_port="2222", cidr_ip="123.123.123.123/32", dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the GrantSecurityGroupEgress operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the GrantSecurityGroupEgress operation: Request would have succeeded, but DryRun flag is set')
@ -203,9 +203,9 @@ def test_authorize_ip_range_and_revoke():
egress_security_group.revoke.when.called_with(ip_protocol="tcp", from_port="22", to_port="2222", cidr_ip="123.123.123.122/32").should.throw(EC2ResponseError) egress_security_group.revoke.when.called_with(ip_protocol="tcp", from_port="22", to_port="2222", cidr_ip="123.123.123.122/32").should.throw(EC2ResponseError)
# Actually revoke # Actually revoke
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
conn.revoke_security_group_egress(egress_security_group.id, "tcp", from_port="22", to_port="2222", cidr_ip="123.123.123.123/32", dry_run=True) conn.revoke_security_group_egress(egress_security_group.id, "tcp", from_port="22", to_port="2222", cidr_ip="123.123.123.123/32", dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the RevokeSecurityGroupEgress operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the RevokeSecurityGroupEgress operation: Request would have succeeded, but DryRun flag is set')
@ -339,9 +339,9 @@ def test_security_group_tagging():
sg = conn.create_security_group("test-sg", "Test SG", vpc.id) sg = conn.create_security_group("test-sg", "Test SG", vpc.id)
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
sg.add_tag("Test", "Tag", dry_run=True) sg.add_tag("Test", "Tag", dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set')
@ -540,11 +540,11 @@ def test_security_group_tagging_boto3():
sg = conn.create_security_group(GroupName="test-sg", Description="Test SG") sg = conn.create_security_group(GroupName="test-sg", Description="Test SG")
with assert_raises(JSONResponseError) as ex: with assert_raises(ClientError) as ex:
conn.create_tags(Resources=[sg['GroupId']], Tags=[{'Key': 'Test', 'Value': 'Tag'}], DryRun=True) conn.create_tags(Resources=[sg['GroupId']], Tags=[{'Key': 'Test', 'Value': 'Tag'}], DryRun=True)
ex.exception.reason.should.equal('DryRunOperation') ex.exception.response['Error']['Code'].should.equal('DryRunOperation')
ex.exception.status.should.equal(400) ex.exception.response['ResponseMetadata']['HTTPStatusCode'].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') ex.exception.response['Error']['Message'].should.equal('An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set')
conn.create_tags(Resources=[sg['GroupId']], Tags=[{'Key': 'Test', 'Value': 'Tag'}]) conn.create_tags(Resources=[sg['GroupId']], Tags=[{'Key': 'Test', 'Value': 'Tag'}])
describe = conn.describe_security_groups(Filters=[{'Name': 'tag-value', 'Values': ['Tag']}]) describe = conn.describe_security_groups(Filters=[{'Name': 'tag-value', 'Values': ['Tag']}])

View File

@ -4,8 +4,10 @@ import datetime
import boto import boto
import boto3 import boto3
from boto.exception import EC2ResponseError
from botocore.exceptions import ClientError
import pytz
import sure # noqa import sure # noqa
from boto.exception import JSONResponseError
from moto import mock_ec2, mock_ec2_deprecated from moto import mock_ec2, mock_ec2_deprecated
from moto.backends import get_model from moto.backends import get_model
@ -13,98 +15,130 @@ from moto.core.utils import iso_8601_datetime_with_milliseconds
@mock_ec2 @mock_ec2
@mock_ec2_deprecated
def test_request_spot_instances(): def test_request_spot_instances():
conn = boto3.client('ec2', 'us-east-1') conn = boto3.client('ec2', 'us-east-1')
vpc = conn.create_vpc(CidrBlock="10.0.0.0/8")['Vpc'] vpc = conn.create_vpc(CidrBlock="10.0.0.0/8")['Vpc']
subnet = conn.create_subnet(VpcId=vpc['VpcId'], CidrBlock='10.0.0.0/16', AvailabilityZone='us-east-1a')['Subnet'] subnet = conn.create_subnet(VpcId=vpc['VpcId'], CidrBlock='10.0.0.0/16', AvailabilityZone='us-east-1a')['Subnet']
subnet_id = subnet['SubnetId'] subnet_id = subnet['SubnetId']
conn = boto.connect_ec2() conn.create_security_group(GroupName='group1', Description='description')
conn.create_security_group(GroupName='group2', Description='description')
conn.create_security_group('group1', 'description') start_dt = datetime.datetime(2013, 1, 1).replace(tzinfo=pytz.utc)
conn.create_security_group('group2', 'description') end_dt = datetime.datetime(2013, 1, 2).replace(tzinfo=pytz.utc)
start = iso_8601_datetime_with_milliseconds(start_dt)
end = iso_8601_datetime_with_milliseconds(end_dt)
start = iso_8601_datetime_with_milliseconds(datetime.datetime(2013, 1, 1)) with assert_raises(ClientError) as ex:
end = iso_8601_datetime_with_milliseconds(datetime.datetime(2013, 1, 2))
with assert_raises(JSONResponseError) as ex:
request = conn.request_spot_instances( request = conn.request_spot_instances(
price=0.5, image_id='ami-abcd1234', count=1, type='one-time', SpotPrice="0.5", InstanceCount=1, Type='one-time',
valid_from=start, valid_until=end, launch_group="the-group", ValidFrom=start, ValidUntil=end, LaunchGroup="the-group",
availability_zone_group='my-group', key_name="test", AvailabilityZoneGroup='my-group',
security_groups=['group1', 'group2'], user_data=b"some test data", LaunchSpecification={
instance_type='m1.small', placement='us-east-1c', "ImageId": 'ami-abcd1234',
kernel_id="test-kernel", ramdisk_id="test-ramdisk", "KeyName": "test",
monitoring_enabled=True, subnet_id=subnet_id, dry_run=True "SecurityGroups": ['group1', 'group2'],
"UserData": b"some test data",
"InstanceType": 'm1.small',
"Placement": {
"AvailabilityZone": 'us-east-1c',
},
"KernelId": "test-kernel",
"RamdiskId": "test-ramdisk",
"Monitoring": {
"Enabled": True,
},
"SubnetId": subnet_id,
},
DryRun=True,
) )
ex.exception.reason.should.equal('DryRunOperation') ex.exception.response['Error']['Code'].should.equal('DryRunOperation')
ex.exception.status.should.equal(400) ex.exception.response['ResponseMetadata']['HTTPStatusCode'].should.equal(400)
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the RequestSpotInstance operation: Request would have succeeded, but DryRun flag is set') ex.exception.response['Error']['Message'].should.equal('An error occurred (DryRunOperation) when calling the RequestSpotInstance operation: Request would have succeeded, but DryRun flag is set')
request = conn.request_spot_instances( request = conn.request_spot_instances(
price=0.5, image_id='ami-abcd1234', count=1, type='one-time', SpotPrice="0.5", InstanceCount=1, Type='one-time',
valid_from=start, valid_until=end, launch_group="the-group", ValidFrom=start, ValidUntil=end, LaunchGroup="the-group",
availability_zone_group='my-group', key_name="test", AvailabilityZoneGroup='my-group',
security_groups=['group1', 'group2'], user_data=b"some test data", LaunchSpecification={
instance_type='m1.small', placement='us-east-1c', "ImageId": 'ami-abcd1234',
kernel_id="test-kernel", ramdisk_id="test-ramdisk", "KeyName": "test",
monitoring_enabled=True, subnet_id=subnet_id, "SecurityGroups": ['group1', 'group2'],
"UserData": b"some test data",
"InstanceType": 'm1.small',
"Placement": {
"AvailabilityZone": 'us-east-1c',
},
"KernelId": "test-kernel",
"RamdiskId": "test-ramdisk",
"Monitoring": {
"Enabled": True,
},
"SubnetId": subnet_id,
},
) )
requests = conn.get_all_spot_instance_requests() requests = conn.describe_spot_instance_requests()['SpotInstanceRequests']
requests.should.have.length_of(1) requests.should.have.length_of(1)
request = requests[0] request = requests[0]
request.state.should.equal("open") request['State'].should.equal("open")
request.price.should.equal(0.5) request['SpotPrice'].should.equal("0.5")
request.launch_specification.image_id.should.equal('ami-abcd1234') request['Type'].should.equal('one-time')
request.type.should.equal('one-time') request['ValidFrom'].should.equal(start_dt)
request.valid_from.should.equal(start) request['ValidUntil'].should.equal(end_dt)
request.valid_until.should.equal(end) request['LaunchGroup'].should.equal("the-group")
request.launch_group.should.equal("the-group") request['AvailabilityZoneGroup'].should.equal('my-group')
request.availability_zone_group.should.equal('my-group')
request.launch_specification.key_name.should.equal("test") launch_spec = request['LaunchSpecification']
security_group_names = [group.name for group in request.launch_specification.groups] security_group_names = [group['GroupName'] for group in launch_spec['SecurityGroups']]
set(security_group_names).should.equal(set(['group1', 'group2'])) set(security_group_names).should.equal(set(['group1', 'group2']))
request.launch_specification.instance_type.should.equal('m1.small')
request.launch_specification.placement.should.equal('us-east-1c') launch_spec['ImageId'].should.equal('ami-abcd1234')
request.launch_specification.kernel.should.equal("test-kernel") launch_spec['KeyName'].should.equal("test")
request.launch_specification.ramdisk.should.equal("test-ramdisk") launch_spec['InstanceType'].should.equal('m1.small')
request.launch_specification.subnet_id.should.equal(subnet_id) launch_spec['KernelId'].should.equal("test-kernel")
launch_spec['RamdiskId'].should.equal("test-ramdisk")
launch_spec['SubnetId'].should.equal(subnet_id)
@mock_ec2_deprecated @mock_ec2
def test_request_spot_instances_default_arguments(): def test_request_spot_instances_default_arguments():
""" """
Test that moto set the correct default arguments Test that moto set the correct default arguments
""" """
conn = boto.connect_ec2() conn = boto3.client('ec2', 'us-east-1')
request = conn.request_spot_instances( request = conn.request_spot_instances(
price=0.5, image_id='ami-abcd1234', SpotPrice="0.5",
LaunchSpecification={
"ImageId": 'ami-abcd1234',
}
) )
requests = conn.get_all_spot_instance_requests() requests = conn.describe_spot_instance_requests()['SpotInstanceRequests']
requests.should.have.length_of(1) requests.should.have.length_of(1)
request = requests[0] request = requests[0]
request.state.should.equal("open") request['State'].should.equal("open")
request.price.should.equal(0.5) request['SpotPrice'].should.equal("0.5")
request.launch_specification.image_id.should.equal('ami-abcd1234') request['Type'].should.equal('one-time')
request.type.should.equal('one-time') request.shouldnt.contain('ValidFrom')
request.valid_from.should.equal(None) request.shouldnt.contain('ValidUntil')
request.valid_until.should.equal(None) request.shouldnt.contain('LaunchGroup')
request.launch_group.should.equal(None) request.shouldnt.contain('AvailabilityZoneGroup')
request.availability_zone_group.should.equal(None)
request.launch_specification.key_name.should.equal(None) launch_spec = request['LaunchSpecification']
security_group_names = [group.name for group in request.launch_specification.groups]
security_group_names = [group['GroupName'] for group in launch_spec['SecurityGroups']]
security_group_names.should.equal(["default"]) security_group_names.should.equal(["default"])
request.launch_specification.instance_type.should.equal('m1.small')
request.launch_specification.placement.should.equal(None) launch_spec['ImageId'].should.equal('ami-abcd1234')
request.launch_specification.kernel.should.equal(None) request.shouldnt.contain('KeyName')
request.launch_specification.ramdisk.should.equal(None) launch_spec['InstanceType'].should.equal('m1.small')
request.launch_specification.subnet_id.should.equal(None) request.shouldnt.contain('KernelId')
request.shouldnt.contain('RamdiskId')
request.shouldnt.contain('SubnetId')
@mock_ec2_deprecated @mock_ec2_deprecated
@ -119,9 +153,9 @@ def test_cancel_spot_instance_request():
requests.should.have.length_of(1) requests.should.have.length_of(1)
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
conn.cancel_spot_instance_requests([requests[0].id], dry_run=True) conn.cancel_spot_instance_requests([requests[0].id], dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the CancelSpotInstance operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CancelSpotInstance operation: Request would have succeeded, but DryRun flag is set')
@ -148,7 +182,7 @@ def test_request_spot_instances_fulfilled():
request.state.should.equal("open") request.state.should.equal("open")
get_model('SpotInstanceRequest')[0].state = 'active' get_model('SpotInstanceRequest', 'us-east-1')[0].state = 'active'
requests = conn.get_all_spot_instance_requests() requests = conn.get_all_spot_instance_requests()
requests.should.have.length_of(1) requests.should.have.length_of(1)
@ -218,7 +252,7 @@ def test_request_spot_instances_setting_instance_id():
request = conn.request_spot_instances( request = conn.request_spot_instances(
price=0.5, image_id='ami-abcd1234') price=0.5, image_id='ami-abcd1234')
req = get_model('SpotInstanceRequest')[0] req = get_model('SpotInstanceRequest', 'us-east-1')[0]
req.state = 'active' req.state = 'active'
req.instance_id = 'i-12345678' req.instance_id = 'i-12345678'

View File

@ -4,7 +4,7 @@ from nose.tools import assert_raises
import itertools import itertools
import boto import boto
from boto.exception import EC2ResponseError, JSONResponseError from boto.exception import EC2ResponseError
from boto.ec2.instance import Reservation from boto.ec2.instance import Reservation
import sure # noqa import sure # noqa
@ -18,9 +18,9 @@ def test_add_tag():
reservation = conn.run_instances('ami-1234abcd') reservation = conn.run_instances('ami-1234abcd')
instance = reservation.instances[0] instance = reservation.instances[0]
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
instance.add_tag("a key", "some value", dry_run=True) instance.add_tag("a key", "some value", dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set')
@ -45,9 +45,9 @@ def test_remove_tag():
tag.name.should.equal("a key") tag.name.should.equal("a key")
tag.value.should.equal("some value") tag.value.should.equal("some value")
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
instance.remove_tag("a key", dry_run=True) instance.remove_tag("a key", dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the DeleteTags operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the DeleteTags operation: Request would have succeeded, but DryRun flag is set')
@ -96,9 +96,9 @@ def test_create_tags():
'another key': 'some other value', 'another key': 'some other value',
'blank key': ''} 'blank key': ''}
with assert_raises(JSONResponseError) as ex: with assert_raises(EC2ResponseError) as ex:
conn.create_tags(instance.id, tag_dict, dry_run=True) conn.create_tags(instance.id, tag_dict, dry_run=True)
ex.exception.reason.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('An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set') ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set')

View File

@ -112,7 +112,7 @@ def test_describe_jobflows():
args = run_jobflow_args.copy() args = run_jobflow_args.copy()
expected = {} expected = {}
for idx in range(400): for idx in range(4):
cluster_name = 'cluster' + str(idx) cluster_name = 'cluster' + str(idx)
args['name'] = cluster_name args['name'] = cluster_name
cluster_id = conn.run_jobflow(**args) cluster_id = conn.run_jobflow(**args)
@ -128,7 +128,7 @@ def test_describe_jobflows():
timestamp = datetime.now(pytz.utc) timestamp = datetime.now(pytz.utc)
time.sleep(1) time.sleep(1)
for idx in range(400, 600): for idx in range(4, 6):
cluster_name = 'cluster' + str(idx) cluster_name = 'cluster' + str(idx)
args['name'] = cluster_name args['name'] = cluster_name
cluster_id = conn.run_jobflow(**args) cluster_id = conn.run_jobflow(**args)
@ -139,7 +139,7 @@ def test_describe_jobflows():
'state': 'TERMINATED' 'state': 'TERMINATED'
} }
jobs = conn.describe_jobflows() jobs = conn.describe_jobflows()
jobs.should.have.length_of(512) jobs.should.have.length_of(6)
for cluster_id, y in expected.items(): for cluster_id, y in expected.items():
resp = conn.describe_jobflows(jobflow_ids=[cluster_id]) resp = conn.describe_jobflows(jobflow_ids=[cluster_id])
@ -147,15 +147,15 @@ def test_describe_jobflows():
resp[0].jobflowid.should.equal(cluster_id) resp[0].jobflowid.should.equal(cluster_id)
resp = conn.describe_jobflows(states=['WAITING']) resp = conn.describe_jobflows(states=['WAITING'])
resp.should.have.length_of(400) resp.should.have.length_of(4)
for x in resp: for x in resp:
x.state.should.equal('WAITING') x.state.should.equal('WAITING')
resp = conn.describe_jobflows(created_before=timestamp) resp = conn.describe_jobflows(created_before=timestamp)
resp.should.have.length_of(400) resp.should.have.length_of(4)
resp = conn.describe_jobflows(created_after=timestamp) resp = conn.describe_jobflows(created_after=timestamp)
resp.should.have.length_of(200) resp.should.have.length_of(2)
@mock_emr_deprecated @mock_emr_deprecated

View File

@ -128,7 +128,7 @@ def test_describe_job_flows():
args = deepcopy(run_job_flow_args) args = deepcopy(run_job_flow_args)
expected = {} expected = {}
for idx in range(400): for idx in range(4):
cluster_name = 'cluster' + str(idx) cluster_name = 'cluster' + str(idx)
args['Name'] = cluster_name args['Name'] = cluster_name
cluster_id = client.run_job_flow(**args)['JobFlowId'] cluster_id = client.run_job_flow(**args)['JobFlowId']
@ -144,7 +144,7 @@ def test_describe_job_flows():
timestamp = datetime.now(pytz.utc) timestamp = datetime.now(pytz.utc)
time.sleep(1) time.sleep(1)
for idx in range(400, 600): for idx in range(4, 6):
cluster_name = 'cluster' + str(idx) cluster_name = 'cluster' + str(idx)
args['Name'] = cluster_name args['Name'] = cluster_name
cluster_id = client.run_job_flow(**args)['JobFlowId'] cluster_id = client.run_job_flow(**args)['JobFlowId']
@ -156,7 +156,7 @@ def test_describe_job_flows():
} }
resp = client.describe_job_flows() resp = client.describe_job_flows()
resp['JobFlows'].should.have.length_of(512) resp['JobFlows'].should.have.length_of(6)
for cluster_id, y in expected.items(): for cluster_id, y in expected.items():
resp = client.describe_job_flows(JobFlowIds=[cluster_id]) resp = client.describe_job_flows(JobFlowIds=[cluster_id])
@ -164,15 +164,15 @@ def test_describe_job_flows():
resp['JobFlows'][0]['JobFlowId'].should.equal(cluster_id) resp['JobFlows'][0]['JobFlowId'].should.equal(cluster_id)
resp = client.describe_job_flows(JobFlowStates=['WAITING']) resp = client.describe_job_flows(JobFlowStates=['WAITING'])
resp['JobFlows'].should.have.length_of(400) resp['JobFlows'].should.have.length_of(4)
for x in resp['JobFlows']: for x in resp['JobFlows']:
x['ExecutionStatusDetail']['State'].should.equal('WAITING') x['ExecutionStatusDetail']['State'].should.equal('WAITING')
resp = client.describe_job_flows(CreatedBefore=timestamp) resp = client.describe_job_flows(CreatedBefore=timestamp)
resp['JobFlows'].should.have.length_of(400) resp['JobFlows'].should.have.length_of(4)
resp = client.describe_job_flows(CreatedAfter=timestamp) resp = client.describe_job_flows(CreatedAfter=timestamp)
resp['JobFlows'].should.have.length_of(200) resp['JobFlows'].should.have.length_of(2)
@mock_emr @mock_emr
@ -327,13 +327,13 @@ def test_run_job_flow():
@mock_emr @mock_emr
def test_run_job_flow_with_invalid_params(): def test_run_job_flow_with_invalid_params():
client = boto3.client('emr', region_name='us-east-1') client = boto3.client('emr', region_name='us-east-1')
with assert_raises(ClientError) as e: with assert_raises(ClientError) as ex:
# cannot set both AmiVersion and ReleaseLabel # cannot set both AmiVersion and ReleaseLabel
args = deepcopy(run_job_flow_args) args = deepcopy(run_job_flow_args)
args['AmiVersion'] = '2.4' args['AmiVersion'] = '2.4'
args['ReleaseLabel'] = 'emr-5.0.0' args['ReleaseLabel'] = 'emr-5.0.0'
client.run_job_flow(**args) client.run_job_flow(**args)
e.exception.response['Error']['Code'].should.equal('ValidationException') ex.exception.response['Error']['Message'].should.contain('ValidationException')
@mock_emr @mock_emr

View File

@ -201,7 +201,7 @@ def test_get_user():
def test_list_users(): def test_list_users():
path_prefix = '/' path_prefix = '/'
max_items = 10 max_items = 10
conn = boto3.client('iam') conn = boto3.client('iam', region_name='us-east-1')
conn.create_user(UserName='my-user') conn.create_user(UserName='my-user')
response = conn.list_users(PathPrefix=path_prefix, MaxItems=max_items) response = conn.list_users(PathPrefix=path_prefix, MaxItems=max_items)
user = response['Users'][0] user = response['Users'][0]
@ -337,7 +337,7 @@ def test_managed_policy():
@mock_iam @mock_iam
def test_boto3_create_login_profile(): def test_boto3_create_login_profile():
conn = boto3.client('iam') conn = boto3.client('iam', region_name='us-east-1')
with assert_raises(ClientError): with assert_raises(ClientError):
conn.create_login_profile(UserName='my-user', Password='Password') conn.create_login_profile(UserName='my-user', Password='Password')

View File

@ -4,7 +4,6 @@ import datetime
from botocore.exceptions import ClientError from botocore.exceptions import ClientError
import boto3 import boto3
from freezegun import freeze_time
import sure # noqa import sure # noqa
from moto import mock_kinesis from moto import mock_kinesis
@ -37,7 +36,6 @@ def create_stream(client, stream_name):
@mock_kinesis @mock_kinesis
@freeze_time("2015-03-01")
def test_create_stream(): def test_create_stream():
client = boto3.client('firehose', region_name='us-east-1') client = boto3.client('firehose', region_name='us-east-1')
@ -48,11 +46,8 @@ def test_create_stream():
stream_description = response['DeliveryStreamDescription'] stream_description = response['DeliveryStreamDescription']
# Sure and Freezegun don't play nicely together # Sure and Freezegun don't play nicely together
created = stream_description.pop('CreateTimestamp') _ = stream_description.pop('CreateTimestamp')
last_updated = stream_description.pop('LastUpdateTimestamp') _ = stream_description.pop('LastUpdateTimestamp')
from dateutil.tz import tzlocal
assert created == datetime.datetime(2015, 3, 1, tzinfo=tzlocal())
assert last_updated == datetime.datetime(2015, 3, 1, tzinfo=tzlocal())
stream_description.should.equal({ stream_description.should.equal({
'DeliveryStreamName': 'stream1', 'DeliveryStreamName': 'stream1',
@ -88,7 +83,6 @@ def test_create_stream():
@mock_kinesis @mock_kinesis
@freeze_time("2015-03-01")
def test_create_stream_without_redshift(): def test_create_stream_without_redshift():
client = boto3.client('firehose', region_name='us-east-1') client = boto3.client('firehose', region_name='us-east-1')
@ -111,11 +105,8 @@ def test_create_stream_without_redshift():
stream_description = response['DeliveryStreamDescription'] stream_description = response['DeliveryStreamDescription']
# Sure and Freezegun don't play nicely together # Sure and Freezegun don't play nicely together
created = stream_description.pop('CreateTimestamp') _ = stream_description.pop('CreateTimestamp')
last_updated = stream_description.pop('LastUpdateTimestamp') _ = stream_description.pop('LastUpdateTimestamp')
from dateutil.tz import tzlocal
assert created == datetime.datetime(2015, 3, 1, tzinfo=tzlocal())
assert last_updated == datetime.datetime(2015, 3, 1, tzinfo=tzlocal())
stream_description.should.equal({ stream_description.should.equal({
'DeliveryStreamName': 'stream1', 'DeliveryStreamName': 'stream1',
@ -142,7 +133,6 @@ def test_create_stream_without_redshift():
}) })
@mock_kinesis @mock_kinesis
@freeze_time("2015-03-01")
def test_deescribe_non_existant_stream(): def test_deescribe_non_existant_stream():
client = boto3.client('firehose', region_name='us-east-1') client = boto3.client('firehose', region_name='us-east-1')
@ -150,7 +140,6 @@ def test_deescribe_non_existant_stream():
@mock_kinesis @mock_kinesis
@freeze_time("2015-03-01")
def test_list_and_delete_stream(): def test_list_and_delete_stream():
client = boto3.client('firehose', region_name='us-east-1') client = boto3.client('firehose', region_name='us-east-1')

View File

@ -308,7 +308,7 @@ def test_hosted_zone_private_zone_preserved():
@mock_route53 @mock_route53
def test_hosted_zone_private_zone_preserved_boto3(): def test_hosted_zone_private_zone_preserved_boto3():
conn = boto3.client('route53') conn = boto3.client('route53', region_name='us-east-1')
# TODO: actually create_hosted_zone statements with PrivateZone=True, but without # TODO: actually create_hosted_zone statements with PrivateZone=True, but without
# a _valid_ vpc-id should fail. # a _valid_ vpc-id should fail.
firstzone = conn.create_hosted_zone( firstzone = conn.create_hosted_zone(
@ -333,8 +333,20 @@ def test_hosted_zone_private_zone_preserved_boto3():
@mock_route53 @mock_route53
def test_list_or_change_tags_for_resource_request(): def test_list_or_change_tags_for_resource_request():
conn = boto3.client('route53') conn = boto3.client('route53', region_name='us-east-1')
healthcheck_id = str(uuid.uuid4()) health_check = conn.create_health_check(
CallerReference='foobar',
HealthCheckConfig={
'IPAddress': '192.0.2.44',
'Port': 123,
'Type': 'HTTP',
'ResourcePath': '/',
'RequestInterval': 30,
'FailureThreshold': 123,
'HealthThreshold': 123,
}
)
healthcheck_id = health_check['HealthCheck']['Id']
tag1 = {"Key": "Deploy", "Value": "True"} tag1 = {"Key": "Deploy", "Value": "True"}
tag2 = {"Key": "Name", "Value": "UnitTest"} tag2 = {"Key": "Name", "Value": "UnitTest"}

View File

@ -20,17 +20,21 @@ from nose.tools import assert_raises
import sure # noqa import sure # noqa
from moto import mock_s3, mock_s3_deprecated from moto import settings, mock_s3, mock_s3_deprecated
import moto.s3.models as s3model
if settings.TEST_SERVER_MODE:
REDUCED_PART_SIZE = s3model.UPLOAD_PART_MIN_SIZE
EXPECTED_ETAG = '"140f92a6df9f9e415f74a1463bcee9bb-2"'
else:
REDUCED_PART_SIZE = 256 REDUCED_PART_SIZE = 256
EXPECTED_ETAG = '"66d1a1a2ed08fd05c137f316af4ff255-2"'
def reduced_min_part_size(f): def reduced_min_part_size(f):
""" speed up tests by temporarily making the multipart minimum part size """ speed up tests by temporarily making the multipart minimum part size
small small
""" """
import moto.s3.models as s3model
orig_size = s3model.UPLOAD_PART_MIN_SIZE orig_size = s3model.UPLOAD_PART_MIN_SIZE
@wraps(f) @wraps(f)
@ -49,24 +53,23 @@ class MyModel(object):
self.value = value self.value = value
def save(self): def save(self):
conn = boto.connect_s3('the_key', 'the_secret') s3 = boto3.client('s3', region_name='us-east-1')
bucket = conn.get_bucket('mybucket') s3.put_object(Bucket='mybucket', Key=self.name, Body=self.value)
k = Key(bucket)
k.key = self.name
k.set_contents_from_string(self.value)
@mock_s3_deprecated @mock_s3
def test_my_model_save(): def test_my_model_save():
# Create Bucket so that test can run # Create Bucket so that test can run
conn = boto.connect_s3('the_key', 'the_secret') conn = boto3.resource('s3', region_name='us-east-1')
conn.create_bucket('mybucket') conn.create_bucket(Bucket='mybucket')
#################################### ####################################
model_instance = MyModel('steve', 'is awesome') model_instance = MyModel('steve', 'is awesome')
model_instance.save() model_instance.save()
conn.get_bucket('mybucket').get_key('steve').get_contents_as_string().should.equal(b'is awesome') body = conn.Object('mybucket', 'steve').get()['Body'].read().decode("utf-8")
assert body == b'is awesome'
@mock_s3_deprecated @mock_s3_deprecated
@ -190,8 +193,7 @@ def test_multipart_etag():
multipart.upload_part_from_file(BytesIO(part2), 2) multipart.upload_part_from_file(BytesIO(part2), 2)
multipart.complete_upload() multipart.complete_upload()
# we should get both parts as the key contents # we should get both parts as the key contents
bucket.get_key("the-key").etag.should.equal( bucket.get_key("the-key").etag.should.equal(EXPECTED_ETAG)
'"66d1a1a2ed08fd05c137f316af4ff255-2"')
@mock_s3_deprecated @mock_s3_deprecated
@ -544,16 +546,6 @@ def test_delete_keys_with_invalid():
keys[0].name.should.equal('file1') keys[0].name.should.equal('file1')
@mock_s3
def test_bucket_method_not_implemented():
requests.patch.when.called_with("https://foobar.s3.amazonaws.com/").should.throw(NotImplementedError)
@mock_s3
def test_key_method_not_implemented():
requests.post.when.called_with("https://foobar.s3.amazonaws.com/foo").should.throw(NotImplementedError)
@mock_s3_deprecated @mock_s3_deprecated
def test_bucket_name_with_dot(): def test_bucket_name_with_dot():
conn = boto.connect_s3() conn = boto.connect_s3()
@ -1241,7 +1233,7 @@ def test_boto3_multipart_etag():
for i, etag in enumerate(etags, 1)]}) for i, etag in enumerate(etags, 1)]})
# we should get both parts as the key contents # we should get both parts as the key contents
resp = s3.get_object(Bucket='mybucket', Key='the-key') resp = s3.get_object(Bucket='mybucket', Key='the-key')
resp['ETag'].should.equal('"66d1a1a2ed08fd05c137f316af4ff255-2"') resp['ETag'].should.equal(EXPECTED_ETAG)
TEST_XML = """\ TEST_XML = """\

View File

@ -211,16 +211,6 @@ def test_post_with_metadata_to_bucket():
bucket.get_key('the-key').get_metadata('test').should.equal('metadata') bucket.get_key('the-key').get_metadata('test').should.equal('metadata')
@mock_s3
def test_bucket_method_not_implemented():
requests.patch.when.called_with("https://s3.amazonaws.com/foobar").should.throw(NotImplementedError)
@mock_s3
def test_key_method_not_implemented():
requests.post.when.called_with("https://s3.amazonaws.com/foobar/foo").should.throw(NotImplementedError)
@mock_s3_deprecated @mock_s3_deprecated
def test_bucket_name_with_dot(): def test_bucket_name_with_dot():
conn = create_connection() conn = create_connection()

View File

@ -67,20 +67,3 @@ def test_publish_to_http():
response = conn.publish(topic=topic_arn, message="my message", subject="my subject") response = conn.publish(topic=topic_arn, message="my message", subject="my subject")
message_id = response['PublishResponse']['PublishResult']['MessageId'] message_id = response['PublishResponse']['PublishResult']['MessageId']
last_request = responses.calls[-1].request
last_request.method.should.equal("POST")
parse_qs(last_request.body).should.equal({
"Type": ["Notification"],
"MessageId": [message_id],
"TopicArn": ["arn:aws:sns:{0}:123456789012:some-topic".format(conn.region.name)],
"Subject": ["my subject"],
"Message": ["my message"],
"Timestamp": ["2013-01-01T00:00:00.000Z"],
"SignatureVersion": ["1"],
"Signature": ["EXAMPLElDMXvB8r9R83tGoNn0ecwd5UjllzsvSvbItzfaMpN2nk5HVSw7XnOn/49IkxDKz8YrlH2qJXj2iZB0Zo2O71c4qQk1fMUDi3LGpij7RCW7AW9vYYsSqIKRnFS94ilu7NFhUzLiieYr4BKHpdTmdD6c0esKEYBpabxDSc="],
"SigningCertURL": ["https://sns.us-east-1.amazonaws.com/SimpleNotificationService-f3ecfb7224c7233fe7bb5f59f96de52f.pem"],
"UnsubscribeURL": ["https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-1:123456789012:some-topic:2bcfbf39-05c3-41de-beaa-fcfcc21c8f55"],
})

View File

@ -72,18 +72,3 @@ def test_publish_to_http():
response = conn.publish(TopicArn=topic_arn, Message="my message", Subject="my subject") response = conn.publish(TopicArn=topic_arn, Message="my message", Subject="my subject")
message_id = response['MessageId'] message_id = response['MessageId']
last_request = responses.calls[-2].request
last_request.method.should.equal("POST")
parse_qs(last_request.body).should.equal({
"Type": ["Notification"],
"MessageId": [message_id],
"TopicArn": ["arn:aws:sns:{0}:123456789012:some-topic".format(conn._client_config.region_name)],
"Subject": ["my subject"],
"Message": ["my message"],
"Timestamp": ["2013-01-01T00:00:00.000Z"],
"SignatureVersion": ["1"],
"Signature": ["EXAMPLElDMXvB8r9R83tGoNn0ecwd5UjllzsvSvbItzfaMpN2nk5HVSw7XnOn/49IkxDKz8YrlH2qJXj2iZB0Zo2O71c4qQk1fMUDi3LGpij7RCW7AW9vYYsSqIKRnFS94ilu7NFhUzLiieYr4BKHpdTmdD6c0esKEYBpabxDSc="],
"SigningCertURL": ["https://sns.us-east-1.amazonaws.com/SimpleNotificationService-f3ecfb7224c7233fe7bb5f59f96de52f.pem"],
"UnsubscribeURL": ["https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-1:123456789012:some-topic:2bcfbf39-05c3-41de-beaa-fcfcc21c8f55"],
})

View File

@ -408,11 +408,6 @@ def test_delete_batch_operation():
queue.count().should.equal(1) queue.count().should.equal(1)
@mock_sqs
def test_sqs_method_not_implemented():
requests.post.when.called_with("https://sqs.amazonaws.com/?Action=[foobar]").should.throw(NotImplementedError)
@mock_sqs_deprecated @mock_sqs_deprecated
def test_queue_attributes(): def test_queue_attributes():
conn = boto.connect_sqs('the_key', 'the_secret') conn = boto.connect_sqs('the_key', 'the_secret')

View File

@ -68,7 +68,7 @@ def test_assume_role():
@mock_sts @mock_sts
def test_get_caller_identity(): def test_get_caller_identity():
identity = boto3.client("sts").get_caller_identity() identity = boto3.client("sts", region_name='us-east-1').get_caller_identity()
identity['Arn'].should.equal('arn:aws:sts::123456789012:user/moto') identity['Arn'].should.equal('arn:aws:sts::123456789012:user/moto')
identity['UserId'].should.equal('AKIAIOSFODNN7EXAMPLE') identity['UserId'].should.equal('AKIAIOSFODNN7EXAMPLE')

View File

@ -1,6 +1,5 @@
import boto import boto
from moto import mock_swf
from moto.swf.models import ( from moto.swf.models import (
ActivityType, ActivityType,
Domain, Domain,
@ -76,7 +75,6 @@ def auto_start_decision_tasks(wfe):
# Setup a complete example workflow and return the connection object # Setup a complete example workflow and return the connection object
@mock_swf
def setup_workflow(): def setup_workflow():
conn = boto.connect_swf("the_key", "the_secret") conn = boto.connect_swf("the_key", "the_secret")
conn.register_domain("test-domain", "60", description="A test domain") conn.register_domain("test-domain", "60", description="A test domain")

View File

@ -11,3 +11,4 @@ commands =
[flake8] [flake8]
ignore = E128,E501 ignore = E128,E501
exclude = moto/packages,dist