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 @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
------

View File

@ -9,5 +9,8 @@ test:
rm -rf cover
@nosetests -sv --with-coverage --cover-html ./tests/
test_server:
@TEST_SERVER_MODE=true nosetests -sv --with-coverage --cover-html ./tests/
publish:
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)
[![Coverage Status](https://coveralls.io/repos/spulec/moto/badge.png?branch=master)](https://coveralls.io/r/spulec/moto)
# 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
import boto
from boto.s3.key import Key
import boto3
class MyModel(object):
def __init__(self, name, value):
@ -19,11 +18,9 @@ class MyModel(object):
self.value = value
def save(self):
conn = boto.connect_s3()
bucket = conn.get_bucket('mybucket')
k = Key(bucket)
k.key = self.name
k.set_contents_from_string(self.value)
s3 = boto3.client('s3', region_name='us-east-1')
s3.put_object(Bucket='mybucket', Key=self.name, Body=self.value)
```
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:
```python
import boto
import boto3
from moto import mock_s3
from mymodule import MyModel
@mock_s3
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
conn.create_bucket('mybucket')
conn.create_bucket(Bucket='mybucket')
model_instance = MyModel('steve', 'is awesome')
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.
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
|------------------------------------------------------------------------------|
@ -193,11 +193,6 @@ def test_my_model_save():
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
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
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)
responses.add_callback(responses.GET, stage_url.lower(), callback=self.resource_callback)
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, callback=self.resource_callback)
def create_stage(self, name, deployment_id,variables=None,description='',cacheClusterEnabled=None,cacheClusterSize=None):
if variables is None:

View File

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

View File

@ -10,32 +10,32 @@ from .models import lambda_backends
class LambdaResponse(BaseResponse):
@classmethod
def root(cls, request, full_url, headers):
def root(self, request, full_url, headers):
self.setup_class(request, full_url, headers)
if request.method == 'GET':
return cls()._list_functions(request, full_url, headers)
return self._list_functions(request, full_url, headers)
elif request.method == 'POST':
return cls()._create_function(request, full_url, headers)
return self._create_function(request, full_url, headers)
else:
raise ValueError("Cannot handle request")
@classmethod
def function(cls, request, full_url, headers):
def function(self, request, full_url, headers):
self.setup_class(request, full_url, headers)
if request.method == 'GET':
return cls()._get_function(request, full_url, headers)
return self._get_function(request, full_url, headers)
elif request.method == 'DELETE':
return cls()._delete_function(request, full_url, headers)
return self._delete_function(request, full_url, headers)
else:
raise ValueError("Cannot handle request")
@classmethod
def invoke(cls, request, full_url, headers):
def invoke(self, request, full_url, headers):
self.setup_class(request, full_url, headers)
if request.method == 'POST':
return cls()._invoke(request, full_url, headers)
return self._invoke(request, full_url)
else:
raise ValueError("Cannot handle request")
def _invoke(self, request, full_url, headers):
def _invoke(self, request, full_url):
response_headers = {}
lambda_backend = self.get_lambda_backend(full_url)
@ -44,7 +44,7 @@ class LambdaResponse(BaseResponse):
if lambda_backend.has_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))
return 202, response_headers, payload
else:
@ -59,7 +59,7 @@ class LambdaResponse(BaseResponse):
def _create_function(self, request, full_url, headers):
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:
fn = lambda_backend.create_function(spec)
except ValueError as e:

View File

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

View File

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

View File

@ -17,8 +17,11 @@ class CloudFormationResponse(BaseResponse):
def _get_stack_from_s3_url(self, template_url):
template_url_parts = urlparse(template_url)
bucket_name = template_url_parts.netloc.split(".")[0]
key_name = template_url_parts.path.lstrip("/")
if "localhost" in template_url:
bucket_name, key_name = template_url_parts.path.lstrip("/").split("/")
else:
bucket_name = template_url_parts.netloc.split(".")[0]
key_name = template_url_parts.path.lstrip("/")
key = s3_backend.get_key(bucket_name, key_name)
return key.value.decode("utf-8")

View File

@ -1,2 +1,4 @@
from __future__ import unicode_literals
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 jinja2 import DictLoader, Environment
from six import text_type
@ -47,6 +49,10 @@ class RESTError(HTTPException):
error_type=error_type, message=message, **kwargs)
class DryRunClientError(RESTError):
code = 400
class JsonRESTError(RESTError):
def __init__(self, error_type, message, template='error_json', **kwargs):
super(JsonRESTError, self).__init__(error_type, message, template, **kwargs)

View File

