Get standalone server mode working for all tests.
This commit is contained in:
parent
cb28eeefbb
commit
81836b6981
@ -8,6 +8,9 @@ Latest
|
|||||||
* The normal @mock_<service> decorators will no longer work with boto. It is suggested that you upgrade to boto3 or use the standalone-server mode. If you would still like to use boto, you must use the @mock_<service>_deprecated decorators which will be removed in a future release.
|
* The normal @mock_<service> decorators will no longer work with boto. It is suggested that you upgrade to boto3 or use the standalone-server mode. If you would still like to use boto, you must use the @mock_<service>_deprecated decorators which will be removed in a future release.
|
||||||
* The @mock_s3bucket_path decorator is now deprecated. Use the @mock_s3 decorator instead.
|
* The @mock_s3bucket_path decorator is now deprecated. Use the @mock_s3 decorator instead.
|
||||||
|
|
||||||
|
Added
|
||||||
|
* Reset API: a reset API has been added to flush all of the current data ex: `requests.post("http://motoapi.amazonaws.com/moto-api/reset")`
|
||||||
|
|
||||||
0.4.31
|
0.4.31
|
||||||
------
|
------
|
||||||
|
|
||||||
|
3
Makefile
3
Makefile
@ -9,5 +9,8 @@ test:
|
|||||||
rm -rf cover
|
rm -rf cover
|
||||||
@nosetests -sv --with-coverage --cover-html ./tests/
|
@nosetests -sv --with-coverage --cover-html ./tests/
|
||||||
|
|
||||||
|
test_server:
|
||||||
|
@TEST_SERVER_MODE=true nosetests -sv --with-coverage --cover-html ./tests/
|
||||||
|
|
||||||
publish:
|
publish:
|
||||||
python setup.py sdist bdist_wheel upload
|
python setup.py sdist bdist_wheel upload
|
||||||
|
35
README.md
35
README.md
@ -1,17 +1,16 @@
|
|||||||
# Moto - Mock Boto
|
# Moto - Mock AWS Services
|
||||||
|
|
||||||
[](https://travis-ci.org/spulec/moto)
|
[](https://travis-ci.org/spulec/moto)
|
||||||
[](https://coveralls.io/r/spulec/moto)
|
[](https://coveralls.io/r/spulec/moto)
|
||||||
|
|
||||||
# In a nutshell
|
# In a nutshell
|
||||||
|
|
||||||
Moto is a library that allows your python tests to easily mock out the boto library.
|
Moto is a library that allows your tests to easily mock out AWS Services.
|
||||||
|
|
||||||
Imagine you have the following code that you want to test:
|
Imagine you have the following python code that you want to test:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
import boto
|
import boto3
|
||||||
from boto.s3.key import Key
|
|
||||||
|
|
||||||
class MyModel(object):
|
class MyModel(object):
|
||||||
def __init__(self, name, value):
|
def __init__(self, name, value):
|
||||||
@ -19,11 +18,9 @@ class MyModel(object):
|
|||||||
self.value = value
|
self.value = value
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
conn = boto.connect_s3()
|
s3 = boto3.client('s3', region_name='us-east-1')
|
||||||
bucket = conn.get_bucket('mybucket')
|
s3.put_object(Bucket='mybucket', Key=self.name, Body=self.value)
|
||||||
k = Key(bucket)
|
|
||||||
k.key = self.name
|
|
||||||
k.set_contents_from_string(self.value)
|
|
||||||
```
|
```
|
||||||
|
|
||||||
Take a minute to think how you would have tested that in the past.
|
Take a minute to think how you would have tested that in the past.
|
||||||
@ -31,25 +28,28 @@ Take a minute to think how you would have tested that in the past.
|
|||||||
Now see how you could test it with Moto:
|
Now see how you could test it with Moto:
|
||||||
|
|
||||||
```python
|
```python
|
||||||
import boto
|
import boto3
|
||||||
from moto import mock_s3
|
from moto import mock_s3
|
||||||
from mymodule import MyModel
|
from mymodule import MyModel
|
||||||
|
|
||||||
|
|
||||||
@mock_s3
|
@mock_s3
|
||||||
def test_my_model_save():
|
def test_my_model_save():
|
||||||
conn = boto.connect_s3()
|
conn = boto3.resource('s3', region_name='us-east-1')
|
||||||
# We need to create the bucket since this is all in Moto's 'virtual' AWS account
|
# We need to create the bucket since this is all in Moto's 'virtual' AWS account
|
||||||
conn.create_bucket('mybucket')
|
conn.create_bucket(Bucket='mybucket')
|
||||||
|
|
||||||
model_instance = MyModel('steve', 'is awesome')
|
model_instance = MyModel('steve', 'is awesome')
|
||||||
model_instance.save()
|
model_instance.save()
|
||||||
|
|
||||||
assert conn.get_bucket('mybucket').get_key('steve').get_contents_as_string() == 'is awesome'
|
body = conn.Object('mybucket', 'steve').get()['Body'].read().decode("utf-8")
|
||||||
|
|
||||||
|
assert body == b'is awesome'
|
||||||
```
|
```
|
||||||
|
|
||||||
With the decorator wrapping the test, all the calls to s3 are automatically mocked out. The mock keeps the state of the buckets and keys.
|
With the decorator wrapping the test, all the calls to s3 are automatically mocked out. The mock keeps the state of the buckets and keys.
|
||||||
|
|
||||||
It gets even better! Moto isn't just S3. Here's the status of the other AWS services implemented.
|
It gets even better! Moto isn't just for Python code and it isn't just for S3. Look at the [standalone server mode](https://github.com/spulec/moto#stand-alone-server-mode) for more information about running Moto with other languages. Here's the status of the other AWS services implemented:
|
||||||
|
|
||||||
```gherkin
|
```gherkin
|
||||||
|------------------------------------------------------------------------------|
|
|------------------------------------------------------------------------------|
|
||||||
@ -193,11 +193,6 @@ def test_my_model_save():
|
|||||||
mock.stop()
|
mock.stop()
|
||||||
```
|
```
|
||||||
|
|
||||||
## Use with other libraries (boto3) or languages
|
|
||||||
|
|
||||||
In general, Moto doesn't rely on anything specific to Boto. It only mocks AWS endpoints, so there should be no issue with boto3 or using other languages. Feel free to open an issue if something isn't working though. If you are using another language, you will need to either use the stand-alone server mode (more below) or monkey patch the HTTP calls yourself.
|
|
||||||
|
|
||||||
|
|
||||||
## Stand-alone Server Mode
|
## Stand-alone Server Mode
|
||||||
|
|
||||||
Moto also has a stand-alone server mode. This allows you to utilize
|
Moto also has a stand-alone server mode. This allows you to utilize
|
||||||
|
@ -326,8 +326,8 @@ class RestAPI(object):
|
|||||||
return status_code, {}, response
|
return status_code, {}, response
|
||||||
|
|
||||||
def update_integration_mocks(self, stage_name):
|
def update_integration_mocks(self, stage_name):
|
||||||
stage_url = STAGE_URL.format(api_id=self.id, region_name=self.region_name, stage_name=stage_name)
|
stage_url = STAGE_URL.format(api_id=self.id.upper(), region_name=self.region_name, stage_name=stage_name)
|
||||||
responses.add_callback(responses.GET, stage_url.lower(), callback=self.resource_callback)
|
responses.add_callback(responses.GET, stage_url, callback=self.resource_callback)
|
||||||
|
|
||||||
def create_stage(self, name, deployment_id,variables=None,description='',cacheClusterEnabled=None,cacheClusterSize=None):
|
def create_stage(self, name, deployment_id,variables=None,description='',cacheClusterEnabled=None,cacheClusterSize=None):
|
||||||
if variables is None:
|
if variables is None:
|
||||||
|
@ -154,15 +154,15 @@ class LambdaFunction(object):
|
|||||||
sys.stderr = sys.__stderr__
|
sys.stderr = sys.__stderr__
|
||||||
return self.convert(result)
|
return self.convert(result)
|
||||||
|
|
||||||
def invoke(self, request, headers):
|
def invoke(self, body, request_headers, response_headers):
|
||||||
payload = dict()
|
payload = dict()
|
||||||
|
|
||||||
# Get the invocation type:
|
# Get the invocation type:
|
||||||
r = self._invoke_lambda(code=self.code, event=request.body)
|
r = self._invoke_lambda(code=self.code, event=body)
|
||||||
if request.headers.get("x-amz-invocation-type") == "RequestResponse":
|
if request_headers.get("x-amz-invocation-type") == "RequestResponse":
|
||||||
encoded = base64.b64encode(r.encode('utf-8'))
|
encoded = base64.b64encode(r.encode('utf-8'))
|
||||||
headers["x-amz-log-result"] = encoded.decode('utf-8')
|
response_headers["x-amz-log-result"] = encoded.decode('utf-8')
|
||||||
payload['result'] = headers["x-amz-log-result"]
|
payload['result'] = response_headers["x-amz-log-result"]
|
||||||
result = r.encode('utf-8')
|
result = r.encode('utf-8')
|
||||||
else:
|
else:
|
||||||
result = json.dumps(payload)
|
result = json.dumps(payload)
|
||||||
|
@ -10,32 +10,32 @@ from .models import lambda_backends
|
|||||||
|
|
||||||
class LambdaResponse(BaseResponse):
|
class LambdaResponse(BaseResponse):
|
||||||
|
|
||||||
@classmethod
|
def root(self, request, full_url, headers):
|
||||||
def root(cls, request, full_url, headers):
|
self.setup_class(request, full_url, headers)
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
return cls()._list_functions(request, full_url, headers)
|
return self._list_functions(request, full_url, headers)
|
||||||
elif request.method == 'POST':
|
elif request.method == 'POST':
|
||||||
return cls()._create_function(request, full_url, headers)
|
return self._create_function(request, full_url, headers)
|
||||||
else:
|
else:
|
||||||
raise ValueError("Cannot handle request")
|
raise ValueError("Cannot handle request")
|
||||||
|
|
||||||
@classmethod
|
def function(self, request, full_url, headers):
|
||||||
def function(cls, request, full_url, headers):
|
self.setup_class(request, full_url, headers)
|
||||||
if request.method == 'GET':
|
if request.method == 'GET':
|
||||||
return cls()._get_function(request, full_url, headers)
|
return self._get_function(request, full_url, headers)
|
||||||
elif request.method == 'DELETE':
|
elif request.method == 'DELETE':
|
||||||
return cls()._delete_function(request, full_url, headers)
|
return self._delete_function(request, full_url, headers)
|
||||||
else:
|
else:
|
||||||
raise ValueError("Cannot handle request")
|
raise ValueError("Cannot handle request")
|
||||||
|
|
||||||
@classmethod
|
def invoke(self, request, full_url, headers):
|
||||||
def invoke(cls, request, full_url, headers):
|
self.setup_class(request, full_url, headers)
|
||||||
if request.method == 'POST':
|
if request.method == 'POST':
|
||||||
return cls()._invoke(request, full_url, headers)
|
return self._invoke(request, full_url)
|
||||||
else:
|
else:
|
||||||
raise ValueError("Cannot handle request")
|
raise ValueError("Cannot handle request")
|
||||||
|
|
||||||
def _invoke(self, request, full_url, headers):
|
def _invoke(self, request, full_url):
|
||||||
response_headers = {}
|
response_headers = {}
|
||||||
lambda_backend = self.get_lambda_backend(full_url)
|
lambda_backend = self.get_lambda_backend(full_url)
|
||||||
|
|
||||||
@ -44,7 +44,7 @@ class LambdaResponse(BaseResponse):
|
|||||||
|
|
||||||
if lambda_backend.has_function(function_name):
|
if lambda_backend.has_function(function_name):
|
||||||
fn = lambda_backend.get_function(function_name)
|
fn = lambda_backend.get_function(function_name)
|
||||||
payload = fn.invoke(request, response_headers)
|
payload = fn.invoke(self.body, self.headers, response_headers)
|
||||||
response_headers['Content-Length'] = str(len(payload))
|
response_headers['Content-Length'] = str(len(payload))
|
||||||
return 202, response_headers, payload
|
return 202, response_headers, payload
|
||||||
else:
|
else:
|
||||||
@ -59,7 +59,7 @@ class LambdaResponse(BaseResponse):
|
|||||||
|
|
||||||
def _create_function(self, request, full_url, headers):
|
def _create_function(self, request, full_url, headers):
|
||||||
lambda_backend = self.get_lambda_backend(full_url)
|
lambda_backend = self.get_lambda_backend(full_url)
|
||||||
spec = json.loads(request.body.decode('utf-8'))
|
spec = json.loads(self.body.decode('utf-8'))
|
||||||
try:
|
try:
|
||||||
fn = lambda_backend.create_function(spec)
|
fn = lambda_backend.create_function(spec)
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
|
@ -5,9 +5,10 @@ url_bases = [
|
|||||||
"https?://lambda.(.+).amazonaws.com",
|
"https?://lambda.(.+).amazonaws.com",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
response = LambdaResponse()
|
||||||
|
|
||||||
url_paths = {
|
url_paths = {
|
||||||
# double curly braces because the `format()` method is called on the strings
|
'{0}/(?P<api_version>[^/]+)/functions/?$': response.root,
|
||||||
'{0}/\d{{4}}-\d{{2}}-\d{{2}}/functions/?$': LambdaResponse.root,
|
'{0}/(?P<api_version>[^/]+)/functions/(?P<function_name>[\w_-]+)/?$': response.function,
|
||||||
'{0}/\d{{4}}-\d{{2}}-\d{{2}}/functions/(?P<function_name>[\w_-]+)/?$': LambdaResponse.function,
|
'{0}/(?P<api_version>[^/]+)/functions/(?P<function_name>[\w_-]+)/invocations/?$': response.invoke,
|
||||||
'{0}/\d{{4}}-\d{{2}}-\d{{2}}/functions/(?P<function_name>[\w_-]+)/invocations?$': LambdaResponse.invoke,
|
|
||||||
}
|
}
|
||||||
|
118
moto/backends.py
118
moto/backends.py
@ -1,67 +1,71 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from moto.apigateway import apigateway_backend
|
from moto.apigateway import apigateway_backends
|
||||||
from moto.autoscaling import autoscaling_backend
|
from moto.autoscaling import autoscaling_backends
|
||||||
from moto.awslambda import lambda_backend
|
from moto.awslambda import lambda_backends
|
||||||
from moto.cloudformation import cloudformation_backend
|
from moto.cloudformation import cloudformation_backends
|
||||||
from moto.cloudwatch import cloudwatch_backend
|
from moto.cloudwatch import cloudwatch_backends
|
||||||
from moto.core import moto_api_backend
|
from moto.core import moto_api_backends
|
||||||
from moto.datapipeline import datapipeline_backend
|
from moto.datapipeline import datapipeline_backends
|
||||||
from moto.dynamodb import dynamodb_backend
|
from moto.dynamodb import dynamodb_backends
|
||||||
from moto.dynamodb2 import dynamodb_backend2
|
from moto.dynamodb2 import dynamodb_backends2
|
||||||
from moto.ec2 import ec2_backend
|
from moto.ec2 import ec2_backends
|
||||||
from moto.ecs import ecs_backend
|
from moto.ecs import ecs_backends
|
||||||
from moto.elb import elb_backend
|
from moto.elb import elb_backends
|
||||||
from moto.emr import emr_backend
|
from moto.emr import emr_backends
|
||||||
from moto.events import events_backend
|
from moto.events import events_backends
|
||||||
from moto.glacier import glacier_backend
|
from moto.glacier import glacier_backends
|
||||||
from moto.iam import iam_backend
|
from moto.iam import iam_backends
|
||||||
from moto.kinesis import kinesis_backend
|
from moto.instance_metadata import instance_metadata_backends
|
||||||
from moto.kms import kms_backend
|
from moto.kinesis import kinesis_backends
|
||||||
from moto.opsworks import opsworks_backend
|
from moto.kms import kms_backends
|
||||||
from moto.rds import rds_backend
|
from moto.opsworks import opsworks_backends
|
||||||
from moto.redshift import redshift_backend
|
from moto.rds2 import rds2_backends
|
||||||
from moto.route53 import route53_backend
|
from moto.redshift import redshift_backends
|
||||||
from moto.s3 import s3_backend
|
from moto.route53 import route53_backends
|
||||||
from moto.ses import ses_backend
|
from moto.s3 import s3_backends
|
||||||
from moto.sns import sns_backend
|
from moto.ses import ses_backends
|
||||||
from moto.sqs import sqs_backend
|
from moto.sns import sns_backends
|
||||||
from moto.sts import sts_backend
|
from moto.sqs import sqs_backends
|
||||||
|
from moto.sts import sts_backends
|
||||||
|
|
||||||
BACKENDS = {
|
BACKENDS = {
|
||||||
'apigateway': apigateway_backend,
|
'apigateway': apigateway_backends,
|
||||||
'autoscaling': autoscaling_backend,
|
'autoscaling': autoscaling_backends,
|
||||||
'cloudformation': cloudformation_backend,
|
'cloudformation': cloudformation_backends,
|
||||||
'cloudwatch': cloudwatch_backend,
|
'cloudwatch': cloudwatch_backends,
|
||||||
'datapipeline': datapipeline_backend,
|
'datapipeline': datapipeline_backends,
|
||||||
'dynamodb': dynamodb_backend,
|
'dynamodb': dynamodb_backends,
|
||||||
'dynamodb2': dynamodb_backend2,
|
'dynamodb2': dynamodb_backends2,
|
||||||
'ec2': ec2_backend,
|
'ec2': ec2_backends,
|
||||||
'ecs': ecs_backend,
|
'ecs': ecs_backends,
|
||||||
'elb': elb_backend,
|
'elb': elb_backends,
|
||||||
'events': events_backend,
|
'events': events_backends,
|
||||||
'emr': emr_backend,
|
'emr': emr_backends,
|
||||||
'glacier': glacier_backend,
|
'glacier': glacier_backends,
|
||||||
'iam': iam_backend,
|
'iam': iam_backends,
|
||||||
'moto_api': moto_api_backend,
|
'moto_api': moto_api_backends,
|
||||||
'opsworks': opsworks_backend,
|
'instance_metadata': instance_metadata_backends,
|
||||||
'kinesis': kinesis_backend,
|
'opsworks': opsworks_backends,
|
||||||
'kms': kms_backend,
|
'kinesis': kinesis_backends,
|
||||||
'redshift': redshift_backend,
|
'kms': kms_backends,
|
||||||
'rds': rds_backend,
|
'redshift': redshift_backends,
|
||||||
's3': s3_backend,
|
'rds': rds2_backends,
|
||||||
's3bucket_path': s3_backend,
|
's3': s3_backends,
|
||||||
'ses': ses_backend,
|
's3bucket_path': s3_backends,
|
||||||
'sns': sns_backend,
|
'ses': ses_backends,
|
||||||
'sqs': sqs_backend,
|
'sns': sns_backends,
|
||||||
'sts': sts_backend,
|
'sqs': sqs_backends,
|
||||||
'route53': route53_backend,
|
'sts': sts_backends,
|
||||||
'lambda': lambda_backend,
|
'route53': route53_backends,
|
||||||
|
'lambda': lambda_backends,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def get_model(name):
|
def get_model(name, region):
|
||||||
for backend in BACKENDS.values():
|
for backends in BACKENDS.values():
|
||||||
|
for region, backend in backends.items():
|
||||||
|
if region == region:
|
||||||
models = getattr(backend.__class__, '__models__', {})
|
models = getattr(backend.__class__, '__models__', {})
|
||||||
if name in models:
|
if name in models:
|
||||||
return list(getattr(backend, models[name])())
|
return list(getattr(backend, models[name])())
|
||||||
|
@ -17,6 +17,9 @@ class CloudFormationResponse(BaseResponse):
|
|||||||
|
|
||||||
def _get_stack_from_s3_url(self, template_url):
|
def _get_stack_from_s3_url(self, template_url):
|
||||||
template_url_parts = urlparse(template_url)
|
template_url_parts = urlparse(template_url)
|
||||||
|
if "localhost" in template_url:
|
||||||
|
bucket_name, key_name = template_url_parts.path.lstrip("/").split("/")
|
||||||
|
else:
|
||||||
bucket_name = template_url_parts.netloc.split(".")[0]
|
bucket_name = template_url_parts.netloc.split(".")[0]
|
||||||
key_name = template_url_parts.path.lstrip("/")
|
key_name = template_url_parts.path.lstrip("/")
|
||||||
|
|
||||||
|
@ -1,2 +1,4 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from .models import BaseBackend, moto_api_backend # flake8: noqa
|
from .models import BaseBackend, moto_api_backend # flake8: noqa
|
||||||
|
|
||||||
|
moto_api_backends = {"global": moto_api_backend}
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from werkzeug.exceptions import HTTPException
|
from werkzeug.exceptions import HTTPException
|
||||||
from jinja2 import DictLoader, Environment
|
from jinja2 import DictLoader, Environment
|
||||||
from six import text_type
|
from six import text_type
|
||||||
@ -47,6 +49,10 @@ class RESTError(HTTPException):
|
|||||||
error_type=error_type, message=message, **kwargs)
|
error_type=error_type, message=message, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
class DryRunClientError(RESTError):
|
||||||
|
code = 400
|
||||||
|
|
||||||
|
|
||||||
class JsonRESTError(RESTError):
|
class JsonRESTError(RESTError):
|
||||||
def __init__(self, error_type, message, template='error_json', **kwargs):
|
def __init__(self, error_type, message, template='error_json', **kwargs):
|
||||||
super(JsonRESTError, self).__init__(error_type, message, template, **kwargs)
|
super(JsonRESTError, self).__init__(error_type, message, template, **kwargs)
|
||||||
|
@ -6,9 +6,9 @@ import inspect
|
|||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
from moto import settings
|
||||||
from moto.packages.responses import responses
|
from moto.packages.responses import responses
|
||||||
from moto.packages.httpretty import HTTPretty
|
from moto.packages.httpretty import HTTPretty
|
||||||
from .responses import metadata_response
|
|
||||||
from .utils import (
|
from .utils import (
|
||||||
convert_httpretty_response,
|
convert_httpretty_response,
|
||||||
convert_regex_to_flask_path,
|
convert_regex_to_flask_path,
|
||||||
@ -21,6 +21,15 @@ class BaseMockAWS(object):
|
|||||||
def __init__(self, backends):
|
def __init__(self, backends):
|
||||||
self.backends = backends
|
self.backends = backends
|
||||||
|
|
||||||
|
self.backends_for_urls = {}
|
||||||
|
from moto.backends import BACKENDS
|
||||||
|
default_backends = {
|
||||||
|
"instance_metadata": BACKENDS['instance_metadata']['global'],
|
||||||
|
"moto_api": BACKENDS['moto_api']['global'],
|
||||||
|
}
|
||||||
|
self.backends_for_urls.update(self.backends)
|
||||||
|
self.backends_for_urls.update(default_backends)
|
||||||
|
|
||||||
if self.__class__.nested_count == 0:
|
if self.__class__.nested_count == 0:
|
||||||
self.reset()
|
self.reset()
|
||||||
|
|
||||||
@ -95,7 +104,7 @@ class HttprettyMockAWS(BaseMockAWS):
|
|||||||
HTTPretty.enable()
|
HTTPretty.enable()
|
||||||
|
|
||||||
for method in HTTPretty.METHODS:
|
for method in HTTPretty.METHODS:
|
||||||
backend = list(self.backends.values())[0]
|
for backend in self.backends_for_urls.values():
|
||||||
for key, value in backend.urls.items():
|
for key, value in backend.urls.items():
|
||||||
HTTPretty.register_uri(
|
HTTPretty.register_uri(
|
||||||
method=method,
|
method=method,
|
||||||
@ -103,13 +112,6 @@ class HttprettyMockAWS(BaseMockAWS):
|
|||||||
body=convert_httpretty_response(value),
|
body=convert_httpretty_response(value),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Mock out localhost instance metadata
|
|
||||||
HTTPretty.register_uri(
|
|
||||||
method=method,
|
|
||||||
uri=re.compile('http://169.254.169.254/latest/meta-data/.*'),
|
|
||||||
body=convert_httpretty_response(metadata_response),
|
|
||||||
)
|
|
||||||
|
|
||||||
def disable_patching(self):
|
def disable_patching(self):
|
||||||
HTTPretty.disable()
|
HTTPretty.disable()
|
||||||
HTTPretty.reset()
|
HTTPretty.reset()
|
||||||
@ -126,7 +128,7 @@ class ResponsesMockAWS(BaseMockAWS):
|
|||||||
def enable_patching(self):
|
def enable_patching(self):
|
||||||
responses.start()
|
responses.start()
|
||||||
for method in RESPONSES_METHODS:
|
for method in RESPONSES_METHODS:
|
||||||
backend = list(self.backends.values())[0]
|
for backend in self.backends_for_urls.values():
|
||||||
for key, value in backend.urls.items():
|
for key, value in backend.urls.items():
|
||||||
responses.add_callback(
|
responses.add_callback(
|
||||||
method=method,
|
method=method,
|
||||||
@ -134,12 +136,6 @@ class ResponsesMockAWS(BaseMockAWS):
|
|||||||
callback=convert_flask_to_responses_response(value),
|
callback=convert_flask_to_responses_response(value),
|
||||||
)
|
)
|
||||||
|
|
||||||
# Mock out localhost instance metadata
|
|
||||||
responses.add_callback(
|
|
||||||
method=method,
|
|
||||||
url=re.compile('http://169.254.169.254/latest/meta-data/.*'),
|
|
||||||
callback=convert_flask_to_responses_response(metadata_response),
|
|
||||||
)
|
|
||||||
for pattern in responses.mock._urls:
|
for pattern in responses.mock._urls:
|
||||||
pattern['stream'] = True
|
pattern['stream'] = True
|
||||||
|
|
||||||
@ -270,10 +266,15 @@ class BaseBackend(object):
|
|||||||
return paths
|
return paths
|
||||||
|
|
||||||
def decorator(self, func=None):
|
def decorator(self, func=None):
|
||||||
if func:
|
if settings.TEST_SERVER_MODE:
|
||||||
return MockAWS({'global': self})(func)
|
mocked_backend = ServerModeMockAWS({'global': self})
|
||||||
else:
|
else:
|
||||||
return MockAWS({'global': self})
|
mocked_backend = MockAWS({'global': self})
|
||||||
|
|
||||||
|
if func:
|
||||||
|
return mocked_backend(func)
|
||||||
|
else:
|
||||||
|
return mocked_backend
|
||||||
|
|
||||||
def deprecated_decorator(self, func=None):
|
def deprecated_decorator(self, func=None):
|
||||||
if func:
|
if func:
|
||||||
@ -289,13 +290,15 @@ class base_decorator(object):
|
|||||||
self.backends = backends
|
self.backends = backends
|
||||||
|
|
||||||
def __call__(self, func=None):
|
def __call__(self, func=None):
|
||||||
if self.mock_backend == MockAWS and os.environ.get('TEST_SERVER_MODE', '0').lower() == 'true':
|
if self.mock_backend != HttprettyMockAWS and settings.TEST_SERVER_MODE:
|
||||||
self.mock_backend = ServerModeMockAWS
|
mocked_backend = ServerModeMockAWS(self.backends)
|
||||||
|
else:
|
||||||
|
mocked_backend = self.mock_backend(self.backends)
|
||||||
|
|
||||||
if func:
|
if func:
|
||||||
return self.mock_backend(self.backends)(func)
|
return mocked_backend(func)
|
||||||
else:
|
else:
|
||||||
return self.mock_backend(self.backends)
|
return mocked_backend
|
||||||
|
|
||||||
|
|
||||||
class deprecated_base_decorator(base_decorator):
|
class deprecated_base_decorator(base_decorator):
|
||||||
@ -303,14 +306,12 @@ class deprecated_base_decorator(base_decorator):
|
|||||||
|
|
||||||
|
|
||||||
class MotoAPIBackend(BaseBackend):
|
class MotoAPIBackend(BaseBackend):
|
||||||
def __init__(self):
|
|
||||||
super(MotoAPIBackend, self).__init__()
|
|
||||||
|
|
||||||
def reset(self):
|
def reset(self):
|
||||||
from moto.backends import BACKENDS
|
from moto.backends import BACKENDS
|
||||||
for name, backend in BACKENDS.items():
|
for name, backends in BACKENDS.items():
|
||||||
if name == "moto_api":
|
if name == "moto_api":
|
||||||
continue
|
continue
|
||||||
|
for region_name, backend in backends.items():
|
||||||
backend.reset()
|
backend.reset()
|
||||||
self.__init__()
|
self.__init__()
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import logging
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
import pytz
|
import pytz
|
||||||
from boto.exception import JSONResponseError
|
from moto.core.exceptions import DryRunClientError
|
||||||
|
|
||||||
from jinja2 import Environment, DictLoader, TemplateNotFound
|
from jinja2 import Environment, DictLoader, TemplateNotFound
|
||||||
|
|
||||||
@ -149,17 +149,19 @@ class BaseResponse(_TemplateEnvironmentMixin):
|
|||||||
self.path = urlparse(full_url).path
|
self.path = urlparse(full_url).path
|
||||||
self.querystring = querystring
|
self.querystring = querystring
|
||||||
self.method = request.method
|
self.method = request.method
|
||||||
self.region = self.get_region_from_url(full_url)
|
self.region = self.get_region_from_url(request, full_url)
|
||||||
|
|
||||||
self.headers = request.headers
|
self.headers = request.headers
|
||||||
if 'host' not in self.headers:
|
if 'host' not in self.headers:
|
||||||
self.headers['host'] = urlparse(full_url).netloc
|
self.headers['host'] = urlparse(full_url).netloc
|
||||||
self.response_headers = {"server": "amazon.com"}
|
self.response_headers = {"server": "amazon.com"}
|
||||||
|
|
||||||
def get_region_from_url(self, full_url):
|
def get_region_from_url(self, request, full_url):
|
||||||
match = re.search(self.region_regex, full_url)
|
match = re.search(self.region_regex, full_url)
|
||||||
if match:
|
if match:
|
||||||
region = match.group(1)
|
region = match.group(1)
|
||||||
|
elif 'Authorization' in request.headers:
|
||||||
|
region = request.headers['Authorization'].split(",")[0].split("/")[2]
|
||||||
else:
|
else:
|
||||||
region = self.default_region
|
region = self.default_region
|
||||||
return region
|
return region
|
||||||
@ -195,6 +197,7 @@ class BaseResponse(_TemplateEnvironmentMixin):
|
|||||||
if "status" in headers:
|
if "status" in headers:
|
||||||
headers['status'] = str(headers['status'])
|
headers['status'] = str(headers['status'])
|
||||||
return status, headers, body
|
return status, headers, body
|
||||||
|
|
||||||
raise NotImplementedError("The {0} action has not been implemented".format(action))
|
raise NotImplementedError("The {0} action has not been implemented".format(action))
|
||||||
|
|
||||||
def _get_param(self, param_name, if_none=None):
|
def _get_param(self, param_name, if_none=None):
|
||||||
@ -323,55 +326,19 @@ class BaseResponse(_TemplateEnvironmentMixin):
|
|||||||
|
|
||||||
def is_not_dryrun(self, action):
|
def is_not_dryrun(self, action):
|
||||||
if 'true' in self.querystring.get('DryRun', ['false']):
|
if 'true' in self.querystring.get('DryRun', ['false']):
|
||||||
raise JSONResponseError(400, 'DryRunOperation', body={'message': 'An error occurred (DryRunOperation) when calling the %s operation: Request would have succeeded, but DryRun flag is set' % action})
|
message = 'An error occurred (DryRunOperation) when calling the %s operation: Request would have succeeded, but DryRun flag is set' % action
|
||||||
|
raise DryRunClientError(error_type="DryRunOperation", message=message)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def metadata_response(request, full_url, headers):
|
|
||||||
"""
|
|
||||||
Mock response for localhost metadata
|
|
||||||
|
|
||||||
http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/AESDG-chapter-instancedata.html
|
|
||||||
"""
|
|
||||||
|
|
||||||
parsed_url = urlparse(full_url)
|
|
||||||
tomorrow = datetime.datetime.utcnow() + datetime.timedelta(days=1)
|
|
||||||
credentials = dict(
|
|
||||||
AccessKeyId="test-key",
|
|
||||||
SecretAccessKey="test-secret-key",
|
|
||||||
Token="test-session-token",
|
|
||||||
Expiration=tomorrow.strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
||||||
)
|
|
||||||
|
|
||||||
path = parsed_url.path
|
|
||||||
|
|
||||||
meta_data_prefix = "/latest/meta-data/"
|
|
||||||
# Strip prefix if it is there
|
|
||||||
if path.startswith(meta_data_prefix):
|
|
||||||
path = path[len(meta_data_prefix):]
|
|
||||||
|
|
||||||
if path == '':
|
|
||||||
result = 'iam'
|
|
||||||
elif path == 'iam':
|
|
||||||
result = json.dumps({
|
|
||||||
'security-credentials': {
|
|
||||||
'default-role': credentials
|
|
||||||
}
|
|
||||||
})
|
|
||||||
elif path == 'iam/security-credentials/':
|
|
||||||
result = 'default-role'
|
|
||||||
elif path == 'iam/security-credentials/default-role':
|
|
||||||
result = json.dumps(credentials)
|
|
||||||
else:
|
|
||||||
raise NotImplementedError("The {0} metadata path has not been implemented".format(path))
|
|
||||||
return 200, headers, result
|
|
||||||
|
|
||||||
|
|
||||||
class MotoAPIResponse(BaseResponse):
|
class MotoAPIResponse(BaseResponse):
|
||||||
|
|
||||||
def reset_response(self, request, full_url, headers):
|
def reset_response(self, request, full_url, headers):
|
||||||
|
if request.method == "POST":
|
||||||
from .models import moto_api_backend
|
from .models import moto_api_backend
|
||||||
moto_api_backend.reset()
|
moto_api_backend.reset()
|
||||||
return 200, {}, json.dumps({"status": "ok"})
|
return 200, {}, json.dumps({"status": "ok"})
|
||||||
|
return 400, {}, json.dumps({"Error": "Need to POST to reset Moto"})
|
||||||
|
|
||||||
|
|
||||||
class _RecursiveDictRef(object):
|
class _RecursiveDictRef(object):
|
||||||
|
@ -118,12 +118,16 @@ class convert_flask_to_httpretty_response(object):
|
|||||||
return "{0}.{1}".format(outer, self.callback.__name__)
|
return "{0}.{1}".format(outer, self.callback.__name__)
|
||||||
|
|
||||||
def __call__(self, args=None, **kwargs):
|
def __call__(self, args=None, **kwargs):
|
||||||
from flask import request
|
from flask import request, Response
|
||||||
|
|
||||||
result = self.callback(request, request.url, {})
|
result = self.callback(request, request.url, {})
|
||||||
# result is a status, headers, response tuple
|
# result is a status, headers, response tuple
|
||||||
status, headers, response = result
|
status, headers, content = result
|
||||||
return response, status, headers
|
|
||||||
|
response = Response(response=content, status=status, headers=headers)
|
||||||
|
if request.method == "HEAD" and 'content-length' in headers:
|
||||||
|
response.headers['Content-Length'] = headers['content-length']
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
class convert_flask_to_responses_response(object):
|
class convert_flask_to_responses_response(object):
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from .models import dynamodb_backend
|
from .models import dynamodb_backend
|
||||||
|
|
||||||
|
dynamodb_backends = {"global": dynamodb_backend}
|
||||||
mock_dynamodb = dynamodb_backend.decorator
|
mock_dynamodb = dynamodb_backend.decorator
|
||||||
mock_dynamodb_deprecated = dynamodb_backend.deprecated_decorator
|
mock_dynamodb_deprecated = dynamodb_backend.deprecated_decorator
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from .models import dynamodb_backend2
|
from .models import dynamodb_backend2
|
||||||
|
|
||||||
|
dynamodb_backends2 = {"global": dynamodb_backend2}
|
||||||
mock_dynamodb2 = dynamodb_backend2.decorator
|
mock_dynamodb2 = dynamodb_backend2.decorator
|
||||||
mock_dynamodb2_deprecated = dynamodb_backend2.deprecated_decorator
|
mock_dynamodb2_deprecated = dynamodb_backend2.deprecated_decorator
|
@ -1,6 +1,5 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from boto.ec2.instancetype import InstanceType
|
from boto.ec2.instancetype import InstanceType
|
||||||
from boto.exception import JSONResponseError
|
|
||||||
from moto.core.responses import BaseResponse
|
from moto.core.responses import BaseResponse
|
||||||
from moto.core.utils import camelcase_to_underscores
|
from moto.core.utils import camelcase_to_underscores
|
||||||
from moto.ec2.utils import instance_ids_from_querystring, filters_from_querystring, \
|
from moto.ec2.utils import instance_ids_from_querystring, filters_from_querystring, \
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from boto.exception import JSONResponseError
|
|
||||||
from moto.core.responses import BaseResponse
|
from moto.core.responses import BaseResponse
|
||||||
|
|
||||||
|
|
||||||
|
@ -35,8 +35,8 @@ class SpotInstances(BaseResponse):
|
|||||||
def request_spot_instances(self):
|
def request_spot_instances(self):
|
||||||
price = self._get_param('SpotPrice')
|
price = self._get_param('SpotPrice')
|
||||||
image_id = self._get_param('LaunchSpecification.ImageId')
|
image_id = self._get_param('LaunchSpecification.ImageId')
|
||||||
count = self._get_int_param('InstanceCount')
|
count = self._get_int_param('InstanceCount', 1)
|
||||||
type = self._get_param('Type')
|
type = self._get_param('Type', 'one-time')
|
||||||
valid_from = self._get_param('ValidFrom')
|
valid_from = self._get_param('ValidFrom')
|
||||||
valid_until = self._get_param('ValidUntil')
|
valid_until = self._get_param('ValidUntil')
|
||||||
launch_group = self._get_param('LaunchGroup')
|
launch_group = self._get_param('LaunchGroup')
|
||||||
@ -44,7 +44,7 @@ class SpotInstances(BaseResponse):
|
|||||||
key_name = self._get_param('LaunchSpecification.KeyName')
|
key_name = self._get_param('LaunchSpecification.KeyName')
|
||||||
security_groups = self._get_multi_param('LaunchSpecification.SecurityGroup')
|
security_groups = self._get_multi_param('LaunchSpecification.SecurityGroup')
|
||||||
user_data = self._get_param('LaunchSpecification.UserData')
|
user_data = self._get_param('LaunchSpecification.UserData')
|
||||||
instance_type = self._get_param('LaunchSpecification.InstanceType')
|
instance_type = self._get_param('LaunchSpecification.InstanceType', 'm1.small')
|
||||||
placement = self._get_param('LaunchSpecification.Placement.AvailabilityZone')
|
placement = self._get_param('LaunchSpecification.Placement.AvailabilityZone')
|
||||||
kernel_id = self._get_param('LaunchSpecification.KernelId')
|
kernel_id = self._get_param('LaunchSpecification.KernelId')
|
||||||
ramdisk_id = self._get_param('LaunchSpecification.RamdiskId')
|
ramdisk_id = self._get_param('LaunchSpecification.RamdiskId')
|
||||||
|
7
moto/emr/exceptions.py
Normal file
7
moto/emr/exceptions.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from moto.core.exceptions import RESTError
|
||||||
|
|
||||||
|
|
||||||
|
class EmrError(RESTError):
|
||||||
|
code = 400
|
@ -299,6 +299,7 @@ class ElasticMapReduceBackend(BaseBackend):
|
|||||||
created_before = dtparse(created_before)
|
created_before = dtparse(created_before)
|
||||||
clusters = [c for c in clusters if c.creation_datetime < created_before]
|
clusters = [c for c in clusters if c.creation_datetime < created_before]
|
||||||
|
|
||||||
|
# Amazon EMR can return a maximum of 512 job flow descriptions
|
||||||
return sorted(clusters, key=lambda x: x.id)[:512]
|
return sorted(clusters, key=lambda x: x.id)[:512]
|
||||||
|
|
||||||
def describe_step(self, cluster_id, step_id):
|
def describe_step(self, cluster_id, step_id):
|
||||||
|
@ -5,15 +5,14 @@ from datetime import datetime
|
|||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
|
||||||
import pytz
|
import pytz
|
||||||
from botocore.exceptions import ClientError
|
|
||||||
|
|
||||||
from moto.compat import urlparse
|
from moto.compat import urlparse
|
||||||
from moto.core.responses import AWSServiceSpec
|
from moto.core.responses import AWSServiceSpec
|
||||||
from moto.core.responses import BaseResponse
|
from moto.core.responses import BaseResponse
|
||||||
from moto.core.responses import xml_to_json_response
|
from moto.core.responses import xml_to_json_response
|
||||||
|
from .exceptions import EmrError
|
||||||
from .models import emr_backends
|
from .models import emr_backends
|
||||||
from .utils import steps_from_query_string
|
from .utils import steps_from_query_string, tags_from_query_string
|
||||||
from .utils import tags_from_query_string
|
|
||||||
|
|
||||||
|
|
||||||
def generate_boto3_response(operation):
|
def generate_boto3_response(operation):
|
||||||
@ -46,7 +45,7 @@ class ElasticMapReduceResponse(BaseResponse):
|
|||||||
|
|
||||||
aws_service_spec = AWSServiceSpec('data/emr/2009-03-31/service-2.json')
|
aws_service_spec = AWSServiceSpec('data/emr/2009-03-31/service-2.json')
|
||||||
|
|
||||||
def get_region_from_url(self, full_url):
|
def get_region_from_url(self, request, full_url):
|
||||||
parsed = urlparse(full_url)
|
parsed = urlparse(full_url)
|
||||||
for regex in self.region_regex:
|
for regex in self.region_regex:
|
||||||
match = regex.search(parsed.netloc)
|
match = regex.search(parsed.netloc)
|
||||||
@ -240,9 +239,7 @@ class ElasticMapReduceResponse(BaseResponse):
|
|||||||
'Only one AMI version and release label may be specified. '
|
'Only one AMI version and release label may be specified. '
|
||||||
'Provided AMI: {0}, release label: {1}.').format(
|
'Provided AMI: {0}, release label: {1}.').format(
|
||||||
ami_version, release_label)
|
ami_version, release_label)
|
||||||
raise ClientError(
|
raise EmrError(error_type="ValidationException", message=message, template='single_error')
|
||||||
{'Error': {'Code': 'ValidationException',
|
|
||||||
'Message': message}}, 'RunJobFlow')
|
|
||||||
else:
|
else:
|
||||||
if ami_version:
|
if ami_version:
|
||||||
kwargs['requested_ami_version'] = ami_version
|
kwargs['requested_ami_version'] = ami_version
|
||||||
|
@ -2,4 +2,5 @@ from __future__ import unicode_literals
|
|||||||
|
|
||||||
from .models import events_backend
|
from .models import events_backend
|
||||||
|
|
||||||
|
events_backends = {"global": events_backend}
|
||||||
mock_events = events_backend.decorator
|
mock_events = events_backend.decorator
|
||||||
|
@ -3,7 +3,7 @@ from __future__ import unicode_literals
|
|||||||
from .responses import EventsHandler
|
from .responses import EventsHandler
|
||||||
|
|
||||||
url_bases = [
|
url_bases = [
|
||||||
"https://events.(.+).amazonaws.com"
|
"https?://events.(.+).amazonaws.com"
|
||||||
]
|
]
|
||||||
|
|
||||||
url_paths = {
|
url_paths = {
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from .models import iam_backend
|
from .models import iam_backend
|
||||||
|
|
||||||
|
iam_backends = {"global": iam_backend}
|
||||||
mock_iam = iam_backend.decorator
|
mock_iam = iam_backend.decorator
|
||||||
mock_iam_deprecated = iam_backend.deprecated_decorator
|
mock_iam_deprecated = iam_backend.deprecated_decorator
|
@ -2,7 +2,7 @@ from __future__ import unicode_literals
|
|||||||
from .responses import IamResponse
|
from .responses import IamResponse
|
||||||
|
|
||||||
url_bases = [
|
url_bases = [
|
||||||
"https?://iam.amazonaws.com",
|
"https?://iam(.*).amazonaws.com",
|
||||||
]
|
]
|
||||||
|
|
||||||
url_paths = {
|
url_paths = {
|
||||||
|
4
moto/instance_metadata/__init__.py
Normal file
4
moto/instance_metadata/__init__.py
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
from __future__ import unicode_literals
|
||||||
|
from .models import instance_metadata_backend
|
||||||
|
|
||||||
|
instance_metadata_backends = {"global": instance_metadata_backend}
|
7
moto/instance_metadata/models.py
Normal file
7
moto/instance_metadata/models.py
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
from moto.core.models import BaseBackend
|
||||||
|
|
||||||
|
|
||||||
|
class InstanceMetadataBackend(BaseBackend):
|
||||||
|
pass
|
||||||
|
|
||||||
|
instance_metadata_backend = InstanceMetadataBackend()
|
47
moto/instance_metadata/responses.py
Normal file
47
moto/instance_metadata/responses.py
Normal 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
|
12
moto/instance_metadata/urls.py
Normal file
12
moto/instance_metadata/urls.py
Normal 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,
|
||||||
|
}
|
@ -20,7 +20,7 @@ class KinesisResponse(BaseResponse):
|
|||||||
@property
|
@property
|
||||||
def is_firehose(self):
|
def is_firehose(self):
|
||||||
host = self.headers.get('host') or self.headers['Host']
|
host = self.headers.get('host') or self.headers['Host']
|
||||||
return host.startswith('firehose')
|
return host.startswith('firehose') or 'firehose' in self.headers.get('Authorization', '')
|
||||||
|
|
||||||
def create_stream(self):
|
def create_stream(self):
|
||||||
stream_name = self.parameters.get('StreamName')
|
stream_name = self.parameters.get('StreamName')
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from .models import route53_backend
|
from .models import route53_backend
|
||||||
|
|
||||||
|
route53_backends = {"global": route53_backend}
|
||||||
mock_route53 = route53_backend.decorator
|
mock_route53 = route53_backend.decorator
|
||||||
mock_route53_deprecated = route53_backend.deprecated_decorator
|
mock_route53_deprecated = route53_backend.deprecated_decorator
|
||||||
|
@ -1,14 +1,18 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from jinja2 import Template
|
from jinja2 import Template
|
||||||
from six.moves.urllib.parse import parse_qs, urlparse
|
from six.moves.urllib.parse import parse_qs, urlparse
|
||||||
|
|
||||||
|
from moto.core.responses import BaseResponse
|
||||||
from .models import route53_backend
|
from .models import route53_backend
|
||||||
import xmltodict
|
import xmltodict
|
||||||
|
|
||||||
|
|
||||||
def list_or_create_hostzone_response(request, full_url, headers):
|
class Route53 (BaseResponse):
|
||||||
|
def list_or_create_hostzone_response(self, request, full_url, headers):
|
||||||
|
self.setup_class(request, full_url, headers)
|
||||||
|
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
elements = xmltodict.parse(request.body)
|
elements = xmltodict.parse(self.body)
|
||||||
if "HostedZoneConfig" in elements["CreateHostedZoneRequest"]:
|
if "HostedZoneConfig" in elements["CreateHostedZoneRequest"]:
|
||||||
comment = elements["CreateHostedZoneRequest"]["HostedZoneConfig"]["Comment"]
|
comment = elements["CreateHostedZoneRequest"]["HostedZoneConfig"]["Comment"]
|
||||||
try:
|
try:
|
||||||
@ -22,7 +26,6 @@ def list_or_create_hostzone_response(request, full_url, headers):
|
|||||||
comment = None
|
comment = None
|
||||||
private_zone = False
|
private_zone = False
|
||||||
|
|
||||||
|
|
||||||
name = elements["CreateHostedZoneRequest"]["Name"]
|
name = elements["CreateHostedZoneRequest"]["Name"]
|
||||||
|
|
||||||
if name[-1] != ".":
|
if name[-1] != ".":
|
||||||
@ -42,7 +45,8 @@ def list_or_create_hostzone_response(request, full_url, headers):
|
|||||||
return 200, headers, template.render(zones=all_zones)
|
return 200, headers, template.render(zones=all_zones)
|
||||||
|
|
||||||
|
|
||||||
def get_or_delete_hostzone_response(request, full_url, headers):
|
def get_or_delete_hostzone_response(self, request, full_url, headers):
|
||||||
|
self.setup_class(request, full_url, headers)
|
||||||
parsed_url = urlparse(full_url)
|
parsed_url = urlparse(full_url)
|
||||||
zoneid = parsed_url.path.rstrip('/').rsplit('/', 1)[1]
|
zoneid = parsed_url.path.rstrip('/').rsplit('/', 1)[1]
|
||||||
the_zone = route53_backend.get_hosted_zone(zoneid)
|
the_zone = route53_backend.get_hosted_zone(zoneid)
|
||||||
@ -58,7 +62,9 @@ def get_or_delete_hostzone_response(request, full_url, headers):
|
|||||||
return 200, headers, DELETE_HOSTED_ZONE_RESPONSE
|
return 200, headers, DELETE_HOSTED_ZONE_RESPONSE
|
||||||
|
|
||||||
|
|
||||||
def rrset_response(request, full_url, headers):
|
def rrset_response(self, request, full_url, headers):
|
||||||
|
self.setup_class(request, full_url, headers)
|
||||||
|
|
||||||
parsed_url = urlparse(full_url)
|
parsed_url = urlparse(full_url)
|
||||||
method = request.method
|
method = request.method
|
||||||
|
|
||||||
@ -68,7 +74,7 @@ def rrset_response(request, full_url, headers):
|
|||||||
return 404, headers, "Zone %s Not Found" % zoneid
|
return 404, headers, "Zone %s Not Found" % zoneid
|
||||||
|
|
||||||
if method == "POST":
|
if method == "POST":
|
||||||
elements = xmltodict.parse(request.body)
|
elements = xmltodict.parse(self.body)
|
||||||
|
|
||||||
change_list = elements['ChangeResourceRecordSetsRequest']['ChangeBatch']['Changes']['Change']
|
change_list = elements['ChangeResourceRecordSetsRequest']['ChangeBatch']['Changes']['Change']
|
||||||
if not isinstance(change_list, list):
|
if not isinstance(change_list, list):
|
||||||
@ -108,12 +114,14 @@ def rrset_response(request, full_url, headers):
|
|||||||
return 200, headers, template.render(record_sets=record_sets)
|
return 200, headers, template.render(record_sets=record_sets)
|
||||||
|
|
||||||
|
|
||||||
def health_check_response(request, full_url, headers):
|
def health_check_response(self, request, full_url, headers):
|
||||||
|
self.setup_class(request, full_url, headers)
|
||||||
|
|
||||||
parsed_url = urlparse(full_url)
|
parsed_url = urlparse(full_url)
|
||||||
method = request.method
|
method = request.method
|
||||||
|
|
||||||
if method == "POST":
|
if method == "POST":
|
||||||
properties = xmltodict.parse(request.body)['CreateHealthCheckRequest']['HealthCheckConfig']
|
properties = xmltodict.parse(self.body)['CreateHealthCheckRequest']['HealthCheckConfig']
|
||||||
health_check_args = {
|
health_check_args = {
|
||||||
"ip_address": properties.get('IPAddress'),
|
"ip_address": properties.get('IPAddress'),
|
||||||
"port": properties.get('Port'),
|
"port": properties.get('Port'),
|
||||||
@ -136,7 +144,9 @@ def health_check_response(request, full_url, headers):
|
|||||||
health_checks = route53_backend.get_health_checks()
|
health_checks = route53_backend.get_health_checks()
|
||||||
return 200, headers, template.render(health_checks=health_checks)
|
return 200, headers, template.render(health_checks=health_checks)
|
||||||
|
|
||||||
def not_implemented_response(request, full_url, headers):
|
def not_implemented_response(self, request, full_url, headers):
|
||||||
|
self.setup_class(request, full_url, headers)
|
||||||
|
|
||||||
action = ''
|
action = ''
|
||||||
if 'tags' in full_url:
|
if 'tags' in full_url:
|
||||||
action = 'tags'
|
action = 'tags'
|
||||||
@ -145,7 +155,9 @@ def not_implemented_response(request, full_url, headers):
|
|||||||
raise NotImplementedError("The action for {0} has not been implemented for route 53".format(action))
|
raise NotImplementedError("The action for {0} has not been implemented for route 53".format(action))
|
||||||
|
|
||||||
|
|
||||||
def list_or_change_tags_for_resource_request(request, full_url, headers):
|
def list_or_change_tags_for_resource_request(self, request, full_url, headers):
|
||||||
|
self.setup_class(request, full_url, headers)
|
||||||
|
|
||||||
parsed_url = urlparse(full_url)
|
parsed_url = urlparse(full_url)
|
||||||
id_ = parsed_url.path.split("/")[-1]
|
id_ = parsed_url.path.split("/")[-1]
|
||||||
type_ = parsed_url.path.split("/")[-2]
|
type_ = parsed_url.path.split("/")[-2]
|
||||||
@ -158,7 +170,7 @@ def list_or_change_tags_for_resource_request(request, full_url, headers):
|
|||||||
|
|
||||||
if request.method == "POST":
|
if request.method == "POST":
|
||||||
tags = xmltodict.parse(
|
tags = xmltodict.parse(
|
||||||
request.body)['ChangeTagsForResourceRequest']
|
self.body)['ChangeTagsForResourceRequest']
|
||||||
|
|
||||||
if 'AddTags' in tags:
|
if 'AddTags' in tags:
|
||||||
tags = tags['AddTags']
|
tags = tags['AddTags']
|
||||||
|
@ -1,15 +1,25 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from . import responses
|
from .responses import Route53
|
||||||
|
|
||||||
url_bases = [
|
url_bases = [
|
||||||
"https://route53.amazonaws.com/201.-..-../",
|
"https?://route53(.*).amazonaws.com",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def tag_response1(*args, **kwargs):
|
||||||
|
return Route53().list_or_change_tags_for_resource_request(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
|
def tag_response2(*args, **kwargs):
|
||||||
|
return Route53().list_or_change_tags_for_resource_request(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
url_paths = {
|
url_paths = {
|
||||||
'{0}hostedzone$': responses.list_or_create_hostzone_response,
|
'{0}/(?P<api_version>[\d_-]+)/hostedzone$': Route53().list_or_create_hostzone_response,
|
||||||
'{0}hostedzone/[^/]+$': responses.get_or_delete_hostzone_response,
|
'{0}/(?P<api_version>[\d_-]+)/hostedzone/(?P<zone_id>[^/]+)$': Route53().get_or_delete_hostzone_response,
|
||||||
'{0}hostedzone/[^/]+/rrset/?$': responses.rrset_response,
|
'{0}/(?P<api_version>[\d_-]+)/hostedzone/(?P<zone_id>[^/]+)/rrset/?$': Route53().rrset_response,
|
||||||
'{0}healthcheck': responses.health_check_response,
|
'{0}/(?P<api_version>[\d_-]+)/healthcheck': Route53().health_check_response,
|
||||||
'{0}tags/(healthcheck|hostedzone)/*': responses.list_or_change_tags_for_resource_request,
|
'{0}/(?P<api_version>[\d_-]+)/tags/healthcheck/(?P<zone_id>[^/]+)$': tag_response1,
|
||||||
'{0}trafficpolicyinstances/*': responses.not_implemented_response
|
'{0}/(?P<api_version>[\d_-]+)/tags/hostedzone/(?P<zone_id>[^/]+)$': tag_response2,
|
||||||
|
'{0}/(?P<api_version>[\d_-]+)/trafficpolicyinstances/*': Route53().not_implemented_response
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from .models import s3_backend
|
from .models import s3_backend
|
||||||
|
|
||||||
|
s3_backends = {"global": s3_backend}
|
||||||
mock_s3 = s3_backend.decorator
|
mock_s3 = s3_backend.decorator
|
||||||
mock_s3_deprecated = s3_backend.deprecated_decorator
|
mock_s3_deprecated = s3_backend.deprecated_decorator
|
@ -89,21 +89,21 @@ class FakeKey(object):
|
|||||||
|
|
||||||
@property
|
@property
|
||||||
def response_dict(self):
|
def response_dict(self):
|
||||||
r = {
|
res = {
|
||||||
'etag': self.etag,
|
'etag': self.etag,
|
||||||
'last-modified': self.last_modified_RFC1123,
|
'last-modified': self.last_modified_RFC1123,
|
||||||
'content-length': str(len(self.value)),
|
'content-length': str(len(self.value)),
|
||||||
}
|
}
|
||||||
if self._storage_class != 'STANDARD':
|
if self._storage_class != 'STANDARD':
|
||||||
r['x-amz-storage-class'] = self._storage_class
|
res['x-amz-storage-class'] = self._storage_class
|
||||||
if self._expiry is not None:
|
if self._expiry is not None:
|
||||||
rhdr = 'ongoing-request="false", expiry-date="{0}"'
|
rhdr = 'ongoing-request="false", expiry-date="{0}"'
|
||||||
r['x-amz-restore'] = rhdr.format(self.expiry_date)
|
res['x-amz-restore'] = rhdr.format(self.expiry_date)
|
||||||
|
|
||||||
if self._is_versioned:
|
if self._is_versioned:
|
||||||
r['x-amz-version-id'] = str(self._version_id)
|
res['x-amz-version-id'] = str(self._version_id)
|
||||||
|
|
||||||
return r
|
return res
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def size(self):
|
def size(self):
|
||||||
|
@ -39,21 +39,28 @@ class DomainDispatcherApplication(object):
|
|||||||
return host
|
return host
|
||||||
|
|
||||||
for backend_name, backend in BACKENDS.items():
|
for backend_name, backend in BACKENDS.items():
|
||||||
for url_base in backend.url_bases:
|
for url_base in backend.values()[0].url_bases:
|
||||||
if re.match(url_base, 'http://%s' % host):
|
if re.match(url_base, 'http://%s' % host):
|
||||||
return backend_name
|
return backend_name
|
||||||
|
|
||||||
raise RuntimeError('Invalid host: "%s"' % host)
|
raise RuntimeError('Invalid host: "%s"' % host)
|
||||||
|
|
||||||
def get_application(self, environ):
|
def get_application(self, environ):
|
||||||
if environ.get('PATH_INFO', '').startswith("/moto-api"):
|
path_info = environ.get('PATH_INFO', '')
|
||||||
|
if path_info.startswith("/moto-api"):
|
||||||
host = "moto_api"
|
host = "moto_api"
|
||||||
|
elif path_info.startswith("/latest/meta-data/"):
|
||||||
|
host = "instance_metadata"
|
||||||
else:
|
else:
|
||||||
host = environ['HTTP_HOST'].split(':')[0]
|
host = environ['HTTP_HOST'].split(':')[0]
|
||||||
if host == "localhost":
|
if host == "localhost":
|
||||||
# Fall back to parsing auth header to find service
|
# Fall back to parsing auth header to find service
|
||||||
# ['Credential=sdffdsa', '20170220', 'us-east-1', 'sns', 'aws4_request']
|
# ['Credential=sdffdsa', '20170220', 'us-east-1', 'sns', 'aws4_request']
|
||||||
|
try:
|
||||||
_, _, region, service, _ = environ['HTTP_AUTHORIZATION'].split(",")[0].split()[1].split("/")
|
_, _, region, service, _ = environ['HTTP_AUTHORIZATION'].split(",")[0].split()[1].split("/")
|
||||||
|
except ValueError:
|
||||||
|
region = 'us-east-1'
|
||||||
|
service = 's3'
|
||||||
host = "{service}.{region}.amazonaws.com".format(service=service, region=region)
|
host = "{service}.{region}.amazonaws.com".format(service=service, region=region)
|
||||||
|
|
||||||
with self.lock:
|
with self.lock:
|
||||||
@ -108,7 +115,7 @@ def create_backend_app(service):
|
|||||||
backend_app.view_functions = {}
|
backend_app.view_functions = {}
|
||||||
backend_app.url_map = Map()
|
backend_app.url_map = Map()
|
||||||
backend_app.url_map.converters['regex'] = RegexConverter
|
backend_app.url_map.converters['regex'] = RegexConverter
|
||||||
backend = BACKENDS[service]
|
backend = BACKENDS[service].values()[0]
|
||||||
for url_path, handler in backend.flask_paths.items():
|
for url_path, handler in backend.flask_paths.items():
|
||||||
if handler.__name__ == 'dispatch':
|
if handler.__name__ == 'dispatch':
|
||||||
endpoint = '{0}.dispatch'.format(handler.__self__.__name__)
|
endpoint = '{0}.dispatch'.format(handler.__self__.__name__)
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from .models import ses_backend
|
from .models import ses_backend
|
||||||
|
|
||||||
|
ses_backends = {"global": ses_backend}
|
||||||
mock_ses = ses_backend.decorator
|
mock_ses = ses_backend.decorator
|
||||||
mock_ses_deprecated = ses_backend.deprecated_decorator
|
mock_ses_deprecated = ses_backend.deprecated_decorator
|
@ -2,7 +2,8 @@ from __future__ import unicode_literals
|
|||||||
from .responses import EmailResponse
|
from .responses import EmailResponse
|
||||||
|
|
||||||
url_bases = [
|
url_bases = [
|
||||||
"https?://email.(.+).amazonaws.com"
|
"https?://email.(.+).amazonaws.com",
|
||||||
|
"https?://ses.(.+).amazonaws.com",
|
||||||
]
|
]
|
||||||
|
|
||||||
url_paths = {
|
url_paths = {
|
||||||
|
3
moto/settings.py
Normal file
3
moto/settings.py
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
import os
|
||||||
|
|
||||||
|
TEST_SERVER_MODE = os.environ.get('TEST_SERVER_MODE', '0').lower() == 'true'
|
@ -1,4 +1,6 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
from .models import sts_backend
|
from .models import sts_backend
|
||||||
|
|
||||||
|
sts_backends = {"global": sts_backend}
|
||||||
mock_sts = sts_backend.decorator
|
mock_sts = sts_backend.decorator
|
||||||
mock_sts_deprecated = sts_backend.deprecated_decorator
|
mock_sts_deprecated = sts_backend.deprecated_decorator
|
||||||
|
@ -2,7 +2,7 @@ from __future__ import unicode_literals
|
|||||||
from .responses import TokenResponse
|
from .responses import TokenResponse
|
||||||
|
|
||||||
url_bases = [
|
url_bases = [
|
||||||
"https?://sts.amazonaws.com"
|
"https?://sts(.*).amazonaws.com"
|
||||||
]
|
]
|
||||||
|
|
||||||
url_paths = {
|
url_paths = {
|
||||||
|
52
other_langs/sqsSample.java
Normal file
52
other_langs/sqsSample.java
Normal 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
26
other_langs/test.js
Normal 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
6
other_langs/test.rb
Normal 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()
|
@ -10,7 +10,7 @@ import sure # noqa
|
|||||||
from botocore.exceptions import ClientError
|
from botocore.exceptions import ClientError
|
||||||
|
|
||||||
from moto.packages.responses import responses
|
from moto.packages.responses import responses
|
||||||
from moto import mock_apigateway
|
from moto import mock_apigateway, settings
|
||||||
|
|
||||||
|
|
||||||
@freeze_time("2015-01-01")
|
@freeze_time("2015-01-01")
|
||||||
@ -29,11 +29,11 @@ def test_create_and_get_rest_api():
|
|||||||
)
|
)
|
||||||
|
|
||||||
response.pop('ResponseMetadata')
|
response.pop('ResponseMetadata')
|
||||||
|
response.pop('createdDate')
|
||||||
response.should.equal({
|
response.should.equal({
|
||||||
'id': api_id,
|
'id': api_id,
|
||||||
'name': 'my_api',
|
'name': 'my_api',
|
||||||
'description': 'this is my api',
|
'description': 'this is my api',
|
||||||
'createdDate': datetime(2015, 1, 1, tzinfo=tzutc())
|
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
@ -930,4 +930,5 @@ def test_http_proxying_integration():
|
|||||||
|
|
||||||
deploy_url = "https://{api_id}.execute-api.{region_name}.amazonaws.com/{stage_name}".format(api_id=api_id, region_name=region_name, stage_name=stage_name)
|
deploy_url = "https://{api_id}.execute-api.{region_name}.amazonaws.com/{stage_name}".format(api_id=api_id, region_name=region_name, stage_name=stage_name)
|
||||||
|
|
||||||
|
if not settings.TEST_SERVER_MODE:
|
||||||
requests.get(deploy_url).content.should.equal(b"a fake response")
|
requests.get(deploy_url).content.should.equal(b"a fake response")
|
||||||
|
@ -10,7 +10,7 @@ import zipfile
|
|||||||
import sure # noqa
|
import sure # noqa
|
||||||
|
|
||||||
from freezegun import freeze_time
|
from freezegun import freeze_time
|
||||||
from moto import mock_lambda, mock_s3, mock_ec2
|
from moto import mock_lambda, mock_s3, mock_ec2, settings
|
||||||
|
|
||||||
|
|
||||||
def _process_lamda(pfunc):
|
def _process_lamda(pfunc):
|
||||||
@ -36,16 +36,15 @@ def lambda_handler(event, context):
|
|||||||
volume_id = event.get('volume_id')
|
volume_id = event.get('volume_id')
|
||||||
print('get volume details for %s' % volume_id)
|
print('get volume details for %s' % volume_id)
|
||||||
import boto3
|
import boto3
|
||||||
ec2 = boto3.resource('ec2', region_name='us-west-2')
|
ec2 = boto3.resource('ec2', region_name='us-west-2', endpoint_url="http://{base_url}")
|
||||||
vol = ec2.Volume(volume_id)
|
vol = ec2.Volume(volume_id)
|
||||||
print('Volume - %s state=%s, size=%s' % (volume_id, vol.state, vol.size))
|
print('Volume - %s state=%s, size=%s' % (volume_id, vol.state, vol.size))
|
||||||
return event
|
return event
|
||||||
"""
|
""".format(base_url="localhost:8086" if settings.TEST_SERVER_MODE else "ec2.us-west-2.amazonaws.com")
|
||||||
return _process_lamda(pfunc)
|
return _process_lamda(pfunc)
|
||||||
|
|
||||||
|
|
||||||
@mock_lambda
|
@mock_lambda
|
||||||
@mock_s3
|
|
||||||
def test_list_functions():
|
def test_list_functions():
|
||||||
conn = boto3.client('lambda', 'us-west-2')
|
conn = boto3.client('lambda', 'us-west-2')
|
||||||
result = conn.list_functions()
|
result = conn.list_functions()
|
||||||
@ -53,7 +52,6 @@ def test_list_functions():
|
|||||||
|
|
||||||
|
|
||||||
@mock_lambda
|
@mock_lambda
|
||||||
@freeze_time('2015-01-01 00:00:00')
|
|
||||||
def test_invoke_requestresponse_function():
|
def test_invoke_requestresponse_function():
|
||||||
conn = boto3.client('lambda', 'us-west-2')
|
conn = boto3.client('lambda', 'us-west-2')
|
||||||
conn.create_function(
|
conn.create_function(
|
||||||
@ -80,7 +78,6 @@ def test_invoke_requestresponse_function():
|
|||||||
|
|
||||||
|
|
||||||
@mock_lambda
|
@mock_lambda
|
||||||
@freeze_time('2015-01-01 00:00:00')
|
|
||||||
def test_invoke_event_function():
|
def test_invoke_event_function():
|
||||||
conn = boto3.client('lambda', 'us-west-2')
|
conn = boto3.client('lambda', 'us-west-2')
|
||||||
conn.create_function(
|
conn.create_function(
|
||||||
@ -111,7 +108,6 @@ def test_invoke_event_function():
|
|||||||
|
|
||||||
@mock_ec2
|
@mock_ec2
|
||||||
@mock_lambda
|
@mock_lambda
|
||||||
@freeze_time('2015-01-01 00:00:00')
|
|
||||||
def test_invoke_function_get_ec2_volume():
|
def test_invoke_function_get_ec2_volume():
|
||||||
conn = boto3.resource("ec2", "us-west-2")
|
conn = boto3.resource("ec2", "us-west-2")
|
||||||
vol = conn.create_volume(Size=99, AvailabilityZone='us-west-2')
|
vol = conn.create_volume(Size=99, AvailabilityZone='us-west-2')
|
||||||
@ -141,7 +137,6 @@ def test_invoke_function_get_ec2_volume():
|
|||||||
|
|
||||||
|
|
||||||
@mock_lambda
|
@mock_lambda
|
||||||
@freeze_time('2015-01-01 00:00:00')
|
|
||||||
def test_create_based_on_s3_with_missing_bucket():
|
def test_create_based_on_s3_with_missing_bucket():
|
||||||
conn = boto3.client('lambda', 'us-west-2')
|
conn = boto3.client('lambda', 'us-west-2')
|
||||||
|
|
||||||
@ -196,6 +191,7 @@ def test_create_function_from_aws_bucket():
|
|||||||
)
|
)
|
||||||
result['ResponseMetadata'].pop('HTTPHeaders', None) # this is hard to match against, so remove it
|
result['ResponseMetadata'].pop('HTTPHeaders', None) # this is hard to match against, so remove it
|
||||||
result['ResponseMetadata'].pop('RetryAttempts', None) # Botocore inserts retry attempts not seen in Python27
|
result['ResponseMetadata'].pop('RetryAttempts', None) # Botocore inserts retry attempts not seen in Python27
|
||||||
|
result.pop('LastModified')
|
||||||
result.should.equal({
|
result.should.equal({
|
||||||
'FunctionName': 'testFunction',
|
'FunctionName': 'testFunction',
|
||||||
'FunctionArn': 'arn:aws:lambda:123456789012:function:testFunction',
|
'FunctionArn': 'arn:aws:lambda:123456789012:function:testFunction',
|
||||||
@ -207,7 +203,6 @@ def test_create_function_from_aws_bucket():
|
|||||||
'Description': 'test lambda function',
|
'Description': 'test lambda function',
|
||||||
'Timeout': 3,
|
'Timeout': 3,
|
||||||
'MemorySize': 128,
|
'MemorySize': 128,
|
||||||
'LastModified': '2015-01-01 00:00:00',
|
|
||||||
'Version': '$LATEST',
|
'Version': '$LATEST',
|
||||||
'VpcConfig': {
|
'VpcConfig': {
|
||||||
"SecurityGroupIds": ["sg-123abc"],
|
"SecurityGroupIds": ["sg-123abc"],
|
||||||
@ -238,6 +233,7 @@ def test_create_function_from_zipfile():
|
|||||||
)
|
)
|
||||||
result['ResponseMetadata'].pop('HTTPHeaders', None) # this is hard to match against, so remove it
|
result['ResponseMetadata'].pop('HTTPHeaders', None) # this is hard to match against, so remove it
|
||||||
result['ResponseMetadata'].pop('RetryAttempts', None) # Botocore inserts retry attempts not seen in Python27
|
result['ResponseMetadata'].pop('RetryAttempts', None) # Botocore inserts retry attempts not seen in Python27
|
||||||
|
result.pop('LastModified')
|
||||||
|
|
||||||
result.should.equal({
|
result.should.equal({
|
||||||
'FunctionName': 'testFunction',
|
'FunctionName': 'testFunction',
|
||||||
@ -249,7 +245,6 @@ def test_create_function_from_zipfile():
|
|||||||
'Description': 'test lambda function',
|
'Description': 'test lambda function',
|
||||||
'Timeout': 3,
|
'Timeout': 3,
|
||||||
'MemorySize': 128,
|
'MemorySize': 128,
|
||||||
'LastModified': '2015-01-01 00:00:00',
|
|
||||||
'CodeSha256': hashlib.sha256(zip_content).hexdigest(),
|
'CodeSha256': hashlib.sha256(zip_content).hexdigest(),
|
||||||
'Version': '$LATEST',
|
'Version': '$LATEST',
|
||||||
'VpcConfig': {
|
'VpcConfig': {
|
||||||
@ -290,6 +285,7 @@ def test_get_function():
|
|||||||
result = conn.get_function(FunctionName='testFunction')
|
result = conn.get_function(FunctionName='testFunction')
|
||||||
result['ResponseMetadata'].pop('HTTPHeaders', None) # this is hard to match against, so remove it
|
result['ResponseMetadata'].pop('HTTPHeaders', None) # this is hard to match against, so remove it
|
||||||
result['ResponseMetadata'].pop('RetryAttempts', None) # Botocore inserts retry attempts not seen in Python27
|
result['ResponseMetadata'].pop('RetryAttempts', None) # Botocore inserts retry attempts not seen in Python27
|
||||||
|
result['Configuration'].pop('LastModified')
|
||||||
|
|
||||||
result.should.equal({
|
result.should.equal({
|
||||||
"Code": {
|
"Code": {
|
||||||
@ -303,7 +299,6 @@ def test_get_function():
|
|||||||
"FunctionArn": "arn:aws:lambda:123456789012:function:testFunction",
|
"FunctionArn": "arn:aws:lambda:123456789012:function:testFunction",
|
||||||
"FunctionName": "testFunction",
|
"FunctionName": "testFunction",
|
||||||
"Handler": "lambda_function.handler",
|
"Handler": "lambda_function.handler",
|
||||||
"LastModified": "2015-01-01 00:00:00",
|
|
||||||
"MemorySize": 128,
|
"MemorySize": 128,
|
||||||
"Role": "test-iam-role",
|
"Role": "test-iam-role",
|
||||||
"Runtime": "python2.7",
|
"Runtime": "python2.7",
|
||||||
@ -395,7 +390,6 @@ def test_list_create_list_get_delete_list():
|
|||||||
"FunctionArn": "arn:aws:lambda:123456789012:function:testFunction",
|
"FunctionArn": "arn:aws:lambda:123456789012:function:testFunction",
|
||||||
"FunctionName": "testFunction",
|
"FunctionName": "testFunction",
|
||||||
"Handler": "lambda_function.handler",
|
"Handler": "lambda_function.handler",
|
||||||
"LastModified": "2015-01-01 00:00:00",
|
|
||||||
"MemorySize": 128,
|
"MemorySize": 128,
|
||||||
"Role": "test-iam-role",
|
"Role": "test-iam-role",
|
||||||
"Runtime": "python2.7",
|
"Runtime": "python2.7",
|
||||||
@ -408,11 +402,14 @@ def test_list_create_list_get_delete_list():
|
|||||||
},
|
},
|
||||||
'ResponseMetadata': {'HTTPStatusCode': 200},
|
'ResponseMetadata': {'HTTPStatusCode': 200},
|
||||||
}
|
}
|
||||||
conn.list_functions()['Functions'].should.equal([expected_function_result['Configuration']])
|
func = conn.list_functions()['Functions'][0]
|
||||||
|
func.pop('LastModified')
|
||||||
|
func.should.equal(expected_function_result['Configuration'])
|
||||||
|
|
||||||
func = conn.get_function(FunctionName='testFunction')
|
func = conn.get_function(FunctionName='testFunction')
|
||||||
func['ResponseMetadata'].pop('HTTPHeaders', None) # this is hard to match against, so remove it
|
func['ResponseMetadata'].pop('HTTPHeaders', None) # this is hard to match against, so remove it
|
||||||
func['ResponseMetadata'].pop('RetryAttempts', None) # Botocore inserts retry attempts not seen in Python27
|
func['ResponseMetadata'].pop('RetryAttempts', None) # Botocore inserts retry attempts not seen in Python27
|
||||||
|
func['Configuration'].pop('LastModified')
|
||||||
|
|
||||||
func.should.equal(expected_function_result)
|
func.should.equal(expected_function_result)
|
||||||
conn.delete_function(FunctionName='testFunction')
|
conn.delete_function(FunctionName='testFunction')
|
||||||
|
@ -5,7 +5,7 @@ import boto
|
|||||||
import boto.s3
|
import boto.s3
|
||||||
import boto.s3.key
|
import boto.s3.key
|
||||||
from botocore.exceptions import ClientError
|
from botocore.exceptions import ClientError
|
||||||
from moto import mock_cloudformation, mock_s3_deprecated
|
from moto import mock_cloudformation, mock_s3
|
||||||
|
|
||||||
import json
|
import json
|
||||||
import sure # noqa
|
import sure # noqa
|
||||||
@ -118,14 +118,20 @@ def test_create_stack_with_role_arn():
|
|||||||
|
|
||||||
|
|
||||||
@mock_cloudformation
|
@mock_cloudformation
|
||||||
@mock_s3_deprecated
|
@mock_s3
|
||||||
def test_create_stack_from_s3_url():
|
def test_create_stack_from_s3_url():
|
||||||
s3_conn = boto.s3.connect_to_region('us-west-1')
|
s3 = boto3.client('s3')
|
||||||
bucket = s3_conn.create_bucket("foobar")
|
s3_conn = boto3.resource('s3')
|
||||||
key = boto.s3.key.Key(bucket)
|
bucket = s3_conn.create_bucket(Bucket="foobar")
|
||||||
key.key = "template-key"
|
|
||||||
key.set_contents_from_string(dummy_template_json)
|
key = s3_conn.Object('foobar', 'template-key').put(Body=dummy_template_json)
|
||||||
key_url = key.generate_url(expires_in=0, query_auth=False)
|
key_url = s3.generate_presigned_url(
|
||||||
|
ClientMethod='get_object',
|
||||||
|
Params={
|
||||||
|
'Bucket': 'foobar',
|
||||||
|
'Key': 'template-key'
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
cf_conn = boto3.client('cloudformation', region_name='us-west-1')
|
cf_conn = boto3.client('cloudformation', region_name='us-west-1')
|
||||||
cf_conn.create_stack(
|
cf_conn.create_stack(
|
||||||
|
@ -701,19 +701,20 @@ def test_vpc_single_instance_in_subnet():
|
|||||||
eip_resource = [resource for resource in resources if resource.resource_type == 'AWS::EC2::EIP'][0]
|
eip_resource = [resource for resource in resources if resource.resource_type == 'AWS::EC2::EIP'][0]
|
||||||
eip_resource.physical_resource_id.should.equal(eip.allocation_id)
|
eip_resource.physical_resource_id.should.equal(eip.allocation_id)
|
||||||
|
|
||||||
@mock_cloudformation_deprecated()
|
@mock_cloudformation()
|
||||||
@mock_ec2_deprecated()
|
@mock_ec2()
|
||||||
@mock_rds2()
|
@mock_rds2()
|
||||||
def test_rds_db_parameter_groups():
|
def test_rds_db_parameter_groups():
|
||||||
ec2_conn = boto.ec2.connect_to_region("us-west-1")
|
ec2_conn = boto3.client("ec2", region_name="us-west-1")
|
||||||
ec2_conn.create_security_group('application', 'Our Application Group')
|
ec2_conn.create_security_group(GroupName='application', Description='Our Application Group')
|
||||||
|
|
||||||
template_json = json.dumps(rds_mysql_with_db_parameter_group.template)
|
template_json = json.dumps(rds_mysql_with_db_parameter_group.template)
|
||||||
conn = boto.cloudformation.connect_to_region("us-west-1")
|
cf_conn = boto3.client('cloudformation', 'us-west-1')
|
||||||
conn.create_stack(
|
cf_conn.create_stack(
|
||||||
"test_stack",
|
StackName="test_stack",
|
||||||
template_body=template_json,
|
TemplateBody=template_json,
|
||||||
parameters=[
|
Parameters=[{'ParameterKey': key, 'ParameterValue': value} for
|
||||||
|
key, value in [
|
||||||
("DBInstanceIdentifier", "master_db"),
|
("DBInstanceIdentifier", "master_db"),
|
||||||
("DBName", "my_db"),
|
("DBName", "my_db"),
|
||||||
("DBUser", "my_user"),
|
("DBUser", "my_user"),
|
||||||
@ -722,6 +723,7 @@ def test_rds_db_parameter_groups():
|
|||||||
("DBInstanceClass", "db.m1.medium"),
|
("DBInstanceClass", "db.m1.medium"),
|
||||||
("EC2SecurityGroup", "application"),
|
("EC2SecurityGroup", "application"),
|
||||||
("MultiAZ", "true"),
|
("MultiAZ", "true"),
|
||||||
|
]
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -1802,7 +1804,7 @@ def lambda_handler(event, context):
|
|||||||
return _process_lamda(pfunc)
|
return _process_lamda(pfunc)
|
||||||
|
|
||||||
|
|
||||||
@mock_cloudformation_deprecated
|
@mock_cloudformation
|
||||||
@mock_lambda
|
@mock_lambda
|
||||||
def test_lambda_function():
|
def test_lambda_function():
|
||||||
# switch this to python as backend lambda only supports python execution.
|
# switch this to python as backend lambda only supports python execution.
|
||||||
@ -1826,10 +1828,10 @@ def test_lambda_function():
|
|||||||
}
|
}
|
||||||
|
|
||||||
template_json = json.dumps(template)
|
template_json = json.dumps(template)
|
||||||
cf_conn = boto.cloudformation.connect_to_region("us-east-1")
|
cf_conn = boto3.client('cloudformation', 'us-east-1')
|
||||||
cf_conn.create_stack(
|
cf_conn.create_stack(
|
||||||
"test_stack",
|
StackName="test_stack",
|
||||||
template_body=template_json,
|
TemplateBody=template_json,
|
||||||
)
|
)
|
||||||
|
|
||||||
conn = boto3.client('lambda', 'us-east-1')
|
conn = boto3.client('lambda', 'us-east-1')
|
||||||
|
@ -3,18 +3,23 @@ import sure # noqa
|
|||||||
from nose.tools import assert_raises
|
from nose.tools import assert_raises
|
||||||
import requests
|
import requests
|
||||||
|
|
||||||
from moto import mock_ec2
|
from moto import mock_ec2, settings
|
||||||
|
|
||||||
|
if settings.TEST_SERVER_MODE:
|
||||||
|
BASE_URL = 'http://localhost:8086'
|
||||||
|
else:
|
||||||
|
BASE_URL = 'http://169.254.169.254'
|
||||||
|
|
||||||
|
|
||||||
@mock_ec2
|
@mock_ec2
|
||||||
def test_latest_meta_data():
|
def test_latest_meta_data():
|
||||||
res = requests.get("http://169.254.169.254/latest/meta-data/")
|
res = requests.get("{0}/latest/meta-data/".format(BASE_URL))
|
||||||
res.content.should.equal(b"iam")
|
res.content.should.equal(b"iam")
|
||||||
|
|
||||||
|
|
||||||
@mock_ec2
|
@mock_ec2
|
||||||
def test_meta_data_iam():
|
def test_meta_data_iam():
|
||||||
res = requests.get("http://169.254.169.254/latest/meta-data/iam")
|
res = requests.get("{0}/latest/meta-data/iam".format(BASE_URL))
|
||||||
json_response = res.json()
|
json_response = res.json()
|
||||||
default_role = json_response['security-credentials']['default-role']
|
default_role = json_response['security-credentials']['default-role']
|
||||||
default_role.should.contain('AccessKeyId')
|
default_role.should.contain('AccessKeyId')
|
||||||
@ -25,21 +30,15 @@ def test_meta_data_iam():
|
|||||||
|
|
||||||
@mock_ec2
|
@mock_ec2
|
||||||
def test_meta_data_security_credentials():
|
def test_meta_data_security_credentials():
|
||||||
res = requests.get("http://169.254.169.254/latest/meta-data/iam/security-credentials/")
|
res = requests.get("{0}/latest/meta-data/iam/security-credentials/".format(BASE_URL))
|
||||||
res.content.should.equal(b"default-role")
|
res.content.should.equal(b"default-role")
|
||||||
|
|
||||||
|
|
||||||
@mock_ec2
|
@mock_ec2
|
||||||
def test_meta_data_default_role():
|
def test_meta_data_default_role():
|
||||||
res = requests.get("http://169.254.169.254/latest/meta-data/iam/security-credentials/default-role")
|
res = requests.get("{0}/latest/meta-data/iam/security-credentials/default-role".format(BASE_URL))
|
||||||
json_response = res.json()
|
json_response = res.json()
|
||||||
json_response.should.contain('AccessKeyId')
|
json_response.should.contain('AccessKeyId')
|
||||||
json_response.should.contain('SecretAccessKey')
|
json_response.should.contain('SecretAccessKey')
|
||||||
json_response.should.contain('Token')
|
json_response.should.contain('Token')
|
||||||
json_response.should.contain('Expiration')
|
json_response.should.contain('Expiration')
|
||||||
|
|
||||||
|
|
||||||
@mock_ec2
|
|
||||||
def test_meta_data_unknown_path():
|
|
||||||
with assert_raises(NotImplementedError):
|
|
||||||
requests.get("http://169.254.169.254/latest/meta-data/badpath")
|
|
||||||
|
21
tests/test_core/test_moto_api.py
Normal file
21
tests/test_core/test_moto_api.py
Normal 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
|
@ -42,13 +42,6 @@ def test_describe_missing_table():
|
|||||||
conn.describe_table('messages')
|
conn.describe_table('messages')
|
||||||
|
|
||||||
|
|
||||||
@mock_dynamodb
|
|
||||||
def test_sts_handler():
|
|
||||||
res = requests.post("https://sts.amazonaws.com/", data={"GetSessionToken": ""})
|
|
||||||
res.ok.should.be.ok
|
|
||||||
res.text.should.contain("SecretAccessKey")
|
|
||||||
|
|
||||||
|
|
||||||
@mock_dynamodb_deprecated
|
@mock_dynamodb_deprecated
|
||||||
def test_dynamodb_with_connect_to_region():
|
def test_dynamodb_with_connect_to_region():
|
||||||
# this will work if connected with boto.connect_dynamodb()
|
# this will work if connected with boto.connect_dynamodb()
|
||||||
|
@ -63,11 +63,3 @@ def test_describe_missing_table():
|
|||||||
aws_secret_access_key="sk")
|
aws_secret_access_key="sk")
|
||||||
with assert_raises(JSONResponseError):
|
with assert_raises(JSONResponseError):
|
||||||
conn.describe_table('messages')
|
conn.describe_table('messages')
|
||||||
|
|
||||||
|
|
||||||
@requires_boto_gte("2.9")
|
|
||||||
@mock_dynamodb2
|
|
||||||
def test_sts_handler():
|
|
||||||
res = requests.post("https://sts.amazonaws.com/", data={"GetSessionToken": ""})
|
|
||||||
res.ok.should.be.ok
|
|
||||||
res.text.should.contain("SecretAccessKey")
|
|
||||||
|
@ -5,7 +5,7 @@ from nose.tools import assert_raises
|
|||||||
|
|
||||||
import boto
|
import boto
|
||||||
import boto.ec2
|
import boto.ec2
|
||||||
from boto.exception import EC2ResponseError, JSONResponseError
|
from boto.exception import EC2ResponseError, EC2ResponseError
|
||||||
|
|
||||||
import sure # noqa
|
import sure # noqa
|
||||||
|
|
||||||
@ -19,9 +19,9 @@ def test_ami_create_and_delete():
|
|||||||
reservation = conn.run_instances('ami-1234abcd')
|
reservation = conn.run_instances('ami-1234abcd')
|
||||||
instance = reservation.instances[0]
|
instance = reservation.instances[0]
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
image_id = conn.create_image(instance.id, "test-ami", "this is a test ami", dry_run=True)
|
image_id = conn.create_image(instance.id, "test-ami", "this is a test ami", dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateImage operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateImage operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -52,9 +52,9 @@ def test_ami_create_and_delete():
|
|||||||
snapshot.volume_id.should.equal(volume.id)
|
snapshot.volume_id.should.equal(volume.id)
|
||||||
|
|
||||||
# Deregister
|
# Deregister
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
success = conn.deregister_image(image_id, dry_run=True)
|
success = conn.deregister_image(image_id, dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the DeregisterImage operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the DeregisterImage operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -80,9 +80,9 @@ def test_ami_copy():
|
|||||||
source_image = conn.get_all_images(image_ids=[source_image_id])[0]
|
source_image = conn.get_all_images(image_ids=[source_image_id])[0]
|
||||||
|
|
||||||
# Boto returns a 'CopyImage' object with an image_id attribute here. Use the image_id to fetch the full info.
|
# Boto returns a 'CopyImage' object with an image_id attribute here. Use the image_id to fetch the full info.
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
copy_image_ref = conn.copy_image(source_image.region.name, source_image.id, "test-copy-ami", "this is a test copy ami", dry_run=True)
|
copy_image_ref = conn.copy_image(source_image.region.name, source_image.id, "test-copy-ami", "this is a test copy ami", dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CopyImage operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CopyImage operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -127,9 +127,9 @@ def test_ami_tagging():
|
|||||||
conn.create_image(instance.id, "test-ami", "this is a test ami")
|
conn.create_image(instance.id, "test-ami", "this is a test ami")
|
||||||
image = conn.get_all_images()[0]
|
image = conn.get_all_images()[0]
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
image.add_tag("a key", "some value", dry_run=True)
|
image.add_tag("a key", "some value", dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -289,9 +289,9 @@ def test_ami_attribute_group_permissions():
|
|||||||
'groups': 'all'}
|
'groups': 'all'}
|
||||||
|
|
||||||
# Add 'all' group and confirm
|
# Add 'all' group and confirm
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
conn.modify_image_attribute(**dict(ADD_GROUP_ARGS, **{'dry_run': True}))
|
conn.modify_image_attribute(**dict(ADD_GROUP_ARGS, **{'dry_run': True}))
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ModifyImageAttribute operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ModifyImageAttribute operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
|
@ -1,11 +1 @@
|
|||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import requests
|
|
||||||
from moto import mock_ec2
|
|
||||||
|
|
||||||
|
|
||||||
@mock_ec2
|
|
||||||
def test_not_implemented_method():
|
|
||||||
requests.post.when.called_with(
|
|
||||||
"https://ec2.us-east-1.amazonaws.com/",
|
|
||||||
data={'Action': ['foobar']}
|
|
||||||
).should.throw(NotImplementedError)
|
|
||||||
|
@ -5,7 +5,7 @@ from nose.tools import assert_raises
|
|||||||
|
|
||||||
from moto.ec2 import ec2_backends
|
from moto.ec2 import ec2_backends
|
||||||
import boto
|
import boto
|
||||||
from boto.exception import EC2ResponseError, JSONResponseError
|
from boto.exception import EC2ResponseError
|
||||||
import sure # noqa
|
import sure # noqa
|
||||||
|
|
||||||
from moto import mock_ec2_deprecated
|
from moto import mock_ec2_deprecated
|
||||||
@ -24,9 +24,9 @@ def test_create_and_delete_volume():
|
|||||||
|
|
||||||
volume = all_volumes[0]
|
volume = all_volumes[0]
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
volume.delete(dry_run=True)
|
volume.delete(dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the DeleteVolume operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the DeleteVolume operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -46,9 +46,9 @@ def test_create_and_delete_volume():
|
|||||||
@mock_ec2_deprecated
|
@mock_ec2_deprecated
|
||||||
def test_create_encrypted_volume_dryrun():
|
def test_create_encrypted_volume_dryrun():
|
||||||
conn = boto.connect_ec2('the_key', 'the_secret')
|
conn = boto.connect_ec2('the_key', 'the_secret')
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
conn.create_volume(80, "us-east-1a", encrypted=True, dry_run=True)
|
conn.create_volume(80, "us-east-1a", encrypted=True, dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateVolume operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateVolume operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -58,9 +58,9 @@ def test_create_encrypted_volume():
|
|||||||
conn = boto.connect_ec2('the_key', 'the_secret')
|
conn = boto.connect_ec2('the_key', 'the_secret')
|
||||||
conn.create_volume(80, "us-east-1a", encrypted=True)
|
conn.create_volume(80, "us-east-1a", encrypted=True)
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
conn.create_volume(80, "us-east-1a", encrypted=True, dry_run=True)
|
conn.create_volume(80, "us-east-1a", encrypted=True, dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateVolume operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateVolume operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -165,9 +165,9 @@ def test_volume_attach_and_detach():
|
|||||||
volume.update()
|
volume.update()
|
||||||
volume.volume_state().should.equal('available')
|
volume.volume_state().should.equal('available')
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
volume.attach(instance.id, "/dev/sdh", dry_run=True)
|
volume.attach(instance.id, "/dev/sdh", dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the AttachVolume operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the AttachVolume operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -179,9 +179,9 @@ def test_volume_attach_and_detach():
|
|||||||
|
|
||||||
volume.attach_data.instance_id.should.equal(instance.id)
|
volume.attach_data.instance_id.should.equal(instance.id)
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
volume.detach(dry_run=True)
|
volume.detach(dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the DetachVolume operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the DetachVolume operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -214,9 +214,9 @@ def test_create_snapshot():
|
|||||||
conn = boto.connect_ec2('the_key', 'the_secret')
|
conn = boto.connect_ec2('the_key', 'the_secret')
|
||||||
volume = conn.create_volume(80, "us-east-1a")
|
volume = conn.create_volume(80, "us-east-1a")
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
snapshot = volume.create_snapshot('a dryrun snapshot', dry_run=True)
|
snapshot = volume.create_snapshot('a dryrun snapshot', dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateSnapshot operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateSnapshot operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -347,9 +347,9 @@ def test_snapshot_attribute():
|
|||||||
|
|
||||||
# Add 'all' group and confirm
|
# Add 'all' group and confirm
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
conn.modify_snapshot_attribute(**dict(ADD_GROUP_ARGS, **{'dry_run': True}))
|
conn.modify_snapshot_attribute(**dict(ADD_GROUP_ARGS, **{'dry_run': True}))
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ModifySnapshotAttribute operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ModifySnapshotAttribute operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -363,9 +363,9 @@ def test_snapshot_attribute():
|
|||||||
conn.modify_snapshot_attribute.when.called_with(**ADD_GROUP_ARGS).should_not.throw(EC2ResponseError)
|
conn.modify_snapshot_attribute.when.called_with(**ADD_GROUP_ARGS).should_not.throw(EC2ResponseError)
|
||||||
|
|
||||||
# Remove 'all' group and confirm
|
# Remove 'all' group and confirm
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
conn.modify_snapshot_attribute(**dict(REMOVE_GROUP_ARGS, **{'dry_run': True}))
|
conn.modify_snapshot_attribute(**dict(REMOVE_GROUP_ARGS, **{'dry_run': True}))
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ModifySnapshotAttribute operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ModifySnapshotAttribute operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -424,9 +424,9 @@ def test_create_volume_from_snapshot():
|
|||||||
volume = conn.create_volume(80, "us-east-1a")
|
volume = conn.create_volume(80, "us-east-1a")
|
||||||
snapshot = volume.create_snapshot('a test snapshot')
|
snapshot = volume.create_snapshot('a test snapshot')
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
snapshot = volume.create_snapshot('a test snapshot', dry_run=True)
|
snapshot = volume.create_snapshot('a test snapshot', dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateSnapshot operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateSnapshot operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -468,9 +468,9 @@ def test_modify_attribute_blockDeviceMapping():
|
|||||||
|
|
||||||
instance = reservation.instances[0]
|
instance = reservation.instances[0]
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
instance.modify_attribute('blockDeviceMapping', {'/dev/sda1': True}, dry_run=True)
|
instance.modify_attribute('blockDeviceMapping', {'/dev/sda1': True}, dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ModifyInstanceAttribute operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ModifyInstanceAttribute operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -487,9 +487,9 @@ def test_volume_tag_escaping():
|
|||||||
vol = conn.create_volume(10, 'us-east-1a')
|
vol = conn.create_volume(10, 'us-east-1a')
|
||||||
snapshot = conn.create_snapshot(vol.id, 'Desc')
|
snapshot = conn.create_snapshot(vol.id, 'Desc')
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
snapshot.add_tags({'key': '</closed>'}, dry_run=True)
|
snapshot.add_tags({'key': '</closed>'}, dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set')
|
||||||
dict(conn.get_all_snapshots()[0].tags).should_not.be.equal({'key': '</closed>'})
|
dict(conn.get_all_snapshots()[0].tags).should_not.be.equal({'key': '</closed>'})
|
||||||
|
@ -5,7 +5,7 @@ from nose.tools import assert_raises
|
|||||||
|
|
||||||
import boto
|
import boto
|
||||||
import boto3
|
import boto3
|
||||||
from boto.exception import EC2ResponseError, JSONResponseError
|
from boto.exception import EC2ResponseError
|
||||||
import six
|
import six
|
||||||
|
|
||||||
import sure # noqa
|
import sure # noqa
|
||||||
@ -20,9 +20,9 @@ def test_eip_allocate_classic():
|
|||||||
"""Allocate/release Classic EIP"""
|
"""Allocate/release Classic EIP"""
|
||||||
conn = boto.connect_ec2('the_key', 'the_secret')
|
conn = boto.connect_ec2('the_key', 'the_secret')
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
standard = conn.allocate_address(dry_run=True)
|
standard = conn.allocate_address(dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the AllocateAddress operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the AllocateAddress operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -32,9 +32,9 @@ def test_eip_allocate_classic():
|
|||||||
standard.instance_id.should.be.none
|
standard.instance_id.should.be.none
|
||||||
standard.domain.should.be.equal("standard")
|
standard.domain.should.be.equal("standard")
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
standard.release(dry_run=True)
|
standard.release(dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ReleaseAddress operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ReleaseAddress operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -47,9 +47,9 @@ def test_eip_allocate_vpc():
|
|||||||
"""Allocate/release VPC EIP"""
|
"""Allocate/release VPC EIP"""
|
||||||
conn = boto.connect_ec2('the_key', 'the_secret')
|
conn = boto.connect_ec2('the_key', 'the_secret')
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
vpc = conn.allocate_address(domain="vpc", dry_run=True)
|
vpc = conn.allocate_address(domain="vpc", dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the AllocateAddress operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the AllocateAddress operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -89,9 +89,9 @@ def test_eip_associate_classic():
|
|||||||
cm.exception.status.should.equal(400)
|
cm.exception.status.should.equal(400)
|
||||||
cm.exception.request_id.should_not.be.none
|
cm.exception.request_id.should_not.be.none
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
conn.associate_address(instance_id=instance.id, public_ip=eip.public_ip, dry_run=True)
|
conn.associate_address(instance_id=instance.id, public_ip=eip.public_ip, dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the AssociateAddress operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the AssociateAddress operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -99,9 +99,9 @@ def test_eip_associate_classic():
|
|||||||
eip = conn.get_all_addresses(addresses=[eip.public_ip])[0] # no .update() on address ):
|
eip = conn.get_all_addresses(addresses=[eip.public_ip])[0] # no .update() on address ):
|
||||||
eip.instance_id.should.be.equal(instance.id)
|
eip.instance_id.should.be.equal(instance.id)
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
conn.disassociate_address(public_ip=eip.public_ip, dry_run=True)
|
conn.disassociate_address(public_ip=eip.public_ip, dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the DisAssociateAddress operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the DisAssociateAddress operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -139,9 +139,9 @@ def test_eip_associate_vpc():
|
|||||||
eip.instance_id.should.be.equal(u'')
|
eip.instance_id.should.be.equal(u'')
|
||||||
eip.association_id.should.be.none
|
eip.association_id.should.be.none
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
eip.release(dry_run=True)
|
eip.release(dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ReleaseAddress operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ReleaseAddress operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -153,9 +153,8 @@ def test_eip_associate_vpc():
|
|||||||
@mock_ec2
|
@mock_ec2
|
||||||
def test_eip_boto3_vpc_association():
|
def test_eip_boto3_vpc_association():
|
||||||
"""Associate EIP to VPC instance in a new subnet with boto3"""
|
"""Associate EIP to VPC instance in a new subnet with boto3"""
|
||||||
session = boto3.session.Session(region_name='us-west-1')
|
service = boto3.resource('ec2', region_name='us-west-1')
|
||||||
service = session.resource('ec2')
|
client = boto3.client('ec2', region_name='us-west-1')
|
||||||
client = session.client('ec2')
|
|
||||||
vpc_res = client.create_vpc(CidrBlock='10.0.0.0/24')
|
vpc_res = client.create_vpc(CidrBlock='10.0.0.0/24')
|
||||||
subnet_res = client.create_subnet(
|
subnet_res = client.create_subnet(
|
||||||
VpcId=vpc_res['Vpc']['VpcId'], CidrBlock='10.0.0.0/24')
|
VpcId=vpc_res['Vpc']['VpcId'], CidrBlock='10.0.0.0/24')
|
||||||
|
@ -4,10 +4,11 @@ import tests.backport_assert_raises
|
|||||||
from nose.tools import assert_raises
|
from nose.tools import assert_raises
|
||||||
|
|
||||||
import boto3
|
import boto3
|
||||||
|
from botocore.exceptions import ClientError
|
||||||
import boto
|
import boto
|
||||||
import boto.cloudformation
|
import boto.cloudformation
|
||||||
import boto.ec2
|
import boto.ec2
|
||||||
from boto.exception import EC2ResponseError, JSONResponseError
|
from boto.exception import EC2ResponseError
|
||||||
import sure # noqa
|
import sure # noqa
|
||||||
|
|
||||||
from moto import mock_ec2, mock_cloudformation_deprecated, mock_ec2_deprecated
|
from moto import mock_ec2, mock_cloudformation_deprecated, mock_ec2_deprecated
|
||||||
@ -22,9 +23,9 @@ def test_elastic_network_interfaces():
|
|||||||
vpc = conn.create_vpc("10.0.0.0/16")
|
vpc = conn.create_vpc("10.0.0.0/16")
|
||||||
subnet = conn.create_subnet(vpc.id, "10.0.0.0/18")
|
subnet = conn.create_subnet(vpc.id, "10.0.0.0/18")
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
eni = conn.create_network_interface(subnet.id, dry_run=True)
|
eni = conn.create_network_interface(subnet.id, dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateNetworkInterface operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateNetworkInterface operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -36,9 +37,9 @@ def test_elastic_network_interfaces():
|
|||||||
eni.groups.should.have.length_of(0)
|
eni.groups.should.have.length_of(0)
|
||||||
eni.private_ip_addresses.should.have.length_of(0)
|
eni.private_ip_addresses.should.have.length_of(0)
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
conn.delete_network_interface(eni.id, dry_run=True)
|
conn.delete_network_interface(eni.id, dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the DeleteNetworkInterface operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the DeleteNetworkInterface operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -49,7 +50,7 @@ def test_elastic_network_interfaces():
|
|||||||
|
|
||||||
with assert_raises(EC2ResponseError) as cm:
|
with assert_raises(EC2ResponseError) as cm:
|
||||||
conn.delete_network_interface(eni.id)
|
conn.delete_network_interface(eni.id)
|
||||||
cm.exception.code.should.equal('InvalidNetworkInterfaceID.NotFound')
|
cm.exception.error_code.should.equal('InvalidNetworkInterfaceID.NotFound')
|
||||||
cm.exception.status.should.equal(400)
|
cm.exception.status.should.equal(400)
|
||||||
cm.exception.request_id.should_not.be.none
|
cm.exception.request_id.should_not.be.none
|
||||||
|
|
||||||
@ -60,7 +61,7 @@ def test_elastic_network_interfaces_subnet_validation():
|
|||||||
|
|
||||||
with assert_raises(EC2ResponseError) as cm:
|
with assert_raises(EC2ResponseError) as cm:
|
||||||
conn.create_network_interface("subnet-abcd1234")
|
conn.create_network_interface("subnet-abcd1234")
|
||||||
cm.exception.code.should.equal('InvalidSubnetID.NotFound')
|
cm.exception.error_code.should.equal('InvalidSubnetID.NotFound')
|
||||||
cm.exception.status.should.equal(400)
|
cm.exception.status.should.equal(400)
|
||||||
cm.exception.request_id.should_not.be.none
|
cm.exception.request_id.should_not.be.none
|
||||||
|
|
||||||
@ -117,9 +118,9 @@ def test_elastic_network_interfaces_modify_attribute():
|
|||||||
eni.groups.should.have.length_of(1)
|
eni.groups.should.have.length_of(1)
|
||||||
eni.groups[0].id.should.equal(security_group1.id)
|
eni.groups[0].id.should.equal(security_group1.id)
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
conn.modify_network_interface_attribute(eni.id, 'groupset', [security_group2.id], dry_run=True)
|
conn.modify_network_interface_attribute(eni.id, 'groupset', [security_group2.id], dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ModifyNetworkInterface operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ModifyNetworkInterface operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -183,11 +184,11 @@ def test_elastic_network_interfaces_get_by_tag_name():
|
|||||||
|
|
||||||
eni1 = ec2.create_network_interface(SubnetId=subnet.id, PrivateIpAddress='10.0.10.5')
|
eni1 = ec2.create_network_interface(SubnetId=subnet.id, PrivateIpAddress='10.0.10.5')
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(ClientError) as ex:
|
||||||
eni1.create_tags(Tags=[{'Key': 'Name', 'Value': 'eni1'}], DryRun=True)
|
eni1.create_tags(Tags=[{'Key': 'Name', 'Value': 'eni1'}], DryRun=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.response['Error']['Code'].should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.response['ResponseMetadata']['HTTPStatusCode'].should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.response['Error']['Message'].should.equal('An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
eni1.create_tags(Tags=[{'Key': 'Name', 'Value': 'eni1'}])
|
eni1.create_tags(Tags=[{'Key': 'Name', 'Value': 'eni1'}])
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ import datetime
|
|||||||
|
|
||||||
import boto
|
import boto
|
||||||
from boto.ec2.instance import Reservation, InstanceAttribute
|
from boto.ec2.instance import Reservation, InstanceAttribute
|
||||||
from boto.exception import EC2ResponseError, JSONResponseError
|
from boto.exception import EC2ResponseError, EC2ResponseError
|
||||||
from freezegun import freeze_time
|
from freezegun import freeze_time
|
||||||
import sure # noqa
|
import sure # noqa
|
||||||
|
|
||||||
@ -41,9 +41,9 @@ def test_add_servers():
|
|||||||
def test_instance_launch_and_terminate():
|
def test_instance_launch_and_terminate():
|
||||||
conn = boto.connect_ec2('the_key', 'the_secret')
|
conn = boto.connect_ec2('the_key', 'the_secret')
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
reservation = conn.run_instances('ami-1234abcd', dry_run=True)
|
reservation = conn.run_instances('ami-1234abcd', dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the RunInstance operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the RunInstance operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -74,9 +74,9 @@ def test_instance_launch_and_terminate():
|
|||||||
volume.attach_data.instance_id.should.equal(instance.id)
|
volume.attach_data.instance_id.should.equal(instance.id)
|
||||||
volume.status.should.equal('in-use')
|
volume.status.should.equal('in-use')
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
conn.terminate_instances([instance.id], dry_run=True)
|
conn.terminate_instances([instance.id], dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the TerminateInstance operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the TerminateInstance operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -427,9 +427,9 @@ def test_instance_start_and_stop():
|
|||||||
|
|
||||||
instance_ids = [instance.id for instance in instances]
|
instance_ids = [instance.id for instance in instances]
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
stopped_instances = conn.stop_instances(instance_ids, dry_run=True)
|
stopped_instances = conn.stop_instances(instance_ids, dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the StopInstance operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the StopInstance operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -438,9 +438,9 @@ def test_instance_start_and_stop():
|
|||||||
for instance in stopped_instances:
|
for instance in stopped_instances:
|
||||||
instance.state.should.equal('stopping')
|
instance.state.should.equal('stopping')
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
started_instances = conn.start_instances([instances[0].id], dry_run=True)
|
started_instances = conn.start_instances([instances[0].id], dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the StartInstance operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the StartInstance operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -454,9 +454,9 @@ def test_instance_reboot():
|
|||||||
reservation = conn.run_instances('ami-1234abcd')
|
reservation = conn.run_instances('ami-1234abcd')
|
||||||
instance = reservation.instances[0]
|
instance = reservation.instances[0]
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
instance.reboot(dry_run=True)
|
instance.reboot(dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the RebootInstance operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the RebootInstance operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -470,9 +470,9 @@ def test_instance_attribute_instance_type():
|
|||||||
reservation = conn.run_instances('ami-1234abcd')
|
reservation = conn.run_instances('ami-1234abcd')
|
||||||
instance = reservation.instances[0]
|
instance = reservation.instances[0]
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
instance.modify_attribute("instanceType", "m1.small", dry_run=True)
|
instance.modify_attribute("instanceType", "m1.small", dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ModifyInstanceType operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ModifyInstanceType operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -491,9 +491,9 @@ def test_modify_instance_attribute_security_groups():
|
|||||||
sg_id = 'sg-1234abcd'
|
sg_id = 'sg-1234abcd'
|
||||||
sg_id2 = 'sg-abcd4321'
|
sg_id2 = 'sg-abcd4321'
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
instance.modify_attribute("groupSet", [sg_id, sg_id2], dry_run=True)
|
instance.modify_attribute("groupSet", [sg_id, sg_id2], dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ModifyInstanceSecurityGroups operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ModifyInstanceSecurityGroups operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -512,9 +512,9 @@ def test_instance_attribute_user_data():
|
|||||||
reservation = conn.run_instances('ami-1234abcd')
|
reservation = conn.run_instances('ami-1234abcd')
|
||||||
instance = reservation.instances[0]
|
instance = reservation.instances[0]
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
instance.modify_attribute("userData", "this is my user data", dry_run=True)
|
instance.modify_attribute("userData", "this is my user data", dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ModifyUserData operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ModifyUserData operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -540,9 +540,9 @@ def test_instance_attribute_source_dest_check():
|
|||||||
|
|
||||||
# Set to false (note: Boto converts bool to string, eg 'false')
|
# Set to false (note: Boto converts bool to string, eg 'false')
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
instance.modify_attribute("sourceDestCheck", False, dry_run=True)
|
instance.modify_attribute("sourceDestCheck", False, dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ModifySourceDestCheck operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ModifySourceDestCheck operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -584,9 +584,9 @@ def test_user_data_with_run_instance():
|
|||||||
def test_run_instance_with_security_group_name():
|
def test_run_instance_with_security_group_name():
|
||||||
conn = boto.connect_ec2('the_key', 'the_secret')
|
conn = boto.connect_ec2('the_key', 'the_secret')
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
group = conn.create_security_group('group1', "some description", dry_run=True)
|
group = conn.create_security_group('group1', "some description", dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateSecurityGroup operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateSecurityGroup operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -745,9 +745,9 @@ def test_instance_with_nic_attach_detach():
|
|||||||
set([group.id for group in eni.groups]).should.equal(set([security_group2.id]))
|
set([group.id for group in eni.groups]).should.equal(set([security_group2.id]))
|
||||||
|
|
||||||
# Attach
|
# Attach
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
conn.attach_network_interface(eni.id, instance.id, device_index=1, dry_run=True)
|
conn.attach_network_interface(eni.id, instance.id, device_index=1, dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the AttachNetworkInterface operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the AttachNetworkInterface operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -766,9 +766,9 @@ def test_instance_with_nic_attach_detach():
|
|||||||
set([group.id for group in eni.groups]).should.equal(set([security_group1.id,security_group2.id]))
|
set([group.id for group in eni.groups]).should.equal(set([security_group1.id,security_group2.id]))
|
||||||
|
|
||||||
# Detach
|
# Detach
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
conn.detach_network_interface(instance_eni.attachment.id, dry_run=True)
|
conn.detach_network_interface(instance_eni.attachment.id, dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the DetachNetworkInterface operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the DetachNetworkInterface operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -886,9 +886,9 @@ def test_get_instance_by_security_group():
|
|||||||
|
|
||||||
security_group = conn.create_security_group('test', 'test')
|
security_group = conn.create_security_group('test', 'test')
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
conn.modify_instance_attribute(instance.id, "groupSet", [security_group.id], dry_run=True)
|
conn.modify_instance_attribute(instance.id, "groupSet", [security_group.id], dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ModifyInstanceSecurityGroups operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ModifyInstanceSecurityGroups operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
|
@ -6,7 +6,7 @@ from nose.tools import assert_raises
|
|||||||
import re
|
import re
|
||||||
|
|
||||||
import boto
|
import boto
|
||||||
from boto.exception import EC2ResponseError, JSONResponseError
|
from boto.exception import EC2ResponseError
|
||||||
|
|
||||||
import sure # noqa
|
import sure # noqa
|
||||||
|
|
||||||
@ -24,9 +24,9 @@ def test_igw_create():
|
|||||||
|
|
||||||
conn.get_all_internet_gateways().should.have.length_of(0)
|
conn.get_all_internet_gateways().should.have.length_of(0)
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
igw = conn.create_internet_gateway(dry_run=True)
|
igw = conn.create_internet_gateway(dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateInternetGateway operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateInternetGateway operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -44,9 +44,9 @@ def test_igw_attach():
|
|||||||
igw = conn.create_internet_gateway()
|
igw = conn.create_internet_gateway()
|
||||||
vpc = conn.create_vpc(VPC_CIDR)
|
vpc = conn.create_vpc(VPC_CIDR)
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
conn.attach_internet_gateway(igw.id, vpc.id, dry_run=True)
|
conn.attach_internet_gateway(igw.id, vpc.id, dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the AttachInternetGateway operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the AttachInternetGateway operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -90,9 +90,9 @@ def test_igw_detach():
|
|||||||
vpc = conn.create_vpc(VPC_CIDR)
|
vpc = conn.create_vpc(VPC_CIDR)
|
||||||
conn.attach_internet_gateway(igw.id, vpc.id)
|
conn.attach_internet_gateway(igw.id, vpc.id)
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
conn.detach_internet_gateway(igw.id, vpc.id, dry_run=True)
|
conn.detach_internet_gateway(igw.id, vpc.id, dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the DetachInternetGateway operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the DetachInternetGateway operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -151,9 +151,9 @@ def test_igw_delete():
|
|||||||
igw = conn.create_internet_gateway()
|
igw = conn.create_internet_gateway()
|
||||||
conn.get_all_internet_gateways().should.have.length_of(1)
|
conn.get_all_internet_gateways().should.have.length_of(1)
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
conn.delete_internet_gateway(igw.id, dry_run=True)
|
conn.delete_internet_gateway(igw.id, dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the DeleteInternetGateway operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the DeleteInternetGateway operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
|
@ -7,7 +7,7 @@ import boto
|
|||||||
import six
|
import six
|
||||||
import sure # noqa
|
import sure # noqa
|
||||||
|
|
||||||
from boto.exception import EC2ResponseError, JSONResponseError
|
from boto.exception import EC2ResponseError
|
||||||
from moto import mock_ec2_deprecated
|
from moto import mock_ec2_deprecated
|
||||||
|
|
||||||
|
|
||||||
@ -32,9 +32,9 @@ def test_key_pairs_invalid_id():
|
|||||||
def test_key_pairs_create():
|
def test_key_pairs_create():
|
||||||
conn = boto.connect_ec2('the_key', 'the_secret')
|
conn = boto.connect_ec2('the_key', 'the_secret')
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
kp = conn.create_key_pair('foo', dry_run=True)
|
kp = conn.create_key_pair('foo', dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateKeyPair operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateKeyPair operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -87,9 +87,9 @@ def test_key_pairs_delete_exist():
|
|||||||
conn = boto.connect_ec2('the_key', 'the_secret')
|
conn = boto.connect_ec2('the_key', 'the_secret')
|
||||||
conn.create_key_pair('foo')
|
conn.create_key_pair('foo')
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
r = conn.delete_key_pair('foo', dry_run=True)
|
r = conn.delete_key_pair('foo', dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the DeleteKeyPair operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the DeleteKeyPair operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -102,9 +102,9 @@ def test_key_pairs_delete_exist():
|
|||||||
def test_key_pairs_import():
|
def test_key_pairs_import():
|
||||||
conn = boto.connect_ec2('the_key', 'the_secret')
|
conn = boto.connect_ec2('the_key', 'the_secret')
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
kp = conn.import_key_pair('foo', b'content', dry_run=True)
|
kp = conn.import_key_pair('foo', b'content', dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ImportKeyPair operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the ImportKeyPair operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@ from nose.tools import assert_raises
|
|||||||
import boto3
|
import boto3
|
||||||
import boto
|
import boto
|
||||||
from botocore.exceptions import ClientError
|
from botocore.exceptions import ClientError
|
||||||
from boto.exception import EC2ResponseError, JSONResponseError
|
from boto.exception import EC2ResponseError
|
||||||
import sure # noqa
|
import sure # noqa
|
||||||
|
|
||||||
from moto import mock_ec2, mock_ec2_deprecated
|
from moto import mock_ec2, mock_ec2_deprecated
|
||||||
@ -19,9 +19,9 @@ from moto import mock_ec2, mock_ec2_deprecated
|
|||||||
def test_create_and_describe_security_group():
|
def test_create_and_describe_security_group():
|
||||||
conn = boto.connect_ec2('the_key', 'the_secret')
|
conn = boto.connect_ec2('the_key', 'the_secret')
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
security_group = conn.create_security_group('test security group', 'this is a test security group', dry_run=True)
|
security_group = conn.create_security_group('test security group', 'this is a test security group', dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateSecurityGroup operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateSecurityGroup operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -121,9 +121,9 @@ def test_deleting_security_groups():
|
|||||||
cm.exception.request_id.should_not.be.none
|
cm.exception.request_id.should_not.be.none
|
||||||
|
|
||||||
# Delete by name
|
# Delete by name
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
conn.delete_security_group('test2', dry_run=True)
|
conn.delete_security_group('test2', dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the DeleteSecurityGroup operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the DeleteSecurityGroup operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -150,9 +150,9 @@ def test_authorize_ip_range_and_revoke():
|
|||||||
conn = boto.connect_ec2('the_key', 'the_secret')
|
conn = boto.connect_ec2('the_key', 'the_secret')
|
||||||
security_group = conn.create_security_group('test', 'test')
|
security_group = conn.create_security_group('test', 'test')
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
success = security_group.authorize(ip_protocol="tcp", from_port="22", to_port="2222", cidr_ip="123.123.123.123/32", dry_run=True)
|
success = security_group.authorize(ip_protocol="tcp", from_port="22", to_port="2222", cidr_ip="123.123.123.123/32", dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the GrantSecurityGroupIngress operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the GrantSecurityGroupIngress operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -171,9 +171,9 @@ def test_authorize_ip_range_and_revoke():
|
|||||||
cm.exception.request_id.should_not.be.none
|
cm.exception.request_id.should_not.be.none
|
||||||
|
|
||||||
# Actually revoke
|
# Actually revoke
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
security_group.revoke(ip_protocol="tcp", from_port="22", to_port="2222", cidr_ip="123.123.123.123/32", dry_run=True)
|
security_group.revoke(ip_protocol="tcp", from_port="22", to_port="2222", cidr_ip="123.123.123.123/32", dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the RevokeSecurityGroupIngress operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the RevokeSecurityGroupIngress operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -185,9 +185,9 @@ def test_authorize_ip_range_and_revoke():
|
|||||||
# Test for egress as well
|
# Test for egress as well
|
||||||
egress_security_group = conn.create_security_group('testegress', 'testegress', vpc_id='vpc-3432589')
|
egress_security_group = conn.create_security_group('testegress', 'testegress', vpc_id='vpc-3432589')
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
success = conn.authorize_security_group_egress(egress_security_group.id, "tcp", from_port="22", to_port="2222", cidr_ip="123.123.123.123/32", dry_run=True)
|
success = conn.authorize_security_group_egress(egress_security_group.id, "tcp", from_port="22", to_port="2222", cidr_ip="123.123.123.123/32", dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the GrantSecurityGroupEgress operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the GrantSecurityGroupEgress operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -203,9 +203,9 @@ def test_authorize_ip_range_and_revoke():
|
|||||||
egress_security_group.revoke.when.called_with(ip_protocol="tcp", from_port="22", to_port="2222", cidr_ip="123.123.123.122/32").should.throw(EC2ResponseError)
|
egress_security_group.revoke.when.called_with(ip_protocol="tcp", from_port="22", to_port="2222", cidr_ip="123.123.123.122/32").should.throw(EC2ResponseError)
|
||||||
|
|
||||||
# Actually revoke
|
# Actually revoke
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
conn.revoke_security_group_egress(egress_security_group.id, "tcp", from_port="22", to_port="2222", cidr_ip="123.123.123.123/32", dry_run=True)
|
conn.revoke_security_group_egress(egress_security_group.id, "tcp", from_port="22", to_port="2222", cidr_ip="123.123.123.123/32", dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the RevokeSecurityGroupEgress operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the RevokeSecurityGroupEgress operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -339,9 +339,9 @@ def test_security_group_tagging():
|
|||||||
|
|
||||||
sg = conn.create_security_group("test-sg", "Test SG", vpc.id)
|
sg = conn.create_security_group("test-sg", "Test SG", vpc.id)
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
sg.add_tag("Test", "Tag", dry_run=True)
|
sg.add_tag("Test", "Tag", dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -540,11 +540,11 @@ def test_security_group_tagging_boto3():
|
|||||||
|
|
||||||
sg = conn.create_security_group(GroupName="test-sg", Description="Test SG")
|
sg = conn.create_security_group(GroupName="test-sg", Description="Test SG")
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(ClientError) as ex:
|
||||||
conn.create_tags(Resources=[sg['GroupId']], Tags=[{'Key': 'Test', 'Value': 'Tag'}], DryRun=True)
|
conn.create_tags(Resources=[sg['GroupId']], Tags=[{'Key': 'Test', 'Value': 'Tag'}], DryRun=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.response['Error']['Code'].should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.response['ResponseMetadata']['HTTPStatusCode'].should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.response['Error']['Message'].should.equal('An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
conn.create_tags(Resources=[sg['GroupId']], Tags=[{'Key': 'Test', 'Value': 'Tag'}])
|
conn.create_tags(Resources=[sg['GroupId']], Tags=[{'Key': 'Test', 'Value': 'Tag'}])
|
||||||
describe = conn.describe_security_groups(Filters=[{'Name': 'tag-value', 'Values': ['Tag']}])
|
describe = conn.describe_security_groups(Filters=[{'Name': 'tag-value', 'Values': ['Tag']}])
|
||||||
|
@ -4,8 +4,10 @@ import datetime
|
|||||||
|
|
||||||
import boto
|
import boto
|
||||||
import boto3
|
import boto3
|
||||||
|
from boto.exception import EC2ResponseError
|
||||||
|
from botocore.exceptions import ClientError
|
||||||
|
import pytz
|
||||||
import sure # noqa
|
import sure # noqa
|
||||||
from boto.exception import JSONResponseError
|
|
||||||
|
|
||||||
from moto import mock_ec2, mock_ec2_deprecated
|
from moto import mock_ec2, mock_ec2_deprecated
|
||||||
from moto.backends import get_model
|
from moto.backends import get_model
|
||||||
@ -13,98 +15,130 @@ from moto.core.utils import iso_8601_datetime_with_milliseconds
|
|||||||
|
|
||||||
|
|
||||||
@mock_ec2
|
@mock_ec2
|
||||||
@mock_ec2_deprecated
|
|
||||||
def test_request_spot_instances():
|
def test_request_spot_instances():
|
||||||
conn = boto3.client('ec2', 'us-east-1')
|
conn = boto3.client('ec2', 'us-east-1')
|
||||||
vpc = conn.create_vpc(CidrBlock="10.0.0.0/8")['Vpc']
|
vpc = conn.create_vpc(CidrBlock="10.0.0.0/8")['Vpc']
|
||||||
subnet = conn.create_subnet(VpcId=vpc['VpcId'], CidrBlock='10.0.0.0/16', AvailabilityZone='us-east-1a')['Subnet']
|
subnet = conn.create_subnet(VpcId=vpc['VpcId'], CidrBlock='10.0.0.0/16', AvailabilityZone='us-east-1a')['Subnet']
|
||||||
subnet_id = subnet['SubnetId']
|
subnet_id = subnet['SubnetId']
|
||||||
|
|
||||||
conn = boto.connect_ec2()
|
conn.create_security_group(GroupName='group1', Description='description')
|
||||||
|
conn.create_security_group(GroupName='group2', Description='description')
|
||||||
|
|
||||||
conn.create_security_group('group1', 'description')
|
start_dt = datetime.datetime(2013, 1, 1).replace(tzinfo=pytz.utc)
|
||||||
conn.create_security_group('group2', 'description')
|
end_dt = datetime.datetime(2013, 1, 2).replace(tzinfo=pytz.utc)
|
||||||
|
start = iso_8601_datetime_with_milliseconds(start_dt)
|
||||||
|
end = iso_8601_datetime_with_milliseconds(end_dt)
|
||||||
|
|
||||||
start = iso_8601_datetime_with_milliseconds(datetime.datetime(2013, 1, 1))
|
with assert_raises(ClientError) as ex:
|
||||||
end = iso_8601_datetime_with_milliseconds(datetime.datetime(2013, 1, 2))
|
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
|
||||||
request = conn.request_spot_instances(
|
request = conn.request_spot_instances(
|
||||||
price=0.5, image_id='ami-abcd1234', count=1, type='one-time',
|
SpotPrice="0.5", InstanceCount=1, Type='one-time',
|
||||||
valid_from=start, valid_until=end, launch_group="the-group",
|
ValidFrom=start, ValidUntil=end, LaunchGroup="the-group",
|
||||||
availability_zone_group='my-group', key_name="test",
|
AvailabilityZoneGroup='my-group',
|
||||||
security_groups=['group1', 'group2'], user_data=b"some test data",
|
LaunchSpecification={
|
||||||
instance_type='m1.small', placement='us-east-1c',
|
"ImageId": 'ami-abcd1234',
|
||||||
kernel_id="test-kernel", ramdisk_id="test-ramdisk",
|
"KeyName": "test",
|
||||||
monitoring_enabled=True, subnet_id=subnet_id, dry_run=True
|
"SecurityGroups": ['group1', 'group2'],
|
||||||
|
"UserData": b"some test data",
|
||||||
|
"InstanceType": 'm1.small',
|
||||||
|
"Placement": {
|
||||||
|
"AvailabilityZone": 'us-east-1c',
|
||||||
|
},
|
||||||
|
"KernelId": "test-kernel",
|
||||||
|
"RamdiskId": "test-ramdisk",
|
||||||
|
"Monitoring": {
|
||||||
|
"Enabled": True,
|
||||||
|
},
|
||||||
|
"SubnetId": subnet_id,
|
||||||
|
},
|
||||||
|
DryRun=True,
|
||||||
)
|
)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.response['Error']['Code'].should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.response['ResponseMetadata']['HTTPStatusCode'].should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the RequestSpotInstance operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.response['Error']['Message'].should.equal('An error occurred (DryRunOperation) when calling the RequestSpotInstance operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
request = conn.request_spot_instances(
|
request = conn.request_spot_instances(
|
||||||
price=0.5, image_id='ami-abcd1234', count=1, type='one-time',
|
SpotPrice="0.5", InstanceCount=1, Type='one-time',
|
||||||
valid_from=start, valid_until=end, launch_group="the-group",
|
ValidFrom=start, ValidUntil=end, LaunchGroup="the-group",
|
||||||
availability_zone_group='my-group', key_name="test",
|
AvailabilityZoneGroup='my-group',
|
||||||
security_groups=['group1', 'group2'], user_data=b"some test data",
|
LaunchSpecification={
|
||||||
instance_type='m1.small', placement='us-east-1c',
|
"ImageId": 'ami-abcd1234',
|
||||||
kernel_id="test-kernel", ramdisk_id="test-ramdisk",
|
"KeyName": "test",
|
||||||
monitoring_enabled=True, subnet_id=subnet_id,
|
"SecurityGroups": ['group1', 'group2'],
|
||||||
|
"UserData": b"some test data",
|
||||||
|
"InstanceType": 'm1.small',
|
||||||
|
"Placement": {
|
||||||
|
"AvailabilityZone": 'us-east-1c',
|
||||||
|
},
|
||||||
|
"KernelId": "test-kernel",
|
||||||
|
"RamdiskId": "test-ramdisk",
|
||||||
|
"Monitoring": {
|
||||||
|
"Enabled": True,
|
||||||
|
},
|
||||||
|
"SubnetId": subnet_id,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
requests = conn.get_all_spot_instance_requests()
|
requests = conn.describe_spot_instance_requests()['SpotInstanceRequests']
|
||||||
requests.should.have.length_of(1)
|
requests.should.have.length_of(1)
|
||||||
request = requests[0]
|
request = requests[0]
|
||||||
|
|
||||||
request.state.should.equal("open")
|
request['State'].should.equal("open")
|
||||||
request.price.should.equal(0.5)
|
request['SpotPrice'].should.equal("0.5")
|
||||||
request.launch_specification.image_id.should.equal('ami-abcd1234')
|
request['Type'].should.equal('one-time')
|
||||||
request.type.should.equal('one-time')
|
request['ValidFrom'].should.equal(start_dt)
|
||||||
request.valid_from.should.equal(start)
|
request['ValidUntil'].should.equal(end_dt)
|
||||||
request.valid_until.should.equal(end)
|
request['LaunchGroup'].should.equal("the-group")
|
||||||
request.launch_group.should.equal("the-group")
|
request['AvailabilityZoneGroup'].should.equal('my-group')
|
||||||
request.availability_zone_group.should.equal('my-group')
|
|
||||||
request.launch_specification.key_name.should.equal("test")
|
launch_spec = request['LaunchSpecification']
|
||||||
security_group_names = [group.name for group in request.launch_specification.groups]
|
security_group_names = [group['GroupName'] for group in launch_spec['SecurityGroups']]
|
||||||
set(security_group_names).should.equal(set(['group1', 'group2']))
|
set(security_group_names).should.equal(set(['group1', 'group2']))
|
||||||
request.launch_specification.instance_type.should.equal('m1.small')
|
|
||||||
request.launch_specification.placement.should.equal('us-east-1c')
|
launch_spec['ImageId'].should.equal('ami-abcd1234')
|
||||||
request.launch_specification.kernel.should.equal("test-kernel")
|
launch_spec['KeyName'].should.equal("test")
|
||||||
request.launch_specification.ramdisk.should.equal("test-ramdisk")
|
launch_spec['InstanceType'].should.equal('m1.small')
|
||||||
request.launch_specification.subnet_id.should.equal(subnet_id)
|
launch_spec['KernelId'].should.equal("test-kernel")
|
||||||
|
launch_spec['RamdiskId'].should.equal("test-ramdisk")
|
||||||
|
launch_spec['SubnetId'].should.equal(subnet_id)
|
||||||
|
|
||||||
|
|
||||||
@mock_ec2_deprecated
|
@mock_ec2
|
||||||
def test_request_spot_instances_default_arguments():
|
def test_request_spot_instances_default_arguments():
|
||||||
"""
|
"""
|
||||||
Test that moto set the correct default arguments
|
Test that moto set the correct default arguments
|
||||||
"""
|
"""
|
||||||
conn = boto.connect_ec2()
|
conn = boto3.client('ec2', 'us-east-1')
|
||||||
|
|
||||||
request = conn.request_spot_instances(
|
request = conn.request_spot_instances(
|
||||||
price=0.5, image_id='ami-abcd1234',
|
SpotPrice="0.5",
|
||||||
|
LaunchSpecification={
|
||||||
|
"ImageId": 'ami-abcd1234',
|
||||||
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
requests = conn.get_all_spot_instance_requests()
|
requests = conn.describe_spot_instance_requests()['SpotInstanceRequests']
|
||||||
requests.should.have.length_of(1)
|
requests.should.have.length_of(1)
|
||||||
request = requests[0]
|
request = requests[0]
|
||||||
|
|
||||||
request.state.should.equal("open")
|
request['State'].should.equal("open")
|
||||||
request.price.should.equal(0.5)
|
request['SpotPrice'].should.equal("0.5")
|
||||||
request.launch_specification.image_id.should.equal('ami-abcd1234')
|
request['Type'].should.equal('one-time')
|
||||||
request.type.should.equal('one-time')
|
request.shouldnt.contain('ValidFrom')
|
||||||
request.valid_from.should.equal(None)
|
request.shouldnt.contain('ValidUntil')
|
||||||
request.valid_until.should.equal(None)
|
request.shouldnt.contain('LaunchGroup')
|
||||||
request.launch_group.should.equal(None)
|
request.shouldnt.contain('AvailabilityZoneGroup')
|
||||||
request.availability_zone_group.should.equal(None)
|
|
||||||
request.launch_specification.key_name.should.equal(None)
|
launch_spec = request['LaunchSpecification']
|
||||||
security_group_names = [group.name for group in request.launch_specification.groups]
|
|
||||||
|
security_group_names = [group['GroupName'] for group in launch_spec['SecurityGroups']]
|
||||||
security_group_names.should.equal(["default"])
|
security_group_names.should.equal(["default"])
|
||||||
request.launch_specification.instance_type.should.equal('m1.small')
|
|
||||||
request.launch_specification.placement.should.equal(None)
|
launch_spec['ImageId'].should.equal('ami-abcd1234')
|
||||||
request.launch_specification.kernel.should.equal(None)
|
request.shouldnt.contain('KeyName')
|
||||||
request.launch_specification.ramdisk.should.equal(None)
|
launch_spec['InstanceType'].should.equal('m1.small')
|
||||||
request.launch_specification.subnet_id.should.equal(None)
|
request.shouldnt.contain('KernelId')
|
||||||
|
request.shouldnt.contain('RamdiskId')
|
||||||
|
request.shouldnt.contain('SubnetId')
|
||||||
|
|
||||||
|
|
||||||
@mock_ec2_deprecated
|
@mock_ec2_deprecated
|
||||||
@ -119,9 +153,9 @@ def test_cancel_spot_instance_request():
|
|||||||
requests.should.have.length_of(1)
|
requests.should.have.length_of(1)
|
||||||
|
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
conn.cancel_spot_instance_requests([requests[0].id], dry_run=True)
|
conn.cancel_spot_instance_requests([requests[0].id], dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CancelSpotInstance operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CancelSpotInstance operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -148,7 +182,7 @@ def test_request_spot_instances_fulfilled():
|
|||||||
|
|
||||||
request.state.should.equal("open")
|
request.state.should.equal("open")
|
||||||
|
|
||||||
get_model('SpotInstanceRequest')[0].state = 'active'
|
get_model('SpotInstanceRequest', 'us-east-1')[0].state = 'active'
|
||||||
|
|
||||||
requests = conn.get_all_spot_instance_requests()
|
requests = conn.get_all_spot_instance_requests()
|
||||||
requests.should.have.length_of(1)
|
requests.should.have.length_of(1)
|
||||||
@ -218,7 +252,7 @@ def test_request_spot_instances_setting_instance_id():
|
|||||||
request = conn.request_spot_instances(
|
request = conn.request_spot_instances(
|
||||||
price=0.5, image_id='ami-abcd1234')
|
price=0.5, image_id='ami-abcd1234')
|
||||||
|
|
||||||
req = get_model('SpotInstanceRequest')[0]
|
req = get_model('SpotInstanceRequest', 'us-east-1')[0]
|
||||||
req.state = 'active'
|
req.state = 'active'
|
||||||
req.instance_id = 'i-12345678'
|
req.instance_id = 'i-12345678'
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ from nose.tools import assert_raises
|
|||||||
import itertools
|
import itertools
|
||||||
|
|
||||||
import boto
|
import boto
|
||||||
from boto.exception import EC2ResponseError, JSONResponseError
|
from boto.exception import EC2ResponseError
|
||||||
from boto.ec2.instance import Reservation
|
from boto.ec2.instance import Reservation
|
||||||
import sure # noqa
|
import sure # noqa
|
||||||
|
|
||||||
@ -18,9 +18,9 @@ def test_add_tag():
|
|||||||
reservation = conn.run_instances('ami-1234abcd')
|
reservation = conn.run_instances('ami-1234abcd')
|
||||||
instance = reservation.instances[0]
|
instance = reservation.instances[0]
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
instance.add_tag("a key", "some value", dry_run=True)
|
instance.add_tag("a key", "some value", dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -45,9 +45,9 @@ def test_remove_tag():
|
|||||||
tag.name.should.equal("a key")
|
tag.name.should.equal("a key")
|
||||||
tag.value.should.equal("some value")
|
tag.value.should.equal("some value")
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
instance.remove_tag("a key", dry_run=True)
|
instance.remove_tag("a key", dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the DeleteTags operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the DeleteTags operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
@ -96,9 +96,9 @@ def test_create_tags():
|
|||||||
'another key': 'some other value',
|
'another key': 'some other value',
|
||||||
'blank key': ''}
|
'blank key': ''}
|
||||||
|
|
||||||
with assert_raises(JSONResponseError) as ex:
|
with assert_raises(EC2ResponseError) as ex:
|
||||||
conn.create_tags(instance.id, tag_dict, dry_run=True)
|
conn.create_tags(instance.id, tag_dict, dry_run=True)
|
||||||
ex.exception.reason.should.equal('DryRunOperation')
|
ex.exception.error_code.should.equal('DryRunOperation')
|
||||||
ex.exception.status.should.equal(400)
|
ex.exception.status.should.equal(400)
|
||||||
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set')
|
ex.exception.message.should.equal('An error occurred (DryRunOperation) when calling the CreateTags operation: Request would have succeeded, but DryRun flag is set')
|
||||||
|
|
||||||
|
@ -112,7 +112,7 @@ def test_describe_jobflows():
|
|||||||
args = run_jobflow_args.copy()
|
args = run_jobflow_args.copy()
|
||||||
expected = {}
|
expected = {}
|
||||||
|
|
||||||
for idx in range(400):
|
for idx in range(4):
|
||||||
cluster_name = 'cluster' + str(idx)
|
cluster_name = 'cluster' + str(idx)
|
||||||
args['name'] = cluster_name
|
args['name'] = cluster_name
|
||||||
cluster_id = conn.run_jobflow(**args)
|
cluster_id = conn.run_jobflow(**args)
|
||||||
@ -128,7 +128,7 @@ def test_describe_jobflows():
|
|||||||
timestamp = datetime.now(pytz.utc)
|
timestamp = datetime.now(pytz.utc)
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
for idx in range(400, 600):
|
for idx in range(4, 6):
|
||||||
cluster_name = 'cluster' + str(idx)
|
cluster_name = 'cluster' + str(idx)
|
||||||
args['name'] = cluster_name
|
args['name'] = cluster_name
|
||||||
cluster_id = conn.run_jobflow(**args)
|
cluster_id = conn.run_jobflow(**args)
|
||||||
@ -139,7 +139,7 @@ def test_describe_jobflows():
|
|||||||
'state': 'TERMINATED'
|
'state': 'TERMINATED'
|
||||||
}
|
}
|
||||||
jobs = conn.describe_jobflows()
|
jobs = conn.describe_jobflows()
|
||||||
jobs.should.have.length_of(512)
|
jobs.should.have.length_of(6)
|
||||||
|
|
||||||
for cluster_id, y in expected.items():
|
for cluster_id, y in expected.items():
|
||||||
resp = conn.describe_jobflows(jobflow_ids=[cluster_id])
|
resp = conn.describe_jobflows(jobflow_ids=[cluster_id])
|
||||||
@ -147,15 +147,15 @@ def test_describe_jobflows():
|
|||||||
resp[0].jobflowid.should.equal(cluster_id)
|
resp[0].jobflowid.should.equal(cluster_id)
|
||||||
|
|
||||||
resp = conn.describe_jobflows(states=['WAITING'])
|
resp = conn.describe_jobflows(states=['WAITING'])
|
||||||
resp.should.have.length_of(400)
|
resp.should.have.length_of(4)
|
||||||
for x in resp:
|
for x in resp:
|
||||||
x.state.should.equal('WAITING')
|
x.state.should.equal('WAITING')
|
||||||
|
|
||||||
resp = conn.describe_jobflows(created_before=timestamp)
|
resp = conn.describe_jobflows(created_before=timestamp)
|
||||||
resp.should.have.length_of(400)
|
resp.should.have.length_of(4)
|
||||||
|
|
||||||
resp = conn.describe_jobflows(created_after=timestamp)
|
resp = conn.describe_jobflows(created_after=timestamp)
|
||||||
resp.should.have.length_of(200)
|
resp.should.have.length_of(2)
|
||||||
|
|
||||||
|
|
||||||
@mock_emr_deprecated
|
@mock_emr_deprecated
|
||||||
|
@ -128,7 +128,7 @@ def test_describe_job_flows():
|
|||||||
args = deepcopy(run_job_flow_args)
|
args = deepcopy(run_job_flow_args)
|
||||||
expected = {}
|
expected = {}
|
||||||
|
|
||||||
for idx in range(400):
|
for idx in range(4):
|
||||||
cluster_name = 'cluster' + str(idx)
|
cluster_name = 'cluster' + str(idx)
|
||||||
args['Name'] = cluster_name
|
args['Name'] = cluster_name
|
||||||
cluster_id = client.run_job_flow(**args)['JobFlowId']
|
cluster_id = client.run_job_flow(**args)['JobFlowId']
|
||||||
@ -144,7 +144,7 @@ def test_describe_job_flows():
|
|||||||
timestamp = datetime.now(pytz.utc)
|
timestamp = datetime.now(pytz.utc)
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
for idx in range(400, 600):
|
for idx in range(4, 6):
|
||||||
cluster_name = 'cluster' + str(idx)
|
cluster_name = 'cluster' + str(idx)
|
||||||
args['Name'] = cluster_name
|
args['Name'] = cluster_name
|
||||||
cluster_id = client.run_job_flow(**args)['JobFlowId']
|
cluster_id = client.run_job_flow(**args)['JobFlowId']
|
||||||
@ -156,7 +156,7 @@ def test_describe_job_flows():
|
|||||||
}
|
}
|
||||||
|
|
||||||
resp = client.describe_job_flows()
|
resp = client.describe_job_flows()
|
||||||
resp['JobFlows'].should.have.length_of(512)
|
resp['JobFlows'].should.have.length_of(6)
|
||||||
|
|
||||||
for cluster_id, y in expected.items():
|
for cluster_id, y in expected.items():
|
||||||
resp = client.describe_job_flows(JobFlowIds=[cluster_id])
|
resp = client.describe_job_flows(JobFlowIds=[cluster_id])
|
||||||
@ -164,15 +164,15 @@ def test_describe_job_flows():
|
|||||||
resp['JobFlows'][0]['JobFlowId'].should.equal(cluster_id)
|
resp['JobFlows'][0]['JobFlowId'].should.equal(cluster_id)
|
||||||
|
|
||||||
resp = client.describe_job_flows(JobFlowStates=['WAITING'])
|
resp = client.describe_job_flows(JobFlowStates=['WAITING'])
|
||||||
resp['JobFlows'].should.have.length_of(400)
|
resp['JobFlows'].should.have.length_of(4)
|
||||||
for x in resp['JobFlows']:
|
for x in resp['JobFlows']:
|
||||||
x['ExecutionStatusDetail']['State'].should.equal('WAITING')
|
x['ExecutionStatusDetail']['State'].should.equal('WAITING')
|
||||||
|
|
||||||
resp = client.describe_job_flows(CreatedBefore=timestamp)
|
resp = client.describe_job_flows(CreatedBefore=timestamp)
|
||||||
resp['JobFlows'].should.have.length_of(400)
|
resp['JobFlows'].should.have.length_of(4)
|
||||||
|
|
||||||
resp = client.describe_job_flows(CreatedAfter=timestamp)
|
resp = client.describe_job_flows(CreatedAfter=timestamp)
|
||||||
resp['JobFlows'].should.have.length_of(200)
|
resp['JobFlows'].should.have.length_of(2)
|
||||||
|
|
||||||
|
|
||||||
@mock_emr
|
@mock_emr
|
||||||
@ -327,13 +327,13 @@ def test_run_job_flow():
|
|||||||
@mock_emr
|
@mock_emr
|
||||||
def test_run_job_flow_with_invalid_params():
|
def test_run_job_flow_with_invalid_params():
|
||||||
client = boto3.client('emr', region_name='us-east-1')
|
client = boto3.client('emr', region_name='us-east-1')
|
||||||
with assert_raises(ClientError) as e:
|
with assert_raises(ClientError) as ex:
|
||||||
# cannot set both AmiVersion and ReleaseLabel
|
# cannot set both AmiVersion and ReleaseLabel
|
||||||
args = deepcopy(run_job_flow_args)
|
args = deepcopy(run_job_flow_args)
|
||||||
args['AmiVersion'] = '2.4'
|
args['AmiVersion'] = '2.4'
|
||||||
args['ReleaseLabel'] = 'emr-5.0.0'
|
args['ReleaseLabel'] = 'emr-5.0.0'
|
||||||
client.run_job_flow(**args)
|
client.run_job_flow(**args)
|
||||||
e.exception.response['Error']['Code'].should.equal('ValidationException')
|
ex.exception.response['Error']['Message'].should.contain('ValidationException')
|
||||||
|
|
||||||
|
|
||||||
@mock_emr
|
@mock_emr
|
||||||
|
@ -201,7 +201,7 @@ def test_get_user():
|
|||||||
def test_list_users():
|
def test_list_users():
|
||||||
path_prefix = '/'
|
path_prefix = '/'
|
||||||
max_items = 10
|
max_items = 10
|
||||||
conn = boto3.client('iam')
|
conn = boto3.client('iam', region_name='us-east-1')
|
||||||
conn.create_user(UserName='my-user')
|
conn.create_user(UserName='my-user')
|
||||||
response = conn.list_users(PathPrefix=path_prefix, MaxItems=max_items)
|
response = conn.list_users(PathPrefix=path_prefix, MaxItems=max_items)
|
||||||
user = response['Users'][0]
|
user = response['Users'][0]
|
||||||
@ -337,7 +337,7 @@ def test_managed_policy():
|
|||||||
|
|
||||||
@mock_iam
|
@mock_iam
|
||||||
def test_boto3_create_login_profile():
|
def test_boto3_create_login_profile():
|
||||||
conn = boto3.client('iam')
|
conn = boto3.client('iam', region_name='us-east-1')
|
||||||
|
|
||||||
with assert_raises(ClientError):
|
with assert_raises(ClientError):
|
||||||
conn.create_login_profile(UserName='my-user', Password='Password')
|
conn.create_login_profile(UserName='my-user', Password='Password')
|
||||||
|
@ -4,7 +4,6 @@ import datetime
|
|||||||
|
|
||||||
from botocore.exceptions import ClientError
|
from botocore.exceptions import ClientError
|
||||||
import boto3
|
import boto3
|
||||||
from freezegun import freeze_time
|
|
||||||
import sure # noqa
|
import sure # noqa
|
||||||
|
|
||||||
from moto import mock_kinesis
|
from moto import mock_kinesis
|
||||||
@ -37,7 +36,6 @@ def create_stream(client, stream_name):
|
|||||||
|
|
||||||
|
|
||||||
@mock_kinesis
|
@mock_kinesis
|
||||||
@freeze_time("2015-03-01")
|
|
||||||
def test_create_stream():
|
def test_create_stream():
|
||||||
client = boto3.client('firehose', region_name='us-east-1')
|
client = boto3.client('firehose', region_name='us-east-1')
|
||||||
|
|
||||||
@ -48,11 +46,8 @@ def test_create_stream():
|
|||||||
stream_description = response['DeliveryStreamDescription']
|
stream_description = response['DeliveryStreamDescription']
|
||||||
|
|
||||||
# Sure and Freezegun don't play nicely together
|
# Sure and Freezegun don't play nicely together
|
||||||
created = stream_description.pop('CreateTimestamp')
|
_ = stream_description.pop('CreateTimestamp')
|
||||||
last_updated = stream_description.pop('LastUpdateTimestamp')
|
_ = stream_description.pop('LastUpdateTimestamp')
|
||||||
from dateutil.tz import tzlocal
|
|
||||||
assert created == datetime.datetime(2015, 3, 1, tzinfo=tzlocal())
|
|
||||||
assert last_updated == datetime.datetime(2015, 3, 1, tzinfo=tzlocal())
|
|
||||||
|
|
||||||
stream_description.should.equal({
|
stream_description.should.equal({
|
||||||
'DeliveryStreamName': 'stream1',
|
'DeliveryStreamName': 'stream1',
|
||||||
@ -88,7 +83,6 @@ def test_create_stream():
|
|||||||
|
|
||||||
|
|
||||||
@mock_kinesis
|
@mock_kinesis
|
||||||
@freeze_time("2015-03-01")
|
|
||||||
def test_create_stream_without_redshift():
|
def test_create_stream_without_redshift():
|
||||||
client = boto3.client('firehose', region_name='us-east-1')
|
client = boto3.client('firehose', region_name='us-east-1')
|
||||||
|
|
||||||
@ -111,11 +105,8 @@ def test_create_stream_without_redshift():
|
|||||||
stream_description = response['DeliveryStreamDescription']
|
stream_description = response['DeliveryStreamDescription']
|
||||||
|
|
||||||
# Sure and Freezegun don't play nicely together
|
# Sure and Freezegun don't play nicely together
|
||||||
created = stream_description.pop('CreateTimestamp')
|
_ = stream_description.pop('CreateTimestamp')
|
||||||
last_updated = stream_description.pop('LastUpdateTimestamp')
|
_ = stream_description.pop('LastUpdateTimestamp')
|
||||||
from dateutil.tz import tzlocal
|
|
||||||
assert created == datetime.datetime(2015, 3, 1, tzinfo=tzlocal())
|
|
||||||
assert last_updated == datetime.datetime(2015, 3, 1, tzinfo=tzlocal())
|
|
||||||
|
|
||||||
stream_description.should.equal({
|
stream_description.should.equal({
|
||||||
'DeliveryStreamName': 'stream1',
|
'DeliveryStreamName': 'stream1',
|
||||||
@ -142,7 +133,6 @@ def test_create_stream_without_redshift():
|
|||||||
})
|
})
|
||||||
|
|
||||||
@mock_kinesis
|
@mock_kinesis
|
||||||
@freeze_time("2015-03-01")
|
|
||||||
def test_deescribe_non_existant_stream():
|
def test_deescribe_non_existant_stream():
|
||||||
client = boto3.client('firehose', region_name='us-east-1')
|
client = boto3.client('firehose', region_name='us-east-1')
|
||||||
|
|
||||||
@ -150,7 +140,6 @@ def test_deescribe_non_existant_stream():
|
|||||||
|
|
||||||
|
|
||||||
@mock_kinesis
|
@mock_kinesis
|
||||||
@freeze_time("2015-03-01")
|
|
||||||
def test_list_and_delete_stream():
|
def test_list_and_delete_stream():
|
||||||
client = boto3.client('firehose', region_name='us-east-1')
|
client = boto3.client('firehose', region_name='us-east-1')
|
||||||
|
|
||||||
|
@ -308,7 +308,7 @@ def test_hosted_zone_private_zone_preserved():
|
|||||||
|
|
||||||
@mock_route53
|
@mock_route53
|
||||||
def test_hosted_zone_private_zone_preserved_boto3():
|
def test_hosted_zone_private_zone_preserved_boto3():
|
||||||
conn = boto3.client('route53')
|
conn = boto3.client('route53', region_name='us-east-1')
|
||||||
# TODO: actually create_hosted_zone statements with PrivateZone=True, but without
|
# TODO: actually create_hosted_zone statements with PrivateZone=True, but without
|
||||||
# a _valid_ vpc-id should fail.
|
# a _valid_ vpc-id should fail.
|
||||||
firstzone = conn.create_hosted_zone(
|
firstzone = conn.create_hosted_zone(
|
||||||
@ -333,8 +333,20 @@ def test_hosted_zone_private_zone_preserved_boto3():
|
|||||||
|
|
||||||
@mock_route53
|
@mock_route53
|
||||||
def test_list_or_change_tags_for_resource_request():
|
def test_list_or_change_tags_for_resource_request():
|
||||||
conn = boto3.client('route53')
|
conn = boto3.client('route53', region_name='us-east-1')
|
||||||
healthcheck_id = str(uuid.uuid4())
|
health_check = conn.create_health_check(
|
||||||
|
CallerReference='foobar',
|
||||||
|
HealthCheckConfig={
|
||||||
|
'IPAddress': '192.0.2.44',
|
||||||
|
'Port': 123,
|
||||||
|
'Type': 'HTTP',
|
||||||
|
'ResourcePath': '/',
|
||||||
|
'RequestInterval': 30,
|
||||||
|
'FailureThreshold': 123,
|
||||||
|
'HealthThreshold': 123,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
healthcheck_id = health_check['HealthCheck']['Id']
|
||||||
|
|
||||||
tag1 = {"Key": "Deploy", "Value": "True"}
|
tag1 = {"Key": "Deploy", "Value": "True"}
|
||||||
tag2 = {"Key": "Name", "Value": "UnitTest"}
|
tag2 = {"Key": "Name", "Value": "UnitTest"}
|
||||||
|
@ -20,17 +20,21 @@ from nose.tools import assert_raises
|
|||||||
|
|
||||||
import sure # noqa
|
import sure # noqa
|
||||||
|
|
||||||
from moto import mock_s3, mock_s3_deprecated
|
from moto import settings, mock_s3, mock_s3_deprecated
|
||||||
|
import moto.s3.models as s3model
|
||||||
|
|
||||||
|
if settings.TEST_SERVER_MODE:
|
||||||
|
REDUCED_PART_SIZE = s3model.UPLOAD_PART_MIN_SIZE
|
||||||
|
EXPECTED_ETAG = '"140f92a6df9f9e415f74a1463bcee9bb-2"'
|
||||||
|
else:
|
||||||
REDUCED_PART_SIZE = 256
|
REDUCED_PART_SIZE = 256
|
||||||
|
EXPECTED_ETAG = '"66d1a1a2ed08fd05c137f316af4ff255-2"'
|
||||||
|
|
||||||
|
|
||||||
def reduced_min_part_size(f):
|
def reduced_min_part_size(f):
|
||||||
""" speed up tests by temporarily making the multipart minimum part size
|
""" speed up tests by temporarily making the multipart minimum part size
|
||||||
small
|
small
|
||||||
"""
|
"""
|
||||||
import moto.s3.models as s3model
|
|
||||||
orig_size = s3model.UPLOAD_PART_MIN_SIZE
|
orig_size = s3model.UPLOAD_PART_MIN_SIZE
|
||||||
|
|
||||||
@wraps(f)
|
@wraps(f)
|
||||||
@ -49,24 +53,23 @@ class MyModel(object):
|
|||||||
self.value = value
|
self.value = value
|
||||||
|
|
||||||
def save(self):
|
def save(self):
|
||||||
conn = boto.connect_s3('the_key', 'the_secret')
|
s3 = boto3.client('s3', region_name='us-east-1')
|
||||||
bucket = conn.get_bucket('mybucket')
|
s3.put_object(Bucket='mybucket', Key=self.name, Body=self.value)
|
||||||
k = Key(bucket)
|
|
||||||
k.key = self.name
|
|
||||||
k.set_contents_from_string(self.value)
|
|
||||||
|
|
||||||
|
|
||||||
@mock_s3_deprecated
|
@mock_s3
|
||||||
def test_my_model_save():
|
def test_my_model_save():
|
||||||
# Create Bucket so that test can run
|
# Create Bucket so that test can run
|
||||||
conn = boto.connect_s3('the_key', 'the_secret')
|
conn = boto3.resource('s3', region_name='us-east-1')
|
||||||
conn.create_bucket('mybucket')
|
conn.create_bucket(Bucket='mybucket')
|
||||||
####################################
|
####################################
|
||||||
|
|
||||||
model_instance = MyModel('steve', 'is awesome')
|
model_instance = MyModel('steve', 'is awesome')
|
||||||
model_instance.save()
|
model_instance.save()
|
||||||
|
|
||||||
conn.get_bucket('mybucket').get_key('steve').get_contents_as_string().should.equal(b'is awesome')
|
body = conn.Object('mybucket', 'steve').get()['Body'].read().decode("utf-8")
|
||||||
|
|
||||||
|
assert body == b'is awesome'
|
||||||
|
|
||||||
|
|
||||||
@mock_s3_deprecated
|
@mock_s3_deprecated
|
||||||
@ -190,8 +193,7 @@ def test_multipart_etag():
|
|||||||
multipart.upload_part_from_file(BytesIO(part2), 2)
|
multipart.upload_part_from_file(BytesIO(part2), 2)
|
||||||
multipart.complete_upload()
|
multipart.complete_upload()
|
||||||
# we should get both parts as the key contents
|
# we should get both parts as the key contents
|
||||||
bucket.get_key("the-key").etag.should.equal(
|
bucket.get_key("the-key").etag.should.equal(EXPECTED_ETAG)
|
||||||
'"66d1a1a2ed08fd05c137f316af4ff255-2"')
|
|
||||||
|
|
||||||
|
|
||||||
@mock_s3_deprecated
|
@mock_s3_deprecated
|
||||||
@ -544,16 +546,6 @@ def test_delete_keys_with_invalid():
|
|||||||
keys[0].name.should.equal('file1')
|
keys[0].name.should.equal('file1')
|
||||||
|
|
||||||
|
|
||||||
@mock_s3
|
|
||||||
def test_bucket_method_not_implemented():
|
|
||||||
requests.patch.when.called_with("https://foobar.s3.amazonaws.com/").should.throw(NotImplementedError)
|
|
||||||
|
|
||||||
|
|
||||||
@mock_s3
|
|
||||||
def test_key_method_not_implemented():
|
|
||||||
requests.post.when.called_with("https://foobar.s3.amazonaws.com/foo").should.throw(NotImplementedError)
|
|
||||||
|
|
||||||
|
|
||||||
@mock_s3_deprecated
|
@mock_s3_deprecated
|
||||||
def test_bucket_name_with_dot():
|
def test_bucket_name_with_dot():
|
||||||
conn = boto.connect_s3()
|
conn = boto.connect_s3()
|
||||||
@ -1241,7 +1233,7 @@ def test_boto3_multipart_etag():
|
|||||||
for i, etag in enumerate(etags, 1)]})
|
for i, etag in enumerate(etags, 1)]})
|
||||||
# we should get both parts as the key contents
|
# we should get both parts as the key contents
|
||||||
resp = s3.get_object(Bucket='mybucket', Key='the-key')
|
resp = s3.get_object(Bucket='mybucket', Key='the-key')
|
||||||
resp['ETag'].should.equal('"66d1a1a2ed08fd05c137f316af4ff255-2"')
|
resp['ETag'].should.equal(EXPECTED_ETAG)
|
||||||
|
|
||||||
|
|
||||||
TEST_XML = """\
|
TEST_XML = """\
|
||||||
|
@ -211,16 +211,6 @@ def test_post_with_metadata_to_bucket():
|
|||||||
bucket.get_key('the-key').get_metadata('test').should.equal('metadata')
|
bucket.get_key('the-key').get_metadata('test').should.equal('metadata')
|
||||||
|
|
||||||
|
|
||||||
@mock_s3
|
|
||||||
def test_bucket_method_not_implemented():
|
|
||||||
requests.patch.when.called_with("https://s3.amazonaws.com/foobar").should.throw(NotImplementedError)
|
|
||||||
|
|
||||||
|
|
||||||
@mock_s3
|
|
||||||
def test_key_method_not_implemented():
|
|
||||||
requests.post.when.called_with("https://s3.amazonaws.com/foobar/foo").should.throw(NotImplementedError)
|
|
||||||
|
|
||||||
|
|
||||||
@mock_s3_deprecated
|
@mock_s3_deprecated
|
||||||
def test_bucket_name_with_dot():
|
def test_bucket_name_with_dot():
|
||||||
conn = create_connection()
|
conn = create_connection()
|
||||||
|
@ -67,20 +67,3 @@ def test_publish_to_http():
|
|||||||
|
|
||||||
response = conn.publish(topic=topic_arn, message="my message", subject="my subject")
|
response = conn.publish(topic=topic_arn, message="my message", subject="my subject")
|
||||||
message_id = response['PublishResponse']['PublishResult']['MessageId']
|
message_id = response['PublishResponse']['PublishResult']['MessageId']
|
||||||
|
|
||||||
last_request = responses.calls[-1].request
|
|
||||||
last_request.method.should.equal("POST")
|
|
||||||
parse_qs(last_request.body).should.equal({
|
|
||||||
"Type": ["Notification"],
|
|
||||||
"MessageId": [message_id],
|
|
||||||
"TopicArn": ["arn:aws:sns:{0}:123456789012:some-topic".format(conn.region.name)],
|
|
||||||
"Subject": ["my subject"],
|
|
||||||
"Message": ["my message"],
|
|
||||||
"Timestamp": ["2013-01-01T00:00:00.000Z"],
|
|
||||||
"SignatureVersion": ["1"],
|
|
||||||
"Signature": ["EXAMPLElDMXvB8r9R83tGoNn0ecwd5UjllzsvSvbItzfaMpN2nk5HVSw7XnOn/49IkxDKz8YrlH2qJXj2iZB0Zo2O71c4qQk1fMUDi3LGpij7RCW7AW9vYYsSqIKRnFS94ilu7NFhUzLiieYr4BKHpdTmdD6c0esKEYBpabxDSc="],
|
|
||||||
"SigningCertURL": ["https://sns.us-east-1.amazonaws.com/SimpleNotificationService-f3ecfb7224c7233fe7bb5f59f96de52f.pem"],
|
|
||||||
"UnsubscribeURL": ["https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-1:123456789012:some-topic:2bcfbf39-05c3-41de-beaa-fcfcc21c8f55"],
|
|
||||||
})
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -72,18 +72,3 @@ def test_publish_to_http():
|
|||||||
|
|
||||||
response = conn.publish(TopicArn=topic_arn, Message="my message", Subject="my subject")
|
response = conn.publish(TopicArn=topic_arn, Message="my message", Subject="my subject")
|
||||||
message_id = response['MessageId']
|
message_id = response['MessageId']
|
||||||
|
|
||||||
last_request = responses.calls[-2].request
|
|
||||||
last_request.method.should.equal("POST")
|
|
||||||
parse_qs(last_request.body).should.equal({
|
|
||||||
"Type": ["Notification"],
|
|
||||||
"MessageId": [message_id],
|
|
||||||
"TopicArn": ["arn:aws:sns:{0}:123456789012:some-topic".format(conn._client_config.region_name)],
|
|
||||||
"Subject": ["my subject"],
|
|
||||||
"Message": ["my message"],
|
|
||||||
"Timestamp": ["2013-01-01T00:00:00.000Z"],
|
|
||||||
"SignatureVersion": ["1"],
|
|
||||||
"Signature": ["EXAMPLElDMXvB8r9R83tGoNn0ecwd5UjllzsvSvbItzfaMpN2nk5HVSw7XnOn/49IkxDKz8YrlH2qJXj2iZB0Zo2O71c4qQk1fMUDi3LGpij7RCW7AW9vYYsSqIKRnFS94ilu7NFhUzLiieYr4BKHpdTmdD6c0esKEYBpabxDSc="],
|
|
||||||
"SigningCertURL": ["https://sns.us-east-1.amazonaws.com/SimpleNotificationService-f3ecfb7224c7233fe7bb5f59f96de52f.pem"],
|
|
||||||
"UnsubscribeURL": ["https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-1:123456789012:some-topic:2bcfbf39-05c3-41de-beaa-fcfcc21c8f55"],
|
|
||||||
})
|
|
||||||
|
@ -408,11 +408,6 @@ def test_delete_batch_operation():
|
|||||||
queue.count().should.equal(1)
|
queue.count().should.equal(1)
|
||||||
|
|
||||||
|
|
||||||
@mock_sqs
|
|
||||||
def test_sqs_method_not_implemented():
|
|
||||||
requests.post.when.called_with("https://sqs.amazonaws.com/?Action=[foobar]").should.throw(NotImplementedError)
|
|
||||||
|
|
||||||
|
|
||||||
@mock_sqs_deprecated
|
@mock_sqs_deprecated
|
||||||
def test_queue_attributes():
|
def test_queue_attributes():
|
||||||
conn = boto.connect_sqs('the_key', 'the_secret')
|
conn = boto.connect_sqs('the_key', 'the_secret')
|
||||||
|
@ -68,7 +68,7 @@ def test_assume_role():
|
|||||||
|
|
||||||
@mock_sts
|
@mock_sts
|
||||||
def test_get_caller_identity():
|
def test_get_caller_identity():
|
||||||
identity = boto3.client("sts").get_caller_identity()
|
identity = boto3.client("sts", region_name='us-east-1').get_caller_identity()
|
||||||
|
|
||||||
identity['Arn'].should.equal('arn:aws:sts::123456789012:user/moto')
|
identity['Arn'].should.equal('arn:aws:sts::123456789012:user/moto')
|
||||||
identity['UserId'].should.equal('AKIAIOSFODNN7EXAMPLE')
|
identity['UserId'].should.equal('AKIAIOSFODNN7EXAMPLE')
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import boto
|
import boto
|
||||||
|
|
||||||
from moto import mock_swf
|
|
||||||
from moto.swf.models import (
|
from moto.swf.models import (
|
||||||
ActivityType,
|
ActivityType,
|
||||||
Domain,
|
Domain,
|
||||||
@ -76,7 +75,6 @@ def auto_start_decision_tasks(wfe):
|
|||||||
|
|
||||||
|
|
||||||
# Setup a complete example workflow and return the connection object
|
# Setup a complete example workflow and return the connection object
|
||||||
@mock_swf
|
|
||||||
def setup_workflow():
|
def setup_workflow():
|
||||||
conn = boto.connect_swf("the_key", "the_secret")
|
conn = boto.connect_swf("the_key", "the_secret")
|
||||||
conn.register_domain("test-domain", "60", description="A test domain")
|
conn.register_domain("test-domain", "60", description="A test domain")
|
||||||
|
Loading…
Reference in New Issue
Block a user