merging from master

This commit is contained in:
Bryan Alexander 2020-02-18 10:47:05 -06:00
commit 445f474534
125 changed files with 7406 additions and 3847 deletions

View file

@ -26,7 +26,14 @@ def test_create_and_get_rest_api():
response.pop("ResponseMetadata")
response.pop("createdDate")
response.should.equal(
{"id": api_id, "name": "my_api", "description": "this is my api"}
{
"id": api_id,
"name": "my_api",
"description": "this is my api",
"apiKeySource": "HEADER",
"endpointConfiguration": {"types": ["EDGE"]},
"tags": {},
}
)
@ -47,6 +54,114 @@ def test_list_and_delete_apis():
len(response["items"]).should.equal(1)
@mock_apigateway
def test_create_rest_api_with_tags():
client = boto3.client("apigateway", region_name="us-west-2")
response = client.create_rest_api(
name="my_api", description="this is my api", tags={"MY_TAG1": "MY_VALUE1"}
)
api_id = response["id"]
response = client.get_rest_api(restApiId=api_id)
assert "tags" in response
response["tags"].should.equal({"MY_TAG1": "MY_VALUE1"})
@mock_apigateway
def test_create_rest_api_invalid_apikeysource():
client = boto3.client("apigateway", region_name="us-west-2")
with assert_raises(ClientError) as ex:
client.create_rest_api(
name="my_api",
description="this is my api",
apiKeySource="not a valid api key source",
)
ex.exception.response["Error"]["Code"].should.equal("ValidationException")
@mock_apigateway
def test_create_rest_api_valid_apikeysources():
client = boto3.client("apigateway", region_name="us-west-2")
# 1. test creating rest api with HEADER apiKeySource
response = client.create_rest_api(
name="my_api", description="this is my api", apiKeySource="HEADER",
)
api_id = response["id"]
response = client.get_rest_api(restApiId=api_id)
response["apiKeySource"].should.equal("HEADER")
# 2. test creating rest api with AUTHORIZER apiKeySource
response = client.create_rest_api(
name="my_api2", description="this is my api", apiKeySource="AUTHORIZER",
)
api_id = response["id"]
response = client.get_rest_api(restApiId=api_id)
response["apiKeySource"].should.equal("AUTHORIZER")
@mock_apigateway
def test_create_rest_api_invalid_endpointconfiguration():
client = boto3.client("apigateway", region_name="us-west-2")
with assert_raises(ClientError) as ex:
client.create_rest_api(
name="my_api",
description="this is my api",
endpointConfiguration={"types": ["INVALID"]},
)
ex.exception.response["Error"]["Code"].should.equal("ValidationException")
@mock_apigateway
def test_create_rest_api_valid_endpointconfigurations():
client = boto3.client("apigateway", region_name="us-west-2")
# 1. test creating rest api with PRIVATE endpointConfiguration
response = client.create_rest_api(
name="my_api",
description="this is my api",
endpointConfiguration={"types": ["PRIVATE"]},
)
api_id = response["id"]
response = client.get_rest_api(restApiId=api_id)
response["endpointConfiguration"].should.equal(
{"types": ["PRIVATE"],}
)
# 2. test creating rest api with REGIONAL endpointConfiguration
response = client.create_rest_api(
name="my_api2",
description="this is my api",
endpointConfiguration={"types": ["REGIONAL"]},
)
api_id = response["id"]
response = client.get_rest_api(restApiId=api_id)
response["endpointConfiguration"].should.equal(
{"types": ["REGIONAL"],}
)
# 3. test creating rest api with EDGE endpointConfiguration
response = client.create_rest_api(
name="my_api3",
description="this is my api",
endpointConfiguration={"types": ["EDGE"]},
)
api_id = response["id"]
response = client.get_rest_api(restApiId=api_id)
response["endpointConfiguration"].should.equal(
{"types": ["EDGE"],}
)
@mock_apigateway
def test_create_resource__validate_name():
client = boto3.client("apigateway", region_name="us-west-2")
@ -58,15 +173,15 @@ def test_create_resource__validate_name():
0
]["id"]
invalid_names = ["/users", "users/", "users/{user_id}", "us{er"]
valid_names = ["users", "{user_id}", "user_09", "good-dog"]
invalid_names = ["/users", "users/", "users/{user_id}", "us{er", "us+er"]
valid_names = ["users", "{user_id}", "{proxy+}", "user_09", "good-dog"]
# All invalid names should throw an exception
for name in invalid_names:
with assert_raises(ClientError) as ex:
client.create_resource(restApiId=api_id, parentId=root_id, pathPart=name)
ex.exception.response["Error"]["Code"].should.equal("BadRequestException")
ex.exception.response["Error"]["Message"].should.equal(
"Resource's path part only allow a-zA-Z0-9._- and curly braces at the beginning and the end."
"Resource's path part only allow a-zA-Z0-9._- and curly braces at the beginning and the end and an optional plus sign before the closing brace."
)
# All valid names should go through
for name in valid_names:
@ -89,12 +204,7 @@ def test_create_resource():
root_resource["ResponseMetadata"].pop("HTTPHeaders", None)
root_resource["ResponseMetadata"].pop("RetryAttempts", None)
root_resource.should.equal(
{
"path": "/",
"id": root_id,
"ResponseMetadata": {"HTTPStatusCode": 200},
"resourceMethods": {"GET": {}},
}
{"path": "/", "id": root_id, "ResponseMetadata": {"HTTPStatusCode": 200},}
)
client.create_resource(restApiId=api_id, parentId=root_id, pathPart="users")
@ -142,7 +252,6 @@ def test_child_resource():
"parentId": users_id,
"id": tags_id,
"ResponseMetadata": {"HTTPStatusCode": 200},
"resourceMethods": {"GET": {}},
}
)
@ -171,6 +280,41 @@ def test_create_method():
{
"httpMethod": "GET",
"authorizationType": "none",
"apiKeyRequired": False,
"ResponseMetadata": {"HTTPStatusCode": 200},
}
)
@mock_apigateway
def test_create_method_apikeyrequired():
client = boto3.client("apigateway", region_name="us-west-2")
response = client.create_rest_api(name="my_api", description="this is my api")
api_id = response["id"]
resources = client.get_resources(restApiId=api_id)
root_id = [resource for resource in resources["items"] if resource["path"] == "/"][
0
]["id"]
client.put_method(
restApiId=api_id,
resourceId=root_id,
httpMethod="GET",
authorizationType="none",
apiKeyRequired=True,
)
response = client.get_method(restApiId=api_id, resourceId=root_id, httpMethod="GET")
# this is hard to match against, so remove it
response["ResponseMetadata"].pop("HTTPHeaders", None)
response["ResponseMetadata"].pop("RetryAttempts", None)
response.should.equal(
{
"httpMethod": "GET",
"authorizationType": "none",
"apiKeyRequired": True,
"ResponseMetadata": {"HTTPStatusCode": 200},
}
)

View file

@ -706,14 +706,14 @@ def test_create_autoscaling_group_boto3():
"ResourceId": "test_asg",
"ResourceType": "auto-scaling-group",
"Key": "propogated-tag-key",
"Value": "propogate-tag-value",
"Value": "propagate-tag-value",
"PropagateAtLaunch": True,
},
{
"ResourceId": "test_asg",
"ResourceType": "auto-scaling-group",
"Key": "not-propogated-tag-key",
"Value": "not-propogate-tag-value",
"Value": "not-propagate-tag-value",
"PropagateAtLaunch": False,
},
],
@ -744,14 +744,14 @@ def test_create_autoscaling_group_from_instance():
"ResourceId": "test_asg",
"ResourceType": "auto-scaling-group",
"Key": "propogated-tag-key",
"Value": "propogate-tag-value",
"Value": "propagate-tag-value",
"PropagateAtLaunch": True,
},
{
"ResourceId": "test_asg",
"ResourceType": "auto-scaling-group",
"Key": "not-propogated-tag-key",
"Value": "not-propogate-tag-value",
"Value": "not-propagate-tag-value",
"PropagateAtLaunch": False,
},
],
@ -1062,7 +1062,7 @@ def test_detach_one_instance_decrement():
"ResourceId": "test_asg",
"ResourceType": "auto-scaling-group",
"Key": "propogated-tag-key",
"Value": "propogate-tag-value",
"Value": "propagate-tag-value",
"PropagateAtLaunch": True,
}
],
@ -1116,7 +1116,7 @@ def test_detach_one_instance():
"ResourceId": "test_asg",
"ResourceType": "auto-scaling-group",
"Key": "propogated-tag-key",
"Value": "propogate-tag-value",
"Value": "propagate-tag-value",
"PropagateAtLaunch": True,
}
],
@ -1169,7 +1169,7 @@ def test_attach_one_instance():
"ResourceId": "test_asg",
"ResourceType": "auto-scaling-group",
"Key": "propogated-tag-key",
"Value": "propogate-tag-value",
"Value": "propagate-tag-value",
"PropagateAtLaunch": True,
}
],

View file

@ -58,8 +58,7 @@ def lambda_handler(event, context):
volume_id = event.get('volume_id')
vol = ec2.Volume(volume_id)
print('get volume details for %s\\nVolume - %s state=%s, size=%s' % (volume_id, volume_id, vol.state, vol.size))
return event
return {{'id': vol.id, 'state': vol.state, 'size': vol.size}}
""".format(
base_url="motoserver:5000"
if settings.TEST_SERVER_MODE
@ -79,7 +78,7 @@ def lambda_handler(event, context):
def get_test_zip_file4():
pfunc = """
def lambda_handler(event, context):
def lambda_handler(event, context):
raise Exception('I failed!')
"""
return _process_lambda(pfunc)
@ -87,14 +86,14 @@ def lambda_handler(event, context):
@mock_lambda
def test_list_functions():
conn = boto3.client("lambda", "us-west-2")
conn = boto3.client("lambda", _lambda_region)
result = conn.list_functions()
result["Functions"].should.have.length_of(0)
@mock_lambda
def test_invoke_requestresponse_function():
conn = boto3.client("lambda", "us-west-2")
conn = boto3.client("lambda", _lambda_region)
conn.create_function(
FunctionName="testFunction",
Runtime="python2.7",
@ -114,7 +113,44 @@ def test_invoke_requestresponse_function():
Payload=json.dumps(in_data),
)
success_result["StatusCode"].should.equal(202)
success_result["StatusCode"].should.equal(200)
result_obj = json.loads(
base64.b64decode(success_result["LogResult"]).decode("utf-8")
)
result_obj.should.equal(in_data)
payload = success_result["Payload"].read().decode("utf-8")
json.loads(payload).should.equal(in_data)
@mock_lambda
def test_invoke_requestresponse_function_with_arn():
from moto.awslambda.models import ACCOUNT_ID
conn = boto3.client("lambda", "us-west-2")
conn.create_function(
FunctionName="testFunction",
Runtime="python2.7",
Role=get_role_name(),
Handler="lambda_function.lambda_handler",
Code={"ZipFile": get_test_zip_file1()},
Description="test lambda function",
Timeout=3,
MemorySize=128,
Publish=True,
)
in_data = {"msg": "So long and thanks for all the fish"}
success_result = conn.invoke(
FunctionName="arn:aws:lambda:us-west-2:{}:function:testFunction".format(
ACCOUNT_ID
),
InvocationType="RequestResponse",
Payload=json.dumps(in_data),
)
success_result["StatusCode"].should.equal(200)
result_obj = json.loads(
base64.b64decode(success_result["LogResult"]).decode("utf-8")
)
@ -127,7 +163,7 @@ def test_invoke_requestresponse_function():
@mock_lambda
def test_invoke_event_function():
conn = boto3.client("lambda", "us-west-2")
conn = boto3.client("lambda", _lambda_region)
conn.create_function(
FunctionName="testFunction",
Runtime="python2.7",
@ -149,7 +185,35 @@ def test_invoke_event_function():
FunctionName="testFunction", InvocationType="Event", Payload=json.dumps(in_data)
)
success_result["StatusCode"].should.equal(202)
json.loads(success_result["Payload"].read().decode("utf-8")).should.equal({})
json.loads(success_result["Payload"].read().decode("utf-8")).should.equal(in_data)
@mock_lambda
def test_invoke_dryrun_function():
conn = boto3.client("lambda", _lambda_region)
conn.create_function(
FunctionName="testFunction",
Runtime="python2.7",
Role=get_role_name(),
Handler="lambda_function.lambda_handler",
Code={"ZipFile": get_test_zip_file1(),},
Description="test lambda function",
Timeout=3,
MemorySize=128,
Publish=True,
)
conn.invoke.when.called_with(
FunctionName="notAFunction", InvocationType="Event", Payload="{}"
).should.throw(botocore.client.ClientError)
in_data = {"msg": "So long and thanks for all the fish"}
success_result = conn.invoke(
FunctionName="testFunction",
InvocationType="DryRun",
Payload=json.dumps(in_data),
)
success_result["StatusCode"].should.equal(204)
if settings.TEST_SERVER_MODE:
@ -157,11 +221,11 @@ if settings.TEST_SERVER_MODE:
@mock_ec2
@mock_lambda
def test_invoke_function_get_ec2_volume():
conn = boto3.resource("ec2", "us-west-2")
vol = conn.create_volume(Size=99, AvailabilityZone="us-west-2")
conn = boto3.resource("ec2", _lambda_region)
vol = conn.create_volume(Size=99, AvailabilityZone=_lambda_region)
vol = conn.Volume(vol.id)
conn = boto3.client("lambda", "us-west-2")
conn = boto3.client("lambda", _lambda_region)
conn.create_function(
FunctionName="testFunction",
Runtime="python3.7",
@ -180,28 +244,10 @@ if settings.TEST_SERVER_MODE:
InvocationType="RequestResponse",
Payload=json.dumps(in_data),
)
result["StatusCode"].should.equal(202)
msg = "get volume details for %s\nVolume - %s state=%s, size=%s\n%s" % (
vol.id,
vol.id,
vol.state,
vol.size,
json.dumps(in_data).replace(
" ", ""
), # Makes the tests pass as the result is missing the whitespace
)
log_result = base64.b64decode(result["LogResult"]).decode("utf-8")
# The Docker lambda invocation will return an additional '\n', so need to replace it:
log_result = log_result.replace("\n\n", "\n")
log_result.should.equal(msg)
payload = result["Payload"].read().decode("utf-8")
# The Docker lambda invocation will return an additional '\n', so need to replace it:
payload = payload.replace("\n\n", "\n")
payload.should.equal(msg)
result["StatusCode"].should.equal(200)
actual_payload = json.loads(result["Payload"].read().decode("utf-8"))
expected_payload = {"id": vol.id, "state": vol.state, "size": vol.size}
actual_payload.should.equal(expected_payload)
@mock_logs
@ -209,14 +255,14 @@ if settings.TEST_SERVER_MODE:
@mock_ec2
@mock_lambda
def test_invoke_function_from_sns():
logs_conn = boto3.client("logs", region_name="us-west-2")
sns_conn = boto3.client("sns", region_name="us-west-2")
logs_conn = boto3.client("logs", region_name=_lambda_region)
sns_conn = boto3.client("sns", region_name=_lambda_region)
sns_conn.create_topic(Name="some-topic")
topics_json = sns_conn.list_topics()
topics = topics_json["Topics"]
topic_arn = topics[0]["TopicArn"]
conn = boto3.client("lambda", "us-west-2")
conn = boto3.client("lambda", _lambda_region)
result = conn.create_function(
FunctionName="testFunction",
Runtime="python2.7",
@ -259,7 +305,7 @@ def test_invoke_function_from_sns():
@mock_lambda
def test_create_based_on_s3_with_missing_bucket():
conn = boto3.client("lambda", "us-west-2")
conn = boto3.client("lambda", _lambda_region)
conn.create_function.when.called_with(
FunctionName="testFunction",
@ -279,12 +325,15 @@ def test_create_based_on_s3_with_missing_bucket():
@mock_s3
@freeze_time("2015-01-01 00:00:00")
def test_create_function_from_aws_bucket():
s3_conn = boto3.client("s3", "us-west-2")
s3_conn.create_bucket(Bucket="test-bucket")
s3_conn = boto3.client("s3", _lambda_region)
s3_conn.create_bucket(
Bucket="test-bucket",
CreateBucketConfiguration={"LocationConstraint": _lambda_region},
)
zip_content = get_test_zip_file2()
s3_conn.put_object(Bucket="test-bucket", Key="test.zip", Body=zip_content)
conn = boto3.client("lambda", "us-west-2")
conn = boto3.client("lambda", _lambda_region)
result = conn.create_function(
FunctionName="testFunction",
@ -324,6 +373,7 @@ def test_create_function_from_aws_bucket():
"VpcId": "vpc-123abc",
},
"ResponseMetadata": {"HTTPStatusCode": 201},
"State": "Active",
}
)
@ -331,7 +381,7 @@ def test_create_function_from_aws_bucket():
@mock_lambda
@freeze_time("2015-01-01 00:00:00")
def test_create_function_from_zipfile():
conn = boto3.client("lambda", "us-west-2")
conn = boto3.client("lambda", _lambda_region)
zip_content = get_test_zip_file1()
result = conn.create_function(
FunctionName="testFunction",
@ -367,6 +417,7 @@ def test_create_function_from_zipfile():
"Version": "1",
"VpcConfig": {"SecurityGroupIds": [], "SubnetIds": []},
"ResponseMetadata": {"HTTPStatusCode": 201},
"State": "Active",
}
)
@ -375,12 +426,15 @@ def test_create_function_from_zipfile():
@mock_s3
@freeze_time("2015-01-01 00:00:00")
def test_get_function():
s3_conn = boto3.client("s3", "us-west-2")
s3_conn.create_bucket(Bucket="test-bucket")
s3_conn = boto3.client("s3", _lambda_region)
s3_conn.create_bucket(
Bucket="test-bucket",
CreateBucketConfiguration={"LocationConstraint": _lambda_region},
)
zip_content = get_test_zip_file1()
s3_conn.put_object(Bucket="test-bucket", Key="test.zip", Body=zip_content)
conn = boto3.client("lambda", "us-west-2")
conn = boto3.client("lambda", _lambda_region)
conn.create_function(
FunctionName="testFunction",
@ -435,7 +489,7 @@ def test_get_function():
)
# Test get function when can't find function name
with assert_raises(ClientError):
with assert_raises(conn.exceptions.ResourceNotFoundException):
conn.get_function(FunctionName="junk", Qualifier="$LATEST")
@ -444,7 +498,10 @@ def test_get_function():
def test_get_function_by_arn():
bucket_name = "test-bucket"
s3_conn = boto3.client("s3", "us-east-1")
s3_conn.create_bucket(Bucket=bucket_name)
s3_conn.create_bucket(
Bucket=bucket_name,
CreateBucketConfiguration={"LocationConstraint": _lambda_region},
)
zip_content = get_test_zip_file2()
s3_conn.put_object(Bucket=bucket_name, Key="test.zip", Body=zip_content)
@ -469,12 +526,15 @@ def test_get_function_by_arn():
@mock_lambda
@mock_s3
def test_delete_function():
s3_conn = boto3.client("s3", "us-west-2")
s3_conn.create_bucket(Bucket="test-bucket")
s3_conn = boto3.client("s3", _lambda_region)
s3_conn.create_bucket(
Bucket="test-bucket",
CreateBucketConfiguration={"LocationConstraint": _lambda_region},
)
zip_content = get_test_zip_file2()
s3_conn.put_object(Bucket="test-bucket", Key="test.zip", Body=zip_content)
conn = boto3.client("lambda", "us-west-2")
conn = boto3.client("lambda", _lambda_region)
conn.create_function(
FunctionName="testFunction",
@ -505,7 +565,10 @@ def test_delete_function():
def test_delete_function_by_arn():
bucket_name = "test-bucket"
s3_conn = boto3.client("s3", "us-east-1")
s3_conn.create_bucket(Bucket=bucket_name)
s3_conn.create_bucket(
Bucket=bucket_name,
CreateBucketConfiguration={"LocationConstraint": _lambda_region},
)
zip_content = get_test_zip_file2()
s3_conn.put_object(Bucket=bucket_name, Key="test.zip", Body=zip_content)
@ -530,7 +593,7 @@ def test_delete_function_by_arn():
@mock_lambda
def test_delete_unknown_function():
conn = boto3.client("lambda", "us-west-2")
conn = boto3.client("lambda", _lambda_region)
conn.delete_function.when.called_with(
FunctionName="testFunctionThatDoesntExist"
).should.throw(botocore.client.ClientError)
@ -539,12 +602,15 @@ def test_delete_unknown_function():
@mock_lambda
@mock_s3
def test_publish():
s3_conn = boto3.client("s3", "us-west-2")
s3_conn.create_bucket(Bucket="test-bucket")
s3_conn = boto3.client("s3", _lambda_region)
s3_conn.create_bucket(
Bucket="test-bucket",
CreateBucketConfiguration={"LocationConstraint": _lambda_region},
)
zip_content = get_test_zip_file2()
s3_conn.put_object(Bucket="test-bucket", Key="test.zip", Body=zip_content)
conn = boto3.client("lambda", "us-west-2")
conn = boto3.client("lambda", _lambda_region)
conn.create_function(
FunctionName="testFunction",
@ -589,12 +655,15 @@ def test_list_create_list_get_delete_list():
test `list -> create -> list -> get -> delete -> list` integration
"""
s3_conn = boto3.client("s3", "us-west-2")
s3_conn.create_bucket(Bucket="test-bucket")
s3_conn = boto3.client("s3", _lambda_region)
s3_conn.create_bucket(
Bucket="test-bucket",
CreateBucketConfiguration={"LocationConstraint": _lambda_region},
)
zip_content = get_test_zip_file2()
s3_conn.put_object(Bucket="test-bucket", Key="test.zip", Body=zip_content)
conn = boto3.client("lambda", "us-west-2")
conn = boto3.client("lambda", _lambda_region)
conn.list_functions()["Functions"].should.have.length_of(0)
@ -631,6 +700,7 @@ def test_list_create_list_get_delete_list():
"Timeout": 3,
"Version": "$LATEST",
"VpcConfig": {"SecurityGroupIds": [], "SubnetIds": []},
"State": "Active",
},
"ResponseMetadata": {"HTTPStatusCode": 200},
}
@ -690,12 +760,15 @@ def test_tags():
"""
test list_tags -> tag_resource -> list_tags -> tag_resource -> list_tags -> untag_resource -> list_tags integration
"""
s3_conn = boto3.client("s3", "us-west-2")
s3_conn.create_bucket(Bucket="test-bucket")
s3_conn = boto3.client("s3", _lambda_region)
s3_conn.create_bucket(
Bucket="test-bucket",
CreateBucketConfiguration={"LocationConstraint": _lambda_region},
)
zip_content = get_test_zip_file2()
s3_conn.put_object(Bucket="test-bucket", Key="test.zip", Body=zip_content)
conn = boto3.client("lambda", "us-west-2")
conn = boto3.client("lambda", _lambda_region)
function = conn.create_function(
FunctionName="testFunction",
@ -747,7 +820,7 @@ def test_tags_not_found():
"""
Test list_tags and tag_resource when the lambda with the given arn does not exist
"""
conn = boto3.client("lambda", "us-west-2")
conn = boto3.client("lambda", _lambda_region)
conn.list_tags.when.called_with(
Resource="arn:aws:lambda:{}:function:not-found".format(ACCOUNT_ID)
).should.throw(botocore.client.ClientError)
@ -765,7 +838,7 @@ def test_tags_not_found():
@mock_lambda
def test_invoke_async_function():
conn = boto3.client("lambda", "us-west-2")
conn = boto3.client("lambda", _lambda_region)
conn.create_function(
FunctionName="testFunction",
Runtime="python2.7",
@ -788,7 +861,7 @@ def test_invoke_async_function():
@mock_lambda
@freeze_time("2015-01-01 00:00:00")
def test_get_function_created_with_zipfile():
conn = boto3.client("lambda", "us-west-2")
conn = boto3.client("lambda", _lambda_region)
zip_content = get_test_zip_file1()
result = conn.create_function(
FunctionName="testFunction",
@ -827,13 +900,14 @@ def test_get_function_created_with_zipfile():
"Timeout": 3,
"Version": "$LATEST",
"VpcConfig": {"SecurityGroupIds": [], "SubnetIds": []},
"State": "Active",
}
)
@mock_lambda
def test_add_function_permission():
conn = boto3.client("lambda", "us-west-2")
conn = boto3.client("lambda", _lambda_region)
zip_content = get_test_zip_file1()
conn.create_function(
FunctionName="testFunction",
@ -864,7 +938,7 @@ def test_add_function_permission():
@mock_lambda
def test_get_function_policy():
conn = boto3.client("lambda", "us-west-2")
conn = boto3.client("lambda", _lambda_region)
zip_content = get_test_zip_file1()
conn.create_function(
FunctionName="testFunction",
@ -899,12 +973,15 @@ def test_get_function_policy():
@mock_lambda
@mock_s3
def test_list_versions_by_function():
s3_conn = boto3.client("s3", "us-west-2")
s3_conn.create_bucket(Bucket="test-bucket")
s3_conn = boto3.client("s3", _lambda_region)
s3_conn.create_bucket(
Bucket="test-bucket",
CreateBucketConfiguration={"LocationConstraint": _lambda_region},
)
zip_content = get_test_zip_file2()
s3_conn.put_object(Bucket="test-bucket", Key="test.zip", Body=zip_content)
conn = boto3.client("lambda", "us-west-2")
conn = boto3.client("lambda", _lambda_region)
conn.create_function(
FunctionName="testFunction",
@ -955,12 +1032,15 @@ def test_list_versions_by_function():
@mock_lambda
@mock_s3
def test_create_function_with_already_exists():
s3_conn = boto3.client("s3", "us-west-2")
s3_conn.create_bucket(Bucket="test-bucket")
s3_conn = boto3.client("s3", _lambda_region)
s3_conn.create_bucket(
Bucket="test-bucket",
CreateBucketConfiguration={"LocationConstraint": _lambda_region},
)
zip_content = get_test_zip_file2()
s3_conn.put_object(Bucket="test-bucket", Key="test.zip", Body=zip_content)
conn = boto3.client("lambda", "us-west-2")
conn = boto3.client("lambda", _lambda_region)
conn.create_function(
FunctionName="testFunction",
@ -992,7 +1072,7 @@ def test_create_function_with_already_exists():
@mock_lambda
@mock_s3
def test_list_versions_by_function_for_nonexistent_function():
conn = boto3.client("lambda", "us-west-2")
conn = boto3.client("lambda", _lambda_region)
versions = conn.list_versions_by_function(FunctionName="testFunction")
assert len(versions["Versions"]) == 0
@ -1341,12 +1421,15 @@ def test_delete_event_source_mapping():
@mock_lambda
@mock_s3
def test_update_configuration():
s3_conn = boto3.client("s3", "us-west-2")
s3_conn.create_bucket(Bucket="test-bucket")
s3_conn = boto3.client("s3", _lambda_region)
s3_conn.create_bucket(
Bucket="test-bucket",
CreateBucketConfiguration={"LocationConstraint": _lambda_region},
)
zip_content = get_test_zip_file2()
s3_conn.put_object(Bucket="test-bucket", Key="test.zip", Body=zip_content)
conn = boto3.client("lambda", "us-west-2")
conn = boto3.client("lambda", _lambda_region)
fxn = conn.create_function(
FunctionName="testFunction",
@ -1389,7 +1472,7 @@ def test_update_configuration():
@mock_lambda
def test_update_function_zip():
conn = boto3.client("lambda", "us-west-2")
conn = boto3.client("lambda", _lambda_region)
zip_content_one = get_test_zip_file1()
@ -1436,6 +1519,7 @@ def test_update_function_zip():
"Timeout": 3,
"Version": "2",
"VpcConfig": {"SecurityGroupIds": [], "SubnetIds": []},
"State": "Active",
}
)
@ -1443,13 +1527,16 @@ def test_update_function_zip():
@mock_lambda
@mock_s3
def test_update_function_s3():
s3_conn = boto3.client("s3", "us-west-2")
s3_conn.create_bucket(Bucket="test-bucket")
s3_conn = boto3.client("s3", _lambda_region)
s3_conn.create_bucket(
Bucket="test-bucket",
CreateBucketConfiguration={"LocationConstraint": _lambda_region},
)
zip_content = get_test_zip_file1()
s3_conn.put_object(Bucket="test-bucket", Key="test.zip", Body=zip_content)
conn = boto3.client("lambda", "us-west-2")
conn = boto3.client("lambda", _lambda_region)
fxn = conn.create_function(
FunctionName="testFunctionS3",
@ -1498,6 +1585,7 @@ def test_update_function_s3():
"Timeout": 3,
"Version": "2",
"VpcConfig": {"SecurityGroupIds": [], "SubnetIds": []},
"State": "Active",
}
)
@ -1529,7 +1617,7 @@ def test_create_function_with_unknown_arn():
def create_invalid_lambda(role):
conn = boto3.client("lambda", "us-west-2")
conn = boto3.client("lambda", _lambda_region)
zip_content = get_test_zip_file1()
with assert_raises(ClientError) as err:
conn.create_function(
@ -1548,7 +1636,7 @@ def create_invalid_lambda(role):
def get_role_name():
with mock_iam():
iam = boto3.client("iam", region_name="us-west-2")
iam = boto3.client("iam", region_name=_lambda_region)
try:
return iam.get_role(RoleName="my-role")["Role"]["Arn"]
except ClientError:

View file

@ -94,7 +94,7 @@ def test_lambda_can_be_deleted_by_cloudformation():
# Verify function was deleted
with assert_raises(ClientError) as e:
lmbda.get_function(FunctionName=created_fn_name)
e.exception.response["Error"]["Code"].should.equal("404")
e.exception.response["Error"]["Code"].should.equal("ResourceNotFoundException")
def create_stack(cf, s3):

View file

@ -0,0 +1,49 @@
from __future__ import unicode_literals
import json
import sure
from moto.awslambda.policy import Policy
class MockLambdaFunction:
def __init__(self, arn):
self.function_arn = arn
self.policy = None
def test_policy():
policy = Policy(MockLambdaFunction("arn"))
statement = {
"StatementId": "statement0",
"Action": "lambda:InvokeFunction",
"FunctionName": "function_name",
"Principal": "events.amazonaws.com",
"SourceArn": "arn:aws:events:us-east-1:111111111111:rule/rule_name",
"SourceAccount": "111111111111",
}
expected = {
"Action": "lambda:InvokeFunction",
"FunctionName": "function_name",
"Principal": {"Service": "events.amazonaws.com"},
"Effect": "Allow",
"Resource": "arn:$LATEST",
"Sid": "statement0",
"Condition": {
"ArnLike": {
"AWS:SourceArn": "arn:aws:events:us-east-1:111111111111:rule/rule_name",
},
"StringEquals": {"AWS:SourceAccount": "111111111111"},
},
}
policy.add_statement(json.dumps(statement))
expected.should.be.equal(policy.statements[0])
sid = statement.get("StatementId", None)
if sid == None:
raise "TestCase.statement does not contain StatementId"
policy.del_statement(sid)
[].should.be.equal(policy.statements)

View file

@ -1,5 +1,5 @@
from __future__ import unicode_literals
template = {
"Resources": {"VPCEIP": {"Type": "AWS::EC2::EIP", "Properties": {"Domain": "vpc"}}}
}
from __future__ import unicode_literals
template = {
"Resources": {"VPCEIP": {"Type": "AWS::EC2::EIP", "Properties": {"Domain": "vpc"}}}
}

View file

@ -1,276 +1,276 @@
from __future__ import unicode_literals
template = {
"Description": "AWS CloudFormation Sample Template vpc_single_instance_in_subnet.template: Sample template showing how to create a VPC and add an EC2 instance with an Elastic IP address and a security group. **WARNING** This template creates an Amazon EC2 instance. You will be billed for the AWS resources used if you create a stack from this template.",
"Parameters": {
"SSHLocation": {
"ConstraintDescription": "must be a valid IP CIDR range of the form x.x.x.x/x.",
"Description": " The IP address range that can be used to SSH to the EC2 instances",
"Default": "0.0.0.0/0",
"MinLength": "9",
"AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
"MaxLength": "18",
"Type": "String",
},
"KeyName": {
"Type": "String",
"Description": "Name of an existing EC2 KeyPair to enable SSH access to the instance",
"MinLength": "1",
"AllowedPattern": "[\\x20-\\x7E]*",
"MaxLength": "255",
"ConstraintDescription": "can contain only ASCII characters.",
},
"InstanceType": {
"Default": "m1.small",
"ConstraintDescription": "must be a valid EC2 instance type.",
"Type": "String",
"Description": "WebServer EC2 instance type",
"AllowedValues": [
"t1.micro",
"m1.small",
"m1.medium",
"m1.large",
"m1.xlarge",
"m2.xlarge",
"m2.2xlarge",
"m2.4xlarge",
"m3.xlarge",
"m3.2xlarge",
"c1.medium",
"c1.xlarge",
"cc1.4xlarge",
"cc2.8xlarge",
"cg1.4xlarge",
],
},
},
"AWSTemplateFormatVersion": "2010-09-09",
"Outputs": {
"URL": {
"Description": "Newly created application URL",
"Value": {
"Fn::Join": [
"",
["http://", {"Fn::GetAtt": ["WebServerInstance", "PublicIp"]}],
]
},
}
},
"Resources": {
"Subnet": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {"Ref": "VPC"},
"CidrBlock": "10.0.0.0/24",
"Tags": [{"Value": {"Ref": "AWS::StackId"}, "Key": "Application"}],
},
},
"WebServerWaitHandle": {"Type": "AWS::CloudFormation::WaitConditionHandle"},
"Route": {
"Type": "AWS::EC2::Route",
"Properties": {
"GatewayId": {"Ref": "InternetGateway"},
"DestinationCidrBlock": "0.0.0.0/0",
"RouteTableId": {"Ref": "RouteTable"},
},
"DependsOn": "AttachGateway",
},
"SubnetRouteTableAssociation": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": {"Ref": "Subnet"},
"RouteTableId": {"Ref": "RouteTable"},
},
},
"InternetGateway": {
"Type": "AWS::EC2::InternetGateway",
"Properties": {
"Tags": [{"Value": {"Ref": "AWS::StackId"}, "Key": "Application"}]
},
},
"RouteTable": {
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": {"Ref": "VPC"},
"Tags": [{"Value": {"Ref": "AWS::StackId"}, "Key": "Application"}],
},
},
"WebServerWaitCondition": {
"Type": "AWS::CloudFormation::WaitCondition",
"Properties": {"Handle": {"Ref": "WebServerWaitHandle"}, "Timeout": "300"},
"DependsOn": "WebServerInstance",
},
"VPC": {
"Type": "AWS::EC2::VPC",
"Properties": {
"CidrBlock": "10.0.0.0/16",
"Tags": [{"Value": {"Ref": "AWS::StackId"}, "Key": "Application"}],
},
},
"InstanceSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"SecurityGroupIngress": [
{
"ToPort": "22",
"IpProtocol": "tcp",
"CidrIp": {"Ref": "SSHLocation"},
"FromPort": "22",
},
{
"ToPort": "80",
"IpProtocol": "tcp",
"CidrIp": "0.0.0.0/0",
"FromPort": "80",
},
],
"VpcId": {"Ref": "VPC"},
"GroupDescription": "Enable SSH access via port 22",
},
},
"WebServerInstance": {
"Type": "AWS::EC2::Instance",
"Properties": {
"UserData": {
"Fn::Base64": {
"Fn::Join": [
"",
[
"#!/bin/bash\n",
"yum update -y aws-cfn-bootstrap\n",
"# Helper function\n",
"function error_exit\n",
"{\n",
' /opt/aws/bin/cfn-signal -e 1 -r "$1" \'',
{"Ref": "WebServerWaitHandle"},
"'\n",
" exit 1\n",
"}\n",
"# Install the simple web page\n",
"/opt/aws/bin/cfn-init -s ",
{"Ref": "AWS::StackId"},
" -r WebServerInstance ",
" --region ",
{"Ref": "AWS::Region"},
" || error_exit 'Failed to run cfn-init'\n",
"# Start up the cfn-hup daemon to listen for changes to the Web Server metadata\n",
"/opt/aws/bin/cfn-hup || error_exit 'Failed to start cfn-hup'\n",
"# All done so signal success\n",
'/opt/aws/bin/cfn-signal -e 0 -r "WebServer setup complete" \'',
{"Ref": "WebServerWaitHandle"},
"'\n",
],
]
}
},
"Tags": [
{"Value": {"Ref": "AWS::StackId"}, "Key": "Application"},
{"Value": "Bar", "Key": "Foo"},
],
"SecurityGroupIds": [{"Ref": "InstanceSecurityGroup"}],
"KeyName": {"Ref": "KeyName"},
"SubnetId": {"Ref": "Subnet"},
"ImageId": {
"Fn::FindInMap": ["RegionMap", {"Ref": "AWS::Region"}, "AMI"]
},
"InstanceType": {"Ref": "InstanceType"},
},
"Metadata": {
"Comment": "Install a simple PHP application",
"AWS::CloudFormation::Init": {
"config": {
"files": {
"/etc/cfn/cfn-hup.conf": {
"content": {
"Fn::Join": [
"",
[
"[main]\n",
"stack=",
{"Ref": "AWS::StackId"},
"\n",
"region=",
{"Ref": "AWS::Region"},
"\n",
],
]
},
"owner": "root",
"group": "root",
"mode": "000400",
},
"/etc/cfn/hooks.d/cfn-auto-reloader.conf": {
"content": {
"Fn::Join": [
"",
[
"[cfn-auto-reloader-hook]\n",
"triggers=post.update\n",
"path=Resources.WebServerInstance.Metadata.AWS::CloudFormation::Init\n",
"action=/opt/aws/bin/cfn-init -s ",
{"Ref": "AWS::StackId"},
" -r WebServerInstance ",
" --region ",
{"Ref": "AWS::Region"},
"\n",
"runas=root\n",
],
]
}
},
"/var/www/html/index.php": {
"content": {
"Fn::Join": [
"",
[
"<?php\n",
"echo '<h1>AWS CloudFormation sample PHP application</h1>';\n",
"?>\n",
],
]
},
"owner": "apache",
"group": "apache",
"mode": "000644",
},
},
"services": {
"sysvinit": {
"httpd": {"ensureRunning": "true", "enabled": "true"},
"sendmail": {
"ensureRunning": "false",
"enabled": "false",
},
}
},
"packages": {"yum": {"httpd": [], "php": []}},
}
},
},
},
"IPAddress": {
"Type": "AWS::EC2::EIP",
"Properties": {"InstanceId": {"Ref": "WebServerInstance"}, "Domain": "vpc"},
"DependsOn": "AttachGateway",
},
"AttachGateway": {
"Type": "AWS::EC2::VPCGatewayAttachment",
"Properties": {
"VpcId": {"Ref": "VPC"},
"InternetGatewayId": {"Ref": "InternetGateway"},
},
},
},
"Mappings": {
"RegionMap": {
"ap-southeast-1": {"AMI": "ami-74dda626"},
"ap-southeast-2": {"AMI": "ami-b3990e89"},
"us-west-2": {"AMI": "ami-16fd7026"},
"us-east-1": {"AMI": "ami-7f418316"},
"ap-northeast-1": {"AMI": "ami-dcfa4edd"},
"us-west-1": {"AMI": "ami-951945d0"},
"eu-west-1": {"AMI": "ami-24506250"},
"sa-east-1": {"AMI": "ami-3e3be423"},
}
},
}
from __future__ import unicode_literals
template = {
"Description": "AWS CloudFormation Sample Template vpc_single_instance_in_subnet.template: Sample template showing how to create a VPC and add an EC2 instance with an Elastic IP address and a security group. **WARNING** This template creates an Amazon EC2 instance. You will be billed for the AWS resources used if you create a stack from this template.",
"Parameters": {
"SSHLocation": {
"ConstraintDescription": "must be a valid IP CIDR range of the form x.x.x.x/x.",
"Description": " The IP address range that can be used to SSH to the EC2 instances",
"Default": "0.0.0.0/0",
"MinLength": "9",
"AllowedPattern": "(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})\\.(\\d{1,3})/(\\d{1,2})",
"MaxLength": "18",
"Type": "String",
},
"KeyName": {
"Type": "String",
"Description": "Name of an existing EC2 KeyPair to enable SSH access to the instance",
"MinLength": "1",
"AllowedPattern": "[\\x20-\\x7E]*",
"MaxLength": "255",
"ConstraintDescription": "can contain only ASCII characters.",
},
"InstanceType": {
"Default": "m1.small",
"ConstraintDescription": "must be a valid EC2 instance type.",
"Type": "String",
"Description": "WebServer EC2 instance type",
"AllowedValues": [
"t1.micro",
"m1.small",
"m1.medium",
"m1.large",
"m1.xlarge",
"m2.xlarge",
"m2.2xlarge",
"m2.4xlarge",
"m3.xlarge",
"m3.2xlarge",
"c1.medium",
"c1.xlarge",
"cc1.4xlarge",
"cc2.8xlarge",
"cg1.4xlarge",
],
},
},
"AWSTemplateFormatVersion": "2010-09-09",
"Outputs": {
"URL": {
"Description": "Newly created application URL",
"Value": {
"Fn::Join": [
"",
["http://", {"Fn::GetAtt": ["WebServerInstance", "PublicIp"]}],
]
},
}
},
"Resources": {
"Subnet": {
"Type": "AWS::EC2::Subnet",
"Properties": {
"VpcId": {"Ref": "VPC"},
"CidrBlock": "10.0.0.0/24",
"Tags": [{"Value": {"Ref": "AWS::StackId"}, "Key": "Application"}],
},
},
"WebServerWaitHandle": {"Type": "AWS::CloudFormation::WaitConditionHandle"},
"Route": {
"Type": "AWS::EC2::Route",
"Properties": {
"GatewayId": {"Ref": "InternetGateway"},
"DestinationCidrBlock": "0.0.0.0/0",
"RouteTableId": {"Ref": "RouteTable"},
},
"DependsOn": "AttachGateway",
},
"SubnetRouteTableAssociation": {
"Type": "AWS::EC2::SubnetRouteTableAssociation",
"Properties": {
"SubnetId": {"Ref": "Subnet"},
"RouteTableId": {"Ref": "RouteTable"},
},
},
"InternetGateway": {
"Type": "AWS::EC2::InternetGateway",
"Properties": {
"Tags": [{"Value": {"Ref": "AWS::StackId"}, "Key": "Application"}]
},
},
"RouteTable": {
"Type": "AWS::EC2::RouteTable",
"Properties": {
"VpcId": {"Ref": "VPC"},
"Tags": [{"Value": {"Ref": "AWS::StackId"}, "Key": "Application"}],
},
},
"WebServerWaitCondition": {
"Type": "AWS::CloudFormation::WaitCondition",
"Properties": {"Handle": {"Ref": "WebServerWaitHandle"}, "Timeout": "300"},
"DependsOn": "WebServerInstance",
},
"VPC": {
"Type": "AWS::EC2::VPC",
"Properties": {
"CidrBlock": "10.0.0.0/16",
"Tags": [{"Value": {"Ref": "AWS::StackId"}, "Key": "Application"}],
},
},
"InstanceSecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
"SecurityGroupIngress": [
{
"ToPort": "22",
"IpProtocol": "tcp",
"CidrIp": {"Ref": "SSHLocation"},
"FromPort": "22",
},
{
"ToPort": "80",
"IpProtocol": "tcp",
"CidrIp": "0.0.0.0/0",
"FromPort": "80",
},
],
"VpcId": {"Ref": "VPC"},
"GroupDescription": "Enable SSH access via port 22",
},
},
"WebServerInstance": {
"Type": "AWS::EC2::Instance",
"Properties": {
"UserData": {
"Fn::Base64": {
"Fn::Join": [
"",
[
"#!/bin/bash\n",
"yum update -y aws-cfn-bootstrap\n",
"# Helper function\n",
"function error_exit\n",
"{\n",
' /opt/aws/bin/cfn-signal -e 1 -r "$1" \'',
{"Ref": "WebServerWaitHandle"},
"'\n",
" exit 1\n",
"}\n",
"# Install the simple web page\n",
"/opt/aws/bin/cfn-init -s ",
{"Ref": "AWS::StackId"},
" -r WebServerInstance ",
" --region ",
{"Ref": "AWS::Region"},
" || error_exit 'Failed to run cfn-init'\n",
"# Start up the cfn-hup daemon to listen for changes to the Web Server metadata\n",
"/opt/aws/bin/cfn-hup || error_exit 'Failed to start cfn-hup'\n",
"# All done so signal success\n",
'/opt/aws/bin/cfn-signal -e 0 -r "WebServer setup complete" \'',
{"Ref": "WebServerWaitHandle"},
"'\n",
],
]
}
},
"Tags": [
{"Value": {"Ref": "AWS::StackId"}, "Key": "Application"},
{"Value": "Bar", "Key": "Foo"},
],
"SecurityGroupIds": [{"Ref": "InstanceSecurityGroup"}],
"KeyName": {"Ref": "KeyName"},
"SubnetId": {"Ref": "Subnet"},
"ImageId": {
"Fn::FindInMap": ["RegionMap", {"Ref": "AWS::Region"}, "AMI"]
},
"InstanceType": {"Ref": "InstanceType"},
},
"Metadata": {
"Comment": "Install a simple PHP application",
"AWS::CloudFormation::Init": {
"config": {
"files": {
"/etc/cfn/cfn-hup.conf": {
"content": {
"Fn::Join": [
"",
[
"[main]\n",
"stack=",
{"Ref": "AWS::StackId"},
"\n",
"region=",
{"Ref": "AWS::Region"},
"\n",
],
]
},
"owner": "root",
"group": "root",
"mode": "000400",
},
"/etc/cfn/hooks.d/cfn-auto-reloader.conf": {
"content": {
"Fn::Join": [
"",
[
"[cfn-auto-reloader-hook]\n",
"triggers=post.update\n",
"path=Resources.WebServerInstance.Metadata.AWS::CloudFormation::Init\n",
"action=/opt/aws/bin/cfn-init -s ",
{"Ref": "AWS::StackId"},
" -r WebServerInstance ",
" --region ",
{"Ref": "AWS::Region"},
"\n",
"runas=root\n",
],
]
}
},
"/var/www/html/index.php": {
"content": {
"Fn::Join": [
"",
[
"<?php\n",
"echo '<h1>AWS CloudFormation sample PHP application</h1>';\n",
"?>\n",
],
]
},
"owner": "apache",
"group": "apache",
"mode": "000644",
},
},
"services": {
"sysvinit": {
"httpd": {"ensureRunning": "true", "enabled": "true"},
"sendmail": {
"ensureRunning": "false",
"enabled": "false",
},
}
},
"packages": {"yum": {"httpd": [], "php": []}},
}
},
},
},
"IPAddress": {
"Type": "AWS::EC2::EIP",
"Properties": {"InstanceId": {"Ref": "WebServerInstance"}, "Domain": "vpc"},
"DependsOn": "AttachGateway",
},
"AttachGateway": {
"Type": "AWS::EC2::VPCGatewayAttachment",
"Properties": {
"VpcId": {"Ref": "VPC"},
"InternetGatewayId": {"Ref": "InternetGateway"},
},
},
},
"Mappings": {
"RegionMap": {
"ap-southeast-1": {"AMI": "ami-74dda626"},
"ap-southeast-2": {"AMI": "ami-b3990e89"},
"us-west-2": {"AMI": "ami-16fd7026"},
"us-east-1": {"AMI": "ami-7f418316"},
"ap-northeast-1": {"AMI": "ami-dcfa4edd"},
"us-west-1": {"AMI": "ami-951945d0"},
"eu-west-1": {"AMI": "ami-24506250"},
"sa-east-1": {"AMI": "ami-3e3be423"},
}
},
}