@ -6,9 +6,9 @@ import inspect
import os
import re
from moto import settings
from moto.packages.responses import responses
from moto.packages.httpretty import HTTPretty
from .responses import metadata_response
from .utils import (
convert_httpretty_response,
convert_regex_to_flask_path,
@ -21,6 +21,15 @@ class BaseMockAWS(object):
def __init__(self, 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:
self.reset()
@ -95,20 +104,13 @@ class HttprettyMockAWS(BaseMockAWS):
HTTPretty.enable()
for method in HTTPretty.METHODS:
backend = list(self.backends.values())[0]
for key, value in backend.urls.items():
HTTPretty.register_uri(
method=method,
uri=re.compile(key),
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),
)
for backend in self.backends_for_urls.values():
for key, value in backend.urls.items():
HTTPretty.register_uri(
method=method,
uri=re.compile(key),
body=convert_httpretty_response(value),
)
def disable_patching(self):
HTTPretty.disable()
@ -126,20 +128,14 @@ class ResponsesMockAWS(BaseMockAWS):
def enable_patching(self):
responses.start()
for method in RESPONSES_METHODS:
backend = list(self.backends.values())[0]
for key, value in backend.urls.items():
responses.add_callback(
method=method,
url=re.compile(key),
callback=convert_flask_to_responses_response(value),
)
for backend in self.backends_for_urls.values():
for key, value in backend.urls.items():
responses.add_callback(
method=method,
url=re.compile(key),
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:
pattern['stream'] = True
@ -270,10 +266,15 @@ class BaseBackend(object):
return paths
def decorator(self, func=None):
if func:
return MockAWS({'global': self})(func)
if settings.TEST_SERVER_MODE:
mocked_backend = ServerModeMockAWS({'global': self})
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):
if func:
@ -289,13 +290,15 @@ class base_decorator(object):
self.backends = backends
def __call__(self, func=None):
if self.mock_backend == MockAWS and os.environ.get('TEST_SERVER_MODE', '0').lower() == 'true':
self.mock_backend = ServerModeMockAWS
if self.mock_backend != HttprettyMockAWS and settings.TEST_SERVER_MODE:
mocked_backend = ServerModeMockAWS(self.backends)
else:
mocked_backend = self.mock_backend(self.backends)
if func:
return self.mock_backend(self.backends)(func)
return mocked_backend(func)
else:
return self.mock_backend(self.backends)
return mocked_backend
class deprecated_base_decorator(base_decorator):
@ -303,15 +306,13 @@ class deprecated_base_decorator(base_decorator):
class MotoAPIBackend(BaseBackend):
def __init__(self):
super(MotoAPIBackend, self).__init__()
def reset(self):
from moto.backends import BACKENDS
for name, backend in BACKENDS.items():
for name, backends in BACKENDS.items():
if name == "moto_api":
continue
backend.reset()
for region_name, backend in backends.items():
backend.reset()
self.__init__()
moto_api_backend = MotoAPIBackend()

View File

@ -5,7 +5,7 @@ import logging
import re
import pytz
from boto.exception import JSONResponseError
from moto.core.exceptions import DryRunClientError
from jinja2 import Environment, DictLoader, TemplateNotFound
@ -149,17 +149,19 @@ class BaseResponse(_TemplateEnvironmentMixin):
self.path = urlparse(full_url).path
self.querystring = querystring
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
if 'host' not in self.headers:
self.headers['host'] = urlparse(full_url).netloc
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)
if match:
region = match.group(1)
elif 'Authorization' in request.headers:
region = request.headers['Authorization'].split(",")[0].split("/")[2]
else:
region = self.default_region
return region
@ -195,6 +197,7 @@ class BaseResponse(_TemplateEnvironmentMixin):
if "status" in headers:
headers['status'] = str(headers['status'])
return status, headers, body
raise NotImplementedError("The {0} action has not been implemented".format(action))
def _get_param(self, param_name, if_none=None):
@ -323,55 +326,19 @@ class BaseResponse(_TemplateEnvironmentMixin):
def is_not_dryrun(self, action):
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
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):
def reset_response(self, request, full_url, headers):
from .models import moto_api_backend
moto_api_backend.reset()
return 200, {}, json.dumps({"status": "ok"})
if request.method == "POST":
from .models import moto_api_backend
moto_api_backend.reset()
return 200, {}, json.dumps({"status": "ok"})
return 400, {}, json.dumps({"Error": "Need to POST to reset Moto"})
class _RecursiveDictRef(object):

View File

@ -118,12 +118,16 @@ class convert_flask_to_httpretty_response(object):
return "{0}.{1}".format(outer, self.callback.__name__)
def __call__(self, args=None, **kwargs):
from flask import request
from flask import request, Response
result = self.callback(request, request.url, {})
# result is a status, headers, response tuple
status, headers, response = result
return response, status, headers
status, headers, content = result
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):

View File

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

View File

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

View File

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

View File

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

View File

@ -35,8 +35,8 @@ class SpotInstances(BaseResponse):
def request_spot_instances(self):
price = self._get_param('SpotPrice')
image_id = self._get_param('LaunchSpecification.ImageId')
count = self._get_int_param('InstanceCount')
type = self._get_param('Type')
count = self._get_int_param('InstanceCount', 1)
type = self._get_param('Type', 'one-time')
valid_from = self._get_param('ValidFrom')
valid_until = self._get_param('ValidUntil')
launch_group = self._get_param('LaunchGroup')
@ -44,7 +44,7 @@ class SpotInstances(BaseResponse):
key_name = self._get_param('LaunchSpecification.KeyName')
security_groups = self._get_multi_param('LaunchSpecification.SecurityGroup')
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')
kernel_id = self._get_param('LaunchSpecification.KernelId')
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)
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]
def describe_step(self, cluster_id, step_id):

View File

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

View File

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

View File

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

View File

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

View File

@ -2,7 +2,7 @@ from __future__ import unicode_literals
from .responses import IamResponse
url_bases = [
"https?://iam.amazonaws.com",
"https?://iam(.*).amazonaws.com",
]
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
def is_firehose(self):
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):
stream_name = self.parameters.get('StreamName')

View File

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

View File

@ -1,174 +1,186 @@
from __future__ import unicode_literals
from jinja2 import Template
from six.moves.urllib.parse import parse_qs, urlparse
from moto.core.responses import BaseResponse
from .models import route53_backend
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":
elements = xmltodict.parse(request.body)
if "HostedZoneConfig" in elements["CreateHostedZoneRequest"]:
comment = elements["CreateHostedZoneRequest"]["HostedZoneConfig"]["Comment"]
try:
# in boto3, this field is set directly in the xml
private_zone = elements["CreateHostedZoneRequest"]["HostedZoneConfig"]["PrivateZone"]
except KeyError:
# if a VPC subsection is only included in xmls params when private_zone=True,
# see boto: boto/route53/connection.py
private_zone = 'VPC' in elements["CreateHostedZoneRequest"]
else:
comment = None
private_zone = False
if request.method == "POST":
elements = xmltodict.parse(self.body)
if "HostedZoneConfig" in elements["CreateHostedZoneRequest"]:
comment = elements["CreateHostedZoneRequest"]["HostedZoneConfig"]["Comment"]
try:
# in boto3, this field is set directly in the xml
private_zone = elements["CreateHostedZoneRequest"]["HostedZoneConfig"]["PrivateZone"]
except KeyError:
# if a VPC subsection is only included in xmls params when private_zone=True,
# see boto: boto/route53/connection.py
private_zone = 'VPC' in elements["CreateHostedZoneRequest"]
else:
comment = None
private_zone = False
name = elements["CreateHostedZoneRequest"]["Name"]
if name[-1] != ".":
name += "."
new_zone = route53_backend.create_hosted_zone(
name,
comment=comment,
private_zone=private_zone,
)
template = Template(CREATE_HOSTED_ZONE_RESPONSE)
return 201, headers, template.render(zone=new_zone)
elif request.method == "GET":
all_zones = route53_backend.get_all_hosted_zones()
template = Template(LIST_HOSTED_ZONES_RESPONSE)
return 200, headers, template.render(zones=all_zones)
name = elements["CreateHostedZoneRequest"]["Name"]
def get_or_delete_hostzone_response(self, request, full_url, headers):
self.setup_class(request, full_url, headers)
parsed_url = urlparse(full_url)
zoneid = parsed_url.path.rstrip('/').rsplit('/', 1)[1]
the_zone = route53_backend.get_hosted_zone(zoneid)
if not the_zone:
return 404, headers, "Zone %s not Found" % zoneid
if name[-1] != ".":
name += "."
if request.method == "GET":
template = Template(GET_HOSTED_ZONE_RESPONSE)
new_zone = route53_backend.create_hosted_zone(
name,
comment=comment,
private_zone=private_zone,
)
template = Template(CREATE_HOSTED_ZONE_RESPONSE)
return 201, headers, template.render(zone=new_zone)
elif request.method == "GET":
all_zones = route53_backend.get_all_hosted_zones()
template = Template(LIST_HOSTED_ZONES_RESPONSE)
return 200, headers, template.render(zones=all_zones)
return 200, headers, template.render(zone=the_zone)
elif request.method == "DELETE":
route53_backend.delete_hosted_zone(zoneid)
return 200, headers, DELETE_HOSTED_ZONE_RESPONSE
def get_or_delete_hostzone_response(request, full_url, headers):
parsed_url = urlparse(full_url)
zoneid = parsed_url.path.rstrip('/').rsplit('/', 1)[1]
the_zone = route53_backend.get_hosted_zone(zoneid)
if not the_zone:
return 404, headers, "Zone %s not Found" % zoneid
def rrset_response(self, request, full_url, headers):
self.setup_class(request, full_url, headers)
if request.method == "GET":
template = Template(GET_HOSTED_ZONE_RESPONSE)
parsed_url = urlparse(full_url)
method = request.method
return 200, headers, template.render(zone=the_zone)
elif request.method == "DELETE":
route53_backend.delete_hosted_zone(zoneid)
return 200, headers, DELETE_HOSTED_ZONE_RESPONSE
zoneid = parsed_url.path.rstrip('/').rsplit('/', 2)[1]
the_zone = route53_backend.get_hosted_zone(zoneid)
if not the_zone:
return 404, headers, "Zone %s Not Found" % zoneid
if method == "POST":
elements = xmltodict.parse(self.body)
change_list = elements['ChangeResourceRecordSetsRequest']['ChangeBatch']['Changes']['Change']
if not isinstance(change_list, list):
change_list = [elements['ChangeResourceRecordSetsRequest']['ChangeBatch']['Changes']['Change']]
for value in change_list:
action = value['Action']
record_set = value['ResourceRecordSet']
if action in ('CREATE', 'UPSERT'):
if 'ResourceRecords' in record_set:
resource_records = list(record_set['ResourceRecords'].values())[0]
if not isinstance(resource_records, list):
# Depending on how many records there are, this may or may not be a list
resource_records = [resource_records]
record_values = [x['Value'] for x in resource_records]
elif 'AliasTarget' in record_set:
record_values = [record_set['AliasTarget']['DNSName']]
record_set['ResourceRecords'] = record_values
if action == 'CREATE':
the_zone.add_rrset(record_set)
else:
the_zone.upsert_rrset(record_set)
elif action == "DELETE":
if 'SetIdentifier' in record_set:
the_zone.delete_rrset_by_id(record_set["SetIdentifier"])
else:
the_zone.delete_rrset_by_name(record_set["Name"])
return 200, headers, CHANGE_RRSET_RESPONSE
elif method == "GET":
querystring = parse_qs(parsed_url.query)
template = Template(LIST_RRSET_REPONSE)
type_filter = querystring.get("type", [None])[0]
name_filter = querystring.get("name", [None])[0]
record_sets = the_zone.get_record_sets(type_filter, name_filter)
return 200, headers, template.render(record_sets=record_sets)
def rrset_response(request, full_url, headers):
parsed_url = urlparse(full_url)
method = request.method
def health_check_response(self, request, full_url, headers):
self.setup_class(request, full_url, headers)
zoneid = parsed_url.path.rstrip('/').rsplit('/', 2)[1]
the_zone = route53_backend.get_hosted_zone(zoneid)
if not the_zone:
return 404, headers, "Zone %s Not Found" % zoneid
parsed_url = urlparse(full_url)
method = request.method
if method == "POST":
elements = xmltodict.parse(request.body)
if method == "POST":
properties = xmltodict.parse(self.body)['CreateHealthCheckRequest']['HealthCheckConfig']
health_check_args = {
"ip_address": properties.get('IPAddress'),
"port": properties.get('Port'),
"type": properties['Type'],
"resource_path": properties.get('ResourcePath'),
"fqdn": properties.get('FullyQualifiedDomainName'),
"search_string": properties.get('SearchString'),
"request_interval": properties.get('RequestInterval'),
"failure_threshold": properties.get('FailureThreshold'),
}
health_check = route53_backend.create_health_check(health_check_args)
template = Template(CREATE_HEALTH_CHECK_RESPONSE)
return 201, headers, template.render(health_check=health_check)
elif method == "DELETE":
health_check_id = parsed_url.path.split("/")[-1]
route53_backend.delete_health_check(health_check_id)
return 200, headers, DELETE_HEALTH_CHECK_REPONSE
elif method == "GET":
template = Template(LIST_HEALTH_CHECKS_REPONSE)
health_checks = route53_backend.get_health_checks()
return 200, headers, template.render(health_checks=health_checks)
change_list = elements['ChangeResourceRecordSetsRequest']['ChangeBatch']['Changes']['Change']
if not isinstance(change_list, list):
change_list = [elements['ChangeResourceRecordSetsRequest']['ChangeBatch']['Changes']['Change']]
def not_implemented_response(self, request, full_url, headers):
self.setup_class(request, full_url, headers)
for value in change_list:
action = value['Action']
record_set = value['ResourceRecordSet']
if action in ('CREATE', 'UPSERT'):
if 'ResourceRecords' in record_set:
resource_records = list(record_set['ResourceRecords'].values())[0]
if not isinstance(resource_records, list):
# Depending on how many records there are, this may or may not be a list
resource_records = [resource_records]
record_values = [x['Value'] for x in resource_records]
elif 'AliasTarget' in record_set:
record_values = [record_set['AliasTarget']['DNSName']]
record_set['ResourceRecords'] = record_values
if action == 'CREATE':
the_zone.add_rrset(record_set)
else:
the_zone.upsert_rrset(record_set)
elif action == "DELETE":
if 'SetIdentifier' in record_set:
the_zone.delete_rrset_by_id(record_set["SetIdentifier"])
else:
the_zone.delete_rrset_by_name(record_set["Name"])
return 200, headers, CHANGE_RRSET_RESPONSE
elif method == "GET":
querystring = parse_qs(parsed_url.query)
template = Template(LIST_RRSET_REPONSE)
type_filter = querystring.get("type", [None])[0]
name_filter = querystring.get("name", [None])[0]
record_sets = the_zone.get_record_sets(type_filter, name_filter)
return 200, headers, template.render(record_sets=record_sets)
action = ''
if 'tags' in full_url:
action = 'tags'
elif 'trafficpolicyinstances' in full_url:
action = 'policies'
raise NotImplementedError("The action for {0} has not been implemented for route 53".format(action))
def health_check_response(request, full_url, headers):
parsed_url = urlparse(full_url)
method = request.method
def list_or_change_tags_for_resource_request(self, request, full_url, headers):
self.setup_class(request, full_url, headers)
if method == "POST":
properties = xmltodict.parse(request.body)['CreateHealthCheckRequest']['HealthCheckConfig']
health_check_args = {
"ip_address": properties.get('IPAddress'),
"port": properties.get('Port'),
"type": properties['Type'],
"resource_path": properties.get('ResourcePath'),
"fqdn": properties.get('FullyQualifiedDomainName'),
"search_string": properties.get('SearchString'),
"request_interval": properties.get('RequestInterval'),
"failure_threshold": properties.get('FailureThreshold'),
}
health_check = route53_backend.create_health_check(health_check_args)
template = Template(CREATE_HEALTH_CHECK_RESPONSE)
return 201, headers, template.render(health_check=health_check)
elif method == "DELETE":
health_check_id = parsed_url.path.split("/")[-1]
route53_backend.delete_health_check(health_check_id)
return 200, headers, DELETE_HEALTH_CHECK_REPONSE
elif method == "GET":
template = Template(LIST_HEALTH_CHECKS_REPONSE)
health_checks = route53_backend.get_health_checks()
return 200, headers, template.render(health_checks=health_checks)
parsed_url = urlparse(full_url)
id_ = parsed_url.path.split("/")[-1]
type_ = parsed_url.path.split("/")[-2]
def not_implemented_response(request, full_url, headers):
action = ''
if 'tags' in full_url:
action = 'tags'
elif 'trafficpolicyinstances' in full_url:
action = 'policies'
raise NotImplementedError("The action for {0} has not been implemented for route 53".format(action))
if request.method == "GET":
tags = route53_backend.list_tags_for_resource(id_)
template = Template(LIST_TAGS_FOR_RESOURCE_RESPONSE)
return 200, headers, template.render(
resource_type=type_, resource_id=id_, tags=tags)
if request.method == "POST":
tags = xmltodict.parse(
self.body)['ChangeTagsForResourceRequest']
def list_or_change_tags_for_resource_request(request, full_url, headers):
parsed_url = urlparse(full_url)
id_ = parsed_url.path.split("/")[-1]
type_ = parsed_url.path.split("/")[-2]
if 'AddTags' in tags:
tags = tags['AddTags']
elif 'RemoveTagKeys' in tags:
tags = tags['RemoveTagKeys']
if request.method == "GET":
tags = route53_backend.list_tags_for_resource(id_)
template = Template(LIST_TAGS_FOR_RESOURCE_RESPONSE)
return 200, headers, template.render(
resource_type=type_, resource_id=id_, tags=tags)
route53_backend.change_tags_for_resource(id_, tags)
template = Template(CHANGE_TAGS_FOR_RESOURCE_RESPONSE)
if request.method == "POST":
tags = xmltodict.parse(
request.body)['ChangeTagsForResourceRequest']
if 'AddTags' in tags:
tags = tags['AddTags']
elif 'RemoveTagKeys' in tags:
tags = tags['RemoveTagKeys']
route53_backend.change_tags_for_resource(id_, tags)
template = Template(CHANGE_TAGS_FOR_RESOURCE_RESPONSE)
return 200, headers, template.render()
return 200, headers, template.render()
LIST_TAGS_FOR_RESOURCE_RESPONSE = """
<ListTagsForResourceResponse xmlns="https://route53.amazonaws.com/doc/2015-01-01/">

View File

@ -1,15 +1,25 @@
from __future__ import unicode_literals
from . import responses
from .responses import Route53
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 = {
'{0}hostedzone$': responses.list_or_create_hostzone_response,
'{0}hostedzone/[^/]+$': responses.get_or_delete_hostzone_response,
'{0}hostedzone/[^/]+/rrset/?$': responses.rrset_response,
'{0}healthcheck': responses.health_check_response,
'{0}tags/(healthcheck|hostedzone)/*': responses.list_or_change_tags_for_resource_request,
'{0}trafficpolicyinstances/*': responses.not_implemented_response
'{0}/(?P<api_version>[\d_-]+)/hostedzone$': Route53().list_or_create_hostzone_response,
'{0}/(?P<api_version>[\d_-]+)/hostedzone/(?P<zone_id>[^/]+)$': Route53().get_or_delete_hostzone_response,
'{0}/(?P<api_version>[\d_-]+)/hostedzone/(?P<zone_id>[^/]+)/rrset/?$': Route53().rrset_response,
'{0}/(?P<api_version>[\d_-]+)/healthcheck': Route53().health_check_response,
'{0}/(?P<api_version>[\d_-]+)/tags/healthcheck/(?P<zone_id>[^/]+)$': tag_response1,
'{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 .models import s3_backend
s3_backends = {"global": s3_backend}
mock_s3 = s3_backend.decorator
mock_s3_deprecated = s3_backend.deprecated_decorator

View File

@ -89,21 +89,21 @@ class FakeKey(object):
@property
def response_dict(self):
r = {
res = {
'etag': self.etag,
'last-modified': self.last_modified_RFC1123,
'content-length': str(len(self.value)),
}
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:
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:
r['x-amz-version-id'] = str(self._version_id)
res['x-amz-version-id'] = str(self._version_id)
return r
return res
@property
def size(self):

View File

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

View File

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

View File

@ -2,7 +2,8 @@ from __future__ import unicode_literals
from .responses import EmailResponse
url_bases = [
"https?://email.(.+).amazonaws.com"
"https?://email.(.+).amazonaws.com",
"https?://ses.(.+).amazonaws.com",
]
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 .models import sts_backend
sts_backends = {"global": sts_backend}
mock_sts = sts_backend.decorator
mock_sts_deprecated = sts_backend.deprecated_decorator

View File

@ -2,7 +2,7 @@ from __future__ import unicode_literals
from .responses import TokenResponse
url_bases = [
"https?://sts.amazonaws.com"
"https?://sts(.*).amazonaws.com"
]
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

@ -1,2 +1,2 @@
[bdist_wheel]
universal=1
universal=1

View File

@ -10,7 +10,7 @@ import sure # noqa
from botocore.exceptions import ClientError
from moto.packages.responses import responses
from moto import mock_apigateway
from moto import mock_apigateway, settings
@freeze_time("2015-01-01")
@ -29,11 +29,11 @@ def test_create_and_get_rest_api():
)
response.pop('ResponseMetadata')
response.pop('createdDate')
response.should.equal({
'id': api_id,
'name': '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)
requests.get(deploy_url).content.should.equal(b"a fake response")
if not settings.TEST_SERVER_MODE:
requests.get(deploy_url).content.should.equal(b"a fake response")

View File

@ -10,7 +10,7 @@ import zipfile
import sure # noqa
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):
@ -36,16 +36,15 @@ def lambda_handler(event, context):
volume_id = event.get('volume_id')
print('get volume details for %s' % volume_id)
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)
print('Volume - %s state=%s, size=%s' % (volume_id, vol.state, vol.size))
return event
"""
""".format(base_url="localhost:8086" if settings.TEST_SERVER_MODE else "ec2.us-west-2.amazonaws.com")
return _process_lamda(pfunc)
@mock_lambda
@mock_s3
def test_list_functions():
conn = boto3.client('lambda', 'us-west-2')
result = conn.list_functions()
@ -53,7 +52,6 @@ def test_list_functions():
@mock_lambda
@freeze_time('2015-01-01 00:00:00')
def test_invoke_requestresponse_function():
conn = boto3.client('lambda', 'us-west-2')
conn.create_function(
@ -80,7 +78,6 @@ def test_invoke_requestresponse_function():
@mock_lambda
@freeze_time('2015-01-01 00:00:00')
def test_invoke_event_function():
conn = boto3.client('lambda', 'us-west-2')
conn.create_function(
@ -111,7 +108,6 @@ def test_invoke_event_function():
@mock_ec2
@mock_lambda
@freeze_time('2015-01-01 00:00:00')
def test_invoke_function_get_ec2_volume():
conn = boto3.resource("ec2", "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
@freeze_time('2015-01-01 00:00:00')
def test_create_based_on_s3_with_missing_bucket():
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('RetryAttempts', None) # Botocore inserts retry attempts not seen in Python27
result.pop('LastModified')
result.should.equal({
'FunctionName': 'testFunction',
'FunctionArn': 'arn:aws:lambda:123456789012:function:testFunction',
@ -207,7 +203,6 @@ def test_create_function_from_aws_bucket():
'Description': 'test lambda function',
'Timeout': 3,
'MemorySize': 128,
'LastModified': '2015-01-01 00:00:00',
'Version': '$LATEST',
'VpcConfig': {
"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('RetryAttempts', None) # Botocore inserts retry attempts not seen in Python27
result.pop('LastModified')
result.should.equal({
'FunctionName': 'testFunction',
@ -249,7 +245,6 @@ def test_create_function_from_zipfile():
'Description': 'test lambda function',
'Timeout': 3,
'MemorySize': 128,
'LastModified': '2015-01-01 00:00:00',
'CodeSha256': hashlib.sha256(zip_content).hexdigest(),
'Version': '$LATEST',
'VpcConfig': {
@ -290,6 +285,7 @@ def test_get_function():
result = conn.get_function(FunctionName='testFunction')
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['Configuration'].pop('LastModified')
result.should.equal({
"Code": {
@ -303,7 +299,6 @@ def test_get_function():
"FunctionArn": "arn:aws:lambda:123456789012:function:testFunction",
"FunctionName": "testFunction",
"Handler": "lambda_function.handler",
"LastModified": "2015-01-01 00:00:00",
"MemorySize": 128,
"Role": "test-iam-role",
"Runtime": "python2.7",
@ -395,7 +390,6 @@ def test_list_create_list_get_delete_list():
"FunctionArn": "arn:aws:lambda:123456789012:function:testFunction",
"FunctionName": "testFunction",
"Handler": "lambda_function.handler",
"LastModified": "2015-01-01 00:00:00",
"MemorySize": 128,
"Role": "test-iam-role",
"Runtime": "python2.7",
@ -408,11 +402,14 @@ def test_list_create_list_get_delete_list():
},
'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['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['Configuration'].pop('LastModified')
func.should.equal(expected_function_result)
conn.delete_function(FunctionName='testFunction')

View File

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

View File

@ -701,27 +701,29 @@ def test_vpc_single_instance_in_subnet():
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)
@mock_cloudformation_deprecated()
@mock_ec2_deprecated()
@mock_cloudformation()
@mock_ec2()
@mock_rds2()
def test_rds_db_parameter_groups():
ec2_conn = boto.ec2.connect_to_region("us-west-1")
ec2_conn.create_security_group('application', 'Our Application Group')
ec2_conn = boto3.client("ec2", region_name="us-west-1")
ec2_conn.create_security_group(GroupName='application', Description='Our Application Group')
template_json = json.dumps(rds_mysql_with_db_parameter_group.template)
conn = boto.cloudformation.connect_to_region("us-west-1")
conn.create_stack(
"test_stack",
template_body=template_json,
parameters=[
("DBInstanceIdentifier", "master_db"),
("DBName", "my_db"),
("DBUser", "my_user"),
("DBPassword", "my_password"),
("DBAllocatedStorage", "20"),
("DBInstanceClass", "db.m1.medium"),
("EC2SecurityGroup", "application"),
("MultiAZ", "true"),
cf_conn = boto3.client('cloudformation', 'us-west-1')
cf_conn.create_stack(
StackName="test_stack",
TemplateBody=template_json,
Parameters=[{'ParameterKey': key, 'ParameterValue': value} for
key, value in [
("DBInstanceIdentifier", "master_db"),
("DBName", "my_db"),
("DBUser", "my_user"),
("DBPassword", "my_password"),
("DBAllocatedStorage", "20"),
("DBInstanceClass", "db.m1.medium"),
("EC2SecurityGroup", "application"),
("MultiAZ", "true"),
]
],
)
@ -1802,7 +1804,7 @@ def lambda_handler(event, context):
return _process_lamda(pfunc)
@mock_cloudformation_deprecated
@mock_cloudformation
@mock_lambda
def test_lambda_function():
# switch this to python as backend lambda only supports python execution.
@ -1826,10 +1828,10 @@ def test_lambda_function():
}
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(
"test_stack",
template_body=template_json,
StackName="test_stack",
TemplateBody=template_json,
)
conn = boto3.client('lambda', 'us-east-1')

View File

@ -3,18 +3,23 @@ import sure # noqa
from nose.tools import assert_raises
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
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")
@mock_ec2
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()
default_role = json_response['security-credentials']['default-role']
default_role.should.contain('AccessKeyId')
@ -25,21 +30,15 @@ def test_meta_data_iam():
@mock_ec2
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")
@mock_ec2
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.should.contain('AccessKeyId')
json_response.should.contain('SecretAccessKey')
json_response.should.contain('Token')
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')
@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
def test_dynamodb_with_connect_to_region():
# 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")
with assert_raises(JSONResponseError):
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.ec2
from boto.exception import EC2ResponseError, JSONResponseError
from boto.exception import EC2ResponseError, EC2ResponseError
import sure # noqa
@ -19,9 +19,9 @@ def test_ami_create_and_delete():
reservation = conn.run_instances('ami-1234abcd')
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -52,9 +52,9 @@ def test_ami_create_and_delete():
snapshot.volume_id.should.equal(volume.id)
# Deregister
with assert_raises(JSONResponseError) as ex:
with assert_raises(EC2ResponseError) as ex:
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.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]
# 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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -127,9 +127,9 @@ def test_ami_tagging():
conn.create_image(instance.id, "test-ami", "this is a test ami")
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -289,9 +289,9 @@ def test_ami_attribute_group_permissions():
'groups': 'all'}
# 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}))
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')

View File

@ -1,11 +1 @@
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
import boto
from boto.exception import EC2ResponseError, JSONResponseError
from boto.exception import EC2ResponseError
import sure # noqa
from moto import mock_ec2_deprecated
@ -24,9 +24,9 @@ def test_create_and_delete_volume():
volume = all_volumes[0]
with assert_raises(JSONResponseError) as ex:
with assert_raises(EC2ResponseError) as ex:
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.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
def test_create_encrypted_volume_dryrun():
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -58,9 +58,9 @@ def test_create_encrypted_volume():
conn = boto.connect_ec2('the_key', 'the_secret')
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -165,9 +165,9 @@ def test_volume_attach_and_detach():
volume.update()
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -179,9 +179,9 @@ def test_volume_attach_and_detach():
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -214,9 +214,9 @@ def test_create_snapshot():
conn = boto.connect_ec2('the_key', 'the_secret')
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -347,9 +347,9 @@ def test_snapshot_attribute():
# 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}))
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -363,9 +363,9 @@ def test_snapshot_attribute():
conn.modify_snapshot_attribute.when.called_with(**ADD_GROUP_ARGS).should_not.throw(EC2ResponseError)
# 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}))
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -424,9 +424,9 @@ def test_create_volume_from_snapshot():
volume = conn.create_volume(80, "us-east-1a")
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -468,9 +468,9 @@ def test_modify_attribute_blockDeviceMapping():
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -487,9 +487,9 @@ def test_volume_tag_escaping():
vol = conn.create_volume(10, 'us-east-1a')
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
ex.exception.status.should.equal(400)
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set')
dict(conn.get_all_snapshots()[0].tags).should_not.be.equal({'key': '</closed>'})

View File

@ -5,7 +5,7 @@ from nose.tools import assert_raises
import boto
import boto3
from boto.exception import EC2ResponseError, JSONResponseError
from boto.exception import EC2ResponseError
import six
import sure # noqa
@ -20,9 +20,9 @@ def test_eip_allocate_classic():
"""Allocate/release Classic EIP"""
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -32,9 +32,9 @@ def test_eip_allocate_classic():
standard.instance_id.should.be.none
standard.domain.should.be.equal("standard")
with assert_raises(JSONResponseError) as ex:
with assert_raises(EC2ResponseError) as ex:
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.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"""
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -89,9 +89,9 @@ def test_eip_associate_classic():
cm.exception.status.should.equal(400)
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -99,9 +99,9 @@ def test_eip_associate_classic():
eip = conn.get_all_addresses(addresses=[eip.public_ip])[0] # no .update() on address ):
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -139,9 +139,9 @@ def test_eip_associate_vpc():
eip.instance_id.should.be.equal(u'')
eip.association_id.should.be.none
with assert_raises(JSONResponseError) as ex:
with assert_raises(EC2ResponseError) as ex:
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.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
def test_eip_boto3_vpc_association():
"""Associate EIP to VPC instance in a new subnet with boto3"""
session = boto3.session.Session(region_name='us-west-1')
service = session.resource('ec2')
client = session.client('ec2')
service = boto3.resource('ec2', region_name='us-west-1')
client = boto3.client('ec2', region_name='us-west-1')
vpc_res = client.create_vpc(CidrBlock='10.0.0.0/24')
subnet_res = client.create_subnet(
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
import boto3
from botocore.exceptions import ClientError
import boto
import boto.cloudformation
import boto.ec2
from boto.exception import EC2ResponseError, JSONResponseError
from boto.exception import EC2ResponseError
import sure # noqa
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")
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -36,9 +37,9 @@ def test_elastic_network_interfaces():
eni.groups.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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -49,7 +50,7 @@ def test_elastic_network_interfaces():
with assert_raises(EC2ResponseError) as cm:
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.request_id.should_not.be.none
@ -60,7 +61,7 @@ def test_elastic_network_interfaces_subnet_validation():
with assert_raises(EC2ResponseError) as cm:
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.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[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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -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')
with assert_raises(JSONResponseError) as ex:
with assert_raises(ClientError) as ex:
eni1.create_tags(Tags=[{'Key': 'Name', 'Value': 'eni1'}], DryRun=True)
ex.exception.reason.should.equal('DryRunOperation')
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.response['Error']['Code'].should.equal('DryRunOperation')
ex.exception.response['ResponseMetadata']['HTTPStatusCode'].should.equal(400)
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'}])

View File

@ -8,7 +8,7 @@ import datetime
import boto
from boto.ec2.instance import Reservation, InstanceAttribute
from boto.exception import EC2ResponseError, JSONResponseError
from boto.exception import EC2ResponseError, EC2ResponseError
from freezegun import freeze_time
import sure # noqa
@ -41,9 +41,9 @@ def test_add_servers():
def test_instance_launch_and_terminate():
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -74,9 +74,9 @@ def test_instance_launch_and_terminate():
volume.attach_data.instance_id.should.equal(instance.id)
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -427,9 +427,9 @@ def test_instance_start_and_stop():
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -438,9 +438,9 @@ def test_instance_start_and_stop():
for instance in stopped_instances:
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -454,9 +454,9 @@ def test_instance_reboot():
reservation = conn.run_instances('ami-1234abcd')
instance = reservation.instances[0]
with assert_raises(JSONResponseError) as ex:
with assert_raises(EC2ResponseError) as ex:
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.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')
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -491,9 +491,9 @@ def test_modify_instance_attribute_security_groups():
sg_id = 'sg-1234abcd'
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -512,9 +512,9 @@ def test_instance_attribute_user_data():
reservation = conn.run_instances('ami-1234abcd')
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -540,9 +540,9 @@ def test_instance_attribute_source_dest_check():
# 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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -584,9 +584,9 @@ def test_user_data_with_run_instance():
def test_run_instance_with_security_group_name():
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -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]))
# 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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -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]))
# Detach
with assert_raises(JSONResponseError) as ex:
with assert_raises(EC2ResponseError) as ex:
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.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')
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')