View file

@ -143,7 +143,7 @@ def test_create_stack_with_notification_arn():
@mock_s3_deprecated
def test_create_stack_from_s3_url():
s3_conn = boto.s3.connect_to_region("us-west-1")
bucket = s3_conn.create_bucket("foobar")
bucket = s3_conn.create_bucket("foobar", location="us-west-1")
key = boto.s3.key.Key(bucket)
key.key = "template-key"
key.set_contents_from_string(dummy_template_json)

View file

@ -522,6 +522,13 @@ def test_boto3_list_stack_set_operations():
list_operation["Summaries"][-1]["Action"].should.equal("UPDATE")
@mock_cloudformation
def test_boto3_bad_list_stack_resources():
cf_conn = boto3.client("cloudformation", region_name="us-east-1")
with assert_raises(ClientError):
cf_conn.list_stack_resources(StackName="test_stack_set")
@mock_cloudformation
def test_boto3_delete_stack_set():
cf_conn = boto3.client("cloudformation", region_name="us-east-1")

View file

@ -1,117 +1,117 @@
import boto
from boto.ec2.cloudwatch.alarm import MetricAlarm
import sure # noqa
from moto import mock_cloudwatch_deprecated
def alarm_fixture(name="tester", action=None):
action = action or ["arn:alarm"]
return MetricAlarm(
name=name,
namespace="{0}_namespace".format(name),
metric="{0}_metric".format(name),
comparison=">=",
threshold=2.0,
period=60,
evaluation_periods=5,
statistic="Average",
description="A test",
dimensions={"InstanceId": ["i-0123456,i-0123457"]},
alarm_actions=action,
ok_actions=["arn:ok"],
insufficient_data_actions=["arn:insufficient"],
unit="Seconds",
)
@mock_cloudwatch_deprecated
def test_create_alarm():
conn = boto.connect_cloudwatch()
alarm = alarm_fixture()
conn.create_alarm(alarm)
alarms = conn.describe_alarms()
alarms.should.have.length_of(1)
alarm = alarms[0]
alarm.name.should.equal("tester")
alarm.namespace.should.equal("tester_namespace")
alarm.metric.should.equal("tester_metric")
alarm.comparison.should.equal(">=")
alarm.threshold.should.equal(2.0)
alarm.period.should.equal(60)
alarm.evaluation_periods.should.equal(5)
alarm.statistic.should.equal("Average")
alarm.description.should.equal("A test")
dict(alarm.dimensions).should.equal({"InstanceId": ["i-0123456,i-0123457"]})
list(alarm.alarm_actions).should.equal(["arn:alarm"])
list(alarm.ok_actions).should.equal(["arn:ok"])
list(alarm.insufficient_data_actions).should.equal(["arn:insufficient"])
alarm.unit.should.equal("Seconds")
@mock_cloudwatch_deprecated
def test_delete_alarm():
conn = boto.connect_cloudwatch()
alarms = conn.describe_alarms()
alarms.should.have.length_of(0)
alarm = alarm_fixture()
conn.create_alarm(alarm)
alarms = conn.describe_alarms()
alarms.should.have.length_of(1)
alarms[0].delete()
alarms = conn.describe_alarms()
alarms.should.have.length_of(0)
@mock_cloudwatch_deprecated
def test_put_metric_data():
conn = boto.connect_cloudwatch()
conn.put_metric_data(
namespace="tester",
name="metric",
value=1.5,
dimensions={"InstanceId": ["i-0123456,i-0123457"]},
)
metrics = conn.list_metrics()
metrics.should.have.length_of(1)
metric = metrics[0]
metric.namespace.should.equal("tester")
metric.name.should.equal("metric")
dict(metric.dimensions).should.equal({"InstanceId": ["i-0123456,i-0123457"]})
@mock_cloudwatch_deprecated
def test_describe_alarms():
conn = boto.connect_cloudwatch()
alarms = conn.describe_alarms()
alarms.should.have.length_of(0)
conn.create_alarm(alarm_fixture(name="nfoobar", action="afoobar"))
conn.create_alarm(alarm_fixture(name="nfoobaz", action="afoobaz"))
conn.create_alarm(alarm_fixture(name="nbarfoo", action="abarfoo"))
conn.create_alarm(alarm_fixture(name="nbazfoo", action="abazfoo"))
alarms = conn.describe_alarms()
alarms.should.have.length_of(4)
alarms = conn.describe_alarms(alarm_name_prefix="nfoo")
alarms.should.have.length_of(2)
alarms = conn.describe_alarms(alarm_names=["nfoobar", "nbarfoo", "nbazfoo"])
alarms.should.have.length_of(3)
alarms = conn.describe_alarms(action_prefix="afoo")
alarms.should.have.length_of(2)
for alarm in conn.describe_alarms():
alarm.delete()
alarms = conn.describe_alarms()
alarms.should.have.length_of(0)
import boto
from boto.ec2.cloudwatch.alarm import MetricAlarm
import sure # noqa
from moto import mock_cloudwatch_deprecated
def alarm_fixture(name="tester", action=None):
action = action or ["arn:alarm"]
return MetricAlarm(
name=name,
namespace="{0}_namespace".format(name),
metric="{0}_metric".format(name),
comparison=">=",
threshold=2.0,
period=60,
evaluation_periods=5,
statistic="Average",
description="A test",
dimensions={"InstanceId": ["i-0123456,i-0123457"]},
alarm_actions=action,
ok_actions=["arn:ok"],
insufficient_data_actions=["arn:insufficient"],
unit="Seconds",
)
@mock_cloudwatch_deprecated
def test_create_alarm():
conn = boto.connect_cloudwatch()
alarm = alarm_fixture()
conn.create_alarm(alarm)
alarms = conn.describe_alarms()
alarms.should.have.length_of(1)
alarm = alarms[0]
alarm.name.should.equal("tester")
alarm.namespace.should.equal("tester_namespace")
alarm.metric.should.equal("tester_metric")
alarm.comparison.should.equal(">=")
alarm.threshold.should.equal(2.0)
alarm.period.should.equal(60)
alarm.evaluation_periods.should.equal(5)
alarm.statistic.should.equal("Average")
alarm.description.should.equal("A test")
dict(alarm.dimensions).should.equal({"InstanceId": ["i-0123456,i-0123457"]})
list(alarm.alarm_actions).should.equal(["arn:alarm"])
list(alarm.ok_actions).should.equal(["arn:ok"])
list(alarm.insufficient_data_actions).should.equal(["arn:insufficient"])
alarm.unit.should.equal("Seconds")
@mock_cloudwatch_deprecated
def test_delete_alarm():
conn = boto.connect_cloudwatch()
alarms = conn.describe_alarms()
alarms.should.have.length_of(0)
alarm = alarm_fixture()
conn.create_alarm(alarm)
alarms = conn.describe_alarms()
alarms.should.have.length_of(1)
alarms[0].delete()
alarms = conn.describe_alarms()
alarms.should.have.length_of(0)
@mock_cloudwatch_deprecated
def test_put_metric_data():
conn = boto.connect_cloudwatch()
conn.put_metric_data(
namespace="tester",
name="metric",
value=1.5,
dimensions={"InstanceId": ["i-0123456,i-0123457"]},
)
metrics = conn.list_metrics()
metrics.should.have.length_of(1)
metric = metrics[0]
metric.namespace.should.equal("tester")
metric.name.should.equal("metric")
dict(metric.dimensions).should.equal({"InstanceId": ["i-0123456,i-0123457"]})
@mock_cloudwatch_deprecated
def test_describe_alarms():
conn = boto.connect_cloudwatch()
alarms = conn.describe_alarms()
alarms.should.have.length_of(0)
conn.create_alarm(alarm_fixture(name="nfoobar", action="afoobar"))
conn.create_alarm(alarm_fixture(name="nfoobaz", action="afoobaz"))
conn.create_alarm(alarm_fixture(name="nbarfoo", action="abarfoo"))
conn.create_alarm(alarm_fixture(name="nbazfoo", action="abazfoo"))
alarms = conn.describe_alarms()
alarms.should.have.length_of(4)
alarms = conn.describe_alarms(alarm_name_prefix="nfoo")
alarms.should.have.length_of(2)
alarms = conn.describe_alarms(alarm_names=["nfoobar", "nbarfoo", "nbazfoo"])
alarms.should.have.length_of(3)
alarms = conn.describe_alarms(action_prefix="afoo")
alarms.should.have.length_of(2)
for alarm in conn.describe_alarms():
alarm.delete()
alarms = conn.describe_alarms()
alarms.should.have.length_of(0)

View file

@ -27,6 +27,11 @@ def test_create_user_pool():
result["UserPool"]["Id"].should_not.be.none
result["UserPool"]["Id"].should.match(r"[\w-]+_[0-9a-zA-Z]+")
result["UserPool"]["Arn"].should.equal(
"arn:aws:cognito-idp:us-west-2:{}:userpool/{}".format(
ACCOUNT_ID, result["UserPool"]["Id"]
)
)
result["UserPool"]["Name"].should.equal(name)
result["UserPool"]["LambdaConfig"]["PreSignUp"].should.equal(value)
@ -911,6 +916,55 @@ def test_admin_create_existing_user():
caught.should.be.true
@mock_cognitoidp
def test_admin_resend_invitation_existing_user():
conn = boto3.client("cognito-idp", "us-west-2")
username = str(uuid.uuid4())
value = str(uuid.uuid4())
user_pool_id = conn.create_user_pool(PoolName=str(uuid.uuid4()))["UserPool"]["Id"]
conn.admin_create_user(
UserPoolId=user_pool_id,
Username=username,
UserAttributes=[{"Name": "thing", "Value": value}],
)
caught = False
try:
conn.admin_create_user(
UserPoolId=user_pool_id,
Username=username,
UserAttributes=[{"Name": "thing", "Value": value}],
MessageAction="RESEND",
)
except conn.exceptions.UsernameExistsException:
caught = True
caught.should.be.false
@mock_cognitoidp
def test_admin_resend_invitation_missing_user():
conn = boto3.client("cognito-idp", "us-west-2")
username = str(uuid.uuid4())
value = str(uuid.uuid4())
user_pool_id = conn.create_user_pool(PoolName=str(uuid.uuid4()))["UserPool"]["Id"]
caught = False
try:
conn.admin_create_user(
UserPoolId=user_pool_id,
Username=username,
UserAttributes=[{"Name": "thing", "Value": value}],
MessageAction="RESEND",
)
except conn.exceptions.UserNotFoundException:
caught = True
caught.should.be.true
@mock_cognitoidp
def test_admin_get_user():
conn = boto3.client("cognito-idp", "us-west-2")
@ -958,6 +1012,18 @@ def test_list_users():
result["Users"].should.have.length_of(1)
result["Users"][0]["Username"].should.equal(username)
username_bis = str(uuid.uuid4())
conn.admin_create_user(
UserPoolId=user_pool_id,
Username=username_bis,
UserAttributes=[{"Name": "phone_number", "Value": "+33666666666"}],
)
result = conn.list_users(
UserPoolId=user_pool_id, Filter='phone_number="+33666666666'
)
result["Users"].should.have.length_of(1)
result["Users"][0]["Username"].should.equal(username_bis)
@mock_cognitoidp
def test_list_users_returns_limit_items():
@ -1142,11 +1208,13 @@ def test_token_legitimacy():
id_claims = json.loads(jws.verify(id_token, json_web_key, "RS256"))
id_claims["iss"].should.equal(issuer)
id_claims["aud"].should.equal(client_id)
id_claims["token_use"].should.equal("id")
for k, v in outputs["additional_fields"].items():
id_claims[k].should.equal(v)
access_claims = json.loads(jws.verify(access_token, json_web_key, "RS256"))
access_claims["iss"].should.equal(issuer)
access_claims["aud"].should.equal(client_id)
for k, v in outputs["additional_fields"].items():
access_claims[k].should.equal(v)
access_claims["token_use"].should.equal("access")
@mock_cognitoidp

View file

@ -46,4 +46,4 @@ def test_domain_dispatched_with_service():
dispatcher = DomainDispatcherApplication(create_backend_app, service="s3")
backend_app = dispatcher.get_application({"HTTP_HOST": "s3.us-east1.amazonaws.com"})
keys = set(backend_app.view_functions.keys())
keys.should.contain("ResponseObject.key_response")
keys.should.contain("ResponseObject.key_or_control_response")

View file

@ -1,182 +1,182 @@
from __future__ import unicode_literals
import boto.datapipeline
import sure # noqa
from moto import mock_datapipeline_deprecated
from moto.datapipeline.utils import remove_capitalization_of_dict_keys
def get_value_from_fields(key, fields):
for field in fields:
if field["key"] == key:
return field["stringValue"]
@mock_datapipeline_deprecated
def test_create_pipeline():
conn = boto.datapipeline.connect_to_region("us-west-2")
res = conn.create_pipeline("mypipeline", "some-unique-id")
pipeline_id = res["pipelineId"]
pipeline_descriptions = conn.describe_pipelines([pipeline_id])[
"pipelineDescriptionList"
]
pipeline_descriptions.should.have.length_of(1)
pipeline_description = pipeline_descriptions[0]
pipeline_description["name"].should.equal("mypipeline")
pipeline_description["pipelineId"].should.equal(pipeline_id)
fields = pipeline_description["fields"]
get_value_from_fields("@pipelineState", fields).should.equal("PENDING")
get_value_from_fields("uniqueId", fields).should.equal("some-unique-id")
PIPELINE_OBJECTS = [
{
"id": "Default",
"name": "Default",
"fields": [{"key": "workerGroup", "stringValue": "workerGroup"}],
},
{
"id": "Schedule",
"name": "Schedule",
"fields": [
{"key": "startDateTime", "stringValue": "2012-12-12T00:00:00"},
{"key": "type", "stringValue": "Schedule"},
{"key": "period", "stringValue": "1 hour"},
{"key": "endDateTime", "stringValue": "2012-12-21T18:00:00"},
],
},
{
"id": "SayHello",
"name": "SayHello",
"fields": [
{"key": "type", "stringValue": "ShellCommandActivity"},
{"key": "command", "stringValue": "echo hello"},
{"key": "parent", "refValue": "Default"},
{"key": "schedule", "refValue": "Schedule"},
],
},
]
@mock_datapipeline_deprecated
def test_creating_pipeline_definition():
conn = boto.datapipeline.connect_to_region("us-west-2")
res = conn.create_pipeline("mypipeline", "some-unique-id")
pipeline_id = res["pipelineId"]
conn.put_pipeline_definition(PIPELINE_OBJECTS, pipeline_id)
pipeline_definition = conn.get_pipeline_definition(pipeline_id)
pipeline_definition["pipelineObjects"].should.have.length_of(3)
default_object = pipeline_definition["pipelineObjects"][0]
default_object["name"].should.equal("Default")
default_object["id"].should.equal("Default")
default_object["fields"].should.equal(
[{"key": "workerGroup", "stringValue": "workerGroup"}]
)
@mock_datapipeline_deprecated
def test_describing_pipeline_objects():
conn = boto.datapipeline.connect_to_region("us-west-2")
res = conn.create_pipeline("mypipeline", "some-unique-id")
pipeline_id = res["pipelineId"]
conn.put_pipeline_definition(PIPELINE_OBJECTS, pipeline_id)
objects = conn.describe_objects(["Schedule", "Default"], pipeline_id)[
"pipelineObjects"
]
objects.should.have.length_of(2)
default_object = [x for x in objects if x["id"] == "Default"][0]
default_object["name"].should.equal("Default")
default_object["fields"].should.equal(
[{"key": "workerGroup", "stringValue": "workerGroup"}]
)
@mock_datapipeline_deprecated
def test_activate_pipeline():
conn = boto.datapipeline.connect_to_region("us-west-2")
res = conn.create_pipeline("mypipeline", "some-unique-id")
pipeline_id = res["pipelineId"]
conn.activate_pipeline(pipeline_id)
pipeline_descriptions = conn.describe_pipelines([pipeline_id])[
"pipelineDescriptionList"
]
pipeline_descriptions.should.have.length_of(1)
pipeline_description = pipeline_descriptions[0]
fields = pipeline_description["fields"]
get_value_from_fields("@pipelineState", fields).should.equal("SCHEDULED")
@mock_datapipeline_deprecated
def test_delete_pipeline():
conn = boto.datapipeline.connect_to_region("us-west-2")
res = conn.create_pipeline("mypipeline", "some-unique-id")
pipeline_id = res["pipelineId"]
conn.delete_pipeline(pipeline_id)
response = conn.list_pipelines()
response["pipelineIdList"].should.have.length_of(0)
@mock_datapipeline_deprecated
def test_listing_pipelines():
conn = boto.datapipeline.connect_to_region("us-west-2")
res1 = conn.create_pipeline("mypipeline1", "some-unique-id1")
res2 = conn.create_pipeline("mypipeline2", "some-unique-id2")
response = conn.list_pipelines()
response["hasMoreResults"].should.be(False)
response["marker"].should.be.none
response["pipelineIdList"].should.have.length_of(2)
response["pipelineIdList"].should.contain(
{"id": res1["pipelineId"], "name": "mypipeline1"}
)
response["pipelineIdList"].should.contain(
{"id": res2["pipelineId"], "name": "mypipeline2"}
)
@mock_datapipeline_deprecated
def test_listing_paginated_pipelines():
conn = boto.datapipeline.connect_to_region("us-west-2")
for i in range(100):
conn.create_pipeline("mypipeline%d" % i, "some-unique-id%d" % i)
response = conn.list_pipelines()
response["hasMoreResults"].should.be(True)
response["marker"].should.equal(response["pipelineIdList"][-1]["id"])
response["pipelineIdList"].should.have.length_of(50)
# testing a helper function
def test_remove_capitalization_of_dict_keys():
result = remove_capitalization_of_dict_keys(
{
"Id": "IdValue",
"Fields": [{"Key": "KeyValue", "StringValue": "StringValueValue"}],
}
)
result.should.equal(
{
"id": "IdValue",
"fields": [{"key": "KeyValue", "stringValue": "StringValueValue"}],
}
)
from __future__ import unicode_literals
import boto.datapipeline
import sure # noqa
from moto import mock_datapipeline_deprecated
from moto.datapipeline.utils import remove_capitalization_of_dict_keys
def get_value_from_fields(key, fields):
for field in fields:
if field["key"] == key:
return field["stringValue"]
@mock_datapipeline_deprecated
def test_create_pipeline():
conn = boto.datapipeline.connect_to_region("us-west-2")
res = conn.create_pipeline("mypipeline", "some-unique-id")
pipeline_id = res["pipelineId"]
pipeline_descriptions = conn.describe_pipelines([pipeline_id])[
"pipelineDescriptionList"
]
pipeline_descriptions.should.have.length_of(1)
pipeline_description = pipeline_descriptions[0]
pipeline_description["name"].should.equal("mypipeline")
pipeline_description["pipelineId"].should.equal(pipeline_id)
fields = pipeline_description["fields"]
get_value_from_fields("@pipelineState", fields).should.equal("PENDING")
get_value_from_fields("uniqueId", fields).should.equal("some-unique-id")
PIPELINE_OBJECTS = [
{
"id": "Default",
"name": "Default",
"fields": [{"key": "workerGroup", "stringValue": "workerGroup"}],
},
{
"id": "Schedule",
"name": "Schedule",
"fields": [
{"key": "startDateTime", "stringValue": "2012-12-12T00:00:00"},
{"key": "type", "stringValue": "Schedule"},
{"key": "period", "stringValue": "1 hour"},
{"key": "endDateTime", "stringValue": "2012-12-21T18:00:00"},
],
},
{
"id": "SayHello",
"name": "SayHello",
"fields": [
{"key": "type", "stringValue": "ShellCommandActivity"},
{"key": "command", "stringValue": "echo hello"},
{"key": "parent", "refValue": "Default"},
{"key": "schedule", "refValue": "Schedule"},
],
},
]
@mock_datapipeline_deprecated
def test_creating_pipeline_definition():
conn = boto.datapipeline.connect_to_region("us-west-2")
res = conn.create_pipeline("mypipeline", "some-unique-id")
pipeline_id = res["pipelineId"]
conn.put_pipeline_definition(PIPELINE_OBJECTS, pipeline_id)
pipeline_definition = conn.get_pipeline_definition(pipeline_id)
pipeline_definition["pipelineObjects"].should.have.length_of(3)
default_object = pipeline_definition["pipelineObjects"][0]
default_object["name"].should.equal("Default")
default_object["id"].should.equal("Default")
default_object["fields"].should.equal(
[{"key": "workerGroup", "stringValue": "workerGroup"}]
)
@mock_datapipeline_deprecated
def test_describing_pipeline_objects():
conn = boto.datapipeline.connect_to_region("us-west-2")
res = conn.create_pipeline("mypipeline", "some-unique-id")
pipeline_id = res["pipelineId"]
conn.put_pipeline_definition(PIPELINE_OBJECTS, pipeline_id)
objects = conn.describe_objects(["Schedule", "Default"], pipeline_id)[
"pipelineObjects"
]
objects.should.have.length_of(2)
default_object = [x for x in objects if x["id"] == "Default"][0]
default_object["name"].should.equal("Default")
default_object["fields"].should.equal(
[{"key": "workerGroup", "stringValue": "workerGroup"}]
)
@mock_datapipeline_deprecated
def test_activate_pipeline():
conn = boto.datapipeline.connect_to_region("us-west-2")
res = conn.create_pipeline("mypipeline", "some-unique-id")
pipeline_id = res["pipelineId"]
conn.activate_pipeline(pipeline_id)
pipeline_descriptions = conn.describe_pipelines([pipeline_id])[
"pipelineDescriptionList"
]
pipeline_descriptions.should.have.length_of(1)
pipeline_description = pipeline_descriptions[0]
fields = pipeline_description["fields"]
get_value_from_fields("@pipelineState", fields).should.equal("SCHEDULED")
@mock_datapipeline_deprecated
def test_delete_pipeline():
conn = boto.datapipeline.connect_to_region("us-west-2")
res = conn.create_pipeline("mypipeline", "some-unique-id")
pipeline_id = res["pipelineId"]
conn.delete_pipeline(pipeline_id)
response = conn.list_pipelines()
response["pipelineIdList"].should.have.length_of(0)
@mock_datapipeline_deprecated
def test_listing_pipelines():
conn = boto.datapipeline.connect_to_region("us-west-2")
res1 = conn.create_pipeline("mypipeline1", "some-unique-id1")
res2 = conn.create_pipeline("mypipeline2", "some-unique-id2")
response = conn.list_pipelines()
response["hasMoreResults"].should.be(False)
response["marker"].should.be.none
response["pipelineIdList"].should.have.length_of(2)
response["pipelineIdList"].should.contain(
{"id": res1["pipelineId"], "name": "mypipeline1"}
)
response["pipelineIdList"].should.contain(
{"id": res2["pipelineId"], "name": "mypipeline2"}
)
@mock_datapipeline_deprecated
def test_listing_paginated_pipelines():
conn = boto.datapipeline.connect_to_region("us-west-2")
for i in range(100):
conn.create_pipeline("mypipeline%d" % i, "some-unique-id%d" % i)
response = conn.list_pipelines()
response["hasMoreResults"].should.be(True)
response["marker"].should.equal(response["pipelineIdList"][-1]["id"])
response["pipelineIdList"].should.have.length_of(50)
# testing a helper function
def test_remove_capitalization_of_dict_keys():
result = remove_capitalization_of_dict_keys(
{
"Id": "IdValue",
"Fields": [{"Key": "KeyValue", "StringValue": "StringValueValue"}],
}
)
result.should.equal(
{
"id": "IdValue",
"fields": [{"key": "KeyValue", "stringValue": "StringValueValue"}],
}
)

View file

@ -1,470 +1,470 @@
from __future__ import unicode_literals
import boto
import sure # noqa
from freezegun import freeze_time
from moto import mock_dynamodb_deprecated
from boto.dynamodb import condition
from boto.dynamodb.exceptions import DynamoDBKeyNotFoundError, DynamoDBValidationError
from boto.exception import DynamoDBResponseError
def create_table(conn):
message_table_schema = conn.create_schema(
hash_key_name="forum_name",
hash_key_proto_value=str,
range_key_name="subject",
range_key_proto_value=str,
)
table = conn.create_table(
name="messages", schema=message_table_schema, read_units=10, write_units=10
)
return table
@freeze_time("2012-01-14")
@mock_dynamodb_deprecated
def test_create_table():
conn = boto.connect_dynamodb()
create_table(conn)
expected = {
"Table": {
"CreationDateTime": 1326499200.0,
"ItemCount": 0,
"KeySchema": {
"HashKeyElement": {"AttributeName": "forum_name", "AttributeType": "S"},
"RangeKeyElement": {"AttributeName": "subject", "AttributeType": "S"},
},
"ProvisionedThroughput": {
"ReadCapacityUnits": 10,
"WriteCapacityUnits": 10,
},
"TableName": "messages",
"TableSizeBytes": 0,
"TableStatus": "ACTIVE",
}
}
conn.describe_table("messages").should.equal(expected)
@mock_dynamodb_deprecated
def test_delete_table():
conn = boto.connect_dynamodb()
create_table(conn)
conn.list_tables().should.have.length_of(1)
conn.layer1.delete_table("messages")
conn.list_tables().should.have.length_of(0)
conn.layer1.delete_table.when.called_with("messages").should.throw(
DynamoDBResponseError
)
@mock_dynamodb_deprecated
def test_update_table_throughput():
conn = boto.connect_dynamodb()
table = create_table(conn)
table.read_units.should.equal(10)
table.write_units.should.equal(10)
table.update_throughput(5, 6)
table.refresh()
table.read_units.should.equal(5)
table.write_units.should.equal(6)
@mock_dynamodb_deprecated
def test_item_add_and_describe_and_update():
conn = boto.connect_dynamodb()
table = create_table(conn)
item_data = {
"Body": "http://url_to_lolcat.gif",
"SentBy": "User A",
"ReceivedTime": "12/9/2011 11:36:03 PM",
}
item = table.new_item(
hash_key="LOLCat Forum", range_key="Check this out!", attrs=item_data
)
item.put()
table.has_item("LOLCat Forum", "Check this out!").should.equal(True)
returned_item = table.get_item(
hash_key="LOLCat Forum",
range_key="Check this out!",
attributes_to_get=["Body", "SentBy"],
)
dict(returned_item).should.equal(
{
"forum_name": "LOLCat Forum",
"subject": "Check this out!",
"Body": "http://url_to_lolcat.gif",
"SentBy": "User A",
}
)
item["SentBy"] = "User B"
item.put()
returned_item = table.get_item(
hash_key="LOLCat Forum",
range_key="Check this out!",
attributes_to_get=["Body", "SentBy"],
)
dict(returned_item).should.equal(
{
"forum_name": "LOLCat Forum",
"subject": "Check this out!",
"Body": "http://url_to_lolcat.gif",
"SentBy": "User B",
}
)
@mock_dynamodb_deprecated
def test_item_put_without_table():
conn = boto.connect_dynamodb()
conn.layer1.put_item.when.called_with(
table_name="undeclared-table",
item=dict(hash_key="LOLCat Forum", range_key="Check this out!"),
).should.throw(DynamoDBResponseError)
@mock_dynamodb_deprecated
def test_get_missing_item():
conn = boto.connect_dynamodb()
table = create_table(conn)
table.get_item.when.called_with(hash_key="tester", range_key="other").should.throw(
DynamoDBKeyNotFoundError
)
table.has_item("foobar", "more").should.equal(False)
@mock_dynamodb_deprecated
def test_get_item_with_undeclared_table():
conn = boto.connect_dynamodb()
conn.layer1.get_item.when.called_with(
table_name="undeclared-table",
key={"HashKeyElement": {"S": "tester"}, "RangeKeyElement": {"S": "test-range"}},
).should.throw(DynamoDBKeyNotFoundError)
@mock_dynamodb_deprecated
def test_get_item_without_range_key():
conn = boto.connect_dynamodb()
message_table_schema = conn.create_schema(
hash_key_name="test_hash",
hash_key_proto_value=int,
range_key_name="test_range",
range_key_proto_value=int,
)
table = conn.create_table(
name="messages", schema=message_table_schema, read_units=10, write_units=10
)
hash_key = 3241526475
range_key = 1234567890987
new_item = table.new_item(hash_key=hash_key, range_key=range_key)
new_item.put()
table.get_item.when.called_with(hash_key=hash_key).should.throw(
DynamoDBValidationError
)
@mock_dynamodb_deprecated
def test_delete_item():
conn = boto.connect_dynamodb()
table = create_table(conn)
item_data = {
"Body": "http://url_to_lolcat.gif",
"SentBy": "User A",
"ReceivedTime": "12/9/2011 11:36:03 PM",
}
item = table.new_item(
hash_key="LOLCat Forum", range_key="Check this out!", attrs=item_data
)
item.put()
table.refresh()
table.item_count.should.equal(1)
response = item.delete()
response.should.equal({"Attributes": [], "ConsumedCapacityUnits": 0.5})
table.refresh()
table.item_count.should.equal(0)
item.delete.when.called_with().should.throw(DynamoDBResponseError)
@mock_dynamodb_deprecated
def test_delete_item_with_attribute_response():
conn = boto.connect_dynamodb()
table = create_table(conn)
item_data = {
"Body": "http://url_to_lolcat.gif",
"SentBy": "User A",
"ReceivedTime": "12/9/2011 11:36:03 PM",
}
item = table.new_item(
hash_key="LOLCat Forum", range_key="Check this out!", attrs=item_data
)
item.put()
table.refresh()
table.item_count.should.equal(1)
response = item.delete(return_values="ALL_OLD")
response.should.equal(
{
"Attributes": {
"Body": "http://url_to_lolcat.gif",
"forum_name": "LOLCat Forum",
"ReceivedTime": "12/9/2011 11:36:03 PM",
"SentBy": "User A",
"subject": "Check this out!",
},
"ConsumedCapacityUnits": 0.5,
}
)
table.refresh()
table.item_count.should.equal(0)
item.delete.when.called_with().should.throw(DynamoDBResponseError)
@mock_dynamodb_deprecated
def test_delete_item_with_undeclared_table():
conn = boto.connect_dynamodb()
conn.layer1.delete_item.when.called_with(
table_name="undeclared-table",
key={"HashKeyElement": {"S": "tester"}, "RangeKeyElement": {"S": "test-range"}},
).should.throw(DynamoDBResponseError)
@mock_dynamodb_deprecated
def test_query():
conn = boto.connect_dynamodb()
table = create_table(conn)
item_data = {
"Body": "http://url_to_lolcat.gif",
"SentBy": "User A",
"ReceivedTime": "12/9/2011 11:36:03 PM",
}
item = table.new_item(hash_key="the-key", range_key="456", attrs=item_data)
item.put()
item = table.new_item(hash_key="the-key", range_key="123", attrs=item_data)
item.put()
item = table.new_item(hash_key="the-key", range_key="789", attrs=item_data)
item.put()
results = table.query(hash_key="the-key", range_key_condition=condition.GT("1"))
results.response["Items"].should.have.length_of(3)
results = table.query(hash_key="the-key", range_key_condition=condition.GT("234"))
results.response["Items"].should.have.length_of(2)
results = table.query(hash_key="the-key", range_key_condition=condition.GT("9999"))
results.response["Items"].should.have.length_of(0)
results = table.query(
hash_key="the-key", range_key_condition=condition.CONTAINS("12")
)
results.response["Items"].should.have.length_of(1)
results = table.query(
hash_key="the-key", range_key_condition=condition.BEGINS_WITH("7")
)
results.response["Items"].should.have.length_of(1)
results = table.query(
hash_key="the-key", range_key_condition=condition.BETWEEN("567", "890")
)
results.response["Items"].should.have.length_of(1)
@mock_dynamodb_deprecated
def test_query_with_undeclared_table():
conn = boto.connect_dynamodb()
conn.layer1.query.when.called_with(
table_name="undeclared-table",
hash_key_value={"S": "the-key"},
range_key_conditions={
"AttributeValueList": [{"S": "User B"}],
"ComparisonOperator": "EQ",
},
).should.throw(DynamoDBResponseError)
@mock_dynamodb_deprecated
def test_scan():
conn = boto.connect_dynamodb()
table = create_table(conn)
item_data = {
"Body": "http://url_to_lolcat.gif",
"SentBy": "User A",
"ReceivedTime": "12/9/2011 11:36:03 PM",
}
item = table.new_item(hash_key="the-key", range_key="456", attrs=item_data)
item.put()
item = table.new_item(hash_key="the-key", range_key="123", attrs=item_data)
item.put()
item_data = {
"Body": "http://url_to_lolcat.gif",
"SentBy": "User B",
"ReceivedTime": "12/9/2011 11:36:03 PM",
"Ids": set([1, 2, 3]),
"PK": 7,
}
item = table.new_item(hash_key="the-key", range_key="789", attrs=item_data)
item.put()
results = table.scan()
results.response["Items"].should.have.length_of(3)
results = table.scan(scan_filter={"SentBy": condition.EQ("User B")})
results.response["Items"].should.have.length_of(1)
results = table.scan(scan_filter={"Body": condition.BEGINS_WITH("http")})
results.response["Items"].should.have.length_of(3)
results = table.scan(scan_filter={"Ids": condition.CONTAINS(2)})
results.response["Items"].should.have.length_of(1)
results = table.scan(scan_filter={"Ids": condition.NOT_NULL()})
results.response["Items"].should.have.length_of(1)
results = table.scan(scan_filter={"Ids": condition.NULL()})
results.response["Items"].should.have.length_of(2)
results = table.scan(scan_filter={"PK": condition.BETWEEN(8, 9)})
results.response["Items"].should.have.length_of(0)
results = table.scan(scan_filter={"PK": condition.BETWEEN(5, 8)})
results.response["Items"].should.have.length_of(1)
@mock_dynamodb_deprecated
def test_scan_with_undeclared_table():
conn = boto.connect_dynamodb()
conn.layer1.scan.when.called_with(
table_name="undeclared-table",
scan_filter={
"SentBy": {
"AttributeValueList": [{"S": "User B"}],
"ComparisonOperator": "EQ",
}
},
).should.throw(DynamoDBResponseError)
@mock_dynamodb_deprecated
def test_scan_after_has_item():
conn = boto.connect_dynamodb()
table = create_table(conn)
list(table.scan()).should.equal([])
table.has_item(hash_key="the-key", range_key="123")
list(table.scan()).should.equal([])
@mock_dynamodb_deprecated
def test_write_batch():
conn = boto.connect_dynamodb()
table = create_table(conn)
batch_list = conn.new_batch_write_list()
items = []
items.append(
table.new_item(
hash_key="the-key",
range_key="123",
attrs={
"Body": "http://url_to_lolcat.gif",
"SentBy": "User A",
"ReceivedTime": "12/9/2011 11:36:03 PM",
},
)
)
items.append(
table.new_item(
hash_key="the-key",
range_key="789",
attrs={
"Body": "http://url_to_lolcat.gif",
"SentBy": "User B",
"ReceivedTime": "12/9/2011 11:36:03 PM",
"Ids": set([1, 2, 3]),
"PK": 7,
},
)
)
batch_list.add_batch(table, puts=items)
conn.batch_write_item(batch_list)
table.refresh()
table.item_count.should.equal(2)
batch_list = conn.new_batch_write_list()
batch_list.add_batch(table, deletes=[("the-key", "789")])
conn.batch_write_item(batch_list)
table.refresh()
table.item_count.should.equal(1)
@mock_dynamodb_deprecated
def test_batch_read():
conn = boto.connect_dynamodb()
table = create_table(conn)
item_data = {
"Body": "http://url_to_lolcat.gif",
"SentBy": "User A",
"ReceivedTime": "12/9/2011 11:36:03 PM",
}
item = table.new_item(hash_key="the-key", range_key="456", attrs=item_data)
item.put()
item = table.new_item(hash_key="the-key", range_key="123", attrs=item_data)
item.put()
item_data = {
"Body": "http://url_to_lolcat.gif",
"SentBy": "User B",
"ReceivedTime": "12/9/2011 11:36:03 PM",
"Ids": set([1, 2, 3]),
"PK": 7,
}
item = table.new_item(hash_key="another-key", range_key="789", attrs=item_data)
item.put()
items = table.batch_get_item([("the-key", "123"), ("another-key", "789")])
# Iterate through so that batch_item gets called
count = len([x for x in items])
count.should.equal(2)
from __future__ import unicode_literals
import boto
import sure # noqa
from freezegun import freeze_time
from moto import mock_dynamodb_deprecated
from boto.dynamodb import condition
from boto.dynamodb.exceptions import DynamoDBKeyNotFoundError, DynamoDBValidationError
from boto.exception import DynamoDBResponseError
def create_table(conn):
message_table_schema = conn.create_schema(
hash_key_name="forum_name",
hash_key_proto_value=str,
range_key_name="subject",
range_key_proto_value=str,
)
table = conn.create_table(
name="messages", schema=message_table_schema, read_units=10, write_units=10
)
return table
@freeze_time("2012-01-14")
@mock_dynamodb_deprecated
def test_create_table():
conn = boto.connect_dynamodb()
create_table(conn)
expected = {
"Table": {
"CreationDateTime": 1326499200.0,
"ItemCount": 0,
"KeySchema": {
"HashKeyElement": {"AttributeName": "forum_name", "AttributeType": "S"},
"RangeKeyElement": {"AttributeName": "subject", "AttributeType": "S"},
},
"ProvisionedThroughput": {
"ReadCapacityUnits": 10,
"WriteCapacityUnits": 10,
},
"TableName": "messages",
"TableSizeBytes": 0,
"TableStatus": "ACTIVE",
}
}
conn.describe_table("messages").should.equal(expected)
@mock_dynamodb_deprecated
def test_delete_table():
conn = boto.connect_dynamodb()
create_table(conn)
conn.list_tables().should.have.length_of(1)
conn.layer1.delete_table("messages")
conn.list_tables().should.have.length_of(0)
conn.layer1.delete_table.when.called_with("messages").should.throw(
DynamoDBResponseError
)
@mock_dynamodb_deprecated
def test_update_table_throughput():
conn = boto.connect_dynamodb()
table = create_table(conn)
table.read_units.should.equal(10)
table.write_units.should.equal(10)
table.update_throughput(5, 6)
table.refresh()
table.read_units.should.equal(5)
table.write_units.should.equal(6)
@mock_dynamodb_deprecated
def test_item_add_and_describe_and_update():
conn = boto.connect_dynamodb()
table = create_table(conn)
item_data = {
"Body": "http://url_to_lolcat.gif",
"SentBy": "User A",
"ReceivedTime": "12/9/2011 11:36:03 PM",
}
item = table.new_item(
hash_key="LOLCat Forum", range_key="Check this out!", attrs=item_data
)
item.put()
table.has_item("LOLCat Forum", "Check this out!").should.equal(True)
returned_item = table.get_item(
hash_key="LOLCat Forum",
range_key="Check this out!",
attributes_to_get=["Body", "SentBy"],
)
dict(returned_item).should.equal(
{
"forum_name": "LOLCat Forum",
"subject": "Check this out!",
"Body": "http://url_to_lolcat.gif",
"SentBy": "User A",
}
)
item["SentBy"] = "User B"
item.put()
returned_item = table.get_item(
hash_key="LOLCat Forum",
range_key="Check this out!",
attributes_to_get=["Body", "SentBy"],
)
dict(returned_item).should.equal(
{
"forum_name": "LOLCat Forum",
"subject": "Check this out!",
"Body": "http://url_to_lolcat.gif",
"SentBy": "User B",
}
)
@mock_dynamodb_deprecated
def test_item_put_without_table():
conn = boto.connect_dynamodb()
conn.layer1.put_item.when.called_with(
table_name="undeclared-table",
item=dict(hash_key="LOLCat Forum", range_key="Check this out!"),
).should.throw(DynamoDBResponseError)
@mock_dynamodb_deprecated
def test_get_missing_item():
conn = boto.connect_dynamodb()
table = create_table(conn)
table.get_item.when.called_with(hash_key="tester", range_key="other").should.throw(
DynamoDBKeyNotFoundError
)
table.has_item("foobar", "more").should.equal(False)
@mock_dynamodb_deprecated
def test_get_item_with_undeclared_table():
conn = boto.connect_dynamodb()
conn.layer1.get_item.when.called_with(
table_name="undeclared-table",
key={"HashKeyElement": {"S": "tester"}, "RangeKeyElement": {"S": "test-range"}},
).should.throw(DynamoDBKeyNotFoundError)
@mock_dynamodb_deprecated
def test_get_item_without_range_key():
conn = boto.connect_dynamodb()
message_table_schema = conn.create_schema(
hash_key_name="test_hash",
hash_key_proto_value=int,
range_key_name="test_range",
range_key_proto_value=int,
)
table = conn.create_table(
name="messages", schema=message_table_schema, read_units=10, write_units=10
)
hash_key = 3241526475
range_key = 1234567890987
new_item = table.new_item(hash_key=hash_key, range_key=range_key)
new_item.put()
table.get_item.when.called_with(hash_key=hash_key).should.throw(
DynamoDBValidationError
)
@mock_dynamodb_deprecated
def test_delete_item():
conn = boto.connect_dynamodb()
table = create_table(conn)
item_data = {
"Body": "http://url_to_lolcat.gif",
"SentBy": "User A",
"ReceivedTime": "12/9/2011 11:36:03 PM",
}
item = table.new_item(
hash_key="LOLCat Forum", range_key="Check this out!", attrs=item_data
)
item.put()
table.refresh()
table.item_count.should.equal(1)
response = item.delete()
response.should.equal({"Attributes": [], "ConsumedCapacityUnits": 0.5})
table.refresh()
table.item_count.should.equal(0)
item.delete.when.called_with().should.throw(DynamoDBResponseError)
@mock_dynamodb_deprecated
def test_delete_item_with_attribute_response():
conn = boto.connect_dynamodb()
table = create_table(conn)
item_data = {
"Body": "http://url_to_lolcat.gif",
"SentBy": "User A",
"ReceivedTime": "12/9/2011 11:36:03 PM",
}
item = table.new_item(
hash_key="LOLCat Forum", range_key="Check this out!", attrs=item_data
)
item.put()
table.refresh()
table.item_count.should.equal(1)
response = item.delete(return_values="ALL_OLD")
response.should.equal(
{
"Attributes": {
"Body": "http://url_to_lolcat.gif",
"forum_name": "LOLCat Forum",
"ReceivedTime": "12/9/2011 11:36:03 PM",
"SentBy": "User A",
"subject": "Check this out!",
},
"ConsumedCapacityUnits": 0.5,
}
)
table.refresh()
table.item_count.should.equal(0)
item.delete.when.called_with().should.throw(DynamoDBResponseError)
@mock_dynamodb_deprecated
def test_delete_item_with_undeclared_table():
conn = boto.connect_dynamodb()
conn.layer1.delete_item.when.called_with(
table_name="undeclared-table",
key={"HashKeyElement": {"S": "tester"}, "RangeKeyElement": {"S": "test-range"}},
).should.throw(DynamoDBResponseError)
@mock_dynamodb_deprecated
def test_query():
conn = boto.connect_dynamodb()
table = create_table(conn)
item_data = {
"Body": "http://url_to_lolcat.gif",
"SentBy": "User A",
"ReceivedTime": "12/9/2011 11:36:03 PM",
}
item = table.new_item(hash_key="the-key", range_key="456", attrs=item_data)
item.put()
item = table.new_item(hash_key="the-key", range_key="123", attrs=item_data)
item.put()
item = table.new_item(hash_key="the-key", range_key="789", attrs=item_data)
item.put()
results = table.query(hash_key="the-key", range_key_condition=condition.GT("1"))
results.response["Items"].should.have.length_of(3)
results = table.query(hash_key="the-key", range_key_condition=condition.GT("234"))
results.response["Items"].should.have.length_of(2)
results = table.query(hash_key="the-key", range_key_condition=condition.GT("9999"))
results.response["Items"].should.have.length_of(0)
results = table.query(
hash_key="the-key", range_key_condition=condition.CONTAINS("12")
)
results.response["Items"].should.have.length_of(1)
results = table.query(
hash_key="the-key", range_key_condition=condition.BEGINS_WITH("7")
)
results.response["Items"].should.have.length_of(1)
results = table.query(
hash_key="the-key", range_key_condition=condition.BETWEEN("567", "890")
)
results.response["Items"].should.have.length_of(1)
@mock_dynamodb_deprecated
def test_query_with_undeclared_table():
conn = boto.connect_dynamodb()
conn.layer1.query.when.called_with(
table_name="undeclared-table",
hash_key_value={"S": "the-key"},
range_key_conditions={
"AttributeValueList": [{"S": "User B"}],
"ComparisonOperator": "EQ",
},
).should.throw(DynamoDBResponseError)
@mock_dynamodb_deprecated
def test_scan():
conn = boto.connect_dynamodb()
table = create_table(conn)
item_data = {
"Body": "http://url_to_lolcat.gif",
"SentBy": "User A",
"ReceivedTime": "12/9/2011 11:36:03 PM",
}
item = table.new_item(hash_key="the-key", range_key="456", attrs=item_data)
item.put()
item = table.new_item(hash_key="the-key", range_key="123", attrs=item_data)
item.put()
item_data = {
"Body": "http://url_to_lolcat.gif",
"SentBy": "User B",
"ReceivedTime": "12/9/2011 11:36:03 PM",
"Ids": set([1, 2, 3]),
"PK": 7,
}
item = table.new_item(hash_key="the-key", range_key="789", attrs=item_data)
item.put()
results = table.scan()
results.response["Items"].should.have.length_of(3)
results = table.scan(scan_filter={"SentBy": condition.EQ("User B")})
results.response["Items"].should.have.length_of(1)
results = table.scan(scan_filter={"Body": condition.BEGINS_WITH("http")})
results.response["Items"].should.have.length_of(3)
results = table.scan(scan_filter={"Ids": condition.CONTAINS(2)})
results.response["Items"].should.have.length_of(1)
results = table.scan(scan_filter={"Ids": condition.NOT_NULL()})
results.response["Items"].should.have.length_of(1)
results = table.scan(scan_filter={"Ids": condition.NULL()})
results.response["Items"].should.have.length_of(2)
results = table.scan(scan_filter={"PK": condition.BETWEEN(8, 9)})
results.response["Items"].should.have.length_of(0)
results = table.scan(scan_filter={"PK": condition.BETWEEN(5, 8)})
results.response["Items"].should.have.length_of(1)
@mock_dynamodb_deprecated
def test_scan_with_undeclared_table():
conn = boto.connect_dynamodb()
conn.layer1.scan.when.called_with(
table_name="undeclared-table",
scan_filter={
"SentBy": {
"AttributeValueList": [{"S": "User B"}],
"ComparisonOperator": "EQ",
}
},
).should.throw(DynamoDBResponseError)
@mock_dynamodb_deprecated
def test_scan_after_has_item():
conn = boto.connect_dynamodb()
table = create_table(conn)
list(table.scan()).should.equal([])
table.has_item(hash_key="the-key", range_key="123")
list(table.scan()).should.equal([])
@mock_dynamodb_deprecated
def test_write_batch():
conn = boto.connect_dynamodb()
table = create_table(conn)
batch_list = conn.new_batch_write_list()
items = []
items.append(
table.new_item(
hash_key="the-key",
range_key="123",
attrs={
"Body": "http://url_to_lolcat.gif",
"SentBy": "User A",
"ReceivedTime": "12/9/2011 11:36:03 PM",
},
)
)
items.append(
table.new_item(
hash_key="the-key",
range_key="789",
attrs={
"Body": "http://url_to_lolcat.gif",
"SentBy": "User B",
"ReceivedTime": "12/9/2011 11:36:03 PM",
"Ids": set([1, 2, 3]),
"PK": 7,
},
)
)
batch_list.add_batch(table, puts=items)
conn.batch_write_item(batch_list)
table.refresh()
table.item_count.should.equal(2)
batch_list = conn.new_batch_write_list()
batch_list.add_batch(table, deletes=[("the-key", "789")])
conn.batch_write_item(batch_list)
table.refresh()
table.item_count.should.equal(1)
@mock_dynamodb_deprecated
def test_batch_read():
conn = boto.connect_dynamodb()
table = create_table(conn)
item_data = {
"Body": "http://url_to_lolcat.gif",
"SentBy": "User A",
"ReceivedTime": "12/9/2011 11:36:03 PM",
}
item = table.new_item(hash_key="the-key", range_key="456", attrs=item_data)
item.put()
item = table.new_item(hash_key="the-key", range_key="123", attrs=item_data)
item.put()
item_data = {
"Body": "http://url_to_lolcat.gif",
"SentBy": "User B",
"ReceivedTime": "12/9/2011 11:36:03 PM",
"Ids": set([1, 2, 3]),
"PK": 7,
}
item = table.new_item(hash_key="another-key", range_key="789", attrs=item_data)
item.put()
items = table.batch_get_item([("the-key", "123"), ("another-key", "789")])
# Iterate through so that batch_item gets called
count = len([x for x in items])
count.should.equal(2)

View file

@ -1,390 +1,390 @@
from __future__ import unicode_literals
import boto
import sure # noqa
from freezegun import freeze_time
from moto import mock_dynamodb_deprecated
from boto.dynamodb import condition
from boto.dynamodb.exceptions import DynamoDBKeyNotFoundError
from boto.exception import DynamoDBResponseError
def create_table(conn):
message_table_schema = conn.create_schema(
hash_key_name="forum_name", hash_key_proto_value=str
)
table = conn.create_table(
name="messages", schema=message_table_schema, read_units=10, write_units=10
)
return table
@freeze_time("2012-01-14")
@mock_dynamodb_deprecated
def test_create_table():
conn = boto.connect_dynamodb()
create_table(conn)
expected = {
"Table": {
"CreationDateTime": 1326499200.0,
"ItemCount": 0,
"KeySchema": {
"HashKeyElement": {"AttributeName": "forum_name", "AttributeType": "S"}
},
"ProvisionedThroughput": {
"ReadCapacityUnits": 10,
"WriteCapacityUnits": 10,
},
"TableName": "messages",
"TableSizeBytes": 0,
"TableStatus": "ACTIVE",
}
}
conn.describe_table("messages").should.equal(expected)
@mock_dynamodb_deprecated
def test_delete_table():
conn = boto.connect_dynamodb()
create_table(conn)
conn.list_tables().should.have.length_of(1)
conn.layer1.delete_table("messages")
conn.list_tables().should.have.length_of(0)
conn.layer1.delete_table.when.called_with("messages").should.throw(
DynamoDBResponseError
)
@mock_dynamodb_deprecated
def test_update_table_throughput():
conn = boto.connect_dynamodb()
table = create_table(conn)
table.read_units.should.equal(10)
table.write_units.should.equal(10)
table.update_throughput(5, 6)
table.refresh()
table.read_units.should.equal(5)
table.write_units.should.equal(6)
@mock_dynamodb_deprecated
def test_item_add_and_describe_and_update():
conn = boto.connect_dynamodb()
table = create_table(conn)
item_data = {
"Body": "http://url_to_lolcat.gif",
"SentBy": "User A",
"ReceivedTime": "12/9/2011 11:36:03 PM",
}
item = table.new_item(hash_key="LOLCat Forum", attrs=item_data)
item.put()
returned_item = table.get_item(
hash_key="LOLCat Forum", attributes_to_get=["Body", "SentBy"]
)
dict(returned_item).should.equal(
{
"forum_name": "LOLCat Forum",
"Body": "http://url_to_lolcat.gif",
"SentBy": "User A",
}
)
item["SentBy"] = "User B"
item.put()
returned_item = table.get_item(
hash_key="LOLCat Forum", attributes_to_get=["Body", "SentBy"]
)
dict(returned_item).should.equal(
{
"forum_name": "LOLCat Forum",
"Body": "http://url_to_lolcat.gif",
"SentBy": "User B",
}
)
@mock_dynamodb_deprecated
def test_item_put_without_table():
conn = boto.connect_dynamodb()
conn.layer1.put_item.when.called_with(
table_name="undeclared-table", item=dict(hash_key="LOLCat Forum")
).should.throw(DynamoDBResponseError)
@mock_dynamodb_deprecated
def test_get_missing_item():
conn = boto.connect_dynamodb()
table = create_table(conn)
table.get_item.when.called_with(hash_key="tester").should.throw(
DynamoDBKeyNotFoundError
)
@mock_dynamodb_deprecated
def test_get_item_with_undeclared_table():
conn = boto.connect_dynamodb()
conn.layer1.get_item.when.called_with(
table_name="undeclared-table", key={"HashKeyElement": {"S": "tester"}}
).should.throw(DynamoDBKeyNotFoundError)
@mock_dynamodb_deprecated
def test_delete_item():
conn = boto.connect_dynamodb()
table = create_table(conn)
item_data = {
"Body": "http://url_to_lolcat.gif",
"SentBy": "User A",
"ReceivedTime": "12/9/2011 11:36:03 PM",
}
item = table.new_item(hash_key="LOLCat Forum", attrs=item_data)
item.put()
table.refresh()
table.item_count.should.equal(1)
response = item.delete()
response.should.equal({"Attributes": [], "ConsumedCapacityUnits": 0.5})
table.refresh()
table.item_count.should.equal(0)
item.delete.when.called_with().should.throw(DynamoDBResponseError)
@mock_dynamodb_deprecated
def test_delete_item_with_attribute_response():
conn = boto.connect_dynamodb()
table = create_table(conn)
item_data = {
"Body": "http://url_to_lolcat.gif",
"SentBy": "User A",
"ReceivedTime": "12/9/2011 11:36:03 PM",
}
item = table.new_item(hash_key="LOLCat Forum", attrs=item_data)
item.put()
table.refresh()
table.item_count.should.equal(1)
response = item.delete(return_values="ALL_OLD")
response.should.equal(
{
"Attributes": {
"Body": "http://url_to_lolcat.gif",
"forum_name": "LOLCat Forum",
"ReceivedTime": "12/9/2011 11:36:03 PM",
"SentBy": "User A",
},
"ConsumedCapacityUnits": 0.5,
}
)
table.refresh()
table.item_count.should.equal(0)
item.delete.when.called_with().should.throw(DynamoDBResponseError)
@mock_dynamodb_deprecated
def test_delete_item_with_undeclared_table():
conn = boto.connect_dynamodb()
conn.layer1.delete_item.when.called_with(
table_name="undeclared-table", key={"HashKeyElement": {"S": "tester"}}
).should.throw(DynamoDBResponseError)
@mock_dynamodb_deprecated
def test_query():
conn = boto.connect_dynamodb()
table = create_table(conn)
item_data = {
"Body": "http://url_to_lolcat.gif",
"SentBy": "User A",
"ReceivedTime": "12/9/2011 11:36:03 PM",
}
item = table.new_item(hash_key="the-key", attrs=item_data)
item.put()
results = table.query(hash_key="the-key")
results.response["Items"].should.have.length_of(1)
@mock_dynamodb_deprecated
def test_query_with_undeclared_table():
conn = boto.connect_dynamodb()
conn.layer1.query.when.called_with(
table_name="undeclared-table", hash_key_value={"S": "the-key"}
).should.throw(DynamoDBResponseError)
@mock_dynamodb_deprecated
def test_scan():
conn = boto.connect_dynamodb()
table = create_table(conn)
item_data = {
"Body": "http://url_to_lolcat.gif",
"SentBy": "User A",
"ReceivedTime": "12/9/2011 11:36:03 PM",
}
item = table.new_item(hash_key="the-key", attrs=item_data)
item.put()
item = table.new_item(hash_key="the-key2", attrs=item_data)
item.put()
item_data = {
"Body": "http://url_to_lolcat.gif",
"SentBy": "User B",
"ReceivedTime": "12/9/2011 11:36:03 PM",
"Ids": set([1, 2, 3]),
"PK": 7,
}
item = table.new_item(hash_key="the-key3", attrs=item_data)
item.put()
results = table.scan()
results.response["Items"].should.have.length_of(3)
results = table.scan(scan_filter={"SentBy": condition.EQ("User B")})
results.response["Items"].should.have.length_of(1)
results = table.scan(scan_filter={"Body": condition.BEGINS_WITH("http")})
results.response["Items"].should.have.length_of(3)
results = table.scan(scan_filter={"Ids": condition.CONTAINS(2)})
results.response["Items"].should.have.length_of(1)
results = table.scan(scan_filter={"Ids": condition.NOT_NULL()})
results.response["Items"].should.have.length_of(1)
results = table.scan(scan_filter={"Ids": condition.NULL()})
results.response["Items"].should.have.length_of(2)
results = table.scan(scan_filter={"PK": condition.BETWEEN(8, 9)})
results.response["Items"].should.have.length_of(0)
results = table.scan(scan_filter={"PK": condition.BETWEEN(5, 8)})
results.response["Items"].should.have.length_of(1)
@mock_dynamodb_deprecated
def test_scan_with_undeclared_table():
conn = boto.connect_dynamodb()
conn.layer1.scan.when.called_with(
table_name="undeclared-table",
scan_filter={
"SentBy": {
"AttributeValueList": [{"S": "User B"}],
"ComparisonOperator": "EQ",
}
},
).should.throw(DynamoDBResponseError)
@mock_dynamodb_deprecated
def test_scan_after_has_item():
conn = boto.connect_dynamodb()
table = create_table(conn)
list(table.scan()).should.equal([])
table.has_item("the-key")
list(table.scan()).should.equal([])
@mock_dynamodb_deprecated
def test_write_batch():
conn = boto.connect_dynamodb()
table = create_table(conn)
batch_list = conn.new_batch_write_list()
items = []
items.append(
table.new_item(
hash_key="the-key",
attrs={
"Body": "http://url_to_lolcat.gif",
"SentBy": "User A",
"ReceivedTime": "12/9/2011 11:36:03 PM",
},
)
)
items.append(
table.new_item(
hash_key="the-key2",
attrs={
"Body": "http://url_to_lolcat.gif",
"SentBy": "User B",
"ReceivedTime": "12/9/2011 11:36:03 PM",
"Ids": set([1, 2, 3]),
"PK": 7,
},
)
)
batch_list.add_batch(table, puts=items)
conn.batch_write_item(batch_list)
table.refresh()
table.item_count.should.equal(2)
batch_list = conn.new_batch_write_list()
batch_list.add_batch(table, deletes=[("the-key")])
conn.batch_write_item(batch_list)
table.refresh()
table.item_count.should.equal(1)
@mock_dynamodb_deprecated
def test_batch_read():
conn = boto.connect_dynamodb()
table = create_table(conn)
item_data = {
"Body": "http://url_to_lolcat.gif",
"SentBy": "User A",
"ReceivedTime": "12/9/2011 11:36:03 PM",
}
item = table.new_item(hash_key="the-key1", attrs=item_data)
item.put()
item = table.new_item(hash_key="the-key2", attrs=item_data)
item.put()
item_data = {
"Body": "http://url_to_lolcat.gif",
"SentBy": "User B",
"ReceivedTime": "12/9/2011 11:36:03 PM",
"Ids": set([1, 2, 3]),
"PK": 7,
}
item = table.new_item(hash_key="another-key", attrs=item_data)
item.put()
items = table.batch_get_item([("the-key1"), ("another-key")])
# Iterate through so that batch_item gets called
count = len([x for x in items])
count.should.have.equal(2)
from __future__ import unicode_literals
import boto
import sure # noqa
from freezegun import freeze_time
from moto import mock_dynamodb_deprecated
from boto.dynamodb import condition
from boto.dynamodb.exceptions import DynamoDBKeyNotFoundError
from boto.exception import DynamoDBResponseError
def create_table(conn):
message_table_schema = conn.create_schema(
hash_key_name="forum_name", hash_key_proto_value=str
)
table = conn.create_table(
name="messages", schema=message_table_schema, read_units=10, write_units=10
)
return table
@freeze_time("2012-01-14")
@mock_dynamodb_deprecated
def test_create_table():
conn = boto.connect_dynamodb()
create_table(conn)
expected = {
"Table": {
"CreationDateTime": 1326499200.0,
"ItemCount": 0,
"KeySchema": {
"HashKeyElement": {"AttributeName": "forum_name", "AttributeType": "S"}
},
"ProvisionedThroughput": {
"ReadCapacityUnits": 10,
"WriteCapacityUnits": 10,
},
"TableName": "messages",
"TableSizeBytes": 0,
"TableStatus": "ACTIVE",
}
}
conn.describe_table("messages").should.equal(expected)
@mock_dynamodb_deprecated
def test_delete_table():
conn = boto.connect_dynamodb()
create_table(conn)
conn.list_tables().should.have.length_of(1)
conn.layer1.delete_table("messages")
conn.list_tables().should.have.length_of(0)
conn.layer1.delete_table.when.called_with("messages").should.throw(
DynamoDBResponseError
)
@mock_dynamodb_deprecated
def test_update_table_throughput():
conn = boto.connect_dynamodb()
table = create_table(conn)
table.read_units.should.equal(10)
table.write_units.should.equal(10)
table.update_throughput(5, 6)
table.refresh()
table.read_units.should.equal(5)
table.write_units.should.equal(6)
@mock_dynamodb_deprecated
def test_item_add_and_describe_and_update():
conn = boto.connect_dynamodb()
table = create_table(conn)
item_data = {
"Body": "http://url_to_lolcat.gif",
"SentBy": "User A",
"ReceivedTime": "12/9/2011 11:36:03 PM",
}
item = table.new_item(hash_key="LOLCat Forum", attrs=item_data)
item.put()
returned_item = table.get_item(
hash_key="LOLCat Forum", attributes_to_get=["Body", "SentBy"]
)
dict(returned_item).should.equal(
{
"forum_name": "LOLCat Forum",
"Body": "http://url_to_lolcat.gif",
"SentBy": "User A",
}
)
item["SentBy"] = "User B"
item.put()
returned_item = table.get_item(
hash_key="LOLCat Forum", attributes_to_get=["Body", "SentBy"]
)
dict(returned_item).should.equal(
{
"forum_name": "LOLCat Forum",
"Body": "http://url_to_lolcat.gif",
"SentBy": "User B",
}
)
@mock_dynamodb_deprecated
def test_item_put_without_table():
conn = boto.connect_dynamodb()
conn.layer1.put_item.when.called_with(
table_name="undeclared-table", item=dict(hash_key="LOLCat Forum")
).should.throw(DynamoDBResponseError)
@mock_dynamodb_deprecated
def test_get_missing_item():
conn = boto.connect_dynamodb()
table = create_table(conn)
table.get_item.when.called_with(hash_key="tester").should.throw(
DynamoDBKeyNotFoundError
)
@mock_dynamodb_deprecated
def test_get_item_with_undeclared_table():
conn = boto.connect_dynamodb()
conn.layer1.get_item.when.called_with(
table_name="undeclared-table", key={"HashKeyElement": {"S": "tester"}}
).should.throw(DynamoDBKeyNotFoundError)
@mock_dynamodb_deprecated
def test_delete_item():
conn = boto.connect_dynamodb()
table = create_table(conn)
item_data = {
"Body": "http://url_to_lolcat.gif",
"SentBy": "User A",
"ReceivedTime": "12/9/2011 11:36:03 PM",
}
item = table.new_item(hash_key="LOLCat Forum", attrs=item_data)
item.put()
table.refresh()
table.item_count.should.equal(1)
response = item.delete()
response.should.equal({"Attributes": [], "ConsumedCapacityUnits": 0.5})
table.refresh()
table.item_count.should.equal(0)
item.delete.when.called_with().should.throw(DynamoDBResponseError)
@mock_dynamodb_deprecated
def test_delete_item_with_attribute_response():
conn = boto.connect_dynamodb()
table = create_table(conn)
item_data = {
"Body": "http://url_to_lolcat.gif",
"SentBy": "User A",
"ReceivedTime": "12/9/2011 11:36:03 PM",
}
item = table.new_item(hash_key="LOLCat Forum", attrs=item_data)
item.put()
table.refresh()
table.item_count.should.equal(1)
response = item.delete(return_values="ALL_OLD")
response.should.equal(
{
"Attributes": {
"Body": "http://url_to_lolcat.gif",
"forum_name": "LOLCat Forum",
"ReceivedTime": "12/9/2011 11:36:03 PM",
"SentBy": "User A",
},
"ConsumedCapacityUnits": 0.5,
}
)
table.refresh()
table.item_count.should.equal(0)
item.delete.when.called_with().should.throw(DynamoDBResponseError)
@mock_dynamodb_deprecated
def test_delete_item_with_undeclared_table():
conn = boto.connect_dynamodb()
conn.layer1.delete_item.when.called_with(
table_name="undeclared-table", key={"HashKeyElement": {"S": "tester"}}
).should.throw(DynamoDBResponseError)
@mock_dynamodb_deprecated
def test_query():
conn = boto.connect_dynamodb()
table = create_table(conn)
item_data = {
"Body": "http://url_to_lolcat.gif",
"SentBy": "User A",
"ReceivedTime": "12/9/2011 11:36:03 PM",
}
item = table.new_item(hash_key="the-key", attrs=item_data)
item.put()
results = table.query(hash_key="the-key")
results.response["Items"].should.have.length_of(1)
@mock_dynamodb_deprecated
def test_query_with_undeclared_table():
conn = boto.connect_dynamodb()
conn.layer1.query.when.called_with(
table_name="undeclared-table", hash_key_value={"S": "the-key"}
).should.throw(DynamoDBResponseError)
@mock_dynamodb_deprecated
def test_scan():
conn = boto.connect_dynamodb()
table = create_table(conn)
item_data = {
"Body": "http://url_to_lolcat.gif",
"SentBy": "User A",
"ReceivedTime": "12/9/2011 11:36:03 PM",
}
item = table.new_item(hash_key="the-key", attrs=item_data)
item.put()
item = table.new_item(hash_key="the-key2", attrs=item_data)
item.put()
item_data = {
"Body": "http://url_to_lolcat.gif",
"SentBy": "User B",
"ReceivedTime": "12/9/2011 11:36:03 PM",
"Ids": set([1, 2, 3]),
"PK": 7,
}
item = table.new_item(hash_key="the-key3", attrs=item_data)
item.put()
results = table.scan()
results.response["Items"].should.have.length_of(3)
results = table.scan(scan_filter={"SentBy": condition.EQ("User B")})
results.response["Items"].should.have.length_of(1)
results = table.scan(scan_filter={"Body": condition.BEGINS_WITH("http")})
results.response["Items"].should.have.length_of(3)
results = table.scan(scan_filter={"Ids": condition.CONTAINS(2)})
results.response["Items"].should.have.length_of(1)
results = table.scan(scan_filter={"Ids": condition.NOT_NULL()})
results.response["Items"].should.have.length_of(1)
results = table.scan(scan_filter={"Ids": condition.NULL()})
results.response["Items"].should.have.length_of(2)
results = table.scan(scan_filter={"PK": condition.BETWEEN(8, 9)})
results.response["Items"].should.have.length_of(0)
results = table.scan(scan_filter={"PK": condition.BETWEEN(5, 8)})
results.response["Items"].should.have.length_of(1)
@mock_dynamodb_deprecated
def test_scan_with_undeclared_table():
conn = boto.connect_dynamodb()
conn.layer1.scan.when.called_with(
table_name="undeclared-table",
scan_filter={
"SentBy": {
"AttributeValueList": [{"S": "User B"}],
"ComparisonOperator": "EQ",
}
},
).should.throw(DynamoDBResponseError)
@mock_dynamodb_deprecated
def test_scan_after_has_item():
conn = boto.connect_dynamodb()
table = create_table(conn)
list(table.scan()).should.equal([])
table.has_item("the-key")
list(table.scan()).should.equal([])
@mock_dynamodb_deprecated
def test_write_batch():
conn = boto.connect_dynamodb()
table = create_table(conn)
batch_list = conn.new_batch_write_list()
items = []
items.append(
table.new_item(
hash_key="the-key",
attrs={
"Body": "http://url_to_lolcat.gif",
"SentBy": "User A",
"ReceivedTime": "12/9/2011 11:36:03 PM",
},
)
)
items.append(
table.new_item(
hash_key="the-key2",
attrs={
"Body": "http://url_to_lolcat.gif",
"SentBy": "User B",
"ReceivedTime": "12/9/2011 11:36:03 PM",
"Ids": set([1, 2, 3]),
"PK": 7,
},
)
)
batch_list.add_batch(table, puts=items)
conn.batch_write_item(batch_list)
table.refresh()
table.item_count.should.equal(2)
batch_list = conn.new_batch_write_list()
batch_list.add_batch(table, deletes=[("the-key")])
conn.batch_write_item(batch_list)
table.refresh()
table.item_count.should.equal(1)
@mock_dynamodb_deprecated
def test_batch_read():
conn = boto.connect_dynamodb()
table = create_table(conn)
item_data = {
"Body": "http://url_to_lolcat.gif",
"SentBy": "User A",
"ReceivedTime": "12/9/2011 11:36:03 PM",
}
item = table.new_item(hash_key="the-key1", attrs=item_data)
item.put()
item = table.new_item(hash_key="the-key2", attrs=item_data)
item.put()
item_data = {
"Body": "http://url_to_lolcat.gif",
"SentBy": "User B",
"ReceivedTime": "12/9/2011 11:36:03 PM",
"Ids": set([1, 2, 3]),
"PK": 7,
}
item = table.new_item(hash_key="another-key", attrs=item_data)
item.put()
items = table.batch_get_item([("the-key1"), ("another-key")])
# Iterate through so that batch_item gets called
count = len([x for x in items])
count.should.have.equal(2)

View file