View File

@ -6,7 +6,7 @@ from nose.tools import assert_raises
import re
import boto
from boto.exception import EC2ResponseError, JSONResponseError
from boto.exception import EC2ResponseError
import sure # noqa
@ -24,9 +24,9 @@ def test_igw_create():
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -44,9 +44,9 @@ def test_igw_attach():
igw = conn.create_internet_gateway()
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -90,9 +90,9 @@ def test_igw_detach():
vpc = conn.create_vpc(VPC_CIDR)
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -151,9 +151,9 @@ def test_igw_delete():
igw = conn.create_internet_gateway()
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')

View File

@ -7,7 +7,7 @@ import boto
import six
import sure # noqa
from boto.exception import EC2ResponseError, JSONResponseError
from boto.exception import EC2ResponseError
from moto import mock_ec2_deprecated
@ -32,9 +32,9 @@ def test_key_pairs_invalid_id():
def test_key_pairs_create():
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -87,9 +87,9 @@ def test_key_pairs_delete_exist():
conn = boto.connect_ec2('the_key', 'the_secret')
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -102,9 +102,9 @@ def test_key_pairs_delete_exist():
def test_key_pairs_import():
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')

View File

@ -9,7 +9,7 @@ from nose.tools import assert_raises
import boto3
import boto
from botocore.exceptions import ClientError
from boto.exception import EC2ResponseError, JSONResponseError
from boto.exception import EC2ResponseError
import sure # noqa
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():
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -121,9 +121,9 @@ def test_deleting_security_groups():
cm.exception.request_id.should_not.be.none
# Delete by name
with assert_raises(JSONResponseError) as ex:
with assert_raises(EC2ResponseError) as ex:
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.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')
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -171,9 +171,9 @@ def test_authorize_ip_range_and_revoke():
cm.exception.request_id.should_not.be.none
# 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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -185,9 +185,9 @@ def test_authorize_ip_range_and_revoke():
# Test for egress as well
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -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)
# 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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -339,9 +339,9 @@ def test_security_group_tagging():
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -540,11 +540,11 @@ def test_security_group_tagging_boto3():
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)
ex.exception.reason.should.equal('DryRunOperation')
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.response['Error']['Code'].should.equal('DryRunOperation')
ex.exception.response['ResponseMetadata']['HTTPStatusCode'].should.equal(400)
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'}])
describe = conn.describe_security_groups(Filters=[{'Name': 'tag-value', 'Values': ['Tag']}])