@ -1719,6 +1719,32 @@ def test_scan_filter4():
assert response["Count"] == 0
@mock_dynamodb2
def test_scan_filter_should_not_return_non_existing_attributes():
table_name = "my-table"
item = {"partitionKey": "pk-2", "my-attr": 42}
# Create table
res = boto3.resource("dynamodb", region_name="us-east-1")
res.create_table(
TableName=table_name,
KeySchema=[{"AttributeName": "partitionKey", "KeyType": "HASH"}],
AttributeDefinitions=[{"AttributeName": "partitionKey", "AttributeType": "S"}],
BillingMode="PAY_PER_REQUEST",
)
table = res.Table(table_name)
# Insert items
table.put_item(Item={"partitionKey": "pk-1"})
table.put_item(Item=item)
# Verify a few operations
# Assert we only find the item that has this attribute
table.scan(FilterExpression=Attr("my-attr").lt(43))["Items"].should.equal([item])
table.scan(FilterExpression=Attr("my-attr").lte(42))["Items"].should.equal([item])
table.scan(FilterExpression=Attr("my-attr").gte(42))["Items"].should.equal([item])
table.scan(FilterExpression=Attr("my-attr").gt(41))["Items"].should.equal([item])
# Sanity check that we can't find the item if the FE is wrong
table.scan(FilterExpression=Attr("my-attr").gt(43))["Items"].should.equal([])
@mock_dynamodb2
def test_bad_scan_filter():
client = boto3.client("dynamodb", region_name="us-east-1")
@ -2505,6 +2531,48 @@ def test_condition_expressions():
)
@mock_dynamodb2
def test_condition_expression_numerical_attribute():
dynamodb = boto3.resource("dynamodb", region_name="us-east-1")
dynamodb.create_table(
TableName="my-table",
KeySchema=[{"AttributeName": "partitionKey", "KeyType": "HASH"}],
AttributeDefinitions=[{"AttributeName": "partitionKey", "AttributeType": "S"}],
)
table = dynamodb.Table("my-table")
table.put_item(Item={"partitionKey": "pk-pos", "myAttr": 5})
table.put_item(Item={"partitionKey": "pk-neg", "myAttr": -5})
# try to update the item we put in the table using numerical condition expression
# Specifically, verify that we can compare with a zero-value
# First verify that > and >= work on positive numbers
update_numerical_con_expr(
key="pk-pos", con_expr="myAttr > :zero", res="6", table=table
)
update_numerical_con_expr(
key="pk-pos", con_expr="myAttr >= :zero", res="7", table=table
)
# Second verify that < and <= work on negative numbers
update_numerical_con_expr(
key="pk-neg", con_expr="myAttr < :zero", res="-4", table=table
)
update_numerical_con_expr(
key="pk-neg", con_expr="myAttr <= :zero", res="-3", table=table
)
def update_numerical_con_expr(key, con_expr, res, table):
table.update_item(
Key={"partitionKey": key},
UpdateExpression="ADD myAttr :one",
ExpressionAttributeValues={":zero": 0, ":one": 1},
ConditionExpression=con_expr,
)
table.get_item(Key={"partitionKey": key})["Item"]["myAttr"].should.equal(
Decimal(res)
)
@mock_dynamodb2
def test_condition_expression__attr_doesnt_exist():
client = boto3.client("dynamodb", region_name="us-east-1")
@ -3489,6 +3557,83 @@ def test_update_supports_nested_list_append_onto_another_list():
)
@mock_dynamodb2
def test_update_supports_list_append_maps():
client = boto3.client("dynamodb", region_name="us-west-1")
client.create_table(
AttributeDefinitions=[
{"AttributeName": "id", "AttributeType": "S"},
{"AttributeName": "rid", "AttributeType": "S"},
],
TableName="TestTable",
KeySchema=[
{"AttributeName": "id", "KeyType": "HASH"},
{"AttributeName": "rid", "KeyType": "RANGE"},
],
ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5},
)
client.put_item(
TableName="TestTable",
Item={
"id": {"S": "nested_list_append"},
"rid": {"S": "range_key"},
"a": {"L": [{"M": {"b": {"S": "bar1"}}}]},
},
)
# Update item using list_append expression
client.update_item(
TableName="TestTable",
Key={"id": {"S": "nested_list_append"}, "rid": {"S": "range_key"}},
UpdateExpression="SET a = list_append(a, :i)",
ExpressionAttributeValues={":i": {"L": [{"M": {"b": {"S": "bar2"}}}]}},
)
# Verify item is appended to the existing list
result = client.query(
TableName="TestTable",
KeyConditionExpression="id = :i AND begins_with(rid, :r)",
ExpressionAttributeValues={
":i": {"S": "nested_list_append"},
":r": {"S": "range_key"},
},
)["Items"]
result.should.equal(
[
{
"a": {"L": [{"M": {"b": {"S": "bar1"}}}, {"M": {"b": {"S": "bar2"}}}]},
"rid": {"S": "range_key"},
"id": {"S": "nested_list_append"},
}
]
)
@mock_dynamodb2
def test_update_supports_list_append_with_nested_if_not_exists_operation():
dynamo = boto3.resource("dynamodb", region_name="us-west-1")
table_name = "test"
dynamo.create_table(
TableName=table_name,
AttributeDefinitions=[{"AttributeName": "Id", "AttributeType": "S"}],
KeySchema=[{"AttributeName": "Id", "KeyType": "HASH"}],
ProvisionedThroughput={"ReadCapacityUnits": 20, "WriteCapacityUnits": 20},
)
table = dynamo.Table(table_name)
table.put_item(Item={"Id": "item-id", "nest1": {"nest2": {}}})
table.update_item(
Key={"Id": "item-id"},
UpdateExpression="SET nest1.nest2.event_history = list_append(if_not_exists(nest1.nest2.event_history, :empty_list), :new_value)",
ExpressionAttributeValues={":empty_list": [], ":new_value": ["some_value"]},
)
table.get_item(Key={"Id": "item-id"})["Item"].should.equal(
{"Id": "item-id", "nest1": {"nest2": {"event_history": ["some_value"]}}}
)
@mock_dynamodb2
def test_update_catches_invalid_list_append_operation():
client = boto3.client("dynamodb", region_name="us-east-1")
@ -3601,3 +3746,24 @@ def test_allow_update_to_item_with_different_type():
table.get_item(Key={"job_id": "b"})["Item"]["job_details"][
"job_name"
].should.be.equal({"nested": "yes"})
@mock_dynamodb2
def test_query_catches_when_no_filters():
dynamo = boto3.resource("dynamodb", region_name="eu-central-1")
dynamo.create_table(
AttributeDefinitions=[{"AttributeName": "job_id", "AttributeType": "S"}],
TableName="origin-rbu-dev",
KeySchema=[{"AttributeName": "job_id", "KeyType": "HASH"}],
ProvisionedThroughput={"ReadCapacityUnits": 1, "WriteCapacityUnits": 1},
)
table = dynamo.Table("origin-rbu-dev")
with assert_raises(ClientError) as ex:
table.query(TableName="original-rbu-dev")
ex.exception.response["Error"]["Code"].should.equal("ValidationException")
ex.exception.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.exception.response["Error"]["Message"].should.equal(
"Either KeyConditions or QueryFilter should be present"
)

View file

@ -1,37 +1,37 @@
from __future__ import unicode_literals
import boto3
from moto import mock_ec2
import sure # noqa
@mock_ec2
def test_describe_account_attributes():
conn = boto3.client("ec2", region_name="us-east-1")
response = conn.describe_account_attributes()
expected_attribute_values = [
{
"AttributeValues": [{"AttributeValue": "5"}],
"AttributeName": "vpc-max-security-groups-per-interface",
},
{
"AttributeValues": [{"AttributeValue": "20"}],
"AttributeName": "max-instances",
},
{
"AttributeValues": [{"AttributeValue": "EC2"}, {"AttributeValue": "VPC"}],
"AttributeName": "supported-platforms",
},
{
"AttributeValues": [{"AttributeValue": "none"}],
"AttributeName": "default-vpc",
},
{
"AttributeValues": [{"AttributeValue": "5"}],
"AttributeName": "max-elastic-ips",
},
{
"AttributeValues": [{"AttributeValue": "5"}],
"AttributeName": "vpc-max-elastic-ips",
},
]
response["AccountAttributes"].should.equal(expected_attribute_values)
from __future__ import unicode_literals
import boto3
from moto import mock_ec2
import sure # noqa
@mock_ec2
def test_describe_account_attributes():
conn = boto3.client("ec2", region_name="us-east-1")
response = conn.describe_account_attributes()
expected_attribute_values = [
{
"AttributeValues": [{"AttributeValue": "5"}],
"AttributeName": "vpc-max-security-groups-per-interface",
},
{
"AttributeValues": [{"AttributeValue": "20"}],
"AttributeName": "max-instances",
},
{
"AttributeValues": [{"AttributeValue": "EC2"}, {"AttributeValue": "VPC"}],
"AttributeName": "supported-platforms",
},
{
"AttributeValues": [{"AttributeValue": "none"}],
"AttributeName": "default-vpc",
},
{
"AttributeValues": [{"AttributeValue": "5"}],
"AttributeName": "max-elastic-ips",
},
{
"AttributeValues": [{"AttributeValue": "5"}],
"AttributeName": "vpc-max-elastic-ips",
},
]
response["AccountAttributes"].should.equal(expected_attribute_values)

View file

@ -1,10 +1,10 @@
from __future__ import unicode_literals
import boto
import sure # noqa
from moto import mock_ec2
@mock_ec2
def test_amazon_dev_pay():
pass
from __future__ import unicode_literals
import boto
import sure # noqa
from moto import mock_ec2
@mock_ec2
def test_amazon_dev_pay():
pass

View file

@ -12,6 +12,7 @@ import sure # noqa
from moto import mock_ec2_deprecated, mock_ec2
from moto.ec2.models import AMIS, OWNER_ID
from moto.iam.models import ACCOUNT_ID
from tests.helpers import requires_boto_gte
@ -251,6 +252,19 @@ def test_ami_pulls_attributes_from_instance():
image.kernel_id.should.equal("test-kernel")
@mock_ec2_deprecated
def test_ami_uses_account_id_if_valid_access_key_is_supplied():
access_key = "AKIAXXXXXXXXXXXXXXXX"
conn = boto.connect_ec2(access_key, "the_secret")
reservation = conn.run_instances("ami-1234abcd")
instance = reservation.instances[0]
instance.modify_attribute("kernel", "test-kernel")
image_id = conn.create_image(instance.id, "test-ami", "this is a test ami")
images = conn.get_all_images(owners=["self"])
[(ami.id, ami.owner_id) for ami in images].should.equal([(image_id, ACCOUNT_ID)])
@mock_ec2_deprecated
def test_ami_filters():
conn = boto.connect_ec2("the_key", "the_secret")
@ -773,7 +787,7 @@ def test_ami_filter_wildcard():
instance.create_image(Name="not-matching-image")
my_images = ec2_client.describe_images(
Owners=["111122223333"], Filters=[{"Name": "name", "Values": ["test*"]}]
Owners=[ACCOUNT_ID], Filters=[{"Name": "name", "Values": ["test*"]}]
)["Images"]
my_images.should.have.length_of(1)

View file

@ -1 +1 @@
from __future__ import unicode_literals
from __future__ import unicode_literals

View file

@ -1,10 +1,10 @@
from __future__ import unicode_literals
import boto
import sure # noqa
from moto import mock_ec2
@mock_ec2
def test_ip_addresses():
pass
from __future__ import unicode_literals
import boto
import sure # noqa
from moto import mock_ec2
@mock_ec2
def test_ip_addresses():
pass

View file

@ -1,10 +1,10 @@
from __future__ import unicode_literals
import boto
import sure # noqa
from moto import mock_ec2
@mock_ec2
def test_monitoring():
pass
from __future__ import unicode_literals
import boto
import sure # noqa
from moto import mock_ec2
@mock_ec2
def test_monitoring():
pass

View file

@ -1,10 +1,10 @@
from __future__ import unicode_literals
import boto
import sure # noqa
from moto import mock_ec2
@mock_ec2
def test_placement_groups():
pass
from __future__ import unicode_literals
import boto
import sure # noqa
from moto import mock_ec2
@mock_ec2
def test_placement_groups():
pass

View file

@ -1,10 +1,10 @@
from __future__ import unicode_literals
import boto
import sure # noqa
from moto import mock_ec2
@mock_ec2
def test_reserved_instances():
pass
from __future__ import unicode_literals
import boto
import sure # noqa
from moto import mock_ec2
@mock_ec2
def test_reserved_instances():
pass

View file

@ -236,8 +236,8 @@ def test_route_table_associations():
@mock_ec2_deprecated
def test_route_table_replace_route_table_association():
"""
Note: Boto has deprecated replace_route_table_assocation (which returns status)
and now uses replace_route_table_assocation_with_assoc (which returns association ID).
Note: Boto has deprecated replace_route_table_association (which returns status)
and now uses replace_route_table_association_with_assoc (which returns association ID).
"""
conn = boto.connect_vpc("the_key", "the_secret")
vpc = conn.create_vpc("10.0.0.0/16")

View file

@ -1,96 +1,96 @@
from __future__ import unicode_literals
import boto
import sure # noqa
from moto import mock_ec2_deprecated
@mock_ec2_deprecated
def test_virtual_private_gateways():
conn = boto.connect_vpc("the_key", "the_secret")
vpn_gateway = conn.create_vpn_gateway("ipsec.1", "us-east-1a")
vpn_gateway.should_not.be.none
vpn_gateway.id.should.match(r"vgw-\w+")
vpn_gateway.type.should.equal("ipsec.1")
vpn_gateway.state.should.equal("available")
vpn_gateway.availability_zone.should.equal("us-east-1a")
@mock_ec2_deprecated
def test_describe_vpn_gateway():
conn = boto.connect_vpc("the_key", "the_secret")
vpn_gateway = conn.create_vpn_gateway("ipsec.1", "us-east-1a")
vgws = conn.get_all_vpn_gateways()
vgws.should.have.length_of(1)
gateway = vgws[0]
gateway.id.should.match(r"vgw-\w+")
gateway.id.should.equal(vpn_gateway.id)
vpn_gateway.type.should.equal("ipsec.1")
vpn_gateway.state.should.equal("available")
vpn_gateway.availability_zone.should.equal("us-east-1a")
@mock_ec2_deprecated
def test_vpn_gateway_vpc_attachment():
conn = boto.connect_vpc("the_key", "the_secret")
vpc = conn.create_vpc("10.0.0.0/16")
vpn_gateway = conn.create_vpn_gateway("ipsec.1", "us-east-1a")
conn.attach_vpn_gateway(vpn_gateway_id=vpn_gateway.id, vpc_id=vpc.id)
gateway = conn.get_all_vpn_gateways()[0]
attachments = gateway.attachments
attachments.should.have.length_of(1)
attachments[0].vpc_id.should.equal(vpc.id)
attachments[0].state.should.equal("attached")
@mock_ec2_deprecated
def test_delete_vpn_gateway():
conn = boto.connect_vpc("the_key", "the_secret")
vpn_gateway = conn.create_vpn_gateway("ipsec.1", "us-east-1a")
conn.delete_vpn_gateway(vpn_gateway.id)
vgws = conn.get_all_vpn_gateways()
vgws.should.have.length_of(0)
@mock_ec2_deprecated
def test_vpn_gateway_tagging():
conn = boto.connect_vpc("the_key", "the_secret")
vpn_gateway = conn.create_vpn_gateway("ipsec.1", "us-east-1a")
vpn_gateway.add_tag("a key", "some value")
tag = conn.get_all_tags()[0]
tag.name.should.equal("a key")
tag.value.should.equal("some value")
# Refresh the subnet
vpn_gateway = conn.get_all_vpn_gateways()[0]
vpn_gateway.tags.should.have.length_of(1)
vpn_gateway.tags["a key"].should.equal("some value")
@mock_ec2_deprecated
def test_detach_vpn_gateway():
conn = boto.connect_vpc("the_key", "the_secret")
vpc = conn.create_vpc("10.0.0.0/16")
vpn_gateway = conn.create_vpn_gateway("ipsec.1", "us-east-1a")
conn.attach_vpn_gateway(vpn_gateway_id=vpn_gateway.id, vpc_id=vpc.id)
gateway = conn.get_all_vpn_gateways()[0]
attachments = gateway.attachments
attachments.should.have.length_of(1)
attachments[0].vpc_id.should.equal(vpc.id)
attachments[0].state.should.equal("attached")
conn.detach_vpn_gateway(vpn_gateway_id=vpn_gateway.id, vpc_id=vpc.id)
gateway = conn.get_all_vpn_gateways()[0]
attachments = gateway.attachments
attachments.should.have.length_of(0)
from __future__ import unicode_literals
import boto
import sure # noqa
from moto import mock_ec2_deprecated
@mock_ec2_deprecated
def test_virtual_private_gateways():
conn = boto.connect_vpc("the_key", "the_secret")
vpn_gateway = conn.create_vpn_gateway("ipsec.1", "us-east-1a")
vpn_gateway.should_not.be.none
vpn_gateway.id.should.match(r"vgw-\w+")
vpn_gateway.type.should.equal("ipsec.1")
vpn_gateway.state.should.equal("available")
vpn_gateway.availability_zone.should.equal("us-east-1a")
@mock_ec2_deprecated
def test_describe_vpn_gateway():
conn = boto.connect_vpc("the_key", "the_secret")
vpn_gateway = conn.create_vpn_gateway("ipsec.1", "us-east-1a")
vgws = conn.get_all_vpn_gateways()
vgws.should.have.length_of(1)
gateway = vgws[0]
gateway.id.should.match(r"vgw-\w+")
gateway.id.should.equal(vpn_gateway.id)
vpn_gateway.type.should.equal("ipsec.1")
vpn_gateway.state.should.equal("available")
vpn_gateway.availability_zone.should.equal("us-east-1a")
@mock_ec2_deprecated
def test_vpn_gateway_vpc_attachment():
conn = boto.connect_vpc("the_key", "the_secret")
vpc = conn.create_vpc("10.0.0.0/16")
vpn_gateway = conn.create_vpn_gateway("ipsec.1", "us-east-1a")
conn.attach_vpn_gateway(vpn_gateway_id=vpn_gateway.id, vpc_id=vpc.id)
gateway = conn.get_all_vpn_gateways()[0]
attachments = gateway.attachments
attachments.should.have.length_of(1)
attachments[0].vpc_id.should.equal(vpc.id)
attachments[0].state.should.equal("attached")
@mock_ec2_deprecated
def test_delete_vpn_gateway():
conn = boto.connect_vpc("the_key", "the_secret")
vpn_gateway = conn.create_vpn_gateway("ipsec.1", "us-east-1a")
conn.delete_vpn_gateway(vpn_gateway.id)
vgws = conn.get_all_vpn_gateways()
vgws.should.have.length_of(0)
@mock_ec2_deprecated
def test_vpn_gateway_tagging():
conn = boto.connect_vpc("the_key", "the_secret")
vpn_gateway = conn.create_vpn_gateway("ipsec.1", "us-east-1a")
vpn_gateway.add_tag("a key", "some value")
tag = conn.get_all_tags()[0]
tag.name.should.equal("a key")
tag.value.should.equal("some value")
# Refresh the subnet
vpn_gateway = conn.get_all_vpn_gateways()[0]
vpn_gateway.tags.should.have.length_of(1)
vpn_gateway.tags["a key"].should.equal("some value")
@mock_ec2_deprecated
def test_detach_vpn_gateway():
conn = boto.connect_vpc("the_key", "the_secret")
vpc = conn.create_vpc("10.0.0.0/16")
vpn_gateway = conn.create_vpn_gateway("ipsec.1", "us-east-1a")
conn.attach_vpn_gateway(vpn_gateway_id=vpn_gateway.id, vpc_id=vpc.id)
gateway = conn.get_all_vpn_gateways()[0]
attachments = gateway.attachments
attachments.should.have.length_of(1)
attachments[0].vpc_id.should.equal(vpc.id)
attachments[0].state.should.equal("attached")
conn.detach_vpn_gateway(vpn_gateway_id=vpn_gateway.id, vpc_id=vpc.id)
gateway = conn.get_all_vpn_gateways()[0]
attachments = gateway.attachments
attachments.should.have.length_of(0)

View file

@ -1,10 +1,10 @@
from __future__ import unicode_literals
import boto
import sure # noqa
from moto import mock_ec2
@mock_ec2
def test_vm_export():
pass
from __future__ import unicode_literals
import boto
import sure # noqa
from moto import mock_ec2
@mock_ec2
def test_vm_export():
pass

View file

@ -1,10 +1,10 @@
from __future__ import unicode_literals
import boto
import sure # noqa
from moto import mock_ec2
@mock_ec2
def test_vm_import():
pass
from __future__ import unicode_literals
import boto
import sure # noqa
from moto import mock_ec2
@mock_ec2
def test_vm_import():
pass

View file

@ -1,10 +1,10 @@
from __future__ import unicode_literals
import boto
import sure # noqa
from moto import mock_ec2
@mock_ec2
def test_windows():
pass
from __future__ import unicode_literals
import boto
import sure # noqa
from moto import mock_ec2
@mock_ec2
def test_windows():
pass

View file

@ -77,7 +77,7 @@ def test_describe_repositories():
response = client.describe_repositories()
len(response["repositories"]).should.equal(2)
respository_arns = [
repository_arns = [
"arn:aws:ecr:us-east-1:012345678910:repository/test_repository1",
"arn:aws:ecr:us-east-1:012345678910:repository/test_repository0",
]
@ -86,9 +86,9 @@ def test_describe_repositories():
response["repositories"][0]["repositoryArn"],
response["repositories"][1]["repositoryArn"],
]
).should.equal(set(respository_arns))
).should.equal(set(repository_arns))
respository_uris = [
repository_uris = [
"012345678910.dkr.ecr.us-east-1.amazonaws.com/test_repository1",
"012345678910.dkr.ecr.us-east-1.amazonaws.com/test_repository0",
]
@ -97,7 +97,7 @@ def test_describe_repositories():
response["repositories"][0]["repositoryUri"],
response["repositories"][1]["repositoryUri"],
]
).should.equal(set(respository_uris))
).should.equal(set(repository_uris))
@mock_ecr
@ -108,7 +108,7 @@ def test_describe_repositories_1():
response = client.describe_repositories(registryId="012345678910")
len(response["repositories"]).should.equal(2)
respository_arns = [
repository_arns = [
"arn:aws:ecr:us-east-1:012345678910:repository/test_repository1",
"arn:aws:ecr:us-east-1:012345678910:repository/test_repository0",
]
@ -117,9 +117,9 @@ def test_describe_repositories_1():
response["repositories"][0]["repositoryArn"],
response["repositories"][1]["repositoryArn"],
]
).should.equal(set(respository_arns))
).should.equal(set(repository_arns))
respository_uris = [
repository_uris = [
"012345678910.dkr.ecr.us-east-1.amazonaws.com/test_repository1",
"012345678910.dkr.ecr.us-east-1.amazonaws.com/test_repository0",
]
@ -128,7 +128,7 @@ def test_describe_repositories_1():
response["repositories"][0]["repositoryUri"],
response["repositories"][1]["repositoryUri"],
]
).should.equal(set(respository_uris))
).should.equal(set(repository_uris))
@mock_ecr
@ -147,11 +147,11 @@ def test_describe_repositories_3():
_ = client.create_repository(repositoryName="test_repository0")
response = client.describe_repositories(repositoryNames=["test_repository1"])
len(response["repositories"]).should.equal(1)
respository_arn = "arn:aws:ecr:us-east-1:012345678910:repository/test_repository1"
response["repositories"][0]["repositoryArn"].should.equal(respository_arn)
repository_arn = "arn:aws:ecr:us-east-1:012345678910:repository/test_repository1"
response["repositories"][0]["repositoryArn"].should.equal(repository_arn)
respository_uri = "012345678910.dkr.ecr.us-east-1.amazonaws.com/test_repository1"
response["repositories"][0]["repositoryUri"].should.equal(respository_uri)
repository_uri = "012345678910.dkr.ecr.us-east-1.amazonaws.com/test_repository1"
response["repositories"][0]["repositoryUri"].should.equal(repository_uri)
@mock_ecr

View file