View File

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

View File

@ -4,7 +4,7 @@ from nose.tools import assert_raises
import itertools
import boto
from boto.exception import EC2ResponseError, JSONResponseError
from boto.exception import EC2ResponseError
from boto.ec2.instance import Reservation
import sure # noqa
@ -18,9 +18,9 @@ def test_add_tag():
reservation = conn.run_instances('ami-1234abcd')
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -45,9 +45,9 @@ def test_remove_tag():
tag.name.should.equal("a key")
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)
ex.exception.reason.should.equal('DryRunOperation')
ex.exception.error_code.should.equal('DryRunOperation')
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')
@ -96,9 +96,9 @@ def test_create_tags():
'another key': 'some other value',
'blank key': ''}
with assert_raises(JSONResponseError) as ex:
with assert_raises(EC2ResponseError) as ex:
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.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()
expected = {}
for idx in range(400):
for idx in range(4):
cluster_name = 'cluster' + str(idx)
args['name'] = cluster_name
cluster_id = conn.run_jobflow(**args)
@ -128,7 +128,7 @@ def test_describe_jobflows():
timestamp = datetime.now(pytz.utc)
time.sleep(1)
for idx in range(400, 600):
for idx in range(4, 6):
cluster_name = 'cluster' + str(idx)
args['name'] = cluster_name
cluster_id = conn.run_jobflow(**args)
@ -139,7 +139,7 @@ def test_describe_jobflows():
'state': 'TERMINATED'
}
jobs = conn.describe_jobflows()
jobs.should.have.length_of(512)
jobs.should.have.length_of(6)
for cluster_id, y in expected.items():
resp = conn.describe_jobflows(jobflow_ids=[cluster_id])
@ -147,15 +147,15 @@ def test_describe_jobflows():
resp[0].jobflowid.should.equal(cluster_id)
resp = conn.describe_jobflows(states=['WAITING'])
resp.should.have.length_of(400)
resp.should.have.length_of(4)
for x in resp:
x.state.should.equal('WAITING')
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.should.have.length_of(200)
resp.should.have.length_of(2)
@mock_emr_deprecated

View File

@ -128,7 +128,7 @@ def test_describe_job_flows():
args = deepcopy(run_job_flow_args)
expected = {}
for idx in range(400):
for idx in range(4):
cluster_name = 'cluster' + str(idx)
args['Name'] = cluster_name
cluster_id = client.run_job_flow(**args)['JobFlowId']
@ -144,7 +144,7 @@ def test_describe_job_flows():
timestamp = datetime.now(pytz.utc)
time.sleep(1)
for idx in range(400, 600):
for idx in range(4, 6):
cluster_name = 'cluster' + str(idx)
args['Name'] = cluster_name
cluster_id = client.run_job_flow(**args)['JobFlowId']
@ -156,7 +156,7 @@ def test_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():
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 = 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']:
x['ExecutionStatusDetail']['State'].should.equal('WAITING')
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['JobFlows'].should.have.length_of(200)
resp['JobFlows'].should.have.length_of(2)
@mock_emr
@ -327,13 +327,13 @@ def test_run_job_flow():
@mock_emr
def test_run_job_flow_with_invalid_params():
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
args = deepcopy(run_job_flow_args)
args['AmiVersion'] = '2.4'
args['ReleaseLabel'] = 'emr-5.0.0'
client.run_job_flow(**args)
e.exception.response['Error']['Code'].should.equal('ValidationException')
ex.exception.response['Error']['Message'].should.contain('ValidationException')
@mock_emr