@ -94,6 +94,7 @@ def test_register_task_definition():
"logConfiguration": {"logDriver": "json-file"},
}
],
networkMode="bridge",
tags=[
{"key": "createdBy", "value": "moto-unittest"},
{"key": "foo", "value": "bar"},
@ -124,6 +125,7 @@ def test_register_task_definition():
response["taskDefinition"]["containerDefinitions"][0]["logConfiguration"][
"logDriver"
].should.equal("json-file")
response["taskDefinition"]["networkMode"].should.equal("bridge")
@mock_ecs
@ -724,7 +726,7 @@ def test_delete_service():
@mock_ecs
def test_update_non_existant_service():
def test_update_non_existent_service():
client = boto3.client("ecs", region_name="us-east-1")
try:
client.update_service(

View file

@ -1391,7 +1391,7 @@ def test_set_security_groups():
len(resp["LoadBalancers"][0]["SecurityGroups"]).should.equal(2)
with assert_raises(ClientError):
client.set_security_groups(LoadBalancerArn=arn, SecurityGroups=["non_existant"])
client.set_security_groups(LoadBalancerArn=arn, SecurityGroups=["non_existent"])
@mock_elbv2

View file

@ -1,14 +1,18 @@
import random
import boto3
import json
import sure # noqa
from moto.events.models import EventsBackend
from moto.events import mock_events
import json
import random
import unittest
import boto3
from botocore.exceptions import ClientError
from moto.core.exceptions import JsonRESTError
from nose.tools import assert_raises
from moto.core import ACCOUNT_ID
from moto.events.models import EventsBackend
<< << << < HEAD
== == == =
>>>>>> > 100dbd529f174f18d579a1dcc066d55409f2e38f
RULES = [
{"Name": "test1", "ScheduleExpression": "rate(5 minutes)"},
@ -456,6 +460,11 @@ def test_delete_event_bus_errors():
ClientError, "Cannot delete event bus default."
)
<< << << < HEAD
== == == =
>>>>>> > 100dbd529f174f18d579a1dcc066d55409f2e38f
@mock_events
def test_rule_tagging_happy():
client = generate_environment()
@ -466,7 +475,12 @@ def test_rule_tagging_happy():
client.tag_resource(ResourceARN=rule_arn, Tags=tags)
actual = client.list_tags_for_resource(ResourceARN=rule_arn).get("Tags")
assert tags == actual
tc = unittest.TestCase("__init__")
expected = [{"Value": "value1", "Key": "key1"}, {"Value": "value2", "Key": "key2"}]
tc.assertTrue(
(expected[0] == actual[0] and expected[1] == actual[1])
or (expected[1] == actual[0] and expected[0] == actual[1])
)
client.untag_resource(ResourceARN=rule_arn, TagKeys=["key1"])
@ -474,24 +488,25 @@ def test_rule_tagging_happy():
expected = [{"Key": "key2", "Value": "value2"}]
assert expected == actual
@mock_events
def test_rule_tagging_sad():
b = EventsBackend("us-west-2")
back_end = EventsBackend("us-west-2")
try:
b.tag_resource('unknown', [])
raise 'tag_resource should fail if ResourceARN is not known'
back_end.tag_resource("unknown", [])
raise "tag_resource should fail if ResourceARN is not known"
except JsonRESTError:
pass
try:
b.untag_resource('unknown', [])
raise 'untag_resource should fail if ResourceARN is not known'
back_end.untag_resource("unknown", [])
raise "untag_resource should fail if ResourceARN is not known"
except JsonRESTError:
pass
try:
b.list_tags_for_resource('unknown')
raise 'list_tags_for_resource should fail if ResourceARN is not known'
back_end.list_tags_for_resource("unknown")
raise "list_tags_for_resource should fail if ResourceARN is not known"
except JsonRESTError:
pass
pass

View file

@ -1,21 +1,21 @@
from __future__ import unicode_literals
from tempfile import NamedTemporaryFile
import boto.glacier
import sure # noqa
from moto import mock_glacier_deprecated
@mock_glacier_deprecated
def test_create_and_delete_archive():
the_file = NamedTemporaryFile(delete=False)
the_file.write(b"some stuff")
the_file.close()
conn = boto.glacier.connect_to_region("us-west-2")
vault = conn.create_vault("my_vault")
archive_id = vault.upload_archive(the_file.name)
vault.delete_archive(archive_id)
from __future__ import unicode_literals
from tempfile import NamedTemporaryFile
import boto.glacier
import sure # noqa
from moto import mock_glacier_deprecated
@mock_glacier_deprecated
def test_create_and_delete_archive():
the_file = NamedTemporaryFile(delete=False)
the_file.write(b"some stuff")
the_file.close()
conn = boto.glacier.connect_to_region("us-west-2")
vault = conn.create_vault("my_vault")
archive_id = vault.upload_archive(the_file.name)
vault.delete_archive(archive_id)

View file

@ -1,31 +1,31 @@
from __future__ import unicode_literals
import boto.glacier
import sure # noqa
from moto import mock_glacier_deprecated
@mock_glacier_deprecated
def test_create_vault():
conn = boto.glacier.connect_to_region("us-west-2")
conn.create_vault("my_vault")
vaults = conn.list_vaults()
vaults.should.have.length_of(1)
vaults[0].name.should.equal("my_vault")
@mock_glacier_deprecated
def test_delete_vault():
conn = boto.glacier.connect_to_region("us-west-2")
conn.create_vault("my_vault")
vaults = conn.list_vaults()
vaults.should.have.length_of(1)
conn.delete_vault("my_vault")
vaults = conn.list_vaults()
vaults.should.have.length_of(0)
from __future__ import unicode_literals
import boto.glacier
import sure # noqa
from moto import mock_glacier_deprecated
@mock_glacier_deprecated
def test_create_vault():
conn = boto.glacier.connect_to_region("us-west-2")
conn.create_vault("my_vault")
vaults = conn.list_vaults()
vaults.should.have.length_of(1)
vaults[0].name.should.equal("my_vault")
@mock_glacier_deprecated
def test_delete_vault():
conn = boto.glacier.connect_to_region("us-west-2")
conn.create_vault("my_vault")
vaults = conn.list_vaults()
vaults.should.have.length_of(1)
conn.delete_vault("my_vault")
vaults = conn.list_vaults()
vaults.should.have.length_of(0)

View file

@ -1 +1 @@
from __future__ import unicode_literals
from __future__ import unicode_literals

View file

@ -1 +1 @@
from __future__ import unicode_literals
from __future__ import unicode_literals

View file

@ -1,97 +1,97 @@
from __future__ import unicode_literals
import copy
from .fixtures.datacatalog import TABLE_INPUT, PARTITION_INPUT
def create_database(client, database_name):
return client.create_database(DatabaseInput={"Name": database_name})
def get_database(client, database_name):
return client.get_database(Name=database_name)
def create_table_input(database_name, table_name, columns=[], partition_keys=[]):
table_input = copy.deepcopy(TABLE_INPUT)
table_input["Name"] = table_name
table_input["PartitionKeys"] = partition_keys
table_input["StorageDescriptor"]["Columns"] = columns
table_input["StorageDescriptor"][
"Location"
] = "s3://my-bucket/{database_name}/{table_name}".format(
database_name=database_name, table_name=table_name
)
return table_input
def create_table(client, database_name, table_name, table_input=None, **kwargs):
if table_input is None:
table_input = create_table_input(database_name, table_name, **kwargs)
return client.create_table(DatabaseName=database_name, TableInput=table_input)
def update_table(client, database_name, table_name, table_input=None, **kwargs):
if table_input is None:
table_input = create_table_input(database_name, table_name, **kwargs)
return client.update_table(DatabaseName=database_name, TableInput=table_input)
def get_table(client, database_name, table_name):
return client.get_table(DatabaseName=database_name, Name=table_name)
def get_tables(client, database_name):
return client.get_tables(DatabaseName=database_name)
def get_table_versions(client, database_name, table_name):
return client.get_table_versions(DatabaseName=database_name, TableName=table_name)
def get_table_version(client, database_name, table_name, version_id):
return client.get_table_version(
DatabaseName=database_name, TableName=table_name, VersionId=version_id
)
def create_partition_input(database_name, table_name, values=[], columns=[]):
root_path = "s3://my-bucket/{database_name}/{table_name}".format(
database_name=database_name, table_name=table_name
)
part_input = copy.deepcopy(PARTITION_INPUT)
part_input["Values"] = values
part_input["StorageDescriptor"]["Columns"] = columns
part_input["StorageDescriptor"]["SerdeInfo"]["Parameters"]["path"] = root_path
return part_input
def create_partition(client, database_name, table_name, partiton_input=None, **kwargs):
if partiton_input is None:
partiton_input = create_partition_input(database_name, table_name, **kwargs)
return client.create_partition(
DatabaseName=database_name, TableName=table_name, PartitionInput=partiton_input
)
def update_partition(
client, database_name, table_name, old_values=[], partiton_input=None, **kwargs
):
if partiton_input is None:
partiton_input = create_partition_input(database_name, table_name, **kwargs)
return client.update_partition(
DatabaseName=database_name,
TableName=table_name,
PartitionInput=partiton_input,
PartitionValueList=old_values,
)
def get_partition(client, database_name, table_name, values):
return client.get_partition(
DatabaseName=database_name, TableName=table_name, PartitionValues=values
)
from __future__ import unicode_literals
import copy
from .fixtures.datacatalog import TABLE_INPUT, PARTITION_INPUT
def create_database(client, database_name):
return client.create_database(DatabaseInput={"Name": database_name})
def get_database(client, database_name):
return client.get_database(Name=database_name)
def create_table_input(database_name, table_name, columns=[], partition_keys=[]):
table_input = copy.deepcopy(TABLE_INPUT)
table_input["Name"] = table_name
table_input["PartitionKeys"] = partition_keys
table_input["StorageDescriptor"]["Columns"] = columns
table_input["StorageDescriptor"][
"Location"
] = "s3://my-bucket/{database_name}/{table_name}".format(
database_name=database_name, table_name=table_name
)
return table_input
def create_table(client, database_name, table_name, table_input=None, **kwargs):
if table_input is None:
table_input = create_table_input(database_name, table_name, **kwargs)
return client.create_table(DatabaseName=database_name, TableInput=table_input)
def update_table(client, database_name, table_name, table_input=None, **kwargs):
if table_input is None:
table_input = create_table_input(database_name, table_name, **kwargs)
return client.update_table(DatabaseName=database_name, TableInput=table_input)
def get_table(client, database_name, table_name):
return client.get_table(DatabaseName=database_name, Name=table_name)
def get_tables(client, database_name):
return client.get_tables(DatabaseName=database_name)
def get_table_versions(client, database_name, table_name):
return client.get_table_versions(DatabaseName=database_name, TableName=table_name)
def get_table_version(client, database_name, table_name, version_id):
return client.get_table_version(
DatabaseName=database_name, TableName=table_name, VersionId=version_id
)
def create_partition_input(database_name, table_name, values=[], columns=[]):
root_path = "s3://my-bucket/{database_name}/{table_name}".format(
database_name=database_name, table_name=table_name
)
part_input = copy.deepcopy(PARTITION_INPUT)
part_input["Values"] = values
part_input["StorageDescriptor"]["Columns"] = columns
part_input["StorageDescriptor"]["SerdeInfo"]["Parameters"]["path"] = root_path
return part_input
def create_partition(client, database_name, table_name, partiton_input=None, **kwargs):
if partiton_input is None:
partiton_input = create_partition_input(database_name, table_name, **kwargs)
return client.create_partition(
DatabaseName=database_name, TableName=table_name, PartitionInput=partiton_input
)
def update_partition(
client, database_name, table_name, old_values=[], partiton_input=None, **kwargs
):
if partiton_input is None:
partiton_input = create_partition_input(database_name, table_name, **kwargs)
return client.update_partition(
DatabaseName=database_name,
TableName=table_name,
PartitionInput=partiton_input,
PartitionValueList=old_values,
)
def get_partition(client, database_name, table_name, values):
return client.get_partition(
DatabaseName=database_name, TableName=table_name, PartitionValues=values
)

View file

@ -132,7 +132,7 @@ def test_get_table_versions():
helpers.update_table(client, database_name, table_name, table_input)
version_inputs["2"] = table_input
# Updateing with an indentical input should still create a new version
# Updateing with an identical input should still create a new version
helpers.update_table(client, database_name, table_name, table_input)
version_inputs["3"] = table_input

View file

@ -785,7 +785,7 @@ def test_delete_login_profile():
conn.delete_login_profile("my-user")
@mock_iam()
@mock_iam
def test_create_access_key():
conn = boto3.client("iam", region_name="us-east-1")
with assert_raises(ClientError):
@ -798,6 +798,19 @@ def test_create_access_key():
access_key["AccessKeyId"].should.have.length_of(20)
access_key["SecretAccessKey"].should.have.length_of(40)
assert access_key["AccessKeyId"].startswith("AKIA")
conn = boto3.client(
"iam",
region_name="us-east-1",
aws_access_key_id=access_key["AccessKeyId"],
aws_secret_access_key=access_key["SecretAccessKey"],
)
access_key = conn.create_access_key()["AccessKey"]
(
datetime.utcnow() - access_key["CreateDate"].replace(tzinfo=None)
).seconds.should.be.within(0, 10)
access_key["AccessKeyId"].should.have.length_of(20)
access_key["SecretAccessKey"].should.have.length_of(40)
assert access_key["AccessKeyId"].startswith("AKIA")
@mock_iam_deprecated()
@ -825,8 +838,35 @@ def test_get_all_access_keys():
)
@mock_iam
def test_list_access_keys():
conn = boto3.client("iam", region_name="us-east-1")
conn.create_user(UserName="my-user")
response = conn.list_access_keys(UserName="my-user")
assert_equals(
response["AccessKeyMetadata"], [],
)
access_key = conn.create_access_key(UserName="my-user")["AccessKey"]
response = conn.list_access_keys(UserName="my-user")
assert_equals(
sorted(response["AccessKeyMetadata"][0].keys()),
sorted(["Status", "CreateDate", "UserName", "AccessKeyId"]),
)
conn = boto3.client(
"iam",
region_name="us-east-1",
aws_access_key_id=access_key["AccessKeyId"],
aws_secret_access_key=access_key["SecretAccessKey"],
)
response = conn.list_access_keys()
assert_equals(
sorted(response["AccessKeyMetadata"][0].keys()),
sorted(["Status", "CreateDate", "UserName", "AccessKeyId"]),
)
@mock_iam_deprecated()
def test_delete_access_key():
def test_delete_access_key_deprecated():
conn = boto.connect_iam()
conn.create_user("my-user")
access_key_id = conn.create_access_key("my-user")["create_access_key_response"][
@ -835,6 +875,16 @@ def test_delete_access_key():
conn.delete_access_key(access_key_id, "my-user")
@mock_iam
def test_delete_access_key():
conn = boto3.client("iam", region_name="us-east-1")
conn.create_user(UserName="my-user")
key = conn.create_access_key(UserName="my-user")["AccessKey"]
conn.delete_access_key(AccessKeyId=key["AccessKeyId"], UserName="my-user")
key = conn.create_access_key(UserName="my-user")["AccessKey"]
conn.delete_access_key(AccessKeyId=key["AccessKeyId"])
@mock_iam()
def test_mfa_devices():
# Test enable device
@ -1326,6 +1376,9 @@ def test_update_access_key():
)
resp = client.list_access_keys(UserName=username)
resp["AccessKeyMetadata"][0]["Status"].should.equal("Inactive")
client.update_access_key(AccessKeyId=key["AccessKeyId"], Status="Active")
resp = client.list_access_keys(UserName=username)
resp["AccessKeyMetadata"][0]["Status"].should.equal("Active")
@mock_iam

View file

@ -9,6 +9,173 @@ from botocore.exceptions import ClientError
from nose.tools import assert_raises
@mock_iot
def test_attach_policy():
client = boto3.client("iot", region_name="ap-northeast-1")
policy_name = "my-policy"
doc = "{}"
cert = client.create_keys_and_certificate(setAsActive=True)
cert_arn = cert["certificateArn"]
client.create_policy(policyName=policy_name, policyDocument=doc)
client.attach_policy(policyName=policy_name, target=cert_arn)
res = client.list_attached_policies(target=cert_arn)
res.should.have.key("policies").which.should.have.length_of(1)
res["policies"][0]["policyName"].should.equal("my-policy")
@mock_iot
def test_detach_policy():
client = boto3.client("iot", region_name="ap-northeast-1")
policy_name = "my-policy"
doc = "{}"
cert = client.create_keys_and_certificate(setAsActive=True)
cert_arn = cert["certificateArn"]
client.create_policy(policyName=policy_name, policyDocument=doc)
client.attach_policy(policyName=policy_name, target=cert_arn)
res = client.list_attached_policies(target=cert_arn)
res.should.have.key("policies").which.should.have.length_of(1)
res["policies"][0]["policyName"].should.equal("my-policy")
client.detach_policy(policyName=policy_name, target=cert_arn)
res = client.list_attached_policies(target=cert_arn)
res.should.have.key("policies").which.should.be.empty
@mock_iot
def test_list_attached_policies():
client = boto3.client("iot", region_name="ap-northeast-1")
cert = client.create_keys_and_certificate(setAsActive=True)
policies = client.list_attached_policies(target=cert["certificateArn"])
policies["policies"].should.be.empty
@mock_iot
def test_policy_versions():
client = boto3.client("iot", region_name="ap-northeast-1")
policy_name = "my-policy"
doc = "{}"
policy = client.create_policy(policyName=policy_name, policyDocument=doc)
policy.should.have.key("policyName").which.should.equal(policy_name)
policy.should.have.key("policyArn").which.should_not.be.none
policy.should.have.key("policyDocument").which.should.equal(json.dumps({}))
policy.should.have.key("policyVersionId").which.should.equal("1")
policy = client.get_policy(policyName=policy_name)
policy.should.have.key("policyName").which.should.equal(policy_name)
policy.should.have.key("policyArn").which.should_not.be.none
policy.should.have.key("policyDocument").which.should.equal(json.dumps({}))
policy.should.have.key("defaultVersionId").which.should.equal(
policy["defaultVersionId"]
)
policy1 = client.create_policy_version(
policyName=policy_name,
policyDocument=json.dumps({"version": "version_1"}),
setAsDefault=True,
)
policy1.should.have.key("policyArn").which.should_not.be.none
policy1.should.have.key("policyDocument").which.should.equal(
json.dumps({"version": "version_1"})
)
policy1.should.have.key("policyVersionId").which.should.equal("2")
policy1.should.have.key("isDefaultVersion").which.should.equal(True)
policy2 = client.create_policy_version(
policyName=policy_name,
policyDocument=json.dumps({"version": "version_2"}),
setAsDefault=False,
)
policy2.should.have.key("policyArn").which.should_not.be.none
policy2.should.have.key("policyDocument").which.should.equal(
json.dumps({"version": "version_2"})
)
policy2.should.have.key("policyVersionId").which.should.equal("3")
policy2.should.have.key("isDefaultVersion").which.should.equal(False)
policy = client.get_policy(policyName=policy_name)
policy.should.have.key("policyName").which.should.equal(policy_name)
policy.should.have.key("policyArn").which.should_not.be.none
policy.should.have.key("policyDocument").which.should.equal(
json.dumps({"version": "version_1"})
)
policy.should.have.key("defaultVersionId").which.should.equal(
policy1["policyVersionId"]
)
policy_versions = client.list_policy_versions(policyName=policy_name)
policy_versions.should.have.key("policyVersions").which.should.have.length_of(3)
list(
map(lambda item: item["isDefaultVersion"], policy_versions["policyVersions"])
).count(True).should.equal(1)
default_policy = list(
filter(lambda item: item["isDefaultVersion"], policy_versions["policyVersions"])
)
default_policy[0].should.have.key("versionId").should.equal(
policy1["policyVersionId"]
)
policy = client.get_policy(policyName=policy_name)
policy.should.have.key("policyName").which.should.equal(policy_name)
policy.should.have.key("policyArn").which.should_not.be.none
policy.should.have.key("policyDocument").which.should.equal(
json.dumps({"version": "version_1"})
)
policy.should.have.key("defaultVersionId").which.should.equal(
policy1["policyVersionId"]
)
client.set_default_policy_version(
policyName=policy_name, policyVersionId=policy2["policyVersionId"]
)
policy_versions = client.list_policy_versions(policyName=policy_name)
policy_versions.should.have.key("policyVersions").which.should.have.length_of(3)
list(
map(lambda item: item["isDefaultVersion"], policy_versions["policyVersions"])
).count(True).should.equal(1)
default_policy = list(
filter(lambda item: item["isDefaultVersion"], policy_versions["policyVersions"])
)
default_policy[0].should.have.key("versionId").should.equal(
policy2["policyVersionId"]
)
policy = client.get_policy(policyName=policy_name)
policy.should.have.key("policyName").which.should.equal(policy_name)
policy.should.have.key("policyArn").which.should_not.be.none
policy.should.have.key("policyDocument").which.should.equal(
json.dumps({"version": "version_2"})
)
policy.should.have.key("defaultVersionId").which.should.equal(
policy2["policyVersionId"]
)
client.delete_policy_version(policyName=policy_name, policyVersionId="1")
policy_versions = client.list_policy_versions(policyName=policy_name)
policy_versions.should.have.key("policyVersions").which.should.have.length_of(2)
client.delete_policy_version(
policyName=policy_name, policyVersionId=policy1["policyVersionId"]
)
policy_versions = client.list_policy_versions(policyName=policy_name)
policy_versions.should.have.key("policyVersions").which.should.have.length_of(1)
# should fail as it"s the default policy. Should use delete_policy instead
try:
client.delete_policy_version(
policyName=policy_name, policyVersionId=policy2["policyVersionId"]
)
assert False, "Should have failed in previous call"
except Exception as exception:
exception.response["Error"]["Message"].should.equal(
"Cannot delete the default version of a policy"
)
@mock_iot
def test_things():
client = boto3.client("iot", region_name="ap-northeast-1")
@ -994,7 +1161,10 @@ def test_create_job():
client = boto3.client("iot", region_name="eu-west-1")
name = "my-thing"
job_id = "TestJob"
# thing
# thing# job document
# job_document = {
# "field": "value"
# }
thing = client.create_thing(thingName=name)
thing.should.have.key("thingName").which.should.equal(name)
thing.should.have.key("thingArn")
@ -1020,6 +1190,63 @@ def test_create_job():
job.should.have.key("description")
@mock_iot
def test_list_jobs():
client = boto3.client("iot", region_name="eu-west-1")
name = "my-thing"
job_id = "TestJob"
# thing# job document
# job_document = {
# "field": "value"
# }
thing = client.create_thing(thingName=name)
thing.should.have.key("thingName").which.should.equal(name)
thing.should.have.key("thingArn")
# job document
job_document = {"field": "value"}
job1 = client.create_job(
jobId=job_id,
targets=[thing["thingArn"]],
document=json.dumps(job_document),
description="Description",
presignedUrlConfig={
"roleArn": "arn:aws:iam::1:role/service-role/iot_job_role",
"expiresInSec": 123,
},
targetSelection="CONTINUOUS",
jobExecutionsRolloutConfig={"maximumPerMinute": 10},
)
job1.should.have.key("jobId").which.should.equal(job_id)
job1.should.have.key("jobArn")
job1.should.have.key("description")
job2 = client.create_job(
jobId=job_id + "1",
targets=[thing["thingArn"]],
document=json.dumps(job_document),
description="Description",
presignedUrlConfig={
"roleArn": "arn:aws:iam::1:role/service-role/iot_job_role",
"expiresInSec": 123,
},
targetSelection="CONTINUOUS",
jobExecutionsRolloutConfig={"maximumPerMinute": 10},
)
job2.should.have.key("jobId").which.should.equal(job_id + "1")
job2.should.have.key("jobArn")
job2.should.have.key("description")
jobs = client.list_jobs()
jobs.should.have.key("jobs")
jobs.should_not.have.key("nextToken")
jobs["jobs"][0].should.have.key("jobId").which.should.equal(job_id)
jobs["jobs"][1].should.have.key("jobId").which.should.equal(job_id + "1")
@mock_iot
def test_describe_job():
client = boto3.client("iot", region_name="eu-west-1")
@ -1124,3 +1351,387 @@ def test_describe_job_1():
job.should.have.key("job").which.should.have.key(
"jobExecutionsRolloutConfig"
).which.should.have.key("maximumPerMinute").which.should.equal(10)
@mock_iot
def test_delete_job():
client = boto3.client("iot", region_name="eu-west-1")
name = "my-thing"
job_id = "TestJob"
# thing
thing = client.create_thing(thingName=name)
thing.should.have.key("thingName").which.should.equal(name)
thing.should.have.key("thingArn")
job = client.create_job(
jobId=job_id,
targets=[thing["thingArn"]],
documentSource="https://s3-eu-west-1.amazonaws.com/bucket-name/job_document.json",
presignedUrlConfig={
"roleArn": "arn:aws:iam::1:role/service-role/iot_job_role",
"expiresInSec": 123,
},
targetSelection="CONTINUOUS",
jobExecutionsRolloutConfig={"maximumPerMinute": 10},
)
job.should.have.key("jobId").which.should.equal(job_id)
job.should.have.key("jobArn")
job = client.describe_job(jobId=job_id)
job.should.have.key("job")
job.should.have.key("job").which.should.have.key("jobId").which.should.equal(job_id)
client.delete_job(jobId=job_id)
client.list_jobs()["jobs"].should.have.length_of(0)
@mock_iot
def test_cancel_job():
client = boto3.client("iot", region_name="eu-west-1")
name = "my-thing"
job_id = "TestJob"
# thing
thing = client.create_thing(thingName=name)
thing.should.have.key("thingName").which.should.equal(name)
thing.should.have.key("thingArn")
job = client.create_job(
jobId=job_id,
targets=[thing["thingArn"]],
documentSource="https://s3-eu-west-1.amazonaws.com/bucket-name/job_document.json",
presignedUrlConfig={
"roleArn": "arn:aws:iam::1:role/service-role/iot_job_role",
"expiresInSec": 123,
},
targetSelection="CONTINUOUS",
jobExecutionsRolloutConfig={"maximumPerMinute": 10},
)
job.should.have.key("jobId").which.should.equal(job_id)
job.should.have.key("jobArn")
job = client.describe_job(jobId=job_id)
job.should.have.key("job")
job.should.have.key("job").which.should.have.key("jobId").which.should.equal(job_id)
job = client.cancel_job(jobId=job_id, reasonCode="Because", comment="You are")
job.should.have.key("jobId").which.should.equal(job_id)
job.should.have.key("jobArn")
job = client.describe_job(jobId=job_id)
job.should.have.key("job")
job.should.have.key("job").which.should.have.key("jobId").which.should.equal(job_id)
job.should.have.key("job").which.should.have.key("status").which.should.equal(
"CANCELED"
)
job.should.have.key("job").which.should.have.key(
"forceCanceled"
).which.should.equal(False)
job.should.have.key("job").which.should.have.key("reasonCode").which.should.equal(
"Because"
)
job.should.have.key("job").which.should.have.key("comment").which.should.equal(
"You are"
)
@mock_iot
def test_get_job_document_with_document_source():
client = boto3.client("iot", region_name="eu-west-1")
name = "my-thing"
job_id = "TestJob"
# thing
thing = client.create_thing(thingName=name)
thing.should.have.key("thingName").which.should.equal(name)
thing.should.have.key("thingArn")
job = client.create_job(
jobId=job_id,
targets=[thing["thingArn"]],
documentSource="https://s3-eu-west-1.amazonaws.com/bucket-name/job_document.json",
presignedUrlConfig={
"roleArn": "arn:aws:iam::1:role/service-role/iot_job_role",
"expiresInSec": 123,
},
targetSelection="CONTINUOUS",
jobExecutionsRolloutConfig={"maximumPerMinute": 10},
)
job.should.have.key("jobId").which.should.equal(job_id)
job.should.have.key("jobArn")
job_document = client.get_job_document(jobId=job_id)
job_document.should.have.key("document").which.should.equal("")
@mock_iot
def test_get_job_document_with_document():
client = boto3.client("iot", region_name="eu-west-1")
name = "my-thing"
job_id = "TestJob"
# thing
thing = client.create_thing(thingName=name)
thing.should.have.key("thingName").which.should.equal(name)
thing.should.have.key("thingArn")
# job document
job_document = {"field": "value"}
job = client.create_job(
jobId=job_id,
targets=[thing["thingArn"]],
document=json.dumps(job_document),
presignedUrlConfig={
"roleArn": "arn:aws:iam::1:role/service-role/iot_job_role",
"expiresInSec": 123,
},
targetSelection="CONTINUOUS",
jobExecutionsRolloutConfig={"maximumPerMinute": 10},
)
job.should.have.key("jobId").which.should.equal(job_id)
job.should.have.key("jobArn")
job_document = client.get_job_document(jobId=job_id)
job_document.should.have.key("document").which.should.equal('{"field": "value"}')
@mock_iot
def test_describe_job_execution():
client = boto3.client("iot", region_name="eu-west-1")
name = "my-thing"
job_id = "TestJob"
# thing
thing = client.create_thing(thingName=name)
thing.should.have.key("thingName").which.should.equal(name)
thing.should.have.key("thingArn")
# job document
job_document = {"field": "value"}
job = client.create_job(
jobId=job_id,
targets=[thing["thingArn"]],
document=json.dumps(job_document),
description="Description",
presignedUrlConfig={
"roleArn": "arn:aws:iam::1:role/service-role/iot_job_role",
"expiresInSec": 123,
},
targetSelection="CONTINUOUS",
jobExecutionsRolloutConfig={"maximumPerMinute": 10},
)
job.should.have.key("jobId").which.should.equal(job_id)
job.should.have.key("jobArn")
job.should.have.key("description")
job_execution = client.describe_job_execution(jobId=job_id, thingName=name)
job_execution.should.have.key("execution")
job_execution["execution"].should.have.key("jobId").which.should.equal(job_id)
job_execution["execution"].should.have.key("status").which.should.equal("QUEUED")
job_execution["execution"].should.have.key("forceCanceled").which.should.equal(
False
)
job_execution["execution"].should.have.key("statusDetails").which.should.equal(
{"detailsMap": {}}
)
job_execution["execution"].should.have.key("thingArn").which.should.equal(
thing["thingArn"]
)
job_execution["execution"].should.have.key("queuedAt")
job_execution["execution"].should.have.key("startedAt")
job_execution["execution"].should.have.key("lastUpdatedAt")
job_execution["execution"].should.have.key("executionNumber").which.should.equal(
123
)
job_execution["execution"].should.have.key("versionNumber").which.should.equal(123)
job_execution["execution"].should.have.key(
"approximateSecondsBeforeTimedOut"
).which.should.equal(123)
job_execution = client.describe_job_execution(
jobId=job_id, thingName=name, executionNumber=123
)
job_execution.should.have.key("execution")
job_execution["execution"].should.have.key("jobId").which.should.equal(job_id)
job_execution["execution"].should.have.key("status").which.should.equal("QUEUED")
job_execution["execution"].should.have.key("forceCanceled").which.should.equal(
False
)
job_execution["execution"].should.have.key("statusDetails").which.should.equal(
{"detailsMap": {}}
)
job_execution["execution"].should.have.key("thingArn").which.should.equal(
thing["thingArn"]
)
job_execution["execution"].should.have.key("queuedAt")
job_execution["execution"].should.have.key("startedAt")
job_execution["execution"].should.have.key("lastUpdatedAt")
job_execution["execution"].should.have.key("executionNumber").which.should.equal(
123
)
job_execution["execution"].should.have.key("versionNumber").which.should.equal(123)
job_execution["execution"].should.have.key(
"approximateSecondsBeforeTimedOut"
).which.should.equal(123)
try:
client.describe_job_execution(jobId=job_id, thingName=name, executionNumber=456)
except ClientError as exc:
error_code = exc.response["Error"]["Code"]
error_code.should.equal("ResourceNotFoundException")
else:
raise Exception("Should have raised error")
@mock_iot
def test_cancel_job_execution():
client = boto3.client("iot", region_name="eu-west-1")
name = "my-thing"
job_id = "TestJob"
# thing
thing = client.create_thing(thingName=name)
thing.should.have.key("thingName").which.should.equal(name)
thing.should.have.key("thingArn")
# job document
job_document = {"field": "value"}
job = client.create_job(
jobId=job_id,
targets=[thing["thingArn"]],
document=json.dumps(job_document),
description="Description",
presignedUrlConfig={
"roleArn": "arn:aws:iam::1:role/service-role/iot_job_role",
"expiresInSec": 123,
},
targetSelection="CONTINUOUS",
jobExecutionsRolloutConfig={"maximumPerMinute": 10},
)
job.should.have.key("jobId").which.should.equal(job_id)
job.should.have.key("jobArn")
job.should.have.key("description")
client.cancel_job_execution(jobId=job_id, thingName=name)
job_execution = client.describe_job_execution(jobId=job_id, thingName=name)
job_execution.should.have.key("execution")
job_execution["execution"].should.have.key("status").which.should.equal("CANCELED")
@mock_iot
def test_delete_job_execution():
client = boto3.client("iot", region_name="eu-west-1")
name = "my-thing"
job_id = "TestJob"
# thing
thing = client.create_thing(thingName=name)
thing.should.have.key("thingName").which.should.equal(name)
thing.should.have.key("thingArn")
# job document
job_document = {"field": "value"}
job = client.create_job(
jobId=job_id,
targets=[thing["thingArn"]],
document=json.dumps(job_document),
description="Description",
presignedUrlConfig={
"roleArn": "arn:aws:iam::1:role/service-role/iot_job_role",
"expiresInSec": 123,
},
targetSelection="CONTINUOUS",
jobExecutionsRolloutConfig={"maximumPerMinute": 10},
)
job.should.have.key("jobId").which.should.equal(job_id)
job.should.have.key("jobArn")
job.should.have.key("description")
client.delete_job_execution(jobId=job_id, thingName=name, executionNumber=123)
try:
client.describe_job_execution(jobId=job_id, thingName=name, executionNumber=123)
except ClientError as exc:
error_code = exc.response["Error"]["Code"]
error_code.should.equal("ResourceNotFoundException")
else:
raise Exception("Should have raised error")
@mock_iot
def test_list_job_executions_for_job():
client = boto3.client("iot", region_name="eu-west-1")
name = "my-thing"
job_id = "TestJob"
# thing
thing = client.create_thing(thingName=name)
thing.should.have.key("thingName").which.should.equal(name)
thing.should.have.key("thingArn")
# job document
job_document = {"field": "value"}
job = client.create_job(
jobId=job_id,
targets=[thing["thingArn"]],
document=json.dumps(job_document),
description="Description",
presignedUrlConfig={
"roleArn": "arn:aws:iam::1:role/service-role/iot_job_role",
"expiresInSec": 123,
},
targetSelection="CONTINUOUS",
jobExecutionsRolloutConfig={"maximumPerMinute": 10},
)
job.should.have.key("jobId").which.should.equal(job_id)
job.should.have.key("jobArn")
job.should.have.key("description")
job_execution = client.list_job_executions_for_job(jobId=job_id)
job_execution.should.have.key("executionSummaries")
job_execution["executionSummaries"][0].should.have.key(
"thingArn"
).which.should.equal(thing["thingArn"])
@mock_iot
def test_list_job_executions_for_thing():
client = boto3.client("iot", region_name="eu-west-1")
name = "my-thing"
job_id = "TestJob"
# thing
thing = client.create_thing(thingName=name)
thing.should.have.key("thingName").which.should.equal(name)
thing.should.have.key("thingArn")
# job document
job_document = {"field": "value"}
job = client.create_job(
jobId=job_id,
targets=[thing["thingArn"]],
document=json.dumps(job_document),
description="Description",
presignedUrlConfig={
"roleArn": "arn:aws:iam::1:role/service-role/iot_job_role",
"expiresInSec": 123,
},
targetSelection="CONTINUOUS",
jobExecutionsRolloutConfig={"maximumPerMinute": 10},
)
job.should.have.key("jobId").which.should.equal(job_id)
job.should.have.key("jobArn")
job.should.have.key("description")
job_execution = client.list_job_executions_for_thing(thingName=name)
job_execution.should.have.key("executionSummaries")
job_execution["executionSummaries"][0].should.have.key("jobId").which.should.equal(
job_id
)

View file

@ -223,7 +223,7 @@ def test_create_stream_without_redshift():
@mock_kinesis
def test_deescribe_non_existant_stream():
def test_deescribe_non_existent_stream():
client = boto3.client("firehose", region_name="us-east-1")
client.describe_delivery_stream.when.called_with(

View file

@ -32,7 +32,7 @@ def test_create_cluster():
@mock_kinesis_deprecated
def test_describe_non_existant_stream():
def test_describe_non_existent_stream():
conn = boto.kinesis.connect_to_region("us-east-1")
conn.describe_stream.when.called_with("not-a-stream").should.throw(
ResourceNotFoundException

View file

@ -1,26 +1,19 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from datetime import date
from datetime import datetime
from dateutil.tz import tzutc
import base64
import os
import re
import boto3
import boto.kms
import botocore.exceptions
import six
import sure # noqa
from boto.exception import JSONResponseError
from boto.kms.exceptions import AlreadyExistsException, NotFoundException
from freezegun import freeze_time
from nose.tools import assert_raises
from parameterized import parameterized
from moto.core.exceptions import JsonRESTError
from moto.kms.models import KmsBackend
from moto.kms.exceptions import NotFoundException as MotoNotFoundException
from moto import mock_kms, mock_kms_deprecated
from moto import mock_kms_deprecated
PLAINTEXT_VECTORS = (
(b"some encodeable plaintext",),
@ -36,23 +29,6 @@ def _get_encoded_value(plaintext):
return plaintext.encode("utf-8")
@mock_kms
def test_create_key():
conn = boto3.client("kms", region_name="us-east-1")
with freeze_time("2015-01-01 00:00:00"):
key = conn.create_key(
Policy="my policy",
Description="my key",
KeyUsage="ENCRYPT_DECRYPT",
Tags=[{"TagKey": "project", "TagValue": "moto"}],
)
key["KeyMetadata"]["Description"].should.equal("my key")
key["KeyMetadata"]["KeyUsage"].should.equal("ENCRYPT_DECRYPT")
key["KeyMetadata"]["Enabled"].should.equal(True)
key["KeyMetadata"]["CreationDate"].should.be.a(date)
@mock_kms_deprecated
def test_describe_key():
conn = boto.kms.connect_to_region("us-west-2")
@ -97,22 +73,6 @@ def test_describe_key_via_alias_not_found():
)
@parameterized(
(
("alias/does-not-exist",),
("arn:aws:kms:us-east-1:012345678912:alias/does-not-exist",),
("invalid",),
)
)
@mock_kms
def test_describe_key_via_alias_invalid_alias(key_id):
client = boto3.client("kms", region_name="us-east-1")
client.create_key(Description="key")
with assert_raises(client.exceptions.NotFoundException):
client.describe_key(KeyId=key_id)
@mock_kms_deprecated
def test_describe_key_via_arn():
conn = boto.kms.connect_to_region("us-west-2")
@ -240,71 +200,6 @@ def test_generate_data_key():
response["KeyId"].should.equal(key_arn)
@mock_kms
def test_boto3_generate_data_key():
kms = boto3.client("kms", region_name="us-west-2")
key = kms.create_key()
key_id = key["KeyMetadata"]["KeyId"]
key_arn = key["KeyMetadata"]["Arn"]
response = kms.generate_data_key(KeyId=key_id, NumberOfBytes=32)
# CiphertextBlob must NOT be base64-encoded
with assert_raises(Exception):
base64.b64decode(response["CiphertextBlob"], validate=True)
# Plaintext must NOT be base64-encoded
with assert_raises(Exception):
base64.b64decode(response["Plaintext"], validate=True)
response["KeyId"].should.equal(key_arn)
@parameterized(PLAINTEXT_VECTORS)
@mock_kms
def test_encrypt(plaintext):
client = boto3.client("kms", region_name="us-west-2")
key = client.create_key(Description="key")
key_id = key["KeyMetadata"]["KeyId"]
key_arn = key["KeyMetadata"]["Arn"]
response = client.encrypt(KeyId=key_id, Plaintext=plaintext)
response["CiphertextBlob"].should_not.equal(plaintext)
# CiphertextBlob must NOT be base64-encoded
with assert_raises(Exception):
base64.b64decode(response["CiphertextBlob"], validate=True)
response["KeyId"].should.equal(key_arn)
@parameterized(PLAINTEXT_VECTORS)
@mock_kms
def test_decrypt(plaintext):
client = boto3.client("kms", region_name="us-west-2")
key = client.create_key(Description="key")
key_id = key["KeyMetadata"]["KeyId"]
key_arn = key["KeyMetadata"]["Arn"]
encrypt_response = client.encrypt(KeyId=key_id, Plaintext=plaintext)
client.create_key(Description="key")
# CiphertextBlob must NOT be base64-encoded
with assert_raises(Exception):
base64.b64decode(encrypt_response["CiphertextBlob"], validate=True)
decrypt_response = client.decrypt(CiphertextBlob=encrypt_response["CiphertextBlob"])
# Plaintext must NOT be base64-encoded
with assert_raises(Exception):
base64.b64decode(decrypt_response["Plaintext"], validate=True)
decrypt_response["Plaintext"].should.equal(_get_encoded_value(plaintext))
decrypt_response["KeyId"].should.equal(key_arn)
@mock_kms_deprecated
def test_disable_key_rotation_with_missing_key():
conn = boto.kms.connect_to_region("us-west-2")
@ -775,25 +670,6 @@ def test__list_aliases():
len(aliases).should.equal(7)
@parameterized(
(
("not-a-uuid",),
("alias/DoesNotExist",),
("arn:aws:kms:us-east-1:012345678912:alias/DoesNotExist",),
("d25652e4-d2d2-49f7-929a-671ccda580c6",),
(
"arn:aws:kms:us-east-1:012345678912:key/d25652e4-d2d2-49f7-929a-671ccda580c6",
),
)
)
@mock_kms
def test_invalid_key_ids(key_id):
client = boto3.client("kms", region_name="us-east-1")
with assert_raises(client.exceptions.NotFoundException):
client.generate_data_key(KeyId=key_id, NumberOfBytes=5)
@mock_kms_deprecated
def test__assert_default_policy():
from moto.kms.responses import _assert_default_policy
@ -804,431 +680,3 @@ def test__assert_default_policy():
_assert_default_policy.when.called_with("default").should_not.throw(
MotoNotFoundException
)
@parameterized(PLAINTEXT_VECTORS)
@mock_kms
def test_kms_encrypt_boto3(plaintext):
client = boto3.client("kms", region_name="us-east-1")
key = client.create_key(Description="key")
response = client.encrypt(KeyId=key["KeyMetadata"]["KeyId"], Plaintext=plaintext)
response = client.decrypt(CiphertextBlob=response["CiphertextBlob"])
response["Plaintext"].should.equal(_get_encoded_value(plaintext))
@mock_kms
def test_disable_key():
client = boto3.client("kms", region_name="us-east-1")
key = client.create_key(Description="disable-key")
client.disable_key(KeyId=key["KeyMetadata"]["KeyId"])
result = client.describe_key(KeyId=key["KeyMetadata"]["KeyId"])
assert result["KeyMetadata"]["Enabled"] == False
assert result["KeyMetadata"]["KeyState"] == "Disabled"
@mock_kms
def test_enable_key():
client = boto3.client("kms", region_name="us-east-1")
key = client.create_key(Description="enable-key")
client.disable_key(KeyId=key["KeyMetadata"]["KeyId"])
client.enable_key(KeyId=key["KeyMetadata"]["KeyId"])
result = client.describe_key(KeyId=key["KeyMetadata"]["KeyId"])
assert result["KeyMetadata"]["Enabled"] == True
assert result["KeyMetadata"]["KeyState"] == "Enabled"
@mock_kms
def test_schedule_key_deletion():
client = boto3.client("kms", region_name="us-east-1")
key = client.create_key(Description="schedule-key-deletion")
if os.environ.get("TEST_SERVER_MODE", "false").lower() == "false":
with freeze_time("2015-01-01 12:00:00"):
response = client.schedule_key_deletion(KeyId=key["KeyMetadata"]["KeyId"])
assert response["KeyId"] == key["KeyMetadata"]["KeyId"]
assert response["DeletionDate"] == datetime(
2015, 1, 31, 12, 0, tzinfo=tzutc()
)
else:
# Can't manipulate time in server mode
response = client.schedule_key_deletion(KeyId=key["KeyMetadata"]["KeyId"])
assert response["KeyId"] == key["KeyMetadata"]["KeyId"]
result = client.describe_key(KeyId=key["KeyMetadata"]["KeyId"])
assert result["KeyMetadata"]["Enabled"] == False
assert result["KeyMetadata"]["KeyState"] == "PendingDeletion"
assert "DeletionDate" in result["KeyMetadata"]
@mock_kms
def test_schedule_key_deletion_custom():
client = boto3.client("kms", region_name="us-east-1")
key = client.create_key(Description="schedule-key-deletion")
if os.environ.get("TEST_SERVER_MODE", "false").lower() == "false":
with freeze_time("2015-01-01 12:00:00"):
response = client.schedule_key_deletion(
KeyId=key["KeyMetadata"]["KeyId"], PendingWindowInDays=7
)
assert response["KeyId"] == key["KeyMetadata"]["KeyId"]
assert response["DeletionDate"] == datetime(
2015, 1, 8, 12, 0, tzinfo=tzutc()
)
else:
# Can't manipulate time in server mode
response = client.schedule_key_deletion(
KeyId=key["KeyMetadata"]["KeyId"], PendingWindowInDays=7
)
assert response["KeyId"] == key["KeyMetadata"]["KeyId"]
result = client.describe_key(KeyId=key["KeyMetadata"]["KeyId"])
assert result["KeyMetadata"]["Enabled"] == False
assert result["KeyMetadata"]["KeyState"] == "PendingDeletion"
assert "DeletionDate" in result["KeyMetadata"]
@mock_kms
def test_cancel_key_deletion():
client = boto3.client("kms", region_name="us-east-1")
key = client.create_key(Description="cancel-key-deletion")
client.schedule_key_deletion(KeyId=key["KeyMetadata"]["KeyId"])
response = client.cancel_key_deletion(KeyId=key["KeyMetadata"]["KeyId"])
assert response["KeyId"] == key["KeyMetadata"]["KeyId"]
result = client.describe_key(KeyId=key["KeyMetadata"]["KeyId"])
assert result["KeyMetadata"]["Enabled"] == False
assert result["KeyMetadata"]["KeyState"] == "Disabled"
assert "DeletionDate" not in result["KeyMetadata"]
@mock_kms
def test_update_key_description():
client = boto3.client("kms", region_name="us-east-1")
key = client.create_key(Description="old_description")
key_id = key["KeyMetadata"]["KeyId"]
result = client.update_key_description(KeyId=key_id, Description="new_description")
assert "ResponseMetadata" in result
@mock_kms
def test_key_tagging_happy():
client = boto3.client("kms", region_name="us-east-1")
key = client.create_key(Description="test-key-tagging")
key_id = key["KeyMetadata"]["KeyId"]
tags = [{"TagKey": "key1", "TagValue": "value1"}, {"TagKey": "key2", "TagValue": "value2"}]
client.tag_resource(KeyId=key_id, Tags=tags)
result = client.list_resource_tags(KeyId=key_id)
actual = result.get("Tags", [])
assert tags == actual
client.untag_resource(KeyId=key_id, TagKeys=["key1"])
actual = client.list_resource_tags(KeyId=key_id).get("Tags", [])
expected = [{"TagKey": "key2", "TagValue": "value2"}]
assert expected == actual
@mock_kms
def test_key_tagging_sad():
b = KmsBackend()
try:
b.tag_resource('unknown', [])
raise 'tag_resource should fail if KeyId is not known'
except JsonRESTError:
pass
try:
b.untag_resource('unknown', [])
raise 'untag_resource should fail if KeyId is not known'
except JsonRESTError:
pass
try:
b.list_resource_tags('unknown')
raise 'list_resource_tags should fail if KeyId is not known'
except JsonRESTError:
pass
@parameterized(
(
(dict(KeySpec="AES_256"), 32),
(dict(KeySpec="AES_128"), 16),
(dict(NumberOfBytes=64), 64),
(dict(NumberOfBytes=1), 1),
(dict(NumberOfBytes=1024), 1024),
)
)
@mock_kms
def test_generate_data_key_sizes(kwargs, expected_key_length):
client = boto3.client("kms", region_name="us-east-1")
key = client.create_key(Description="generate-data-key-size")
response = client.generate_data_key(KeyId=key["KeyMetadata"]["KeyId"], **kwargs)
assert len(response["Plaintext"]) == expected_key_length
@mock_kms
def test_generate_data_key_decrypt():
client = boto3.client("kms", region_name="us-east-1")
key = client.create_key(Description="generate-data-key-decrypt")
resp1 = client.generate_data_key(
KeyId=key["KeyMetadata"]["KeyId"], KeySpec="AES_256"
)
resp2 = client.decrypt(CiphertextBlob=resp1["CiphertextBlob"])
assert resp1["Plaintext"] == resp2["Plaintext"]
@parameterized(
(
(dict(KeySpec="AES_257"),),
(dict(KeySpec="AES_128", NumberOfBytes=16),),
(dict(NumberOfBytes=2048),),
(dict(NumberOfBytes=0),),
(dict(),),
)
)
@mock_kms
def test_generate_data_key_invalid_size_params(kwargs):
client = boto3.client("kms", region_name="us-east-1")
key = client.create_key(Description="generate-data-key-size")
with assert_raises(
(botocore.exceptions.ClientError, botocore.exceptions.ParamValidationError)
) as err:
client.generate_data_key(KeyId=key["KeyMetadata"]["KeyId"], **kwargs)
@parameterized(
(
("alias/DoesNotExist",),
("arn:aws:kms:us-east-1:012345678912:alias/DoesNotExist",),
("d25652e4-d2d2-49f7-929a-671ccda580c6",),
(
"arn:aws:kms:us-east-1:012345678912:key/d25652e4-d2d2-49f7-929a-671ccda580c6",
),
)
)
@mock_kms
def test_generate_data_key_invalid_key(key_id):
client = boto3.client("kms", region_name="us-east-1")
with assert_raises(client.exceptions.NotFoundException):
client.generate_data_key(KeyId=key_id, KeySpec="AES_256")
@parameterized(
(
("alias/DoesExist", False),
("arn:aws:kms:us-east-1:012345678912:alias/DoesExist", False),
("", True),
("arn:aws:kms:us-east-1:012345678912:key/", True),
)
)
@mock_kms
def test_generate_data_key_all_valid_key_ids(prefix, append_key_id):
client = boto3.client("kms", region_name="us-east-1")
key = client.create_key()
key_id = key["KeyMetadata"]["KeyId"]
client.create_alias(AliasName="alias/DoesExist", TargetKeyId=key_id)
target_id = prefix
if append_key_id:
target_id += key_id
client.generate_data_key(KeyId=key_id, NumberOfBytes=32)
@mock_kms
def test_generate_data_key_without_plaintext_decrypt():
client = boto3.client("kms", region_name="us-east-1")
key = client.create_key(Description="generate-data-key-decrypt")
resp1 = client.generate_data_key_without_plaintext(
KeyId=key["KeyMetadata"]["KeyId"], KeySpec="AES_256"
)
assert "Plaintext" not in resp1
@parameterized(PLAINTEXT_VECTORS)
@mock_kms
def test_re_encrypt_decrypt(plaintext):
client = boto3.client("kms", region_name="us-west-2")
key_1 = client.create_key(Description="key 1")
key_1_id = key_1["KeyMetadata"]["KeyId"]
key_1_arn = key_1["KeyMetadata"]["Arn"]
key_2 = client.create_key(Description="key 2")
key_2_id = key_2["KeyMetadata"]["KeyId"]
key_2_arn = key_2["KeyMetadata"]["Arn"]
encrypt_response = client.encrypt(
KeyId=key_1_id, Plaintext=plaintext, EncryptionContext={"encryption": "context"}
)
re_encrypt_response = client.re_encrypt(
CiphertextBlob=encrypt_response["CiphertextBlob"],
SourceEncryptionContext={"encryption": "context"},
DestinationKeyId=key_2_id,
DestinationEncryptionContext={"another": "context"},
)
# CiphertextBlob must NOT be base64-encoded
with assert_raises(Exception):
base64.b64decode(re_encrypt_response["CiphertextBlob"], validate=True)
re_encrypt_response["SourceKeyId"].should.equal(key_1_arn)
re_encrypt_response["KeyId"].should.equal(key_2_arn)
decrypt_response_1 = client.decrypt(
CiphertextBlob=encrypt_response["CiphertextBlob"],
EncryptionContext={"encryption": "context"},
)
decrypt_response_1["Plaintext"].should.equal(_get_encoded_value(plaintext))
decrypt_response_1["KeyId"].should.equal(key_1_arn)
decrypt_response_2 = client.decrypt(
CiphertextBlob=re_encrypt_response["CiphertextBlob"],
EncryptionContext={"another": "context"},
)
decrypt_response_2["Plaintext"].should.equal(_get_encoded_value(plaintext))
decrypt_response_2["KeyId"].should.equal(key_2_arn)
decrypt_response_1["Plaintext"].should.equal(decrypt_response_2["Plaintext"])
@mock_kms
def test_re_encrypt_to_invalid_destination():
client = boto3.client("kms", region_name="us-west-2")
key = client.create_key(Description="key 1")
key_id = key["KeyMetadata"]["KeyId"]
encrypt_response = client.encrypt(KeyId=key_id, Plaintext=b"some plaintext")
with assert_raises(client.exceptions.NotFoundException):
client.re_encrypt(
CiphertextBlob=encrypt_response["CiphertextBlob"],
DestinationKeyId="alias/DoesNotExist",
)
@parameterized(((12,), (44,), (91,), (1,), (1024,)))
@mock_kms
def test_generate_random(number_of_bytes):
client = boto3.client("kms", region_name="us-west-2")
response = client.generate_random(NumberOfBytes=number_of_bytes)
response["Plaintext"].should.be.a(bytes)
len(response["Plaintext"]).should.equal(number_of_bytes)
@parameterized(
(
(2048, botocore.exceptions.ClientError),
(1025, botocore.exceptions.ClientError),
(0, botocore.exceptions.ParamValidationError),
(-1, botocore.exceptions.ParamValidationError),
(-1024, botocore.exceptions.ParamValidationError),
)
)
@mock_kms
def test_generate_random_invalid_number_of_bytes(number_of_bytes, error_type):
client = boto3.client("kms", region_name="us-west-2")
with assert_raises(error_type):
client.generate_random(NumberOfBytes=number_of_bytes)
@mock_kms
def test_enable_key_rotation_key_not_found():
client = boto3.client("kms", region_name="us-east-1")
with assert_raises(client.exceptions.NotFoundException):
client.enable_key_rotation(KeyId="12366f9b-1230-123d-123e-123e6ae60c02")
@mock_kms
def test_disable_key_rotation_key_not_found():
client = boto3.client("kms", region_name="us-east-1")
with assert_raises(client.exceptions.NotFoundException):
client.disable_key_rotation(KeyId="12366f9b-1230-123d-123e-123e6ae60c02")
@mock_kms
def test_enable_key_key_not_found():
client = boto3.client("kms", region_name="us-east-1")
with assert_raises(client.exceptions.NotFoundException):
client.enable_key(KeyId="12366f9b-1230-123d-123e-123e6ae60c02")
@mock_kms
def test_disable_key_key_not_found():
client = boto3.client("kms", region_name="us-east-1")
with assert_raises(client.exceptions.NotFoundException):
client.disable_key(KeyId="12366f9b-1230-123d-123e-123e6ae60c02")
@mock_kms
def test_cancel_key_deletion_key_not_found():
client = boto3.client("kms", region_name="us-east-1")
with assert_raises(client.exceptions.NotFoundException):
client.cancel_key_deletion(KeyId="12366f9b-1230-123d-123e-123e6ae60c02")
@mock_kms
def test_schedule_key_deletion_key_not_found():
client = boto3.client("kms", region_name="us-east-1")
with assert_raises(client.exceptions.NotFoundException):
client.schedule_key_deletion(KeyId="12366f9b-1230-123d-123e-123e6ae60c02")
@mock_kms
def test_get_key_rotation_status_key_not_found():
client = boto3.client("kms", region_name="us-east-1")
with assert_raises(client.exceptions.NotFoundException):
client.get_key_rotation_status(KeyId="12366f9b-1230-123d-123e-123e6ae60c02")
@mock_kms
def test_get_key_policy_key_not_found():
client = boto3.client("kms", region_name="us-east-1")
with assert_raises(client.exceptions.NotFoundException):
client.get_key_policy(
KeyId="12366f9b-1230-123d-123e-123e6ae60c02", PolicyName="default"
)
@mock_kms
def test_list_key_policies_key_not_found():
client = boto3.client("kms", region_name="us-east-1")
with assert_raises(client.exceptions.NotFoundException):
client.list_key_policies(KeyId="12366f9b-1230-123d-123e-123e6ae60c02")
@mock_kms
def test_put_key_policy_key_not_found():
client = boto3.client("kms", region_name="us-east-1")
with assert_raises(client.exceptions.NotFoundException):
client.put_key_policy(
KeyId="00000000-0000-0000-0000-000000000000",
PolicyName="default",
Policy="new policy",
)

View file

@ -0,0 +1,638 @@
# -*- coding: utf-8 -*-
from __future__ import unicode_literals
from datetime import datetime
from dateutil.tz import tzutc
import base64
import os
import boto3
import botocore.exceptions
import six
import sure # noqa
from freezegun import freeze_time
from nose.tools import assert_raises
from parameterized import parameterized
from moto import mock_kms
PLAINTEXT_VECTORS = (
(b"some encodeable plaintext",),
(b"some unencodeable plaintext \xec\x8a\xcf\xb6r\xe9\xb5\xeb\xff\xa23\x16",),
("some unicode characters ø˚∆øˆˆ∆ßçøˆˆçßøˆ¨¥",),
)
def _get_encoded_value(plaintext):
if isinstance(plaintext, six.binary_type):
return plaintext
return plaintext.encode("utf-8")
@mock_kms
def test_create_key():
conn = boto3.client("kms", region_name="us-east-1")
key = conn.create_key(
Policy="my policy",
Description="my key",
KeyUsage="ENCRYPT_DECRYPT",
Tags=[{"TagKey": "project", "TagValue": "moto"}],
)
key["KeyMetadata"]["Arn"].should.equal(
"arn:aws:kms:us-east-1:123456789012:key/{}".format(key["KeyMetadata"]["KeyId"])
)
key["KeyMetadata"]["AWSAccountId"].should.equal("123456789012")
key["KeyMetadata"]["CreationDate"].should.be.a(datetime)
key["KeyMetadata"]["CustomerMasterKeySpec"].should.equal("SYMMETRIC_DEFAULT")
key["KeyMetadata"]["Description"].should.equal("my key")
key["KeyMetadata"]["Enabled"].should.be.ok
key["KeyMetadata"]["EncryptionAlgorithms"].should.equal(["SYMMETRIC_DEFAULT"])
key["KeyMetadata"]["KeyId"].should_not.be.empty
key["KeyMetadata"]["KeyManager"].should.equal("CUSTOMER")
key["KeyMetadata"]["KeyState"].should.equal("Enabled")
key["KeyMetadata"]["KeyUsage"].should.equal("ENCRYPT_DECRYPT")
key["KeyMetadata"]["Origin"].should.equal("AWS_KMS")
key["KeyMetadata"].should_not.have.key("SigningAlgorithms")
key = conn.create_key(KeyUsage="ENCRYPT_DECRYPT", CustomerMasterKeySpec="RSA_2048",)
sorted(key["KeyMetadata"]["EncryptionAlgorithms"]).should.equal(
["RSAES_OAEP_SHA_1", "RSAES_OAEP_SHA_256"]
)
key["KeyMetadata"].should_not.have.key("SigningAlgorithms")
key = conn.create_key(KeyUsage="SIGN_VERIFY", CustomerMasterKeySpec="RSA_2048",)
key["KeyMetadata"].should_not.have.key("EncryptionAlgorithms")
sorted(key["KeyMetadata"]["SigningAlgorithms"]).should.equal(
[
"RSASSA_PKCS1_V1_5_SHA_256",
"RSASSA_PKCS1_V1_5_SHA_384",
"RSASSA_PKCS1_V1_5_SHA_512",
"RSASSA_PSS_SHA_256",
"RSASSA_PSS_SHA_384",
"RSASSA_PSS_SHA_512",
]
)
key = conn.create_key(
KeyUsage="SIGN_VERIFY", CustomerMasterKeySpec="ECC_SECG_P256K1",
)
key["KeyMetadata"].should_not.have.key("EncryptionAlgorithms")
key["KeyMetadata"]["SigningAlgorithms"].should.equal(["ECDSA_SHA_256"])
key = conn.create_key(
KeyUsage="SIGN_VERIFY", CustomerMasterKeySpec="ECC_NIST_P384",
)
key["KeyMetadata"].should_not.have.key("EncryptionAlgorithms")
key["KeyMetadata"]["SigningAlgorithms"].should.equal(["ECDSA_SHA_384"])
key = conn.create_key(
KeyUsage="SIGN_VERIFY", CustomerMasterKeySpec="ECC_NIST_P521",
)
key["KeyMetadata"].should_not.have.key("EncryptionAlgorithms")
key["KeyMetadata"]["SigningAlgorithms"].should.equal(["ECDSA_SHA_512"])
@mock_kms
def test_describe_key():
client = boto3.client("kms", region_name="us-east-1")
response = client.create_key(Description="my key", KeyUsage="ENCRYPT_DECRYPT",)
key_id = response["KeyMetadata"]["KeyId"]
response = client.describe_key(KeyId=key_id)
response["KeyMetadata"]["AWSAccountId"].should.equal("123456789012")
response["KeyMetadata"]["CreationDate"].should.be.a(datetime)
response["KeyMetadata"]["CustomerMasterKeySpec"].should.equal("SYMMETRIC_DEFAULT")
response["KeyMetadata"]["Description"].should.equal("my key")
response["KeyMetadata"]["Enabled"].should.be.ok
response["KeyMetadata"]["EncryptionAlgorithms"].should.equal(["SYMMETRIC_DEFAULT"])
response["KeyMetadata"]["KeyId"].should_not.be.empty
response["KeyMetadata"]["KeyManager"].should.equal("CUSTOMER")
response["KeyMetadata"]["KeyState"].should.equal("Enabled")
response["KeyMetadata"]["KeyUsage"].should.equal("ENCRYPT_DECRYPT")
response["KeyMetadata"]["Origin"].should.equal("AWS_KMS")
response["KeyMetadata"].should_not.have.key("SigningAlgorithms")
@parameterized(
(
("alias/does-not-exist",),
("arn:aws:kms:us-east-1:012345678912:alias/does-not-exist",),
("invalid",),
)
)
@mock_kms
def test_describe_key_via_alias_invalid_alias(key_id):
client = boto3.client("kms", region_name="us-east-1")
client.create_key(Description="key")
with assert_raises(client.exceptions.NotFoundException):
client.describe_key(KeyId=key_id)
@mock_kms
def test_generate_data_key():
kms = boto3.client("kms", region_name="us-west-2")
key = kms.create_key()
key_id = key["KeyMetadata"]["KeyId"]
key_arn = key["KeyMetadata"]["Arn"]
response = kms.generate_data_key(KeyId=key_id, NumberOfBytes=32)
# CiphertextBlob must NOT be base64-encoded
with assert_raises(Exception):
base64.b64decode(response["CiphertextBlob"], validate=True)
# Plaintext must NOT be base64-encoded
with assert_raises(Exception):
base64.b64decode(response["Plaintext"], validate=True)
response["KeyId"].should.equal(key_arn)
@parameterized(PLAINTEXT_VECTORS)
@mock_kms
def test_encrypt(plaintext):
client = boto3.client("kms", region_name="us-west-2")
key = client.create_key(Description="key")
key_id = key["KeyMetadata"]["KeyId"]
key_arn = key["KeyMetadata"]["Arn"]
response = client.encrypt(KeyId=key_id, Plaintext=plaintext)
response["CiphertextBlob"].should_not.equal(plaintext)
# CiphertextBlob must NOT be base64-encoded
with assert_raises(Exception):
base64.b64decode(response["CiphertextBlob"], validate=True)
response["KeyId"].should.equal(key_arn)
@parameterized(PLAINTEXT_VECTORS)
@mock_kms
def test_decrypt(plaintext):
client = boto3.client("kms", region_name="us-west-2")
key = client.create_key(Description="key")
key_id = key["KeyMetadata"]["KeyId"]
key_arn = key["KeyMetadata"]["Arn"]
encrypt_response = client.encrypt(KeyId=key_id, Plaintext=plaintext)
client.create_key(Description="key")
# CiphertextBlob must NOT be base64-encoded
with assert_raises(Exception):
base64.b64decode(encrypt_response["CiphertextBlob"], validate=True)
decrypt_response = client.decrypt(CiphertextBlob=encrypt_response["CiphertextBlob"])
# Plaintext must NOT be base64-encoded
with assert_raises(Exception):
base64.b64decode(decrypt_response["Plaintext"], validate=True)
decrypt_response["Plaintext"].should.equal(_get_encoded_value(plaintext))
decrypt_response["KeyId"].should.equal(key_arn)
@parameterized(
(
("not-a-uuid",),
("alias/DoesNotExist",),
("arn:aws:kms:us-east-1:012345678912:alias/DoesNotExist",),
("d25652e4-d2d2-49f7-929a-671ccda580c6",),
(
"arn:aws:kms:us-east-1:012345678912:key/d25652e4-d2d2-49f7-929a-671ccda580c6",
),
)
)
@mock_kms
def test_invalid_key_ids(key_id):
client = boto3.client("kms", region_name="us-east-1")
with assert_raises(client.exceptions.NotFoundException):
client.generate_data_key(KeyId=key_id, NumberOfBytes=5)
@parameterized(PLAINTEXT_VECTORS)
@mock_kms
def test_kms_encrypt(plaintext):
client = boto3.client("kms", region_name="us-east-1")
key = client.create_key(Description="key")
response = client.encrypt(KeyId=key["KeyMetadata"]["KeyId"], Plaintext=plaintext)
response = client.decrypt(CiphertextBlob=response["CiphertextBlob"])
response["Plaintext"].should.equal(_get_encoded_value(plaintext))
@mock_kms
def test_disable_key():
client = boto3.client("kms", region_name="us-east-1")
key = client.create_key(Description="disable-key")
client.disable_key(KeyId=key["KeyMetadata"]["KeyId"])
result = client.describe_key(KeyId=key["KeyMetadata"]["KeyId"])
assert result["KeyMetadata"]["Enabled"] == False
assert result["KeyMetadata"]["KeyState"] == "Disabled"
@mock_kms
def test_enable_key():
client = boto3.client("kms", region_name="us-east-1")
key = client.create_key(Description="enable-key")
client.disable_key(KeyId=key["KeyMetadata"]["KeyId"])
client.enable_key(KeyId=key["KeyMetadata"]["KeyId"])
result = client.describe_key(KeyId=key["KeyMetadata"]["KeyId"])
assert result["KeyMetadata"]["Enabled"] == True
assert result["KeyMetadata"]["KeyState"] == "Enabled"
@mock_kms
def test_schedule_key_deletion():
client = boto3.client("kms", region_name="us-east-1")
key = client.create_key(Description="schedule-key-deletion")
if os.environ.get("TEST_SERVER_MODE", "false").lower() == "false":
with freeze_time("2015-01-01 12:00:00"):
response = client.schedule_key_deletion(KeyId=key["KeyMetadata"]["KeyId"])
assert response["KeyId"] == key["KeyMetadata"]["KeyId"]
assert response["DeletionDate"] == datetime(
2015, 1, 31, 12, 0, tzinfo=tzutc()
)
else:
# Can't manipulate time in server mode
response = client.schedule_key_deletion(KeyId=key["KeyMetadata"]["KeyId"])
assert response["KeyId"] == key["KeyMetadata"]["KeyId"]
result = client.describe_key(KeyId=key["KeyMetadata"]["KeyId"])
assert result["KeyMetadata"]["Enabled"] == False
assert result["KeyMetadata"]["KeyState"] == "PendingDeletion"
assert "DeletionDate" in result["KeyMetadata"]
@mock_kms
def test_schedule_key_deletion_custom():
client = boto3.client("kms", region_name="us-east-1")
key = client.create_key(Description="schedule-key-deletion")
if os.environ.get("TEST_SERVER_MODE", "false").lower() == "false":
with freeze_time("2015-01-01 12:00:00"):
response = client.schedule_key_deletion(
KeyId=key["KeyMetadata"]["KeyId"], PendingWindowInDays=7
)
assert response["KeyId"] == key["KeyMetadata"]["KeyId"]
assert response["DeletionDate"] == datetime(
2015, 1, 8, 12, 0, tzinfo=tzutc()
)
else:
# Can't manipulate time in server mode
response = client.schedule_key_deletion(
KeyId=key["KeyMetadata"]["KeyId"], PendingWindowInDays=7
)
assert response["KeyId"] == key["KeyMetadata"]["KeyId"]
result = client.describe_key(KeyId=key["KeyMetadata"]["KeyId"])
assert result["KeyMetadata"]["Enabled"] == False
assert result["KeyMetadata"]["KeyState"] == "PendingDeletion"
assert "DeletionDate" in result["KeyMetadata"]
@mock_kms
def test_cancel_key_deletion():
client = boto3.client("kms", region_name="us-east-1")
key = client.create_key(Description="cancel-key-deletion")
client.schedule_key_deletion(KeyId=key["KeyMetadata"]["KeyId"])
response = client.cancel_key_deletion(KeyId=key["KeyMetadata"]["KeyId"])
assert response["KeyId"] == key["KeyMetadata"]["KeyId"]
result = client.describe_key(KeyId=key["KeyMetadata"]["KeyId"])
assert result["KeyMetadata"]["Enabled"] == False
assert result["KeyMetadata"]["KeyState"] == "Disabled"
assert "DeletionDate" not in result["KeyMetadata"]
@mock_kms
def test_update_key_description():
client = boto3.client("kms", region_name="us-east-1")
key = client.create_key(Description="old_description")
key_id = key["KeyMetadata"]["KeyId"]
result = client.update_key_description(KeyId=key_id, Description="new_description")
assert "ResponseMetadata" in result
@mock_kms
def test_tag_resource():
client = boto3.client("kms", region_name="us-east-1")
key = client.create_key(Description="cancel-key-deletion")
response = client.schedule_key_deletion(KeyId=key["KeyMetadata"]["KeyId"])
keyid = response["KeyId"]
response = client.tag_resource(
KeyId=keyid, Tags=[{"TagKey": "string", "TagValue": "string"}]
)
# Shouldn't have any data, just header
assert len(response.keys()) == 1
@mock_kms
def test_list_resource_tags():
client = boto3.client("kms", region_name="us-east-1")
key = client.create_key(Description="cancel-key-deletion")
response = client.schedule_key_deletion(KeyId=key["KeyMetadata"]["KeyId"])
keyid = response["KeyId"]
response = client.tag_resource(
KeyId=keyid, Tags=[{"TagKey": "string", "TagValue": "string"}]
)
response = client.list_resource_tags(KeyId=keyid)
assert response["Tags"][0]["TagKey"] == "string"
assert response["Tags"][0]["TagValue"] == "string"
@parameterized(
(
(dict(KeySpec="AES_256"), 32),
(dict(KeySpec="AES_128"), 16),
(dict(NumberOfBytes=64), 64),
(dict(NumberOfBytes=1), 1),
(dict(NumberOfBytes=1024), 1024),
)
)
@mock_kms
def test_generate_data_key_sizes(kwargs, expected_key_length):
client = boto3.client("kms", region_name="us-east-1")
key = client.create_key(Description="generate-data-key-size")
response = client.generate_data_key(KeyId=key["KeyMetadata"]["KeyId"], **kwargs)
assert len(response["Plaintext"]) == expected_key_length
@mock_kms
def test_generate_data_key_decrypt():
client = boto3.client("kms", region_name="us-east-1")
key = client.create_key(Description="generate-data-key-decrypt")
resp1 = client.generate_data_key(
KeyId=key["KeyMetadata"]["KeyId"], KeySpec="AES_256"
)
resp2 = client.decrypt(CiphertextBlob=resp1["CiphertextBlob"])
assert resp1["Plaintext"] == resp2["Plaintext"]
@parameterized(
(
(dict(KeySpec="AES_257"),),
(dict(KeySpec="AES_128", NumberOfBytes=16),),
(dict(NumberOfBytes=2048),),
(dict(NumberOfBytes=0),),
(dict(),),
)
)
@mock_kms
def test_generate_data_key_invalid_size_params(kwargs):
client = boto3.client("kms", region_name="us-east-1")
key = client.create_key(Description="generate-data-key-size")
with assert_raises(
(botocore.exceptions.ClientError, botocore.exceptions.ParamValidationError)
) as err:
client.generate_data_key(KeyId=key["KeyMetadata"]["KeyId"], **kwargs)
@parameterized(
(
("alias/DoesNotExist",),
("arn:aws:kms:us-east-1:012345678912:alias/DoesNotExist",),
("d25652e4-d2d2-49f7-929a-671ccda580c6",),
(
"arn:aws:kms:us-east-1:012345678912:key/d25652e4-d2d2-49f7-929a-671ccda580c6",
),
)
)
@mock_kms
def test_generate_data_key_invalid_key(key_id):
client = boto3.client("kms", region_name="us-east-1")
with assert_raises(client.exceptions.NotFoundException):
client.generate_data_key(KeyId=key_id, KeySpec="AES_256")
@parameterized(
(
("alias/DoesExist", False),
("arn:aws:kms:us-east-1:012345678912:alias/DoesExist", False),
("", True),
("arn:aws:kms:us-east-1:012345678912:key/", True),
)
)
@mock_kms
def test_generate_data_key_all_valid_key_ids(prefix, append_key_id):
client = boto3.client("kms", region_name="us-east-1")
key = client.create_key()
key_id = key["KeyMetadata"]["KeyId"]
client.create_alias(AliasName="alias/DoesExist", TargetKeyId=key_id)
target_id = prefix
if append_key_id:
target_id += key_id
client.generate_data_key(KeyId=key_id, NumberOfBytes=32)
@mock_kms
def test_generate_data_key_without_plaintext_decrypt():
client = boto3.client("kms", region_name="us-east-1")
key = client.create_key(Description="generate-data-key-decrypt")
resp1 = client.generate_data_key_without_plaintext(
KeyId=key["KeyMetadata"]["KeyId"], KeySpec="AES_256"
)
assert "Plaintext" not in resp1
@parameterized(PLAINTEXT_VECTORS)
@mock_kms
def test_re_encrypt_decrypt(plaintext):
client = boto3.client("kms", region_name="us-west-2")
key_1 = client.create_key(Description="key 1")
key_1_id = key_1["KeyMetadata"]["KeyId"]
key_1_arn = key_1["KeyMetadata"]["Arn"]
key_2 = client.create_key(Description="key 2")
key_2_id = key_2["KeyMetadata"]["KeyId"]
key_2_arn = key_2["KeyMetadata"]["Arn"]
encrypt_response = client.encrypt(
KeyId=key_1_id, Plaintext=plaintext, EncryptionContext={"encryption": "context"}
)
re_encrypt_response = client.re_encrypt(
CiphertextBlob=encrypt_response["CiphertextBlob"],
SourceEncryptionContext={"encryption": "context"},
DestinationKeyId=key_2_id,
DestinationEncryptionContext={"another": "context"},
)
# CiphertextBlob must NOT be base64-encoded
with assert_raises(Exception):
base64.b64decode(re_encrypt_response["CiphertextBlob"], validate=True)
re_encrypt_response["SourceKeyId"].should.equal(key_1_arn)
re_encrypt_response["KeyId"].should.equal(key_2_arn)
decrypt_response_1 = client.decrypt(
CiphertextBlob=encrypt_response["CiphertextBlob"],
EncryptionContext={"encryption": "context"},
)
decrypt_response_1["Plaintext"].should.equal(_get_encoded_value(plaintext))
decrypt_response_1["KeyId"].should.equal(key_1_arn)
decrypt_response_2 = client.decrypt(
CiphertextBlob=re_encrypt_response["CiphertextBlob"],
EncryptionContext={"another": "context"},
)
decrypt_response_2["Plaintext"].should.equal(_get_encoded_value(plaintext))
decrypt_response_2["KeyId"].should.equal(key_2_arn)
decrypt_response_1["Plaintext"].should.equal(decrypt_response_2["Plaintext"])
@mock_kms
def test_re_encrypt_to_invalid_destination():
client = boto3.client("kms", region_name="us-west-2")
key = client.create_key(Description="key 1")
key_id = key["KeyMetadata"]["KeyId"]
encrypt_response = client.encrypt(KeyId=key_id, Plaintext=b"some plaintext")
with assert_raises(client.exceptions.NotFoundException):
client.re_encrypt(
CiphertextBlob=encrypt_response["CiphertextBlob"],
DestinationKeyId="alias/DoesNotExist",
)
@parameterized(((12,), (44,), (91,), (1,), (1024,)))
@mock_kms
def test_generate_random(number_of_bytes):
client = boto3.client("kms", region_name="us-west-2")
response = client.generate_random(NumberOfBytes=number_of_bytes)
response["Plaintext"].should.be.a(bytes)
len(response["Plaintext"]).should.equal(number_of_bytes)
@parameterized(
(
(2048, botocore.exceptions.ClientError),
(1025, botocore.exceptions.ClientError),
(0, botocore.exceptions.ParamValidationError),
(-1, botocore.exceptions.ParamValidationError),
(-1024, botocore.exceptions.ParamValidationError),
)
)
@mock_kms
def test_generate_random_invalid_number_of_bytes(number_of_bytes, error_type):
client = boto3.client("kms", region_name="us-west-2")
with assert_raises(error_type):
client.generate_random(NumberOfBytes=number_of_bytes)
@mock_kms
def test_enable_key_rotation_key_not_found():
client = boto3.client("kms", region_name="us-east-1")
with assert_raises(client.exceptions.NotFoundException):
client.enable_key_rotation(KeyId="12366f9b-1230-123d-123e-123e6ae60c02")
@mock_kms
def test_disable_key_rotation_key_not_found():
client = boto3.client("kms", region_name="us-east-1")
with assert_raises(client.exceptions.NotFoundException):
client.disable_key_rotation(KeyId="12366f9b-1230-123d-123e-123e6ae60c02")
@mock_kms
def test_enable_key_key_not_found():
client = boto3.client("kms", region_name="us-east-1")
with assert_raises(client.exceptions.NotFoundException):
client.enable_key(KeyId="12366f9b-1230-123d-123e-123e6ae60c02")
@mock_kms
def test_disable_key_key_not_found():
client = boto3.client("kms", region_name="us-east-1")
with assert_raises(client.exceptions.NotFoundException):
client.disable_key(KeyId="12366f9b-1230-123d-123e-123e6ae60c02")
@mock_kms
def test_cancel_key_deletion_key_not_found():
client = boto3.client("kms", region_name="us-east-1")
with assert_raises(client.exceptions.NotFoundException):
client.cancel_key_deletion(KeyId="12366f9b-1230-123d-123e-123e6ae60c02")
@mock_kms
def test_schedule_key_deletion_key_not_found():
client = boto3.client("kms", region_name="us-east-1")
with assert_raises(client.exceptions.NotFoundException):
client.schedule_key_deletion(KeyId="12366f9b-1230-123d-123e-123e6ae60c02")
@mock_kms
def test_get_key_rotation_status_key_not_found():
client = boto3.client("kms", region_name="us-east-1")
with assert_raises(client.exceptions.NotFoundException):
client.get_key_rotation_status(KeyId="12366f9b-1230-123d-123e-123e6ae60c02")
@mock_kms
def test_get_key_policy_key_not_found():
client = boto3.client("kms", region_name="us-east-1")
with assert_raises(client.exceptions.NotFoundException):
client.get_key_policy(
KeyId="12366f9b-1230-123d-123e-123e6ae60c02", PolicyName="default"
)
@mock_kms
def test_list_key_policies_key_not_found():
client = boto3.client("kms", region_name="us-east-1")
with assert_raises(client.exceptions.NotFoundException):
client.list_key_policies(KeyId="12366f9b-1230-123d-123e-123e6ae60c02")
@mock_kms
def test_put_key_policy_key_not_found():
client = boto3.client("kms", region_name="us-east-1")
with assert_raises(client.exceptions.NotFoundException):
client.put_key_policy(
KeyId="00000000-0000-0000-0000-000000000000",
PolicyName="default",
Policy="new policy",
)

View file

@ -102,7 +102,7 @@ def test_deserialize_ciphertext_blob(raw, serialized):
@parameterized(((ec[0],) for ec in ENCRYPTION_CONTEXT_VECTORS))
def test_encrypt_decrypt_cycle(encryption_context):
plaintext = b"some secret plaintext"
master_key = Key("nop", "nop", "nop", "nop")
master_key = Key("nop", "nop", "nop", "nop", [], "nop")
master_key_map = {master_key.id: master_key}
ciphertext_blob = encrypt(
@ -133,7 +133,7 @@ def test_encrypt_unknown_key_id():
def test_decrypt_invalid_ciphertext_format():
master_key = Key("nop", "nop", "nop", "nop")
master_key = Key("nop", "nop", "nop", "nop", [], "nop")
master_key_map = {master_key.id: master_key}
with assert_raises(InvalidCiphertextException):
@ -153,7 +153,7 @@ def test_decrypt_unknwown_key_id():
def test_decrypt_invalid_ciphertext():
master_key = Key("nop", "nop", "nop", "nop")
master_key = Key("nop", "nop", "nop", "nop", [], "nop")
master_key_map = {master_key.id: master_key}
ciphertext_blob = (
master_key.id.encode("utf-8") + b"123456789012"
@ -171,7 +171,7 @@ def test_decrypt_invalid_ciphertext():
def test_decrypt_invalid_encryption_context():
plaintext = b"some secret plaintext"
master_key = Key("nop", "nop", "nop", "nop")
master_key = Key("nop", "nop", "nop", "nop", [], "nop")
master_key_map = {master_key.id: master_key}
ciphertext_blob = encrypt(

View file

@ -1,76 +1,76 @@
from __future__ import unicode_literals
import boto3
from freezegun import freeze_time
import sure # noqa
import re
from moto import mock_opsworks
@freeze_time("2015-01-01")
@mock_opsworks
def test_create_app_response():
client = boto3.client("opsworks", region_name="us-east-1")
stack_id = client.create_stack(
Name="test_stack_1",
Region="us-east-1",
ServiceRoleArn="service_arn",
DefaultInstanceProfileArn="profile_arn",
)["StackId"]
response = client.create_app(StackId=stack_id, Type="other", Name="TestApp")
response.should.contain("AppId")
second_stack_id = client.create_stack(
Name="test_stack_2",
Region="us-east-1",
ServiceRoleArn="service_arn",
DefaultInstanceProfileArn="profile_arn",
)["StackId"]
response = client.create_app(StackId=second_stack_id, Type="other", Name="TestApp")
response.should.contain("AppId")
# ClientError
client.create_app.when.called_with(
StackId=stack_id, Type="other", Name="TestApp"
).should.throw(Exception, re.compile(r'already an app named "TestApp"'))
# ClientError
client.create_app.when.called_with(
StackId="nothere", Type="other", Name="TestApp"
).should.throw(Exception, "nothere")
@freeze_time("2015-01-01")
@mock_opsworks
def test_describe_apps():
client = boto3.client("opsworks", region_name="us-east-1")
stack_id = client.create_stack(
Name="test_stack_1",
Region="us-east-1",
ServiceRoleArn="service_arn",
DefaultInstanceProfileArn="profile_arn",
)["StackId"]
app_id = client.create_app(StackId=stack_id, Type="other", Name="TestApp")["AppId"]
rv1 = client.describe_apps(StackId=stack_id)
rv2 = client.describe_apps(AppIds=[app_id])
rv1["Apps"].should.equal(rv2["Apps"])
rv1["Apps"][0]["Name"].should.equal("TestApp")
# ClientError
client.describe_apps.when.called_with(
StackId=stack_id, AppIds=[app_id]
).should.throw(Exception, "Please provide one or more app IDs or a stack ID")
# ClientError
client.describe_apps.when.called_with(StackId="nothere").should.throw(
Exception, "Unable to find stack with ID nothere"
)
# ClientError
client.describe_apps.when.called_with(AppIds=["nothere"]).should.throw(
Exception, "nothere"
)
from __future__ import unicode_literals
import boto3
from freezegun import freeze_time
import sure # noqa
import re
from moto import mock_opsworks
@freeze_time("2015-01-01")
@mock_opsworks
def test_create_app_response():
client = boto3.client("opsworks", region_name="us-east-1")
stack_id = client.create_stack(
Name="test_stack_1",
Region="us-east-1",
ServiceRoleArn="service_arn",
DefaultInstanceProfileArn="profile_arn",
)["StackId"]
response = client.create_app(StackId=stack_id, Type="other", Name="TestApp")
response.should.contain("AppId")
second_stack_id = client.create_stack(
Name="test_stack_2",
Region="us-east-1",
ServiceRoleArn="service_arn",
DefaultInstanceProfileArn="profile_arn",
)["StackId"]
response = client.create_app(StackId=second_stack_id, Type="other", Name="TestApp")
response.should.contain("AppId")
# ClientError
client.create_app.when.called_with(
StackId=stack_id, Type="other", Name="TestApp"
).should.throw(Exception, re.compile(r'already an app named "TestApp"'))
# ClientError
client.create_app.when.called_with(
StackId="nothere", Type="other", Name="TestApp"
).should.throw(Exception, "nothere")
@freeze_time("2015-01-01")
@mock_opsworks
def test_describe_apps():
client = boto3.client("opsworks", region_name="us-east-1")
stack_id = client.create_stack(
Name="test_stack_1",
Region="us-east-1",
ServiceRoleArn="service_arn",
DefaultInstanceProfileArn="profile_arn",
)["StackId"]
app_id = client.create_app(StackId=stack_id, Type="other", Name="TestApp")["AppId"]
rv1 = client.describe_apps(StackId=stack_id)
rv2 = client.describe_apps(AppIds=[app_id])
rv1["Apps"].should.equal(rv2["Apps"])
rv1["Apps"][0]["Name"].should.equal("TestApp")
# ClientError
client.describe_apps.when.called_with(
StackId=stack_id, AppIds=[app_id]
).should.throw(Exception, "Please provide one or more app IDs or a stack ID")
# ClientError
client.describe_apps.when.called_with(StackId="nothere").should.throw(
Exception, "Unable to find stack with ID nothere"
)
# ClientError
client.describe_apps.when.called_with(AppIds=["nothere"]).should.throw(
Exception, "nothere"
)

View file

@ -1,206 +1,206 @@
from __future__ import unicode_literals
import boto3
import sure # noqa
from moto import mock_opsworks
from moto import mock_ec2
@mock_opsworks
def test_create_instance():
client = boto3.client("opsworks", region_name="us-east-1")
stack_id = client.create_stack(
Name="test_stack_1",
Region="us-east-1",
ServiceRoleArn="service_arn",
DefaultInstanceProfileArn="profile_arn",
)["StackId"]
layer_id = client.create_layer(
StackId=stack_id,
Type="custom",
Name="TestLayer",
Shortname="TestLayerShortName",
)["LayerId"]
second_stack_id = client.create_stack(
Name="test_stack_2",
Region="us-east-1",
ServiceRoleArn="service_arn",
DefaultInstanceProfileArn="profile_arn",
)["StackId"]
second_layer_id = client.create_layer(
StackId=second_stack_id,
Type="custom",
Name="SecondTestLayer",
Shortname="SecondTestLayerShortName",
)["LayerId"]
response = client.create_instance(
StackId=stack_id, LayerIds=[layer_id], InstanceType="t2.micro"
)
response.should.contain("InstanceId")
client.create_instance.when.called_with(
StackId="nothere", LayerIds=[layer_id], InstanceType="t2.micro"
).should.throw(Exception, "Unable to find stack with ID nothere")
client.create_instance.when.called_with(
StackId=stack_id, LayerIds=["nothere"], InstanceType="t2.micro"
).should.throw(Exception, "nothere")
# ClientError
client.create_instance.when.called_with(
StackId=stack_id, LayerIds=[second_layer_id], InstanceType="t2.micro"
).should.throw(Exception, "Please only provide layer IDs from the same stack")
# ClientError
client.start_instance.when.called_with(InstanceId="nothere").should.throw(
Exception, "Unable to find instance with ID nothere"
)
@mock_opsworks
def test_describe_instances():
"""
create two stacks, with 1 layer and 2 layers (S1L1, S2L1, S2L2)
populate S1L1 with 2 instances (S1L1_i1, S1L1_i2)
populate S2L1 with 1 instance (S2L1_i1)
populate S2L2 with 3 instances (S2L2_i1..2)
"""
client = boto3.client("opsworks", region_name="us-east-1")
S1 = client.create_stack(
Name="S1",
Region="us-east-1",
ServiceRoleArn="service_arn",
DefaultInstanceProfileArn="profile_arn",
)["StackId"]
S1L1 = client.create_layer(
StackId=S1, Type="custom", Name="S1L1", Shortname="S1L1"
)["LayerId"]
S2 = client.create_stack(
Name="S2",
Region="us-east-1",
ServiceRoleArn="service_arn",
DefaultInstanceProfileArn="profile_arn",
)["StackId"]
S2L1 = client.create_layer(
StackId=S2, Type="custom", Name="S2L1", Shortname="S2L1"
)["LayerId"]
S2L2 = client.create_layer(
StackId=S2, Type="custom", Name="S2L2", Shortname="S2L2"
)["LayerId"]
S1L1_i1 = client.create_instance(
StackId=S1, LayerIds=[S1L1], InstanceType="t2.micro"
)["InstanceId"]
S1L1_i2 = client.create_instance(
StackId=S1, LayerIds=[S1L1], InstanceType="t2.micro"
)["InstanceId"]
S2L1_i1 = client.create_instance(
StackId=S2, LayerIds=[S2L1], InstanceType="t2.micro"
)["InstanceId"]
S2L2_i1 = client.create_instance(
StackId=S2, LayerIds=[S2L2], InstanceType="t2.micro"
)["InstanceId"]
S2L2_i2 = client.create_instance(
StackId=S2, LayerIds=[S2L2], InstanceType="t2.micro"
)["InstanceId"]
# instances in Stack 1
response = client.describe_instances(StackId=S1)["Instances"]
response.should.have.length_of(2)
S1L1_i1.should.be.within([i["InstanceId"] for i in response])
S1L1_i2.should.be.within([i["InstanceId"] for i in response])
response2 = client.describe_instances(InstanceIds=[S1L1_i1, S1L1_i2])["Instances"]
sorted(response2, key=lambda d: d["InstanceId"]).should.equal(
sorted(response, key=lambda d: d["InstanceId"])
)
response3 = client.describe_instances(LayerId=S1L1)["Instances"]
sorted(response3, key=lambda d: d["InstanceId"]).should.equal(
sorted(response, key=lambda d: d["InstanceId"])
)
response = client.describe_instances(StackId=S1)["Instances"]
response.should.have.length_of(2)
S1L1_i1.should.be.within([i["InstanceId"] for i in response])
S1L1_i2.should.be.within([i["InstanceId"] for i in response])
# instances in Stack 2
response = client.describe_instances(StackId=S2)["Instances"]
response.should.have.length_of(3)
S2L1_i1.should.be.within([i["InstanceId"] for i in response])
S2L2_i1.should.be.within([i["InstanceId"] for i in response])
S2L2_i2.should.be.within([i["InstanceId"] for i in response])
response = client.describe_instances(LayerId=S2L1)["Instances"]
response.should.have.length_of(1)
S2L1_i1.should.be.within([i["InstanceId"] for i in response])
response = client.describe_instances(LayerId=S2L2)["Instances"]
response.should.have.length_of(2)
S2L1_i1.should_not.be.within([i["InstanceId"] for i in response])
# ClientError
client.describe_instances.when.called_with(StackId=S1, LayerId=S1L1).should.throw(
Exception, "Please provide either one or more"
)
# ClientError
client.describe_instances.when.called_with(StackId="nothere").should.throw(
Exception, "nothere"
)
# ClientError
client.describe_instances.when.called_with(LayerId="nothere").should.throw(
Exception, "nothere"
)
# ClientError
client.describe_instances.when.called_with(InstanceIds=["nothere"]).should.throw(
Exception, "nothere"
)
@mock_opsworks
@mock_ec2
def test_ec2_integration():
"""
instances created via OpsWorks should be discoverable via ec2
"""
opsworks = boto3.client("opsworks", region_name="us-east-1")
stack_id = opsworks.create_stack(
Name="S1",
Region="us-east-1",
ServiceRoleArn="service_arn",
DefaultInstanceProfileArn="profile_arn",
)["StackId"]
layer_id = opsworks.create_layer(
StackId=stack_id, Type="custom", Name="S1L1", Shortname="S1L1"
)["LayerId"]
instance_id = opsworks.create_instance(
StackId=stack_id,
LayerIds=[layer_id],
InstanceType="t2.micro",
SshKeyName="testSSH",
)["InstanceId"]
ec2 = boto3.client("ec2", region_name="us-east-1")
# Before starting the instance, it shouldn't be discoverable via ec2
reservations = ec2.describe_instances()["Reservations"]
assert reservations.should.be.empty
# After starting the instance, it should be discoverable via ec2
opsworks.start_instance(InstanceId=instance_id)
reservations = ec2.describe_instances()["Reservations"]
reservations[0]["Instances"].should.have.length_of(1)
instance = reservations[0]["Instances"][0]
opsworks_instance = opsworks.describe_instances(StackId=stack_id)["Instances"][0]
instance["InstanceId"].should.equal(opsworks_instance["Ec2InstanceId"])
instance["PrivateIpAddress"].should.equal(opsworks_instance["PrivateIp"])
from __future__ import unicode_literals
import boto3
import sure # noqa
from moto import mock_opsworks
from moto import mock_ec2
@mock_opsworks
def test_create_instance():
client = boto3.client("opsworks", region_name="us-east-1")
stack_id = client.create_stack(
Name="test_stack_1",
Region="us-east-1",
ServiceRoleArn="service_arn",
DefaultInstanceProfileArn="profile_arn",
)["StackId"]
layer_id = client.create_layer(
StackId=stack_id,
Type="custom",
Name="TestLayer",
Shortname="TestLayerShortName",
)["LayerId"]
second_stack_id = client.create_stack(
Name="test_stack_2",
Region="us-east-1",
ServiceRoleArn="service_arn",
DefaultInstanceProfileArn="profile_arn",
)["StackId"]
second_layer_id = client.create_layer(
StackId=second_stack_id,
Type="custom",
Name="SecondTestLayer",
Shortname="SecondTestLayerShortName",
)["LayerId"]
response = client.create_instance(
StackId=stack_id, LayerIds=[layer_id], InstanceType="t2.micro"
)
response.should.contain("InstanceId")
client.create_instance.when.called_with(
StackId="nothere", LayerIds=[layer_id], InstanceType="t2.micro"
).should.throw(Exception, "Unable to find stack with ID nothere")
client.create_instance.when.called_with(
StackId=stack_id, LayerIds=["nothere"], InstanceType="t2.micro"
).should.throw(Exception, "nothere")
# ClientError
client.create_instance.when.called_with(
StackId=stack_id, LayerIds=[second_layer_id], InstanceType="t2.micro"
).should.throw(Exception, "Please only provide layer IDs from the same stack")
# ClientError
client.start_instance.when.called_with(InstanceId="nothere").should.throw(
Exception, "Unable to find instance with ID nothere"
)
@mock_opsworks
def test_describe_instances():
"""
create two stacks, with 1 layer and 2 layers (S1L1, S2L1, S2L2)
populate S1L1 with 2 instances (S1L1_i1, S1L1_i2)
populate S2L1 with 1 instance (S2L1_i1)
populate S2L2 with 3 instances (S2L2_i1..2)
"""
client = boto3.client("opsworks", region_name="us-east-1")
S1 = client.create_stack(
Name="S1",
Region="us-east-1",
ServiceRoleArn="service_arn",
DefaultInstanceProfileArn="profile_arn",
)["StackId"]
S1L1 = client.create_layer(
StackId=S1, Type="custom", Name="S1L1", Shortname="S1L1"
)["LayerId"]
S2 = client.create_stack(
Name="S2",
Region="us-east-1",
ServiceRoleArn="service_arn",
DefaultInstanceProfileArn="profile_arn",
)["StackId"]
S2L1 = client.create_layer(
StackId=S2, Type="custom", Name="S2L1", Shortname="S2L1"
)["LayerId"]
S2L2 = client.create_layer(
StackId=S2, Type="custom", Name="S2L2", Shortname="S2L2"
)["LayerId"]
S1L1_i1 = client.create_instance(
StackId=S1, LayerIds=[S1L1], InstanceType="t2.micro"
)["InstanceId"]
S1L1_i2 = client.create_instance(
StackId=S1, LayerIds=[S1L1], InstanceType="t2.micro"
)["InstanceId"]
S2L1_i1 = client.create_instance(
StackId=S2, LayerIds=[S2L1], InstanceType="t2.micro"
)["InstanceId"]
S2L2_i1 = client.create_instance(
StackId=S2, LayerIds=[S2L2], InstanceType="t2.micro"
)["InstanceId"]
S2L2_i2 = client.create_instance(
StackId=S2, LayerIds=[S2L2], InstanceType="t2.micro"
)["InstanceId"]
# instances in Stack 1
response = client.describe_instances(StackId=S1)["Instances"]
response.should.have.length_of(2)
S1L1_i1.should.be.within([i["InstanceId"] for i in response])
S1L1_i2.should.be.within([i["InstanceId"] for i in response])
response2 = client.describe_instances(InstanceIds=[S1L1_i1, S1L1_i2])["Instances"]
sorted(response2, key=lambda d: d["InstanceId"]).should.equal(
sorted(response, key=lambda d: d["InstanceId"])
)
response3 = client.describe_instances(LayerId=S1L1)["Instances"]
sorted(response3, key=lambda d: d["InstanceId"]).should.equal(
sorted(response, key=lambda d: d["InstanceId"])
)
response = client.describe_instances(StackId=S1)["Instances"]
response.should.have.length_of(2)
S1L1_i1.should.be.within([i["InstanceId"] for i in response])
S1L1_i2.should.be.within([i["InstanceId"] for i in response])
# instances in Stack 2
response = client.describe_instances(StackId=S2)["Instances"]
response.should.have.length_of(3)
S2L1_i1.should.be.within([i["InstanceId"] for i in response])
S2L2_i1.should.be.within([i["InstanceId"] for i in response])
S2L2_i2.should.be.within([i["InstanceId"] for i in response])
response = client.describe_instances(LayerId=S2L1)["Instances"]
response.should.have.length_of(1)
S2L1_i1.should.be.within([i["InstanceId"] for i in response])
response = client.describe_instances(LayerId=S2L2)["Instances"]
response.should.have.length_of(2)
S2L1_i1.should_not.be.within([i["InstanceId"] for i in response])
# ClientError
client.describe_instances.when.called_with(StackId=S1, LayerId=S1L1).should.throw(
Exception, "Please provide either one or more"
)
# ClientError
client.describe_instances.when.called_with(StackId="nothere").should.throw(
Exception, "nothere"
)
# ClientError
client.describe_instances.when.called_with(LayerId="nothere").should.throw(
Exception, "nothere"
)
# ClientError
client.describe_instances.when.called_with(InstanceIds=["nothere"]).should.throw(
Exception, "nothere"
)
@mock_opsworks
@mock_ec2
def test_ec2_integration():
"""
instances created via OpsWorks should be discoverable via ec2
"""
opsworks = boto3.client("opsworks", region_name="us-east-1")
stack_id = opsworks.create_stack(
Name="S1",
Region="us-east-1",
ServiceRoleArn="service_arn",
DefaultInstanceProfileArn="profile_arn",
)["StackId"]
layer_id = opsworks.create_layer(
StackId=stack_id, Type="custom", Name="S1L1", Shortname="S1L1"
)["LayerId"]
instance_id = opsworks.create_instance(
StackId=stack_id,
LayerIds=[layer_id],
InstanceType="t2.micro",
SshKeyName="testSSH",
)["InstanceId"]
ec2 = boto3.client("ec2", region_name="us-east-1")
# Before starting the instance, it shouldn't be discoverable via ec2
reservations = ec2.describe_instances()["Reservations"]
assert reservations.should.be.empty
# After starting the instance, it should be discoverable via ec2
opsworks.start_instance(InstanceId=instance_id)
reservations = ec2.describe_instances()["Reservations"]
reservations[0]["Instances"].should.have.length_of(1)
instance = reservations[0]["Instances"][0]
opsworks_instance = opsworks.describe_instances(StackId=stack_id)["Instances"][0]
instance["InstanceId"].should.equal(opsworks_instance["Ec2InstanceId"])
instance["PrivateIpAddress"].should.equal(opsworks_instance["PrivateIp"])

View file

@ -1,96 +1,96 @@
from __future__ import unicode_literals
import boto3
from freezegun import freeze_time
import sure # noqa
import re
from moto import mock_opsworks
@freeze_time("2015-01-01")
@mock_opsworks
def test_create_layer_response():
client = boto3.client("opsworks", region_name="us-east-1")
stack_id = client.create_stack(
Name="test_stack_1",
Region="us-east-1",
ServiceRoleArn="service_arn",
DefaultInstanceProfileArn="profile_arn",
)["StackId"]
response = client.create_layer(
StackId=stack_id,
Type="custom",
Name="TestLayer",
Shortname="TestLayerShortName",
)
response.should.contain("LayerId")
second_stack_id = client.create_stack(
Name="test_stack_2",
Region="us-east-1",
ServiceRoleArn="service_arn",
DefaultInstanceProfileArn="profile_arn",
)["StackId"]
response = client.create_layer(
StackId=second_stack_id,
Type="custom",
Name="TestLayer",
Shortname="TestLayerShortName",
)
response.should.contain("LayerId")
# ClientError
client.create_layer.when.called_with(
StackId=stack_id, Type="custom", Name="TestLayer", Shortname="_"
).should.throw(Exception, re.compile(r'already a layer named "TestLayer"'))
# ClientError
client.create_layer.when.called_with(
StackId=stack_id, Type="custom", Name="_", Shortname="TestLayerShortName"
).should.throw(
Exception, re.compile(r'already a layer with shortname "TestLayerShortName"')
)
# ClientError
client.create_layer.when.called_with(
StackId="nothere", Type="custom", Name="TestLayer", Shortname="_"
).should.throw(Exception, "nothere")
@freeze_time("2015-01-01")
@mock_opsworks
def test_describe_layers():
client = boto3.client("opsworks", region_name="us-east-1")
stack_id = client.create_stack(
Name="test_stack_1",
Region="us-east-1",
ServiceRoleArn="service_arn",
DefaultInstanceProfileArn="profile_arn",
)["StackId"]
layer_id = client.create_layer(
StackId=stack_id,
Type="custom",
Name="TestLayer",
Shortname="TestLayerShortName",
)["LayerId"]
rv1 = client.describe_layers(StackId=stack_id)
rv2 = client.describe_layers(LayerIds=[layer_id])
rv1["Layers"].should.equal(rv2["Layers"])
rv1["Layers"][0]["Name"].should.equal("TestLayer")
# ClientError
client.describe_layers.when.called_with(
StackId=stack_id, LayerIds=[layer_id]
).should.throw(Exception, "Please provide one or more layer IDs or a stack ID")
# ClientError
client.describe_layers.when.called_with(StackId="nothere").should.throw(
Exception, "Unable to find stack with ID nothere"
)
# ClientError
client.describe_layers.when.called_with(LayerIds=["nothere"]).should.throw(
Exception, "nothere"
)
from __future__ import unicode_literals
import boto3
from freezegun import freeze_time
import sure # noqa
import re
from moto import mock_opsworks
@freeze_time("2015-01-01")
@mock_opsworks
def test_create_layer_response():
client = boto3.client("opsworks", region_name="us-east-1")
stack_id = client.create_stack(
Name="test_stack_1",
Region="us-east-1",
ServiceRoleArn="service_arn",
DefaultInstanceProfileArn="profile_arn",
)["StackId"]
response = client.create_layer(
StackId=stack_id,
Type="custom",
Name="TestLayer",
Shortname="TestLayerShortName",
)
response.should.contain("LayerId")
second_stack_id = client.create_stack(
Name="test_stack_2",
Region="us-east-1",
ServiceRoleArn="service_arn",
DefaultInstanceProfileArn="profile_arn",
)["StackId"]
response = client.create_layer(
StackId=second_stack_id,
Type="custom",
Name="TestLayer",
Shortname="TestLayerShortName",
)
response.should.contain("LayerId")
# ClientError
client.create_layer.when.called_with(
StackId=stack_id, Type="custom", Name="TestLayer", Shortname="_"
).should.throw(Exception, re.compile(r'already a layer named "TestLayer"'))
# ClientError
client.create_layer.when.called_with(
StackId=stack_id, Type="custom", Name="_", Shortname="TestLayerShortName"
).should.throw(
Exception, re.compile(r'already a layer with shortname "TestLayerShortName"')
)
# ClientError
client.create_layer.when.called_with(
StackId="nothere", Type="custom", Name="TestLayer", Shortname="_"
).should.throw(Exception, "nothere")
@freeze_time("2015-01-01")
@mock_opsworks
def test_describe_layers():
client = boto3.client("opsworks", region_name="us-east-1")
stack_id = client.create_stack(
Name="test_stack_1",
Region="us-east-1",
ServiceRoleArn="service_arn",
DefaultInstanceProfileArn="profile_arn",
)["StackId"]
layer_id = client.create_layer(
StackId=stack_id,
Type="custom",
Name="TestLayer",
Shortname="TestLayerShortName",
)["LayerId"]
rv1 = client.describe_layers(StackId=stack_id)
rv2 = client.describe_layers(LayerIds=[layer_id])
rv1["Layers"].should.equal(rv2["Layers"])
rv1["Layers"][0]["Name"].should.equal("TestLayer")
# ClientError
client.describe_layers.when.called_with(
StackId=stack_id, LayerIds=[layer_id]
).should.throw(Exception, "Please provide one or more layer IDs or a stack ID")
# ClientError
client.describe_layers.when.called_with(StackId="nothere").should.throw(
Exception, "Unable to find stack with ID nothere"
)
# ClientError
client.describe_layers.when.called_with(LayerIds=["nothere"]).should.throw(
Exception, "nothere"
)

View file

@ -713,3 +713,41 @@ def test_untag_resource_errors():
ex.response["Error"]["Message"].should.equal(
"You provided a value that does not match the required pattern."
)
@mock_organizations
def test_update_organizational_unit():
client = boto3.client("organizations", region_name="us-east-1")
org = client.create_organization(FeatureSet="ALL")["Organization"]
root_id = client.list_roots()["Roots"][0]["Id"]
ou_name = "ou01"
response = client.create_organizational_unit(ParentId=root_id, Name=ou_name)
validate_organizational_unit(org, response)
response["OrganizationalUnit"]["Name"].should.equal(ou_name)
new_ou_name = "ou02"
response = client.update_organizational_unit(
OrganizationalUnitId=response["OrganizationalUnit"]["Id"], Name=new_ou_name
)
validate_organizational_unit(org, response)
response["OrganizationalUnit"]["Name"].should.equal(new_ou_name)
@mock_organizations
def test_update_organizational_unit_duplicate_error():
client = boto3.client("organizations", region_name="us-east-1")
org = client.create_organization(FeatureSet="ALL")["Organization"]
root_id = client.list_roots()["Roots"][0]["Id"]
ou_name = "ou01"
response = client.create_organizational_unit(ParentId=root_id, Name=ou_name)
validate_organizational_unit(org, response)
response["OrganizationalUnit"]["Name"].should.equal(ou_name)
with assert_raises(ClientError) as e:
client.update_organizational_unit(
OrganizationalUnitId=response["OrganizationalUnit"]["Id"], Name=ou_name
)
exc = e.exception
exc.operation_name.should.equal("UpdateOrganizationalUnit")
exc.response["Error"]["Code"].should.contain("DuplicateOrganizationalUnitException")
exc.response["Error"]["Message"].should.equal(
"An OU with the same name already exists."
)

View file

@ -1,263 +1,263 @@
from __future__ import unicode_literals
from botocore.exceptions import ClientError
import boto3
import sure # noqa
from nose.tools import assert_raises
from moto import mock_polly
# Polly only available in a few regions
DEFAULT_REGION = "eu-west-1"
LEXICON_XML = """<?xml version="1.0" encoding="UTF-8"?>
<lexicon version="1.0"
xmlns="http://www.w3.org/2005/01/pronunciation-lexicon"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.w3.org/2005/01/pronunciation-lexicon
http://www.w3.org/TR/2007/CR-pronunciation-lexicon-20071212/pls.xsd"
alphabet="ipa"
xml:lang="en-US">
<lexeme>
<grapheme>W3C</grapheme>
<alias>World Wide Web Consortium</alias>
</lexeme>
</lexicon>"""
@mock_polly
def test_describe_voices():
client = boto3.client("polly", region_name=DEFAULT_REGION)
resp = client.describe_voices()
len(resp["Voices"]).should.be.greater_than(1)
resp = client.describe_voices(LanguageCode="en-GB")
len(resp["Voices"]).should.equal(3)
try:
client.describe_voices(LanguageCode="SOME_LANGUAGE")
except ClientError as err:
err.response["Error"]["Code"].should.equal("400")
else:
raise RuntimeError("Should of raised an exception")
@mock_polly
def test_put_list_lexicon():
client = boto3.client("polly", region_name=DEFAULT_REGION)
# Return nothing
client.put_lexicon(Name="test", Content=LEXICON_XML)
resp = client.list_lexicons()
len(resp["Lexicons"]).should.equal(1)
@mock_polly
def test_put_get_lexicon():
client = boto3.client("polly", region_name=DEFAULT_REGION)
# Return nothing
client.put_lexicon(Name="test", Content=LEXICON_XML)
resp = client.get_lexicon(Name="test")
resp.should.contain("Lexicon")
resp.should.contain("LexiconAttributes")
@mock_polly
def test_put_lexicon_bad_name():
client = boto3.client("polly", region_name=DEFAULT_REGION)
try:
client.put_lexicon(Name="test-invalid", Content=LEXICON_XML)
except ClientError as err:
err.response["Error"]["Code"].should.equal("InvalidParameterValue")
else:
raise RuntimeError("Should of raised an exception")
@mock_polly
def test_synthesize_speech():
client = boto3.client("polly", region_name=DEFAULT_REGION)
# Return nothing
client.put_lexicon(Name="test", Content=LEXICON_XML)
tests = (("pcm", "audio/pcm"), ("mp3", "audio/mpeg"), ("ogg_vorbis", "audio/ogg"))
for output_format, content_type in tests:
resp = client.synthesize_speech(
LexiconNames=["test"],
OutputFormat=output_format,
SampleRate="16000",
Text="test1234",
TextType="text",
VoiceId="Astrid",
)
resp["ContentType"].should.equal(content_type)
@mock_polly
def test_synthesize_speech_bad_lexicon():
client = boto3.client("polly", region_name=DEFAULT_REGION)
client.put_lexicon(Name="test", Content=LEXICON_XML)
try:
client.synthesize_speech(
LexiconNames=["test2"],
OutputFormat="pcm",
SampleRate="16000",
Text="test1234",
TextType="text",
VoiceId="Astrid",
)
except ClientError as err:
err.response["Error"]["Code"].should.equal("LexiconNotFoundException")
else:
raise RuntimeError("Should of raised LexiconNotFoundException")
@mock_polly
def test_synthesize_speech_bad_output_format():
client = boto3.client("polly", region_name=DEFAULT_REGION)
client.put_lexicon(Name="test", Content=LEXICON_XML)
try:
client.synthesize_speech(
LexiconNames=["test"],
OutputFormat="invalid",
SampleRate="16000",
Text="test1234",
TextType="text",
VoiceId="Astrid",
)
except ClientError as err:
err.response["Error"]["Code"].should.equal("InvalidParameterValue")
else:
raise RuntimeError("Should of raised ")
@mock_polly
def test_synthesize_speech_bad_sample_rate():
client = boto3.client("polly", region_name=DEFAULT_REGION)
client.put_lexicon(Name="test", Content=LEXICON_XML)
try:
client.synthesize_speech(
LexiconNames=["test"],
OutputFormat="pcm",
SampleRate="18000",
Text="test1234",
TextType="text",
VoiceId="Astrid",
)
except ClientError as err:
err.response["Error"]["Code"].should.equal("InvalidSampleRateException")
else:
raise RuntimeError("Should of raised ")
@mock_polly
def test_synthesize_speech_bad_text_type():
client = boto3.client("polly", region_name=DEFAULT_REGION)
client.put_lexicon(Name="test", Content=LEXICON_XML)
try:
client.synthesize_speech(
LexiconNames=["test"],
OutputFormat="pcm",
SampleRate="16000",
Text="test1234",
TextType="invalid",
VoiceId="Astrid",
)
except ClientError as err:
err.response["Error"]["Code"].should.equal("InvalidParameterValue")
else:
raise RuntimeError("Should of raised ")
@mock_polly
def test_synthesize_speech_bad_voice_id():
client = boto3.client("polly", region_name=DEFAULT_REGION)
client.put_lexicon(Name="test", Content=LEXICON_XML)
try:
client.synthesize_speech(
LexiconNames=["test"],
OutputFormat="pcm",
SampleRate="16000",
Text="test1234",
TextType="text",
VoiceId="Luke",
)
except ClientError as err:
err.response["Error"]["Code"].should.equal("InvalidParameterValue")
else:
raise RuntimeError("Should of raised ")
@mock_polly
def test_synthesize_speech_text_too_long():
client = boto3.client("polly", region_name=DEFAULT_REGION)
client.put_lexicon(Name="test", Content=LEXICON_XML)
try:
client.synthesize_speech(
LexiconNames=["test"],
OutputFormat="pcm",
SampleRate="16000",
Text="test1234" * 376, # = 3008 characters
TextType="text",
VoiceId="Astrid",
)
except ClientError as err:
err.response["Error"]["Code"].should.equal("TextLengthExceededException")
else:
raise RuntimeError("Should of raised ")
@mock_polly
def test_synthesize_speech_bad_speech_marks1():
client = boto3.client("polly", region_name=DEFAULT_REGION)
client.put_lexicon(Name="test", Content=LEXICON_XML)
try:
client.synthesize_speech(
LexiconNames=["test"],
OutputFormat="pcm",
SampleRate="16000",
Text="test1234",
TextType="text",
SpeechMarkTypes=["word"],
VoiceId="Astrid",
)
except ClientError as err:
err.response["Error"]["Code"].should.equal(
"MarksNotSupportedForFormatException"
)
else:
raise RuntimeError("Should of raised ")
@mock_polly
def test_synthesize_speech_bad_speech_marks2():
client = boto3.client("polly", region_name=DEFAULT_REGION)
client.put_lexicon(Name="test", Content=LEXICON_XML)
try:
client.synthesize_speech(
LexiconNames=["test"],
OutputFormat="pcm",
SampleRate="16000",
Text="test1234",
TextType="ssml",
SpeechMarkTypes=["word"],
VoiceId="Astrid",
)
except ClientError as err:
err.response["Error"]["Code"].should.equal(
"MarksNotSupportedForFormatException"
)
else:
raise RuntimeError("Should of raised ")
from __future__ import unicode_literals
from botocore.exceptions import ClientError
import boto3
import sure # noqa
from nose.tools import assert_raises
from moto import mock_polly
# Polly only available in a few regions
DEFAULT_REGION = "eu-west-1"
LEXICON_XML = """<?xml version="1.0" encoding="UTF-8"?>
<lexicon version="1.0"
xmlns="http://www.w3.org/2005/01/pronunciation-lexicon"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.w3.org/2005/01/pronunciation-lexicon
http://www.w3.org/TR/2007/CR-pronunciation-lexicon-20071212/pls.xsd"
alphabet="ipa"
xml:lang="en-US">
<lexeme>
<grapheme>W3C</grapheme>
<alias>World Wide Web Consortium</alias>
</lexeme>
</lexicon>"""
@mock_polly
def test_describe_voices():
client = boto3.client("polly", region_name=DEFAULT_REGION)
resp = client.describe_voices()
len(resp["Voices"]).should.be.greater_than(1)
resp = client.describe_voices(LanguageCode="en-GB")
len(resp["Voices"]).should.equal(3)
try:
client.describe_voices(LanguageCode="SOME_LANGUAGE")
except ClientError as err:
err.response["Error"]["Code"].should.equal("400")
else:
raise RuntimeError("Should of raised an exception")
@mock_polly
def test_put_list_lexicon():
client = boto3.client("polly", region_name=DEFAULT_REGION)
# Return nothing
client.put_lexicon(Name="test", Content=LEXICON_XML)
resp = client.list_lexicons()
len(resp["Lexicons"]).should.equal(1)
@mock_polly
def test_put_get_lexicon():
client = boto3.client("polly", region_name=DEFAULT_REGION)
# Return nothing
client.put_lexicon(Name="test", Content=LEXICON_XML)
resp = client.get_lexicon(Name="test")
resp.should.contain("Lexicon")
resp.should.contain("LexiconAttributes")
@mock_polly
def test_put_lexicon_bad_name():
client = boto3.client("polly", region_name=DEFAULT_REGION)
try:
client.put_lexicon(Name="test-invalid", Content=LEXICON_XML)
except ClientError as err:
err.response["Error"]["Code"].should.equal("InvalidParameterValue")
else:
raise RuntimeError("Should of raised an exception")
@mock_polly
def test_synthesize_speech():
client = boto3.client("polly", region_name=DEFAULT_REGION)
# Return nothing
client.put_lexicon(Name="test", Content=LEXICON_XML)
tests = (("pcm", "audio/pcm"), ("mp3", "audio/mpeg"), ("ogg_vorbis", "audio/ogg"))
for output_format, content_type in tests:
resp = client.synthesize_speech(
LexiconNames=["test"],
OutputFormat=output_format,
SampleRate="16000",
Text="test1234",
TextType="text",
VoiceId="Astrid",
)
resp["ContentType"].should.equal(content_type)
@mock_polly
def test_synthesize_speech_bad_lexicon():
client = boto3.client("polly", region_name=DEFAULT_REGION)
client.put_lexicon(Name="test", Content=LEXICON_XML)
try:
client.synthesize_speech(
LexiconNames=["test2"],
OutputFormat="pcm",
SampleRate="16000",
Text="test1234",
TextType="text",
VoiceId="Astrid",
)
except ClientError as err:
err.response["Error"]["Code"].should.equal("LexiconNotFoundException")
else:
raise RuntimeError("Should of raised LexiconNotFoundException")
@mock_polly
def test_synthesize_speech_bad_output_format():
client = boto3.client("polly", region_name=DEFAULT_REGION)
client.put_lexicon(Name="test", Content=LEXICON_XML)
try:
client.synthesize_speech(
LexiconNames=["test"],
OutputFormat="invalid",
SampleRate="16000",
Text="test1234",
TextType="text",
VoiceId="Astrid",
)
except ClientError as err:
err.response["Error"]["Code"].should.equal("InvalidParameterValue")
else:
raise RuntimeError("Should of raised ")
@mock_polly
def test_synthesize_speech_bad_sample_rate():
client = boto3.client("polly", region_name=DEFAULT_REGION)
client.put_lexicon(Name="test", Content=LEXICON_XML)
try:
client.synthesize_speech(
LexiconNames=["test"],
OutputFormat="pcm",
SampleRate="18000",
Text="test1234",
TextType="text",
VoiceId="Astrid",
)
except ClientError as err:
err.response["Error"]["Code"].should.equal("InvalidSampleRateException")
else:
raise RuntimeError("Should of raised ")
@mock_polly
def test_synthesize_speech_bad_text_type():
client = boto3.client("polly", region_name=DEFAULT_REGION)
client.put_lexicon(Name="test", Content=LEXICON_XML)
try:
client.synthesize_speech(
LexiconNames=["test"],
OutputFormat="pcm",
SampleRate="16000",
Text="test1234",
TextType="invalid",
VoiceId="Astrid",
)
except ClientError as err:
err.response["Error"]["Code"].should.equal("InvalidParameterValue")
else:
raise RuntimeError("Should of raised ")
@mock_polly
def test_synthesize_speech_bad_voice_id():
client = boto3.client("polly", region_name=DEFAULT_REGION)
client.put_lexicon(Name="test", Content=LEXICON_XML)
try:
client.synthesize_speech(
LexiconNames=["test"],
OutputFormat="pcm",
SampleRate="16000",
Text="test1234",
TextType="text",
VoiceId="Luke",
)
except ClientError as err:
err.response["Error"]["Code"].should.equal("InvalidParameterValue")
else:
raise RuntimeError("Should of raised ")
@mock_polly
def test_synthesize_speech_text_too_long():
client = boto3.client("polly", region_name=DEFAULT_REGION)
client.put_lexicon(Name="test", Content=LEXICON_XML)
try:
client.synthesize_speech(
LexiconNames=["test"],
OutputFormat="pcm",
SampleRate="16000",
Text="test1234" * 376, # = 3008 characters
TextType="text",
VoiceId="Astrid",
)
except ClientError as err:
err.response["Error"]["Code"].should.equal("TextLengthExceededException")
else:
raise RuntimeError("Should of raised ")
@mock_polly
def test_synthesize_speech_bad_speech_marks1():
client = boto3.client("polly", region_name=DEFAULT_REGION)
client.put_lexicon(Name="test", Content=LEXICON_XML)
try:
client.synthesize_speech(
LexiconNames=["test"],
OutputFormat="pcm",
SampleRate="16000",
Text="test1234",
TextType="text",
SpeechMarkTypes=["word"],
VoiceId="Astrid",
)
except ClientError as err:
err.response["Error"]["Code"].should.equal(
"MarksNotSupportedForFormatException"
)
else:
raise RuntimeError("Should of raised ")
@mock_polly
def test_synthesize_speech_bad_speech_marks2():
client = boto3.client("polly", region_name=DEFAULT_REGION)
client.put_lexicon(Name="test", Content=LEXICON_XML)
try:
client.synthesize_speech(
LexiconNames=["test"],
OutputFormat="pcm",
SampleRate="16000",
Text="test1234",
TextType="ssml",
SpeechMarkTypes=["word"],
VoiceId="Astrid",
)
except ClientError as err:
err.response["Error"]["Code"].should.equal(
"MarksNotSupportedForFormatException"
)
else:
raise RuntimeError("Should of raised ")

View file

@ -68,7 +68,7 @@ def test_get_databases_paginated():
@mock_rds_deprecated
def test_describe_non_existant_database():
def test_describe_non_existent_database():
conn = boto.rds.connect_to_region("us-west-2")
conn.get_all_dbinstances.when.called_with("not-a-db").should.throw(BotoServerError)
@ -86,7 +86,7 @@ def test_delete_database():
@mock_rds_deprecated
def test_delete_non_existant_database():
def test_delete_non_existent_database():
conn = boto.rds.connect_to_region("us-west-2")
conn.delete_dbinstance.when.called_with("not-a-db").should.throw(BotoServerError)
@ -119,7 +119,7 @@ def test_get_security_groups():
@mock_rds_deprecated
def test_get_non_existant_security_group():
def test_get_non_existent_security_group():
conn = boto.rds.connect_to_region("us-west-2")
conn.get_all_dbsecurity_groups.when.called_with("not-a-sg").should.throw(
BotoServerError
@ -138,7 +138,7 @@ def test_delete_database_security_group():
@mock_rds_deprecated
def test_delete_non_existant_security_group():
def test_delete_non_existent_security_group():
conn = boto.rds.connect_to_region("us-west-2")
conn.delete_dbsecurity_group.when.called_with("not-a-db").should.throw(
BotoServerError

View file

@ -312,7 +312,7 @@ def test_get_databases_paginated():
@mock_rds2
def test_describe_non_existant_database():
def test_describe_non_existent_database():
conn = boto3.client("rds", region_name="us-west-2")
conn.describe_db_instances.when.called_with(
DBInstanceIdentifier="not-a-db"
@ -378,7 +378,7 @@ def test_rename_db_instance():
@mock_rds2
def test_modify_non_existant_database():
def test_modify_non_existent_database():
conn = boto3.client("rds", region_name="us-west-2")
conn.modify_db_instance.when.called_with(
DBInstanceIdentifier="not-a-db", AllocatedStorage=20, ApplyImmediately=True
@ -403,7 +403,7 @@ def test_reboot_db_instance():
@mock_rds2
def test_reboot_non_existant_database():
def test_reboot_non_existent_database():
conn = boto3.client("rds", region_name="us-west-2")
conn.reboot_db_instance.when.called_with(
DBInstanceIdentifier="not-a-db"
@ -444,7 +444,7 @@ def test_delete_database():
@mock_rds2
def test_delete_non_existant_database():
def test_delete_non_existent_database():
conn = boto3.client("rds2", region_name="us-west-2")
conn.delete_db_instance.when.called_with(
DBInstanceIdentifier="not-a-db"
@ -663,7 +663,7 @@ def test_describe_option_group():
@mock_rds2
def test_describe_non_existant_option_group():
def test_describe_non_existent_option_group():
conn = boto3.client("rds", region_name="us-west-2")
conn.describe_option_groups.when.called_with(
OptionGroupName="not-a-option-group"
@ -688,10 +688,10 @@ def test_delete_option_group():
@mock_rds2
def test_delete_non_existant_option_group():
def test_delete_non_existent_option_group():
conn = boto3.client("rds", region_name="us-west-2")
conn.delete_option_group.when.called_with(
OptionGroupName="non-existant"
OptionGroupName="non-existent"
).should.throw(ClientError)
@ -754,10 +754,10 @@ def test_modify_option_group_no_options():
@mock_rds2
def test_modify_non_existant_option_group():
def test_modify_non_existent_option_group():
conn = boto3.client("rds", region_name="us-west-2")
conn.modify_option_group.when.called_with(
OptionGroupName="non-existant",
OptionGroupName="non-existent",
OptionsToInclude=[
(
"OptionName",
@ -771,7 +771,7 @@ def test_modify_non_existant_option_group():
@mock_rds2
def test_delete_non_existant_database():
def test_delete_non_existent_database():
conn = boto3.client("rds", region_name="us-west-2")
conn.delete_db_instance.when.called_with(
DBInstanceIdentifier="not-a-db"
@ -1053,7 +1053,7 @@ def test_get_security_groups():
@mock_rds2
def test_get_non_existant_security_group():
def test_get_non_existent_security_group():
conn = boto3.client("rds", region_name="us-west-2")
conn.describe_db_security_groups.when.called_with(
DBSecurityGroupName="not-a-sg"
@ -1076,7 +1076,7 @@ def test_delete_database_security_group():
@mock_rds2
def test_delete_non_existant_security_group():
def test_delete_non_existent_security_group():
conn = boto3.client("rds", region_name="us-west-2")
conn.delete_db_security_group.when.called_with(
DBSecurityGroupName="not-a-db"
@ -1615,7 +1615,7 @@ def test_describe_db_parameter_group():
@mock_rds2
def test_describe_non_existant_db_parameter_group():
def test_describe_non_existent_db_parameter_group():
conn = boto3.client("rds", region_name="us-west-2")
db_parameter_groups = conn.describe_db_parameter_groups(DBParameterGroupName="test")
len(db_parameter_groups["DBParameterGroups"]).should.equal(0)
@ -1669,10 +1669,10 @@ def test_modify_db_parameter_group():
@mock_rds2
def test_delete_non_existant_db_parameter_group():
def test_delete_non_existent_db_parameter_group():
conn = boto3.client("rds", region_name="us-west-2")
conn.delete_db_parameter_group.when.called_with(
DBParameterGroupName="non-existant"
DBParameterGroupName="non-existent"
).should.throw(ClientError)
@ -1689,3 +1689,36 @@ def test_create_parameter_group_with_tags():
ResourceName="arn:aws:rds:us-west-2:1234567890:pg:test"
)
result["TagList"].should.equal([{"Value": "bar", "Key": "foo"}])
@mock_rds2
def test_create_db_with_iam_authentication():
conn = boto3.client("rds", region_name="us-west-2")
database = conn.create_db_instance(
DBInstanceIdentifier="rds",
DBInstanceClass="db.t1.micro",
Engine="postgres",
EnableIAMDatabaseAuthentication=True,
)
db_instance = database["DBInstance"]
db_instance["IAMDatabaseAuthenticationEnabled"].should.equal(True)
@mock_rds2
def test_create_db_snapshot_with_iam_authentication():
conn = boto3.client("rds", region_name="us-west-2")
conn.create_db_instance(
DBInstanceIdentifier="rds",
DBInstanceClass="db.t1.micro",
Engine="postgres",
EnableIAMDatabaseAuthentication=True,
)
snapshot = conn.create_db_snapshot(
DBInstanceIdentifier="rds", DBSnapshotIdentifier="snapshot"
).get("DBSnapshot")
snapshot.get("IAMDatabaseAuthenticationEnabled").should.equal(True)

View file

@ -21,7 +21,10 @@ def test_get_resources_s3():
# Create 4 buckets
for i in range(1, 5):
i_str = str(i)
s3_client.create_bucket(Bucket="test_bucket" + i_str)
s3_client.create_bucket(
Bucket="test_bucket" + i_str,
CreateBucketConfiguration={"LocationConstraint": "eu-central-1"},
)
s3_client.put_bucket_tagging(
Bucket="test_bucket" + i_str,
Tagging={"TagSet": [{"Key": "key" + i_str, "Value": "value" + i_str}]},

View file

@ -862,6 +862,8 @@ def test_list_resource_record_sets_name_type_filters():
StartRecordName=all_records[start_with][1],
)
response["IsTruncated"].should.equal(False)
returned_records = [
(record["Type"], record["Name"]) for record in response["ResourceRecordSets"]
]

File diff suppressed because it is too large Load diff

View file

@ -16,7 +16,7 @@ from moto import mock_s3_deprecated, mock_s3
@mock_s3_deprecated
def test_lifecycle_create():
conn = boto.s3.connect_to_region("us-west-1")
bucket = conn.create_bucket("foobar")
bucket = conn.create_bucket("foobar", location="us-west-1")
lifecycle = Lifecycle()
lifecycle.add_rule("myid", "", "Enabled", 30)
@ -33,7 +33,9 @@ def test_lifecycle_create():
@mock_s3
def test_lifecycle_with_filters():
client = boto3.client("s3")
client.create_bucket(Bucket="bucket")
client.create_bucket(
Bucket="bucket", CreateBucketConfiguration={"LocationConstraint": "us-west-1"}
)
# Create a lifecycle rule with a Filter (no tags):
lfc = {
@ -245,7 +247,9 @@ def test_lifecycle_with_filters():
@mock_s3
def test_lifecycle_with_eodm():
client = boto3.client("s3")
client.create_bucket(Bucket="bucket")
client.create_bucket(
Bucket="bucket", CreateBucketConfiguration={"LocationConstraint": "us-west-1"}
)
lfc = {
"Rules": [
@ -293,7 +297,9 @@ def test_lifecycle_with_eodm():
@mock_s3
def test_lifecycle_with_nve():
client = boto3.client("s3")
client.create_bucket(Bucket="bucket")
client.create_bucket(
Bucket="bucket", CreateBucketConfiguration={"LocationConstraint": "us-west-1"}
)
lfc = {
"Rules": [
@ -327,7 +333,9 @@ def test_lifecycle_with_nve():
@mock_s3
def test_lifecycle_with_nvt():
client = boto3.client("s3")
client.create_bucket(Bucket="bucket")
client.create_bucket(
Bucket="bucket", CreateBucketConfiguration={"LocationConstraint": "us-west-1"}
)
lfc = {
"Rules": [
@ -393,7 +401,9 @@ def test_lifecycle_with_nvt():
@mock_s3
def test_lifecycle_with_aimu():
client = boto3.client("s3")
client.create_bucket(Bucket="bucket")
client.create_bucket(
Bucket="bucket", CreateBucketConfiguration={"LocationConstraint": "us-west-1"}
)
lfc = {
"Rules": [
@ -432,7 +442,7 @@ def test_lifecycle_with_aimu():
@mock_s3_deprecated
def test_lifecycle_with_glacier_transition():
conn = boto.s3.connect_to_region("us-west-1")
bucket = conn.create_bucket("foobar")
bucket = conn.create_bucket("foobar", location="us-west-1")
lifecycle = Lifecycle()
transition = Transition(days=30, storage_class="GLACIER")
@ -451,7 +461,7 @@ def test_lifecycle_with_glacier_transition():
@mock_s3_deprecated
def test_lifecycle_multi():
conn = boto.s3.connect_to_region("us-west-1")
bucket = conn.create_bucket("foobar")
bucket = conn.create_bucket("foobar", location="us-west-1")
date = "2022-10-12T00:00:00.000Z"
sc = "GLACIER"
@ -493,7 +503,7 @@ def test_lifecycle_multi():
@mock_s3_deprecated
def test_lifecycle_delete():
conn = boto.s3.connect_to_region("us-west-1")
bucket = conn.create_bucket("foobar")
bucket = conn.create_bucket("foobar", location="us-west-1")
lifecycle = Lifecycle()
lifecycle.add_rule(expiration=30)

View file

@ -11,7 +11,7 @@ from moto import mock_s3
@mock_s3
def test_s3_storage_class_standard():
s3 = boto3.client("s3")
s3 = boto3.client("s3", region_name="us-east-1")
s3.create_bucket(Bucket="Bucket")
# add an object to the bucket with standard storage
@ -26,7 +26,9 @@ def test_s3_storage_class_standard():
@mock_s3
def test_s3_storage_class_infrequent_access():
s3 = boto3.client("s3")
s3.create_bucket(Bucket="Bucket")
s3.create_bucket(
Bucket="Bucket", CreateBucketConfiguration={"LocationConstraint": "us-west-2"}
)
# add an object to the bucket with standard storage
@ -46,7 +48,9 @@ def test_s3_storage_class_infrequent_access():
def test_s3_storage_class_intelligent_tiering():
s3 = boto3.client("s3")
s3.create_bucket(Bucket="Bucket")
s3.create_bucket(
Bucket="Bucket", CreateBucketConfiguration={"LocationConstraint": "us-east-2"}
)
s3.put_object(
Bucket="Bucket",
Key="my_key_infrequent",
@ -61,7 +65,7 @@ def test_s3_storage_class_intelligent_tiering():
@mock_s3
def test_s3_storage_class_copy():
s3 = boto3.client("s3")
s3 = boto3.client("s3", region_name="us-east-1")
s3.create_bucket(Bucket="Bucket")
s3.put_object(
Bucket="Bucket", Key="First_Object", Body="Body", StorageClass="STANDARD"
@ -86,7 +90,7 @@ def test_s3_storage_class_copy():
@mock_s3
def test_s3_invalid_copied_storage_class():
s3 = boto3.client("s3")
s3 = boto3.client("s3", region_name="us-east-1")
s3.create_bucket(Bucket="Bucket")
s3.put_object(
Bucket="Bucket", Key="First_Object", Body="Body", StorageClass="STANDARD"
@ -119,7 +123,9 @@ def test_s3_invalid_copied_storage_class():
@mock_s3
def test_s3_invalid_storage_class():
s3 = boto3.client("s3")
s3.create_bucket(Bucket="Bucket")
s3.create_bucket(
Bucket="Bucket", CreateBucketConfiguration={"LocationConstraint": "us-west-1"}
)
# Try to add an object with an invalid storage class
with assert_raises(ClientError) as err:
@ -137,7 +143,9 @@ def test_s3_invalid_storage_class():
@mock_s3
def test_s3_default_storage_class():
s3 = boto3.client("s3")
s3.create_bucket(Bucket="Bucket")
s3.create_bucket(
Bucket="Bucket", CreateBucketConfiguration={"LocationConstraint": "us-west-1"}
)
s3.put_object(Bucket="Bucket", Key="First_Object", Body="Body")
@ -150,7 +158,9 @@ def test_s3_default_storage_class():
@mock_s3
def test_s3_copy_object_error_for_glacier_storage_class():
s3 = boto3.client("s3")
s3.create_bucket(Bucket="Bucket")
s3.create_bucket(
Bucket="Bucket", CreateBucketConfiguration={"LocationConstraint": "us-west-1"}
)
s3.put_object(
Bucket="Bucket", Key="First_Object", Body="Body", StorageClass="GLACIER"
@ -169,7 +179,9 @@ def test_s3_copy_object_error_for_glacier_storage_class():
@mock_s3
def test_s3_copy_object_error_for_deep_archive_storage_class():
s3 = boto3.client("s3")
s3.create_bucket(Bucket="Bucket")
s3.create_bucket(
Bucket="Bucket", CreateBucketConfiguration={"LocationConstraint": "us-west-1"}
)
s3.put_object(
Bucket="Bucket", Key="First_Object", Body="Body", StorageClass="DEEP_ARCHIVE"

View file

@ -174,7 +174,7 @@ def test_bucket_deletion():
# Get non-existing bucket
conn.get_bucket.when.called_with("foobar").should.throw(S3ResponseError)
# Delete non-existant bucket
# Delete non-existent bucket
conn.delete_bucket.when.called_with("foobar").should.throw(S3ResponseError)

View file

@ -40,6 +40,8 @@ def __setup_feedback_env__(
)
# Verify SES domain
ses_conn.verify_domain_identity(Domain=domain)
# Specify email address to allow for raw e-mails to be processed
ses_conn.verify_email_identity(EmailAddress="test@example.com")
# Setup SES notification topic
if expected_msg is not None:
ses_conn.set_identity_notification_topic(
@ -47,7 +49,7 @@ def __setup_feedback_env__(
)
def __test_sns_feedback__(addr, expected_msg):
def __test_sns_feedback__(addr, expected_msg, raw_email=False):
region_name = "us-east-1"
ses_conn = boto3.client("ses", region_name=region_name)
sns_conn = boto3.client("sns", region_name=region_name)
@ -73,7 +75,18 @@ def __test_sns_feedback__(addr, expected_msg):
"Body": {"Text": {"Data": "test body"}},
},
)
ses_conn.send_email(**kwargs)
if raw_email:
kwargs.pop("Message")
kwargs.pop("Destination")
kwargs.update(
{
"Destinations": [addr + "@" + domain],
"RawMessage": {"Data": bytearray("raw_email", "utf-8")},
}
)
ses_conn.send_raw_email(**kwargs)
else:
ses_conn.send_email(**kwargs)
# Wait for messages in the queues
queue = sqs_conn.get_queue_by_name(QueueName=queue)
@ -112,3 +125,12 @@ def test_sns_feedback_complaint():
@mock_ses
def test_sns_feedback_delivery():
__test_sns_feedback__(SESFeedback.SUCCESS_ADDR, SESFeedback.DELIVERY)
@mock_sqs
@mock_sns
@mock_ses
def test_sns_feedback_delivery_raw_email():
__test_sns_feedback__(
SESFeedback.SUCCESS_ADDR, SESFeedback.DELIVERY, raw_email=True
)

View file

@ -88,8 +88,8 @@ def test_list_platform_applications():
conn.create_platform_application(name="application1", platform="APNS")
conn.create_platform_application(name="application2", platform="APNS")
applications_repsonse = conn.list_platform_applications()
applications = applications_repsonse["ListPlatformApplicationsResponse"][
applications_response = conn.list_platform_applications()
applications = applications_response["ListPlatformApplicationsResponse"][
"ListPlatformApplicationsResult"
]["PlatformApplications"]
applications.should.have.length_of(2)
@ -101,8 +101,8 @@ def test_delete_platform_application():
conn.create_platform_application(name="application1", platform="APNS")
conn.create_platform_application(name="application2", platform="APNS")
applications_repsonse = conn.list_platform_applications()
applications = applications_repsonse["ListPlatformApplicationsResponse"][
applications_response = conn.list_platform_applications()
applications = applications_response["ListPlatformApplicationsResponse"][
"ListPlatformApplicationsResult"
]["PlatformApplications"]
applications.should.have.length_of(2)
@ -110,8 +110,8 @@ def test_delete_platform_application():
application_arn = applications[0]["PlatformApplicationArn"]
conn.delete_platform_application(application_arn)
applications_repsonse = conn.list_platform_applications()
applications = applications_repsonse["ListPlatformApplicationsResponse"][
applications_response = conn.list_platform_applications()
applications = applications_response["ListPlatformApplicationsResponse"][
"ListPlatformApplicationsResult"
]["PlatformApplications"]
applications.should.have.length_of(1)

View file

@ -88,8 +88,8 @@ def test_list_platform_applications():
Name="application2", Platform="APNS", Attributes={}
)
applications_repsonse = conn.list_platform_applications()
applications = applications_repsonse["PlatformApplications"]
applications_response = conn.list_platform_applications()
applications = applications_response["PlatformApplications"]
applications.should.have.length_of(2)
@ -103,15 +103,15 @@ def test_delete_platform_application():
Name="application2", Platform="APNS", Attributes={}
)
applications_repsonse = conn.list_platform_applications()
applications = applications_repsonse["PlatformApplications"]
applications_response = conn.list_platform_applications()
applications = applications_response["PlatformApplications"]
applications.should.have.length_of(2)
application_arn = applications[0]["PlatformApplicationArn"]
conn.delete_platform_application(PlatformApplicationArn=application_arn)
applications_repsonse = conn.list_platform_applications()
applications = applications_repsonse["PlatformApplications"]
applications_response = conn.list_platform_applications()
applications = applications_response["PlatformApplications"]
applications.should.have.length_of(1)

View file

@ -806,7 +806,7 @@ def test_filtering_string_array_with_string_no_array_no_match():
topic.publish(
Message="no_match",
MessageAttributes={
"price": {"DataType": "String.Array", "StringValue": "one hundread"}
"price": {"DataType": "String.Array", "StringValue": "one hundred"}
},
)

View file

@ -132,6 +132,35 @@ def test_create_queue_with_tags():
)
@mock_sqs
def test_create_queue_with_policy():
client = boto3.client("sqs", region_name="us-east-1")
response = client.create_queue(
QueueName="test-queue",
Attributes={
"Policy": json.dumps(
{
"Version": "2012-10-17",
"Id": "test",
"Statement": [{"Effect": "Allow", "Principal": "*", "Action": "*"}],
}
)
},
)
queue_url = response["QueueUrl"]
response = client.get_queue_attributes(
QueueUrl=queue_url, AttributeNames=["Policy"]
)
json.loads(response["Attributes"]["Policy"]).should.equal(
{
"Version": "2012-10-17",
"Id": "test",
"Statement": [{"Effect": "Allow", "Principal": "*", "Action": "*"}],
}
)
@mock_sqs
def test_get_queue_url():
client = boto3.client("sqs", region_name="us-east-1")
@ -331,7 +360,20 @@ def test_delete_queue():
@mock_sqs
def test_get_queue_attributes():
client = boto3.client("sqs", region_name="us-east-1")
response = client.create_queue(QueueName="test-queue")
dlq_resp = client.create_queue(QueueName="test-dlr-queue")
dlq_arn1 = client.get_queue_attributes(QueueUrl=dlq_resp["QueueUrl"])["Attributes"][
"QueueArn"
]
response = client.create_queue(
QueueName="test-queue",
Attributes={
"RedrivePolicy": json.dumps(
{"deadLetterTargetArn": dlq_arn1, "maxReceiveCount": 2}
),
},
)
queue_url = response["QueueUrl"]
response = client.get_queue_attributes(QueueUrl=queue_url)
@ -356,6 +398,7 @@ def test_get_queue_attributes():
"ApproximateNumberOfMessages",
"MaximumMessageSize",
"QueueArn",
"RedrivePolicy",
"VisibilityTimeout",
],
)
@ -366,6 +409,9 @@ def test_get_queue_attributes():
"MaximumMessageSize": "65536",
"QueueArn": "arn:aws:sqs:us-east-1:{}:test-queue".format(ACCOUNT_ID),
"VisibilityTimeout": "30",
"RedrivePolicy": json.dumps(
{"deadLetterTargetArn": dlq_arn1, "maxReceiveCount": 2}
),
}
)
@ -1169,18 +1215,169 @@ def test_permissions():
Actions=["SendMessage"],
)
with assert_raises(ClientError):
client.add_permission(
QueueUrl=queue_url,
Label="account2",
AWSAccountIds=["222211111111"],
Actions=["SomeRubbish"],
)
response = client.get_queue_attributes(
QueueUrl=queue_url, AttributeNames=["Policy"]
)
policy = json.loads(response["Attributes"]["Policy"])
policy["Version"].should.equal("2012-10-17")
policy["Id"].should.equal(
"arn:aws:sqs:us-east-1:123456789012:test-dlr-queue.fifo/SQSDefaultPolicy"
)
sorted(policy["Statement"], key=lambda x: x["Sid"]).should.equal(
[
{
"Sid": "account1",
"Effect": "Allow",
"Principal": {"AWS": "arn:aws:iam::111111111111:root"},
"Action": "SQS:*",
"Resource": "arn:aws:sqs:us-east-1:123456789012:test-dlr-queue.fifo",
},
{
"Sid": "account2",
"Effect": "Allow",
"Principal": {"AWS": "arn:aws:iam::222211111111:root"},
"Action": "SQS:SendMessage",
"Resource": "arn:aws:sqs:us-east-1:123456789012:test-dlr-queue.fifo",
},
]
)
client.remove_permission(QueueUrl=queue_url, Label="account2")
with assert_raises(ClientError):
client.remove_permission(QueueUrl=queue_url, Label="non_existant")
response = client.get_queue_attributes(
QueueUrl=queue_url, AttributeNames=["Policy"]
)
json.loads(response["Attributes"]["Policy"]).should.equal(
{
"Version": "2012-10-17",
"Id": "arn:aws:sqs:us-east-1:123456789012:test-dlr-queue.fifo/SQSDefaultPolicy",
"Statement": [
{
"Sid": "account1",
"Effect": "Allow",
"Principal": {"AWS": "arn:aws:iam::111111111111:root"},
"Action": "SQS:*",
"Resource": "arn:aws:sqs:us-east-1:123456789012:test-dlr-queue.fifo",
},
],
}
)
@mock_sqs
def test_add_permission_errors():
client = boto3.client("sqs", region_name="us-east-1")
response = client.create_queue(QueueName="test-queue")
queue_url = response["QueueUrl"]
client.add_permission(
QueueUrl=queue_url,
Label="test",
AWSAccountIds=["111111111111"],
Actions=["ReceiveMessage"],
)
with assert_raises(ClientError) as e:
client.add_permission(
QueueUrl=queue_url,
Label="test",
AWSAccountIds=["111111111111"],
Actions=["ReceiveMessage", "SendMessage"],
)
ex = e.exception
ex.operation_name.should.equal("AddPermission")
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.response["Error"]["Code"].should.contain("InvalidParameterValue")
ex.response["Error"]["Message"].should.equal(
"Value test for parameter Label is invalid. " "Reason: Already exists."
)
with assert_raises(ClientError) as e:
client.add_permission(
QueueUrl=queue_url,
Label="test-2",
AWSAccountIds=["111111111111"],
Actions=["RemovePermission"],
)
ex = e.exception
ex.operation_name.should.equal("AddPermission")
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.response["Error"]["Code"].should.contain("InvalidParameterValue")
ex.response["Error"]["Message"].should.equal(
"Value SQS:RemovePermission for parameter ActionName is invalid. "
"Reason: Only the queue owner is allowed to invoke this action."
)
with assert_raises(ClientError) as e:
client.add_permission(
QueueUrl=queue_url,
Label="test-2",
AWSAccountIds=["111111111111"],
Actions=[],
)
ex = e.exception
ex.operation_name.should.equal("AddPermission")
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.response["Error"]["Code"].should.contain("MissingParameter")
ex.response["Error"]["Message"].should.equal(
"The request must contain the parameter Actions."
)
with assert_raises(ClientError) as e:
client.add_permission(
QueueUrl=queue_url,
Label="test-2",
AWSAccountIds=[],
Actions=["ReceiveMessage"],
)
ex = e.exception
ex.operation_name.should.equal("AddPermission")
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.response["Error"]["Code"].should.contain("InvalidParameterValue")
ex.response["Error"]["Message"].should.equal(
"Value [] for parameter PrincipalId is invalid. Reason: Unable to verify."
)
with assert_raises(ClientError) as e:
client.add_permission(
QueueUrl=queue_url,
Label="test-2",
AWSAccountIds=["111111111111"],
Actions=[
"ChangeMessageVisibility",
"DeleteMessage",
"GetQueueAttributes",
"GetQueueUrl",
"ListDeadLetterSourceQueues",
"PurgeQueue",
"ReceiveMessage",
"SendMessage",
],
)
ex = e.exception
ex.operation_name.should.equal("AddPermission")
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(403)
ex.response["Error"]["Code"].should.contain("OverLimit")
ex.response["Error"]["Message"].should.equal(
"8 Actions were found, maximum allowed is 7."
)
@mock_sqs
def test_remove_permission_errors():
client = boto3.client("sqs", region_name="us-east-1")
response = client.create_queue(QueueName="test-queue")
queue_url = response["QueueUrl"]
with assert_raises(ClientError) as e:
client.remove_permission(QueueUrl=queue_url, Label="test")
ex = e.exception
ex.operation_name.should.equal("RemovePermission")
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
ex.response["Error"]["Code"].should.contain("InvalidParameterValue")
ex.response["Error"]["Message"].should.equal(
"Value test for parameter Label is invalid. "
"Reason: can't find label on existing policy."
)
@mock_sqs
@ -1562,3 +1759,23 @@ def test_receive_message_for_queue_with_receive_message_wait_time_seconds_set():
)
queue.receive_messages()
@mock_sqs
def test_list_queues_limits_to_1000_queues():
client = boto3.client("sqs", region_name="us-east-1")
for i in range(1001):
client.create_queue(QueueName="test-queue-{0}".format(i))
client.list_queues()["QueueUrls"].should.have.length_of(1000)
client.list_queues(QueueNamePrefix="test-queue")["QueueUrls"].should.have.length_of(
1000
)
resource = boto3.resource("sqs", region_name="us-east-1")
list(resource.queues.all()).should.have.length_of(1000)
list(resource.queues.filter(QueueNamePrefix="test-queue")).should.have.length_of(
1000
)

View file

@ -1,107 +1,107 @@
from collections import namedtuple
import sure # noqa
from moto.swf.exceptions import SWFUnknownResourceFault
from moto.swf.models import Domain
# Ensure 'assert_raises' context manager support for Python 2.6
import tests.backport_assert_raises # noqa
# Fake WorkflowExecution for tests purposes
WorkflowExecution = namedtuple(
"WorkflowExecution", ["workflow_id", "run_id", "execution_status", "open"]
)
def test_domain_short_dict_representation():
domain = Domain("foo", "52")
domain.to_short_dict().should.equal({"name": "foo", "status": "REGISTERED"})
domain.description = "foo bar"
domain.to_short_dict()["description"].should.equal("foo bar")
def test_domain_full_dict_representation():
domain = Domain("foo", "52")
domain.to_full_dict()["domainInfo"].should.equal(domain.to_short_dict())
_config = domain.to_full_dict()["configuration"]
_config["workflowExecutionRetentionPeriodInDays"].should.equal("52")
def test_domain_string_representation():
domain = Domain("my-domain", "60")
str(domain).should.equal("Domain(name: my-domain, status: REGISTERED)")
def test_domain_add_to_activity_task_list():
domain = Domain("my-domain", "60")
domain.add_to_activity_task_list("foo", "bar")
domain.activity_task_lists.should.equal({"foo": ["bar"]})
def test_domain_activity_tasks():
domain = Domain("my-domain", "60")
domain.add_to_activity_task_list("foo", "bar")
domain.add_to_activity_task_list("other", "baz")
sorted(domain.activity_tasks).should.equal(["bar", "baz"])
def test_domain_add_to_decision_task_list():
domain = Domain("my-domain", "60")
domain.add_to_decision_task_list("foo", "bar")
domain.decision_task_lists.should.equal({"foo": ["bar"]})
def test_domain_decision_tasks():
domain = Domain("my-domain", "60")
domain.add_to_decision_task_list("foo", "bar")
domain.add_to_decision_task_list("other", "baz")
sorted(domain.decision_tasks).should.equal(["bar", "baz"])
def test_domain_get_workflow_execution():
domain = Domain("my-domain", "60")
wfe1 = WorkflowExecution(
workflow_id="wf-id-1", run_id="run-id-1", execution_status="OPEN", open=True
)
wfe2 = WorkflowExecution(
workflow_id="wf-id-1", run_id="run-id-2", execution_status="CLOSED", open=False
)
wfe3 = WorkflowExecution(
workflow_id="wf-id-2", run_id="run-id-3", execution_status="OPEN", open=True
)
wfe4 = WorkflowExecution(
workflow_id="wf-id-3", run_id="run-id-4", execution_status="CLOSED", open=False
)
domain.workflow_executions = [wfe1, wfe2, wfe3, wfe4]
# get workflow execution through workflow_id and run_id
domain.get_workflow_execution("wf-id-1", run_id="run-id-1").should.equal(wfe1)
domain.get_workflow_execution("wf-id-1", run_id="run-id-2").should.equal(wfe2)
domain.get_workflow_execution("wf-id-3", run_id="run-id-4").should.equal(wfe4)
domain.get_workflow_execution.when.called_with(
"wf-id-1", run_id="non-existent"
).should.throw(SWFUnknownResourceFault)
# get OPEN workflow execution by default if no run_id
domain.get_workflow_execution("wf-id-1").should.equal(wfe1)
domain.get_workflow_execution.when.called_with("wf-id-3").should.throw(
SWFUnknownResourceFault
)
domain.get_workflow_execution.when.called_with("wf-id-non-existent").should.throw(
SWFUnknownResourceFault
)
# raise_if_closed attribute
domain.get_workflow_execution(
"wf-id-1", run_id="run-id-1", raise_if_closed=True
).should.equal(wfe1)
domain.get_workflow_execution.when.called_with(
"wf-id-3", run_id="run-id-4", raise_if_closed=True
).should.throw(SWFUnknownResourceFault)
# raise_if_none attribute
domain.get_workflow_execution("foo", raise_if_none=False).should.be.none
from collections import namedtuple
import sure # noqa
from moto.swf.exceptions import SWFUnknownResourceFault
from moto.swf.models import Domain
# Ensure 'assert_raises' context manager support for Python 2.6
import tests.backport_assert_raises # noqa
# Fake WorkflowExecution for tests purposes
WorkflowExecution = namedtuple(
"WorkflowExecution", ["workflow_id", "run_id", "execution_status", "open"]
)
def test_domain_short_dict_representation():
domain = Domain("foo", "52")
domain.to_short_dict().should.equal({"name": "foo", "status": "REGISTERED"})
domain.description = "foo bar"
domain.to_short_dict()["description"].should.equal("foo bar")
def test_domain_full_dict_representation():
domain = Domain("foo", "52")
domain.to_full_dict()["domainInfo"].should.equal(domain.to_short_dict())
_config = domain.to_full_dict()["configuration"]
_config["workflowExecutionRetentionPeriodInDays"].should.equal("52")
def test_domain_string_representation():
domain = Domain("my-domain", "60")
str(domain).should.equal("Domain(name: my-domain, status: REGISTERED)")
def test_domain_add_to_activity_task_list():
domain = Domain("my-domain", "60")
domain.add_to_activity_task_list("foo", "bar")
domain.activity_task_lists.should.equal({"foo": ["bar"]})
def test_domain_activity_tasks():
domain = Domain("my-domain", "60")
domain.add_to_activity_task_list("foo", "bar")
domain.add_to_activity_task_list("other", "baz")
sorted(domain.activity_tasks).should.equal(["bar", "baz"])
def test_domain_add_to_decision_task_list():
domain = Domain("my-domain", "60")
domain.add_to_decision_task_list("foo", "bar")
domain.decision_task_lists.should.equal({"foo": ["bar"]})
def test_domain_decision_tasks():
domain = Domain("my-domain", "60")
domain.add_to_decision_task_list("foo", "bar")
domain.add_to_decision_task_list("other", "baz")
sorted(domain.decision_tasks).should.equal(["bar", "baz"])
def test_domain_get_workflow_execution():
domain = Domain("my-domain", "60")
wfe1 = WorkflowExecution(
workflow_id="wf-id-1", run_id="run-id-1", execution_status="OPEN", open=True
)
wfe2 = WorkflowExecution(
workflow_id="wf-id-1", run_id="run-id-2", execution_status="CLOSED", open=False
)
wfe3 = WorkflowExecution(
workflow_id="wf-id-2", run_id="run-id-3", execution_status="OPEN", open=True
)
wfe4 = WorkflowExecution(
workflow_id="wf-id-3", run_id="run-id-4", execution_status="CLOSED", open=False
)
domain.workflow_executions = [wfe1, wfe2, wfe3, wfe4]
# get workflow execution through workflow_id and run_id
domain.get_workflow_execution("wf-id-1", run_id="run-id-1").should.equal(wfe1)
domain.get_workflow_execution("wf-id-1", run_id="run-id-2").should.equal(wfe2)
domain.get_workflow_execution("wf-id-3", run_id="run-id-4").should.equal(wfe4)
domain.get_workflow_execution.when.called_with(
"wf-id-1", run_id="non-existent"
).should.throw(SWFUnknownResourceFault)
# get OPEN workflow execution by default if no run_id
domain.get_workflow_execution("wf-id-1").should.equal(wfe1)
domain.get_workflow_execution.when.called_with("wf-id-3").should.throw(
SWFUnknownResourceFault
)
domain.get_workflow_execution.when.called_with("wf-id-non-existent").should.throw(
SWFUnknownResourceFault
)
# raise_if_closed attribute
domain.get_workflow_execution(
"wf-id-1", run_id="run-id-1", raise_if_closed=True
).should.equal(wfe1)
domain.get_workflow_execution.when.called_with(
"wf-id-3", run_id="run-id-4", raise_if_closed=True
).should.throw(SWFUnknownResourceFault)
# raise_if_none attribute
domain.get_workflow_execution("foo", raise_if_none=False).should.be.none

View file

@ -1,19 +1,19 @@
from freezegun import freeze_time
import sure # noqa
from moto.swf.models import Timeout
from ..utils import make_workflow_execution
def test_timeout_creation():
wfe = make_workflow_execution()
# epoch 1420113600 == "2015-01-01 13:00:00"
timeout = Timeout(wfe, 1420117200, "START_TO_CLOSE")
with freeze_time("2015-01-01 12:00:00"):
timeout.reached.should.be.falsy
with freeze_time("2015-01-01 13:00:00"):
timeout.reached.should.be.truthy
from freezegun import freeze_time
import sure # noqa
from moto.swf.models import Timeout
from ..utils import make_workflow_execution
def test_timeout_creation():
wfe = make_workflow_execution()
# epoch 1420113600 == "2015-01-01 13:00:00"
timeout = Timeout(wfe, 1420117200, "START_TO_CLOSE")
with freeze_time("2015-01-01 12:00:00"):
timeout.reached.should.be.falsy
with freeze_time("2015-01-01 13:00:00"):
timeout.reached.should.be.truthy

View file

@ -148,6 +148,39 @@ def test_workflow_execution_full_dict_representation():
)
def test_closed_workflow_execution_full_dict_representation():
domain = get_basic_domain()
wf_type = WorkflowType(
"test-workflow",
"v1.0",
task_list="queue",
default_child_policy="ABANDON",
default_execution_start_to_close_timeout="300",
default_task_start_to_close_timeout="300",
)
wfe = WorkflowExecution(domain, wf_type, "ab1234")
wfe.execution_status = "CLOSED"
wfe.close_status = "CANCELED"
wfe.close_timestamp = 1420066801.123
fd = wfe.to_full_dict()
medium_dict = wfe.to_medium_dict()
medium_dict["closeStatus"] = "CANCELED"
medium_dict["closeTimestamp"] = 1420066801.123
fd["executionInfo"].should.equal(medium_dict)
fd["openCounts"]["openTimers"].should.equal(0)
fd["openCounts"]["openDecisionTasks"].should.equal(0)
fd["openCounts"]["openActivityTasks"].should.equal(0)
fd["executionConfiguration"].should.equal(
{
"childPolicy": "ABANDON",
"executionStartToCloseTimeout": "300",
"taskList": {"name": "queue"},
"taskStartToCloseTimeout": "300",
}
)
def test_workflow_execution_list_dict_representation():
domain = get_basic_domain()
wf_type = WorkflowType(

View file

@ -1,114 +1,114 @@
import boto
from boto.swf.exceptions import SWFResponseError
import sure # noqa
from moto import mock_swf_deprecated
# RegisterDomain endpoint
@mock_swf_deprecated
def test_register_domain():
conn = boto.connect_swf("the_key", "the_secret")
conn.register_domain("test-domain", "60", description="A test domain")
all_domains = conn.list_domains("REGISTERED")
domain = all_domains["domainInfos"][0]
domain["name"].should.equal("test-domain")
domain["status"].should.equal("REGISTERED")
domain["description"].should.equal("A test domain")
@mock_swf_deprecated
def test_register_already_existing_domain():
conn = boto.connect_swf("the_key", "the_secret")
conn.register_domain("test-domain", "60", description="A test domain")
conn.register_domain.when.called_with(
"test-domain", "60", description="A test domain"
).should.throw(SWFResponseError)
@mock_swf_deprecated
def test_register_with_wrong_parameter_type():
conn = boto.connect_swf("the_key", "the_secret")
conn.register_domain.when.called_with(
"test-domain", 60, description="A test domain"
).should.throw(SWFResponseError)
# ListDomains endpoint
@mock_swf_deprecated
def test_list_domains_order():
conn = boto.connect_swf("the_key", "the_secret")
conn.register_domain("b-test-domain", "60")
conn.register_domain("a-test-domain", "60")
conn.register_domain("c-test-domain", "60")
all_domains = conn.list_domains("REGISTERED")
names = [domain["name"] for domain in all_domains["domainInfos"]]
names.should.equal(["a-test-domain", "b-test-domain", "c-test-domain"])
@mock_swf_deprecated
def test_list_domains_reverse_order():
conn = boto.connect_swf("the_key", "the_secret")
conn.register_domain("b-test-domain", "60")
conn.register_domain("a-test-domain", "60")
conn.register_domain("c-test-domain", "60")
all_domains = conn.list_domains("REGISTERED", reverse_order=True)
names = [domain["name"] for domain in all_domains["domainInfos"]]
names.should.equal(["c-test-domain", "b-test-domain", "a-test-domain"])
# DeprecateDomain endpoint
@mock_swf_deprecated
def test_deprecate_domain():
conn = boto.connect_swf("the_key", "the_secret")
conn.register_domain("test-domain", "60", description="A test domain")
conn.deprecate_domain("test-domain")
all_domains = conn.list_domains("DEPRECATED")
domain = all_domains["domainInfos"][0]
domain["name"].should.equal("test-domain")
@mock_swf_deprecated
def test_deprecate_already_deprecated_domain():
conn = boto.connect_swf("the_key", "the_secret")
conn.register_domain("test-domain", "60", description="A test domain")
conn.deprecate_domain("test-domain")
conn.deprecate_domain.when.called_with("test-domain").should.throw(SWFResponseError)
@mock_swf_deprecated
def test_deprecate_non_existent_domain():
conn = boto.connect_swf("the_key", "the_secret")
conn.deprecate_domain.when.called_with("non-existent").should.throw(
SWFResponseError
)
# DescribeDomain endpoint
@mock_swf_deprecated
def test_describe_domain():
conn = boto.connect_swf("the_key", "the_secret")
conn.register_domain("test-domain", "60", description="A test domain")
domain = conn.describe_domain("test-domain")
domain["configuration"]["workflowExecutionRetentionPeriodInDays"].should.equal("60")
domain["domainInfo"]["description"].should.equal("A test domain")
domain["domainInfo"]["name"].should.equal("test-domain")
domain["domainInfo"]["status"].should.equal("REGISTERED")
@mock_swf_deprecated
def test_describe_non_existent_domain():
conn = boto.connect_swf("the_key", "the_secret")
conn.describe_domain.when.called_with("non-existent").should.throw(SWFResponseError)
import boto
from boto.swf.exceptions import SWFResponseError
import sure # noqa
from moto import mock_swf_deprecated
# RegisterDomain endpoint
@mock_swf_deprecated
def test_register_domain():
conn = boto.connect_swf("the_key", "the_secret")
conn.register_domain("test-domain", "60", description="A test domain")
all_domains = conn.list_domains("REGISTERED")
domain = all_domains["domainInfos"][0]
domain["name"].should.equal("test-domain")
domain["status"].should.equal("REGISTERED")
domain["description"].should.equal("A test domain")
@mock_swf_deprecated
def test_register_already_existing_domain():
conn = boto.connect_swf("the_key", "the_secret")
conn.register_domain("test-domain", "60", description="A test domain")
conn.register_domain.when.called_with(
"test-domain", "60", description="A test domain"
).should.throw(SWFResponseError)
@mock_swf_deprecated
def test_register_with_wrong_parameter_type():
conn = boto.connect_swf("the_key", "the_secret")
conn.register_domain.when.called_with(
"test-domain", 60, description="A test domain"
).should.throw(SWFResponseError)
# ListDomains endpoint
@mock_swf_deprecated
def test_list_domains_order():
conn = boto.connect_swf("the_key", "the_secret")
conn.register_domain("b-test-domain", "60")
conn.register_domain("a-test-domain", "60")
conn.register_domain("c-test-domain", "60")
all_domains = conn.list_domains("REGISTERED")
names = [domain["name"] for domain in all_domains["domainInfos"]]
names.should.equal(["a-test-domain", "b-test-domain", "c-test-domain"])
@mock_swf_deprecated
def test_list_domains_reverse_order():
conn = boto.connect_swf("the_key", "the_secret")
conn.register_domain("b-test-domain", "60")
conn.register_domain("a-test-domain", "60")
conn.register_domain("c-test-domain", "60")
all_domains = conn.list_domains("REGISTERED", reverse_order=True)
names = [domain["name"] for domain in all_domains["domainInfos"]]
names.should.equal(["c-test-domain", "b-test-domain", "a-test-domain"])
# DeprecateDomain endpoint
@mock_swf_deprecated
def test_deprecate_domain():
conn = boto.connect_swf("the_key", "the_secret")
conn.register_domain("test-domain", "60", description="A test domain")
conn.deprecate_domain("test-domain")
all_domains = conn.list_domains("DEPRECATED")
domain = all_domains["domainInfos"][0]
domain["name"].should.equal("test-domain")
@mock_swf_deprecated
def test_deprecate_already_deprecated_domain():
conn = boto.connect_swf("the_key", "the_secret")
conn.register_domain("test-domain", "60", description="A test domain")
conn.deprecate_domain("test-domain")
conn.deprecate_domain.when.called_with("test-domain").should.throw(SWFResponseError)
@mock_swf_deprecated
def test_deprecate_non_existent_domain():
conn = boto.connect_swf("the_key", "the_secret")
conn.deprecate_domain.when.called_with("non-existent").should.throw(
SWFResponseError
)
# DescribeDomain endpoint
@mock_swf_deprecated
def test_describe_domain():
conn = boto.connect_swf("the_key", "the_secret")
conn.register_domain("test-domain", "60", description="A test domain")
domain = conn.describe_domain("test-domain")
domain["configuration"]["workflowExecutionRetentionPeriodInDays"].should.equal("60")
domain["domainInfo"]["description"].should.equal("A test domain")
domain["domainInfo"]["name"].should.equal("test-domain")
domain["domainInfo"]["status"].should.equal("REGISTERED")
@mock_swf_deprecated
def test_describe_non_existent_domain():
conn = boto.connect_swf("the_key", "the_secret")
conn.describe_domain.when.called_with("non-existent").should.throw(SWFResponseError)

View file

@ -1,9 +1,9 @@
import sure # noqa
from moto.swf.utils import decapitalize
def test_decapitalize():
cases = {"fooBar": "fooBar", "FooBar": "fooBar", "FOO BAR": "fOO BAR"}
for before, after in cases.items():
decapitalize(before).should.equal(after)
import sure # noqa
from moto.swf.utils import decapitalize
def test_decapitalize():
cases = {"fooBar": "fooBar", "FooBar": "fooBar", "FOO BAR": "fOO BAR"}
for before, after in cases.items():
decapitalize(before).should.equal(after)

View file

@ -5,7 +5,7 @@ from moto.swf.models import ActivityType, Domain, WorkflowType, WorkflowExecutio
# Some useful constants
# Here are some activity timeouts we use in moto/swf tests ; they're extracted
# from semi-real world example, the goal is mostly to have predictible and
# from semi-real world example, the goal is mostly to have predictable and
# intuitive behaviour in moto/swf own tests...
ACTIVITY_TASK_TIMEOUTS = {
"heartbeatTimeout": "300", # 5 mins

View file

@ -1,53 +1,79 @@
import unittest
import sure
from moto.utilities.tagging_service import TaggingService
class TestTaggingService(unittest.TestCase):
def test_list_empty(self):
svc = TaggingService()
result = svc.list_tags_for_resource('test')
self.assertEqual(result, {'Tags': []})
def test_list_empty():
svc = TaggingService()
result = svc.list_tags_for_resource("test")
def test_create_tag(self):
svc = TaggingService('TheTags', 'TagKey', 'TagValue')
tags = [{'TagKey': 'key_key', 'TagValue': 'value_value'}]
svc.tag_resource('arn', tags)
actual = svc.list_tags_for_resource('arn')
expected = {'TheTags': [{'TagKey': 'key_key', 'TagValue': 'value_value'}]}
self.assertDictEqual(expected, actual)
def test_create_tag_without_value(self):
svc = TaggingService()
tags = [{'Key': 'key_key'}]
svc.tag_resource('arn', tags)
actual = svc.list_tags_for_resource('arn')
expected = {'Tags': [{'Key': 'key_key', 'Value': ''}]}
self.assertDictEqual(expected, actual)
def test_delete_tag(self):
svc = TaggingService()
tags = [{'Key': 'key_key', 'Value': 'value_value'}]
svc.tag_resource('arn', tags)
svc.untag_resource('arn', ['key_key'])
result = svc.list_tags_for_resource('arn')
self.assertEqual(
result, {'Tags': []})
def test_list_empty_delete(self):
svc = TaggingService()
svc.untag_resource('arn', ['key_key'])
result = svc.list_tags_for_resource('arn')
self.assertEqual(
result, {'Tags': []})
def test_extract_tag_names(self):
svc = TaggingService()
tags = [{'Key': 'key1', 'Value': 'value1'}, {'Key': 'key2', 'Value': 'value2'}]
actual = svc.extract_tag_names(tags)
expected = ['key1', 'key2']
self.assertEqual(expected, actual)
{"Tags": []}.should.be.equal(result)
if __name__ == '__main__':
unittest.main()
def test_create_tag():
svc = TaggingService("TheTags", "TagKey", "TagValue")
tags = [{"TagKey": "key_key", "TagValue": "value_value"}]
svc.tag_resource("arn", tags)
actual = svc.list_tags_for_resource("arn")
expected = {"TheTags": [{"TagKey": "key_key", "TagValue": "value_value"}]}
expected.should.be.equal(actual)
def test_create_tag_without_value():
svc = TaggingService()
tags = [{"Key": "key_key"}]
svc.tag_resource("arn", tags)
actual = svc.list_tags_for_resource("arn")
expected = {"Tags": [{"Key": "key_key", "Value": None}]}
expected.should.be.equal(actual)
def test_delete_tag_using_names():
svc = TaggingService()
tags = [{"Key": "key_key", "Value": "value_value"}]
svc.tag_resource("arn", tags)
svc.untag_resource_using_names("arn", ["key_key"])
result = svc.list_tags_for_resource("arn")
{"Tags": []}.should.be.equal(result)
def test_delete_all_tags_for_resource():
svc = TaggingService()
tags = [{"Key": "key_key", "Value": "value_value"}]
tags2 = [{"Key": "key_key2", "Value": "value_value2"}]
svc.tag_resource("arn", tags)
svc.tag_resource("arn", tags2)
svc.delete_all_tags_for_resource("arn")
result = svc.list_tags_for_resource("arn")
{"Tags": []}.should.be.equal(result)
def test_list_empty_delete():
svc = TaggingService()
svc.untag_resource_using_names("arn", ["key_key"])
result = svc.list_tags_for_resource("arn")
{"Tags": []}.should.be.equal(result)
def test_delete_tag_using_tags():
svc = TaggingService()
tags = [{"Key": "key_key", "Value": "value_value"}]
svc.tag_resource("arn", tags)
svc.untag_resource_using_tags("arn", tags)
result = svc.list_tags_for_resource("arn")
{"Tags": []}.should.be.equal(result)
def test_extract_tag_names():
svc = TaggingService()
tags = [{"Key": "key1", "Value": "value1"}, {"Key": "key2", "Value": "value2"}]
actual = svc.extract_tag_names(tags)
expected = ["key1", "key2"]
expected.should.be.equal(actual)