View File

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

View File

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

View File

@ -308,7 +308,7 @@ def test_hosted_zone_private_zone_preserved():
@mock_route53
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
# a _valid_ vpc-id should fail.
firstzone = conn.create_hosted_zone(
@ -333,8 +333,20 @@ def test_hosted_zone_private_zone_preserved_boto3():
@mock_route53
def test_list_or_change_tags_for_resource_request():
conn = boto3.client('route53')
healthcheck_id = str(uuid.uuid4())
conn = boto3.client('route53', region_name='us-east-1')
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"}
tag2 = {"Key": "Name", "Value": "UnitTest"}

View File

@ -20,17 +20,21 @@ from nose.tools import assert_raises
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
REDUCED_PART_SIZE = 256
if settings.TEST_SERVER_MODE:
REDUCED_PART_SIZE = s3model.UPLOAD_PART_MIN_SIZE
EXPECTED_ETAG = '"140f92a6df9f9e415f74a1463bcee9bb-2"'
else:
REDUCED_PART_SIZE = 256
EXPECTED_ETAG = '"66d1a1a2ed08fd05c137f316af4ff255-2"'
def reduced_min_part_size(f):
""" speed up tests by temporarily making the multipart minimum part size
small
"""
import moto.s3.models as s3model
orig_size = s3model.UPLOAD_PART_MIN_SIZE
@wraps(f)
@ -49,24 +53,23 @@ class MyModel(object):
self.value = value
def save(self):
conn = boto.connect_s3('the_key', 'the_secret')
bucket = conn.get_bucket('mybucket')
k = Key(bucket)
k.key = self.name
k.set_contents_from_string(self.value)
s3 = boto3.client('s3', region_name='us-east-1')
s3.put_object(Bucket='mybucket', Key=self.name, Body=self.value)
@mock_s3_deprecated
@mock_s3
def test_my_model_save():
# Create Bucket so that test can run
conn = boto.connect_s3('the_key', 'the_secret')
conn.create_bucket('mybucket')
conn = boto3.resource('s3', region_name='us-east-1')
conn.create_bucket(Bucket='mybucket')
####################################
model_instance = MyModel('steve', 'is awesome')
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
@ -190,8 +193,7 @@ def test_multipart_etag():
multipart.upload_part_from_file(BytesIO(part2), 2)
multipart.complete_upload()
# we should get both parts as the key contents
bucket.get_key("the-key").etag.should.equal(
'"66d1a1a2ed08fd05c137f316af4ff255-2"')
bucket.get_key("the-key").etag.should.equal(EXPECTED_ETAG)
@mock_s3_deprecated
@ -544,16 +546,6 @@ def test_delete_keys_with_invalid():
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
def test_bucket_name_with_dot():
conn = boto.connect_s3()
@ -1241,7 +1233,7 @@ def test_boto3_multipart_etag():
for i, etag in enumerate(etags, 1)]})
# we should get both parts as the key contents
resp = s3.get_object(Bucket='mybucket', Key='the-key')
resp['ETag'].should.equal('"66d1a1a2ed08fd05c137f316af4ff255-2"')
resp['ETag'].should.equal(EXPECTED_ETAG)
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')
@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
def test_bucket_name_with_dot():
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")
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")
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)
@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
def test_queue_attributes():
conn = boto.connect_sqs('the_key', 'the_secret')

View File

@ -68,7 +68,7 @@ def test_assume_role():
@mock_sts
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['UserId'].should.equal('AKIAIOSFODNN7EXAMPLE')

View File

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

View File

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