Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
84210f6011
78 changed files with 1510 additions and 618 deletions
|
|
@ -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,
|
||||
}
|
||||
],
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -181,27 +180,9 @@ if settings.TEST_SERVER_MODE:
|
|||
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)
|
||||
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
|
||||
|
|
|
|||
222
tests/test_codecommit/test_codecommit.py
Normal file
222
tests/test_codecommit/test_codecommit.py
Normal file
|
|
@ -0,0 +1,222 @@
|
|||
import boto3
|
||||
|
||||
import sure # noqa
|
||||
from moto import mock_codecommit
|
||||
from moto.iam.models import ACCOUNT_ID
|
||||
from botocore.exceptions import ClientError
|
||||
from nose.tools import assert_raises
|
||||
|
||||
|
||||
@mock_codecommit
|
||||
def test_create_repository():
|
||||
client = boto3.client("codecommit", region_name="eu-central-1")
|
||||
response = client.create_repository(
|
||||
repositoryName="repository_one", repositoryDescription="description repo one"
|
||||
)
|
||||
|
||||
response.should_not.be.none
|
||||
response["repositoryMetadata"].should_not.be.none
|
||||
response["repositoryMetadata"]["creationDate"].should_not.be.none
|
||||
response["repositoryMetadata"]["lastModifiedDate"].should_not.be.none
|
||||
response["repositoryMetadata"]["repositoryId"].should_not.be.empty
|
||||
response["repositoryMetadata"]["repositoryName"].should.equal("repository_one")
|
||||
response["repositoryMetadata"]["repositoryDescription"].should.equal(
|
||||
"description repo one"
|
||||
)
|
||||
response["repositoryMetadata"]["cloneUrlSsh"].should.equal(
|
||||
"ssh://git-codecommit.{0}.amazonaws.com/v1/repos/{1}".format(
|
||||
"eu-central-1", "repository_one"
|
||||
)
|
||||
)
|
||||
response["repositoryMetadata"]["cloneUrlHttp"].should.equal(
|
||||
"https://git-codecommit.{0}.amazonaws.com/v1/repos/{1}".format(
|
||||
"eu-central-1", "repository_one"
|
||||
)
|
||||
)
|
||||
response["repositoryMetadata"]["Arn"].should.equal(
|
||||
"arn:aws:codecommit:{0}:{1}:{2}".format(
|
||||
"eu-central-1", ACCOUNT_ID, "repository_one"
|
||||
)
|
||||
)
|
||||
response["repositoryMetadata"]["accountId"].should.equal(ACCOUNT_ID)
|
||||
|
||||
|
||||
@mock_codecommit
|
||||
def test_create_repository_without_description():
|
||||
client = boto3.client("codecommit", region_name="eu-central-1")
|
||||
|
||||
response = client.create_repository(repositoryName="repository_two")
|
||||
|
||||
response.should_not.be.none
|
||||
response.get("repositoryMetadata").should_not.be.none
|
||||
response.get("repositoryMetadata").get("repositoryName").should.equal(
|
||||
"repository_two"
|
||||
)
|
||||
response.get("repositoryMetadata").get("repositoryDescription").should.be.none
|
||||
response["repositoryMetadata"].should_not.be.none
|
||||
response["repositoryMetadata"]["creationDate"].should_not.be.none
|
||||
response["repositoryMetadata"]["lastModifiedDate"].should_not.be.none
|
||||
response["repositoryMetadata"]["repositoryId"].should_not.be.empty
|
||||
response["repositoryMetadata"]["cloneUrlSsh"].should.equal(
|
||||
"ssh://git-codecommit.{0}.amazonaws.com/v1/repos/{1}".format(
|
||||
"eu-central-1", "repository_two"
|
||||
)
|
||||
)
|
||||
response["repositoryMetadata"]["cloneUrlHttp"].should.equal(
|
||||
"https://git-codecommit.{0}.amazonaws.com/v1/repos/{1}".format(
|
||||
"eu-central-1", "repository_two"
|
||||
)
|
||||
)
|
||||
response["repositoryMetadata"]["Arn"].should.equal(
|
||||
"arn:aws:codecommit:{0}:{1}:{2}".format(
|
||||
"eu-central-1", ACCOUNT_ID, "repository_two"
|
||||
)
|
||||
)
|
||||
response["repositoryMetadata"]["accountId"].should.equal(ACCOUNT_ID)
|
||||
|
||||
|
||||
@mock_codecommit
|
||||
def test_create_repository_repository_name_exists():
|
||||
client = boto3.client("codecommit", region_name="eu-central-1")
|
||||
|
||||
client.create_repository(repositoryName="repository_two")
|
||||
|
||||
with assert_raises(ClientError) as e:
|
||||
client.create_repository(
|
||||
repositoryName="repository_two",
|
||||
repositoryDescription="description repo two",
|
||||
)
|
||||
ex = e.exception
|
||||
ex.operation_name.should.equal("CreateRepository")
|
||||
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||
ex.response["Error"]["Code"].should.contain("RepositoryNameExistsException")
|
||||
ex.response["Error"]["Message"].should.equal(
|
||||
"Repository named {0} already exists".format("repository_two")
|
||||
)
|
||||
|
||||
|
||||
@mock_codecommit
|
||||
def test_create_repository_invalid_repository_name():
|
||||
client = boto3.client("codecommit", region_name="eu-central-1")
|
||||
|
||||
with assert_raises(ClientError) as e:
|
||||
client.create_repository(repositoryName="in_123_valid_@#$_characters")
|
||||
ex = e.exception
|
||||
ex.operation_name.should.equal("CreateRepository")
|
||||
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||
ex.response["Error"]["Code"].should.contain("InvalidRepositoryNameException")
|
||||
ex.response["Error"]["Message"].should.equal(
|
||||
"The repository name is not valid. Repository names can be any valid "
|
||||
"combination of letters, numbers, "
|
||||
"periods, underscores, and dashes between 1 and 100 characters in "
|
||||
"length. Names are case sensitive. "
|
||||
"For more information, see Limits in the AWS CodeCommit User Guide. "
|
||||
)
|
||||
|
||||
|
||||
@mock_codecommit
|
||||
def test_get_repository():
|
||||
client = boto3.client("codecommit", region_name="eu-central-1")
|
||||
|
||||
repository_name = "repository_one"
|
||||
|
||||
client.create_repository(
|
||||
repositoryName=repository_name, repositoryDescription="description repo one"
|
||||
)
|
||||
|
||||
response = client.get_repository(repositoryName=repository_name)
|
||||
|
||||
response.should_not.be.none
|
||||
response.get("repositoryMetadata").should_not.be.none
|
||||
response.get("repositoryMetadata").get("creationDate").should_not.be.none
|
||||
response.get("repositoryMetadata").get("lastModifiedDate").should_not.be.none
|
||||
response.get("repositoryMetadata").get("repositoryId").should_not.be.empty
|
||||
response.get("repositoryMetadata").get("repositoryName").should.equal(
|
||||
repository_name
|
||||
)
|
||||
response.get("repositoryMetadata").get("repositoryDescription").should.equal(
|
||||
"description repo one"
|
||||
)
|
||||
response.get("repositoryMetadata").get("cloneUrlSsh").should.equal(
|
||||
"ssh://git-codecommit.{0}.amazonaws.com/v1/repos/{1}".format(
|
||||
"eu-central-1", "repository_one"
|
||||
)
|
||||
)
|
||||
response.get("repositoryMetadata").get("cloneUrlHttp").should.equal(
|
||||
"https://git-codecommit.{0}.amazonaws.com/v1/repos/{1}".format(
|
||||
"eu-central-1", "repository_one"
|
||||
)
|
||||
)
|
||||
response.get("repositoryMetadata").get("Arn").should.equal(
|
||||
"arn:aws:codecommit:{0}:{1}:{2}".format(
|
||||
"eu-central-1", ACCOUNT_ID, "repository_one"
|
||||
)
|
||||
)
|
||||
response.get("repositoryMetadata").get("accountId").should.equal(ACCOUNT_ID)
|
||||
|
||||
client = boto3.client("codecommit", region_name="us-east-1")
|
||||
|
||||
with assert_raises(ClientError) as e:
|
||||
client.get_repository(repositoryName=repository_name)
|
||||
ex = e.exception
|
||||
ex.operation_name.should.equal("GetRepository")
|
||||
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||
ex.response["Error"]["Code"].should.contain("RepositoryDoesNotExistException")
|
||||
ex.response["Error"]["Message"].should.equal(
|
||||
"{0} does not exist".format(repository_name)
|
||||
)
|
||||
|
||||
|
||||
@mock_codecommit
|
||||
def test_get_repository_invalid_repository_name():
|
||||
client = boto3.client("codecommit", region_name="eu-central-1")
|
||||
|
||||
with assert_raises(ClientError) as e:
|
||||
client.get_repository(repositoryName="repository_one-@#@")
|
||||
ex = e.exception
|
||||
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||
ex.response["Error"]["Code"].should.contain("InvalidRepositoryNameException")
|
||||
ex.response["Error"]["Message"].should.equal(
|
||||
"The repository name is not valid. Repository names can be any valid "
|
||||
"combination of letters, numbers, "
|
||||
"periods, underscores, and dashes between 1 and 100 characters in "
|
||||
"length. Names are case sensitive. "
|
||||
"For more information, see Limits in the AWS CodeCommit User Guide. "
|
||||
)
|
||||
|
||||
|
||||
@mock_codecommit
|
||||
def test_delete_repository():
|
||||
client = boto3.client("codecommit", region_name="us-east-1")
|
||||
|
||||
response = client.create_repository(repositoryName="repository_one")
|
||||
|
||||
repository_id_create = response.get("repositoryMetadata").get("repositoryId")
|
||||
|
||||
response = client.delete_repository(repositoryName="repository_one")
|
||||
|
||||
response.get("repositoryId").should_not.be.none
|
||||
repository_id_create.should.equal(response.get("repositoryId"))
|
||||
|
||||
response = client.delete_repository(repositoryName="unknown_repository")
|
||||
|
||||
response.get("repositoryId").should.be.none
|
||||
|
||||
|
||||
@mock_codecommit
|
||||
def test_delete_repository_invalid_repository_name():
|
||||
client = boto3.client("codecommit", region_name="us-east-1")
|
||||
|
||||
with assert_raises(ClientError) as e:
|
||||
client.delete_repository(repositoryName="_rep@ository_one")
|
||||
ex = e.exception
|
||||
ex.operation_name.should.equal("DeleteRepository")
|
||||
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||
ex.response["Error"]["Code"].should.contain("InvalidRepositoryNameException")
|
||||
ex.response["Error"]["Message"].should.equal(
|
||||
"The repository name is not valid. Repository names can be any valid "
|
||||
"combination of letters, numbers, "
|
||||
"periods, underscores, and dashes between 1 and 100 characters in "
|
||||
"length. Names are case sensitive. "
|
||||
"For more information, see Limits in the AWS CodeCommit User Guide. "
|
||||
)
|
||||
|
|
@ -13,52 +13,7 @@ from moto import mock_codepipeline, mock_iam
|
|||
def test_create_pipeline():
|
||||
client = boto3.client("codepipeline", region_name="us-east-1")
|
||||
|
||||
response = client.create_pipeline(
|
||||
pipeline={
|
||||
"name": "test-pipeline",
|
||||
"roleArn": get_role_arn(),
|
||||
"artifactStore": {
|
||||
"type": "S3",
|
||||
"location": "codepipeline-us-east-1-123456789012",
|
||||
},
|
||||
"stages": [
|
||||
{
|
||||
"name": "Stage-1",
|
||||
"actions": [
|
||||
{
|
||||
"name": "Action-1",
|
||||
"actionTypeId": {
|
||||
"category": "Source",
|
||||
"owner": "AWS",
|
||||
"provider": "S3",
|
||||
"version": "1",
|
||||
},
|
||||
"configuration": {
|
||||
"S3Bucket": "test-bucket",
|
||||
"S3ObjectKey": "test-object",
|
||||
},
|
||||
"outputArtifacts": [{"name": "artifact"},],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "Stage-2",
|
||||
"actions": [
|
||||
{
|
||||
"name": "Action-1",
|
||||
"actionTypeId": {
|
||||
"category": "Approval",
|
||||
"owner": "AWS",
|
||||
"provider": "Manual",
|
||||
"version": "1",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
tags=[{"key": "key", "value": "value"}],
|
||||
)
|
||||
response = create_basic_codepipeline(client, "test-pipeline")
|
||||
|
||||
response["pipeline"].should.equal(
|
||||
{
|
||||
|
|
@ -120,98 +75,10 @@ def test_create_pipeline():
|
|||
def test_create_pipeline_errors():
|
||||
client = boto3.client("codepipeline", region_name="us-east-1")
|
||||
client_iam = boto3.client("iam", region_name="us-east-1")
|
||||
client.create_pipeline(
|
||||
pipeline={
|
||||
"name": "test-pipeline",
|
||||
"roleArn": get_role_arn(),
|
||||
"artifactStore": {
|
||||
"type": "S3",
|
||||
"location": "codepipeline-us-east-1-123456789012",
|
||||
},
|
||||
"stages": [
|
||||
{
|
||||
"name": "Stage-1",
|
||||
"actions": [
|
||||
{
|
||||
"name": "Action-1",
|
||||
"actionTypeId": {
|
||||
"category": "Source",
|
||||
"owner": "AWS",
|
||||
"provider": "S3",
|
||||
"version": "1",
|
||||
},
|
||||
"configuration": {
|
||||
"S3Bucket": "test-bucket",
|
||||
"S3ObjectKey": "test-object",
|
||||
},
|
||||
"outputArtifacts": [{"name": "artifact"},],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "Stage-2",
|
||||
"actions": [
|
||||
{
|
||||
"name": "Action-1",
|
||||
"actionTypeId": {
|
||||
"category": "Approval",
|
||||
"owner": "AWS",
|
||||
"provider": "Manual",
|
||||
"version": "1",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
)
|
||||
create_basic_codepipeline(client, "test-pipeline")
|
||||
|
||||
with assert_raises(ClientError) as e:
|
||||
client.create_pipeline(
|
||||
pipeline={
|
||||
"name": "test-pipeline",
|
||||
"roleArn": get_role_arn(),
|
||||
"artifactStore": {
|
||||
"type": "S3",
|
||||
"location": "codepipeline-us-east-1-123456789012",
|
||||
},
|
||||
"stages": [
|
||||
{
|
||||
"name": "Stage-1",
|
||||
"actions": [
|
||||
{
|
||||
"name": "Action-1",
|
||||
"actionTypeId": {
|
||||
"category": "Source",
|
||||
"owner": "AWS",
|
||||
"provider": "S3",
|
||||
"version": "1",
|
||||
},
|
||||
"configuration": {
|
||||
"S3Bucket": "test-bucket",
|
||||
"S3ObjectKey": "test-object",
|
||||
},
|
||||
"outputArtifacts": [{"name": "artifact"},],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "Stage-2",
|
||||
"actions": [
|
||||
{
|
||||
"name": "Action-1",
|
||||
"actionTypeId": {
|
||||
"category": "Approval",
|
||||
"owner": "AWS",
|
||||
"provider": "Manual",
|
||||
"version": "1",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
}
|
||||
)
|
||||
create_basic_codepipeline(client, "test-pipeline")
|
||||
ex = e.exception
|
||||
ex.operation_name.should.equal("CreatePipeline")
|
||||
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||
|
|
@ -348,52 +215,7 @@ def test_create_pipeline_errors():
|
|||
@mock_codepipeline
|
||||
def test_get_pipeline():
|
||||
client = boto3.client("codepipeline", region_name="us-east-1")
|
||||
client.create_pipeline(
|
||||
pipeline={
|
||||
"name": "test-pipeline",
|
||||
"roleArn": get_role_arn(),
|
||||
"artifactStore": {
|
||||
"type": "S3",
|
||||
"location": "codepipeline-us-east-1-123456789012",
|
||||
},
|
||||
"stages": [
|
||||
{
|
||||
"name": "Stage-1",
|
||||
"actions": [
|
||||
{
|
||||
"name": "Action-1",
|
||||
"actionTypeId": {
|
||||
"category": "Source",
|
||||
"owner": "AWS",
|
||||
"provider": "S3",
|
||||
"version": "1",
|
||||
},
|
||||
"configuration": {
|
||||
"S3Bucket": "test-bucket",
|
||||
"S3ObjectKey": "test-object",
|
||||
},
|
||||
"outputArtifacts": [{"name": "artifact"},],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "Stage-2",
|
||||
"actions": [
|
||||
{
|
||||
"name": "Action-1",
|
||||
"actionTypeId": {
|
||||
"category": "Approval",
|
||||
"owner": "AWS",
|
||||
"provider": "Manual",
|
||||
"version": "1",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
tags=[{"key": "key", "value": "value"}],
|
||||
)
|
||||
create_basic_codepipeline(client, "test-pipeline")
|
||||
|
||||
response = client.get_pipeline(name="test-pipeline")
|
||||
|
||||
|
|
@ -474,53 +296,7 @@ def test_get_pipeline_errors():
|
|||
@mock_codepipeline
|
||||
def test_update_pipeline():
|
||||
client = boto3.client("codepipeline", region_name="us-east-1")
|
||||
role_arn = get_role_arn()
|
||||
client.create_pipeline(
|
||||
pipeline={
|
||||
"name": "test-pipeline",
|
||||
"roleArn": role_arn,
|
||||
"artifactStore": {
|
||||
"type": "S3",
|
||||
"location": "codepipeline-us-east-1-123456789012",
|
||||
},
|
||||
"stages": [
|
||||
{
|
||||
"name": "Stage-1",
|
||||
"actions": [
|
||||
{
|
||||
"name": "Action-1",
|
||||
"actionTypeId": {
|
||||
"category": "Source",
|
||||
"owner": "AWS",
|
||||
"provider": "S3",
|
||||
"version": "1",
|
||||
},
|
||||
"configuration": {
|
||||
"S3Bucket": "test-bucket",
|
||||
"S3ObjectKey": "test-object",
|
||||
},
|
||||
"outputArtifacts": [{"name": "artifact"},],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "Stage-2",
|
||||
"actions": [
|
||||
{
|
||||
"name": "Action-1",
|
||||
"actionTypeId": {
|
||||
"category": "Approval",
|
||||
"owner": "AWS",
|
||||
"provider": "Manual",
|
||||
"version": "1",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
tags=[{"key": "key", "value": "value"}],
|
||||
)
|
||||
create_basic_codepipeline(client, "test-pipeline")
|
||||
|
||||
response = client.get_pipeline(name="test-pipeline")
|
||||
created_time = response["metadata"]["created"]
|
||||
|
|
@ -529,7 +305,7 @@ def test_update_pipeline():
|
|||
response = client.update_pipeline(
|
||||
pipeline={
|
||||
"name": "test-pipeline",
|
||||
"roleArn": role_arn,
|
||||
"roleArn": get_role_arn(),
|
||||
"artifactStore": {
|
||||
"type": "S3",
|
||||
"location": "codepipeline-us-east-1-123456789012",
|
||||
|
|
@ -692,105 +468,19 @@ def test_update_pipeline_errors():
|
|||
@mock_codepipeline
|
||||
def test_list_pipelines():
|
||||
client = boto3.client("codepipeline", region_name="us-east-1")
|
||||
client.create_pipeline(
|
||||
pipeline={
|
||||
"name": "test-pipeline-1",
|
||||
"roleArn": get_role_arn(),
|
||||
"artifactStore": {
|
||||
"type": "S3",
|
||||
"location": "codepipeline-us-east-1-123456789012",
|
||||
},
|
||||
"stages": [
|
||||
{
|
||||
"name": "Stage-1",
|
||||
"actions": [
|
||||
{
|
||||
"name": "Action-1",
|
||||
"actionTypeId": {
|
||||
"category": "Source",
|
||||
"owner": "AWS",
|
||||
"provider": "S3",
|
||||
"version": "1",
|
||||
},
|
||||
"configuration": {
|
||||
"S3Bucket": "test-bucket",
|
||||
"S3ObjectKey": "test-object",
|
||||
},
|
||||
"outputArtifacts": [{"name": "artifact"},],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "Stage-2",
|
||||
"actions": [
|
||||
{
|
||||
"name": "Action-1",
|
||||
"actionTypeId": {
|
||||
"category": "Approval",
|
||||
"owner": "AWS",
|
||||
"provider": "Manual",
|
||||
"version": "1",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
)
|
||||
client.create_pipeline(
|
||||
pipeline={
|
||||
"name": "test-pipeline-2",
|
||||
"roleArn": get_role_arn(),
|
||||
"artifactStore": {
|
||||
"type": "S3",
|
||||
"location": "codepipeline-us-east-1-123456789012",
|
||||
},
|
||||
"stages": [
|
||||
{
|
||||
"name": "Stage-1",
|
||||
"actions": [
|
||||
{
|
||||
"name": "Action-1",
|
||||
"actionTypeId": {
|
||||
"category": "Source",
|
||||
"owner": "AWS",
|
||||
"provider": "S3",
|
||||
"version": "1",
|
||||
},
|
||||
"configuration": {
|
||||
"S3Bucket": "test-bucket",
|
||||
"S3ObjectKey": "test-object",
|
||||
},
|
||||
"outputArtifacts": [{"name": "artifact"},],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "Stage-2",
|
||||
"actions": [
|
||||
{
|
||||
"name": "Action-1",
|
||||
"actionTypeId": {
|
||||
"category": "Approval",
|
||||
"owner": "AWS",
|
||||
"provider": "Manual",
|
||||
"version": "1",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
)
|
||||
name_1 = "test-pipeline-1"
|
||||
create_basic_codepipeline(client, name_1)
|
||||
name_2 = "test-pipeline-2"
|
||||
create_basic_codepipeline(client, name_2)
|
||||
|
||||
response = client.list_pipelines()
|
||||
|
||||
response["pipelines"].should.have.length_of(2)
|
||||
response["pipelines"][0]["name"].should.equal("test-pipeline-1")
|
||||
response["pipelines"][0]["name"].should.equal(name_1)
|
||||
response["pipelines"][0]["version"].should.equal(1)
|
||||
response["pipelines"][0]["created"].should.be.a(datetime)
|
||||
response["pipelines"][0]["updated"].should.be.a(datetime)
|
||||
response["pipelines"][1]["name"].should.equal("test-pipeline-2")
|
||||
response["pipelines"][1]["name"].should.equal(name_2)
|
||||
response["pipelines"][1]["version"].should.equal(1)
|
||||
response["pipelines"][1]["created"].should.be.a(datetime)
|
||||
response["pipelines"][1]["updated"].should.be.a(datetime)
|
||||
|
|
@ -799,68 +489,172 @@ def test_list_pipelines():
|
|||
@mock_codepipeline
|
||||
def test_delete_pipeline():
|
||||
client = boto3.client("codepipeline", region_name="us-east-1")
|
||||
client.create_pipeline(
|
||||
pipeline={
|
||||
"name": "test-pipeline",
|
||||
"roleArn": get_role_arn(),
|
||||
"artifactStore": {
|
||||
"type": "S3",
|
||||
"location": "codepipeline-us-east-1-123456789012",
|
||||
},
|
||||
"stages": [
|
||||
{
|
||||
"name": "Stage-1",
|
||||
"actions": [
|
||||
{
|
||||
"name": "Action-1",
|
||||
"actionTypeId": {
|
||||
"category": "Source",
|
||||
"owner": "AWS",
|
||||
"provider": "S3",
|
||||
"version": "1",
|
||||
},
|
||||
"configuration": {
|
||||
"S3Bucket": "test-bucket",
|
||||
"S3ObjectKey": "test-object",
|
||||
},
|
||||
"outputArtifacts": [{"name": "artifact"},],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "Stage-2",
|
||||
"actions": [
|
||||
{
|
||||
"name": "Action-1",
|
||||
"actionTypeId": {
|
||||
"category": "Approval",
|
||||
"owner": "AWS",
|
||||
"provider": "Manual",
|
||||
"version": "1",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
)
|
||||
name = "test-pipeline"
|
||||
create_basic_codepipeline(client, name)
|
||||
client.list_pipelines()["pipelines"].should.have.length_of(1)
|
||||
|
||||
client.delete_pipeline(name="test-pipeline")
|
||||
client.delete_pipeline(name=name)
|
||||
|
||||
client.list_pipelines()["pipelines"].should.have.length_of(0)
|
||||
|
||||
# deleting a not existing pipeline, should raise no exception
|
||||
client.delete_pipeline(name="test-pipeline")
|
||||
client.delete_pipeline(name=name)
|
||||
|
||||
|
||||
@mock_codepipeline
|
||||
def test_list_tags_for_resource():
|
||||
client = boto3.client("codepipeline", region_name="us-east-1")
|
||||
name = "test-pipeline"
|
||||
create_basic_codepipeline(client, name)
|
||||
|
||||
response = client.list_tags_for_resource(
|
||||
resourceArn="arn:aws:codepipeline:us-east-1:123456789012:{}".format(name)
|
||||
)
|
||||
response["tags"].should.equal([{"key": "key", "value": "value"}])
|
||||
|
||||
|
||||
@mock_codepipeline
|
||||
def test_list_tags_for_resource_errors():
|
||||
client = boto3.client("codepipeline", region_name="us-east-1")
|
||||
|
||||
with assert_raises(ClientError) as e:
|
||||
client.list_tags_for_resource(
|
||||
resourceArn="arn:aws:codepipeline:us-east-1:123456789012:not-existing"
|
||||
)
|
||||
ex = e.exception
|
||||
ex.operation_name.should.equal("ListTagsForResource")
|
||||
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||
ex.response["Error"]["Code"].should.contain("ResourceNotFoundException")
|
||||
ex.response["Error"]["Message"].should.equal(
|
||||
"The account with id '123456789012' does not include a pipeline with the name 'not-existing'"
|
||||
)
|
||||
|
||||
|
||||
@mock_codepipeline
|
||||
def test_tag_resource():
|
||||
client = boto3.client("codepipeline", region_name="us-east-1")
|
||||
name = "test-pipeline"
|
||||
create_basic_codepipeline(client, name)
|
||||
|
||||
client.tag_resource(
|
||||
resourceArn="arn:aws:codepipeline:us-east-1:123456789012:{}".format(name),
|
||||
tags=[{"key": "key-2", "value": "value-2"}],
|
||||
)
|
||||
|
||||
response = client.list_tags_for_resource(
|
||||
resourceArn="arn:aws:codepipeline:us-east-1:123456789012:{}".format(name)
|
||||
)
|
||||
response["tags"].should.equal(
|
||||
[{"key": "key", "value": "value"}, {"key": "key-2", "value": "value-2"}]
|
||||
)
|
||||
|
||||
|
||||
@mock_codepipeline
|
||||
def test_tag_resource_errors():
|
||||
client = boto3.client("codepipeline", region_name="us-east-1")
|
||||
name = "test-pipeline"
|
||||
create_basic_codepipeline(client, name)
|
||||
|
||||
with assert_raises(ClientError) as e:
|
||||
client.tag_resource(
|
||||
resourceArn="arn:aws:codepipeline:us-east-1:123456789012:not-existing",
|
||||
tags=[{"key": "key-2", "value": "value-2"}],
|
||||
)
|
||||
ex = e.exception
|
||||
ex.operation_name.should.equal("TagResource")
|
||||
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||
ex.response["Error"]["Code"].should.contain("ResourceNotFoundException")
|
||||
ex.response["Error"]["Message"].should.equal(
|
||||
"The account with id '123456789012' does not include a pipeline with the name 'not-existing'"
|
||||
)
|
||||
|
||||
with assert_raises(ClientError) as e:
|
||||
client.tag_resource(
|
||||
resourceArn="arn:aws:codepipeline:us-east-1:123456789012:{}".format(name),
|
||||
tags=[{"key": "aws:key", "value": "value"}],
|
||||
)
|
||||
ex = e.exception
|
||||
ex.operation_name.should.equal("TagResource")
|
||||
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||
ex.response["Error"]["Code"].should.contain("InvalidTagsException")
|
||||
ex.response["Error"]["Message"].should.equal(
|
||||
"Not allowed to modify system tags. "
|
||||
"System tags start with 'aws:'. "
|
||||
"msg=[Caller is an end user and not allowed to mutate system tags]"
|
||||
)
|
||||
|
||||
with assert_raises(ClientError) as e:
|
||||
client.tag_resource(
|
||||
resourceArn="arn:aws:codepipeline:us-east-1:123456789012:{}".format(name),
|
||||
tags=[
|
||||
{"key": "key-{}".format(i), "value": "value-{}".format(i)}
|
||||
for i in range(50)
|
||||
],
|
||||
)
|
||||
ex = e.exception
|
||||
ex.operation_name.should.equal("TagResource")
|
||||
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||
ex.response["Error"]["Code"].should.contain("TooManyTagsException")
|
||||
ex.response["Error"]["Message"].should.equal(
|
||||
"Tag limit exceeded for resource [arn:aws:codepipeline:us-east-1:123456789012:{}].".format(
|
||||
name
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@mock_codepipeline
|
||||
def test_untag_resource():
|
||||
client = boto3.client("codepipeline", region_name="us-east-1")
|
||||
name = "test-pipeline"
|
||||
create_basic_codepipeline(client, name)
|
||||
|
||||
response = client.list_tags_for_resource(
|
||||
resourceArn="arn:aws:codepipeline:us-east-1:123456789012:{}".format(name)
|
||||
)
|
||||
response["tags"].should.equal([{"key": "key", "value": "value"}])
|
||||
|
||||
client.untag_resource(
|
||||
resourceArn="arn:aws:codepipeline:us-east-1:123456789012:{}".format(name),
|
||||
tagKeys=["key"],
|
||||
)
|
||||
|
||||
response = client.list_tags_for_resource(
|
||||
resourceArn="arn:aws:codepipeline:us-east-1:123456789012:{}".format(name)
|
||||
)
|
||||
response["tags"].should.have.length_of(0)
|
||||
|
||||
# removing a not existing tag should raise no exception
|
||||
client.untag_resource(
|
||||
resourceArn="arn:aws:codepipeline:us-east-1:123456789012:{}".format(name),
|
||||
tagKeys=["key"],
|
||||
)
|
||||
|
||||
|
||||
@mock_codepipeline
|
||||
def test_untag_resource_errors():
|
||||
client = boto3.client("codepipeline", region_name="us-east-1")
|
||||
|
||||
with assert_raises(ClientError) as e:
|
||||
client.untag_resource(
|
||||
resourceArn="arn:aws:codepipeline:us-east-1:123456789012:not-existing",
|
||||
tagKeys=["key"],
|
||||
)
|
||||
ex = e.exception
|
||||
ex.operation_name.should.equal("UntagResource")
|
||||
ex.response["ResponseMetadata"]["HTTPStatusCode"].should.equal(400)
|
||||
ex.response["Error"]["Code"].should.contain("ResourceNotFoundException")
|
||||
ex.response["Error"]["Message"].should.equal(
|
||||
"The account with id '123456789012' does not include a pipeline with the name 'not-existing'"
|
||||
)
|
||||
|
||||
|
||||
@mock_iam
|
||||
def get_role_arn():
|
||||
iam = boto3.client("iam", region_name="us-east-1")
|
||||
client = boto3.client("iam", region_name="us-east-1")
|
||||
try:
|
||||
return iam.get_role(RoleName="test-role")["Role"]["Arn"]
|
||||
return client.get_role(RoleName="test-role")["Role"]["Arn"]
|
||||
except ClientError:
|
||||
return iam.create_role(
|
||||
return client.create_role(
|
||||
RoleName="test-role",
|
||||
AssumeRolePolicyDocument=json.dumps(
|
||||
{
|
||||
|
|
@ -875,3 +669,52 @@ def get_role_arn():
|
|||
}
|
||||
),
|
||||
)["Role"]["Arn"]
|
||||
|
||||
|
||||
def create_basic_codepipeline(client, name):
|
||||
return client.create_pipeline(
|
||||
pipeline={
|
||||
"name": name,
|
||||
"roleArn": get_role_arn(),
|
||||
"artifactStore": {
|
||||
"type": "S3",
|
||||
"location": "codepipeline-us-east-1-123456789012",
|
||||
},
|
||||
"stages": [
|
||||
{
|
||||
"name": "Stage-1",
|
||||
"actions": [
|
||||
{
|
||||
"name": "Action-1",
|
||||
"actionTypeId": {
|
||||
"category": "Source",
|
||||
"owner": "AWS",
|
||||
"provider": "S3",
|
||||
"version": "1",
|
||||
},
|
||||
"configuration": {
|
||||
"S3Bucket": "test-bucket",
|
||||
"S3ObjectKey": "test-object",
|
||||
},
|
||||
"outputArtifacts": [{"name": "artifact"},],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "Stage-2",
|
||||
"actions": [
|
||||
{
|
||||
"name": "Action-1",
|
||||
"actionTypeId": {
|
||||
"category": "Approval",
|
||||
"owner": "AWS",
|
||||
"provider": "Manual",
|
||||
"version": "1",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
tags=[{"key": "key", "value": "value"}],
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1142,11 +1142,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
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ from boto3.dynamodb.conditions import Attr, Key
|
|||
import sure # noqa
|
||||
import requests
|
||||
from moto import mock_dynamodb2, mock_dynamodb2_deprecated
|
||||
from moto.dynamodb2 import dynamodb_backend2
|
||||
from moto.dynamodb2 import dynamodb_backend2, dynamodb_backends2
|
||||
from boto.exception import JSONResponseError
|
||||
from botocore.exceptions import ClientError, ParamValidationError
|
||||
from tests.helpers import requires_boto_gte
|
||||
|
|
@ -350,6 +350,60 @@ def test_put_item_with_special_chars():
|
|||
)
|
||||
|
||||
|
||||
@requires_boto_gte("2.9")
|
||||
@mock_dynamodb2
|
||||
def test_put_item_with_streams():
|
||||
name = "TestTable"
|
||||
conn = boto3.client(
|
||||
"dynamodb",
|
||||
region_name="us-west-2",
|
||||
aws_access_key_id="ak",
|
||||
aws_secret_access_key="sk",
|
||||
)
|
||||
|
||||
conn.create_table(
|
||||
TableName=name,
|
||||
KeySchema=[{"AttributeName": "forum_name", "KeyType": "HASH"}],
|
||||
AttributeDefinitions=[{"AttributeName": "forum_name", "AttributeType": "S"}],
|
||||
StreamSpecification={
|
||||
"StreamEnabled": True,
|
||||
"StreamViewType": "NEW_AND_OLD_IMAGES",
|
||||
},
|
||||
ProvisionedThroughput={"ReadCapacityUnits": 5, "WriteCapacityUnits": 5},
|
||||
)
|
||||
|
||||
conn.put_item(
|
||||
TableName=name,
|
||||
Item={
|
||||
"forum_name": {"S": "LOLCat Forum"},
|
||||
"subject": {"S": "Check this out!"},
|
||||
"Body": {"S": "http://url_to_lolcat.gif"},
|
||||
"SentBy": {"S": "test"},
|
||||
"Data": {"M": {"Key1": {"S": "Value1"}, "Key2": {"S": "Value2"}}},
|
||||
},
|
||||
)
|
||||
|
||||
result = conn.get_item(TableName=name, Key={"forum_name": {"S": "LOLCat Forum"}})
|
||||
|
||||
result["Item"].should.be.equal(
|
||||
{
|
||||
"forum_name": {"S": "LOLCat Forum"},
|
||||
"subject": {"S": "Check this out!"},
|
||||
"Body": {"S": "http://url_to_lolcat.gif"},
|
||||
"SentBy": {"S": "test"},
|
||||
"Data": {"M": {"Key1": {"S": "Value1"}, "Key2": {"S": "Value2"}}},
|
||||
}
|
||||
)
|
||||
table = dynamodb_backends2["us-west-2"].get_table(name)
|
||||
if not table:
|
||||
# There is no way to access stream data over the API, so this part can't run in server-tests mode.
|
||||
return
|
||||
len(table.stream_shard.items).should.be.equal(1)
|
||||
stream_record = table.stream_shard.items[0].record
|
||||
stream_record["eventName"].should.be.equal("INSERT")
|
||||
stream_record["dynamodb"]["SizeBytes"].should.be.equal(447)
|
||||
|
||||
|
||||
@requires_boto_gte("2.9")
|
||||
@mock_dynamodb2
|
||||
def test_query_returns_consumed_capacity():
|
||||
|
|
@ -1665,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")
|
||||
|
|
@ -2451,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")
|
||||
|
|
@ -3435,6 +3557,58 @@ 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_catches_invalid_list_append_operation():
|
||||
client = boto3.client("dynamodb", region_name="us-east-1")
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ from moto import mock_ec2, mock_ec2_deprecated
|
|||
def test_describe_regions():
|
||||
conn = boto.connect_ec2("the_key", "the_secret")
|
||||
regions = conn.get_all_regions()
|
||||
regions.should.have.length_of(16)
|
||||
len(regions).should.be.greater_than(1)
|
||||
for region in regions:
|
||||
region.endpoint.should.contain(region.name)
|
||||
|
||||
|
|
@ -32,7 +32,7 @@ def test_availability_zones():
|
|||
def test_boto3_describe_regions():
|
||||
ec2 = boto3.client("ec2", "us-east-1")
|
||||
resp = ec2.describe_regions()
|
||||
resp["Regions"].should.have.length_of(16)
|
||||
len(resp["Regions"]).should.be.greater_than(1)
|
||||
for rec in resp["Regions"]:
|
||||
rec["Endpoint"].should.contain(rec["RegionName"])
|
||||
|
||||
|
|
|
|||
|
|
@ -3,13 +3,21 @@ import boto.ec2
|
|||
import boto.ec2.autoscale
|
||||
import boto.ec2.elb
|
||||
import sure
|
||||
from boto3 import Session
|
||||
|
||||
from moto import mock_ec2_deprecated, mock_autoscaling_deprecated, mock_elb_deprecated
|
||||
|
||||
from moto.ec2 import ec2_backends
|
||||
|
||||
|
||||
def test_use_boto_regions():
|
||||
boto_regions = {r.name for r in boto.ec2.regions()}
|
||||
boto_regions = set()
|
||||
for region in Session().get_available_regions("ec2"):
|
||||
boto_regions.add(region)
|
||||
for region in Session().get_available_regions("ec2", partition_name="aws-us-gov"):
|
||||
boto_regions.add(region)
|
||||
for region in Session().get_available_regions("ec2", partition_name="aws-cn"):
|
||||
boto_regions.add(region)
|
||||
moto_regions = set(ec2_backends)
|
||||
|
||||
moto_regions.should.equal(boto_regions)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,23 @@
|
|||
import boto3
|
||||
|
||||
from moto import mock_ec2_instance_connect
|
||||
|
||||
pubkey = """ssh-rsa
|
||||
AAAAB3NzaC1yc2EAAAADAQABAAABAQDV5+voluw2zmzqpqCAqtsyoP01TQ8Ydx1eS1yD6wUsHcPqMIqpo57YxiC8XPwrdeKQ6GG6MC3bHsgXoPypGP0LyixbiuLTU31DnnqorcHt4bWs6rQa7dK2pCCflz2fhYRt5ZjqSNsAKivIbqkH66JozN0SySIka3kEV79GdB0BicioKeEJlCwM9vvxafyzjWf/z8E0lh4ni3vkLpIVJ0t5l+Qd9QMJrT6Is0SCQPVagTYZoi8+fWDoGsBa8vyRwDjEzBl28ZplKh9tSyDkRIYszWTpmK8qHiqjLYZBfAxXjGJbEYL1iig4ZxvbYzKEiKSBi1ZMW9iWjHfZDZuxXAmB
|
||||
example
|
||||
"""
|
||||
|
||||
|
||||
@mock_ec2_instance_connect
|
||||
def test_send_ssh_public_key():
|
||||
client = boto3.client("ec2-instance-connect", region_name="us-east-1")
|
||||
fake_request_id = "example-2a47-4c91-9700-e37e85162cb6"
|
||||
|
||||
response = client.send_ssh_public_key(
|
||||
InstanceId="i-abcdefg12345",
|
||||
InstanceOSUser="ec2-user",
|
||||
SSHPublicKey=pubkey,
|
||||
AvailabilityZone="us-east-1a",
|
||||
)
|
||||
|
||||
assert response["RequestId"] == fake_request_id
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ def test_describe_job():
|
|||
joboutput.should.have.key("Tier").which.should.equal("Standard")
|
||||
joboutput.should.have.key("StatusCode").which.should.equal("InProgress")
|
||||
joboutput.should.have.key("VaultARN").which.should.equal(
|
||||
"arn:aws:glacier:RegionInfo:us-west-2:012345678901:vaults/my_vault"
|
||||
"arn:aws:glacier:us-west-2:012345678901:vaults/my_vault"
|
||||
)
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1737,9 +1737,7 @@ def test_delete_saml_provider():
|
|||
def test_create_role_defaults():
|
||||
"""Tests default values"""
|
||||
conn = boto3.client("iam", region_name="us-east-1")
|
||||
conn.create_role(
|
||||
RoleName="my-role", AssumeRolePolicyDocument="{}",
|
||||
)
|
||||
conn.create_role(RoleName="my-role", AssumeRolePolicyDocument="{}")
|
||||
|
||||
# Get role:
|
||||
role = conn.get_role(RoleName="my-role")["Role"]
|
||||
|
|
@ -2672,3 +2670,33 @@ def test_get_account_summary():
|
|||
"GroupsQuota": 300,
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@mock_iam()
|
||||
def test_list_user_tags():
|
||||
"""Tests both setting a tags on a user in create_user and list_user_tags"""
|
||||
conn = boto3.client("iam", region_name="us-east-1")
|
||||
conn.create_user(UserName="kenny-bania")
|
||||
conn.create_user(
|
||||
UserName="jackie-chiles", Tags=[{"Key": "Sue-Allen", "Value": "Oh-Henry"}]
|
||||
)
|
||||
conn.create_user(
|
||||
UserName="cosmo",
|
||||
Tags=[
|
||||
{"Key": "Stan", "Value": "The Caddy"},
|
||||
{"Key": "like-a", "Value": "glove"},
|
||||
],
|
||||
)
|
||||
response = conn.list_user_tags(UserName="kenny-bania")
|
||||
response["Tags"].should.equal([])
|
||||
response["IsTruncated"].should_not.be.ok
|
||||
|
||||
response = conn.list_user_tags(UserName="jackie-chiles")
|
||||
response["Tags"].should.equal([{"Key": "Sue-Allen", "Value": "Oh-Henry"}])
|
||||
response["IsTruncated"].should_not.be.ok
|
||||
|
||||
response = conn.list_user_tags(UserName="cosmo")
|
||||
response["Tags"].should.equal(
|
||||
[{"Key": "Stan", "Value": "The Caddy"}, {"Key": "like-a", "Value": "glove"}]
|
||||
)
|
||||
response["IsTruncated"].should_not.be.ok
|
||||
|
|
|
|||
|
|
@ -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"]
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1261,7 +1261,7 @@ def test_boto3_list_objects_truncated_response():
|
|||
assert listed_object["Key"] == "one"
|
||||
assert resp["MaxKeys"] == 1
|
||||
assert resp["IsTruncated"] == True
|
||||
assert resp["Prefix"] == "None"
|
||||
assert resp.get("Prefix") is None
|
||||
assert resp["Delimiter"] == "None"
|
||||
assert "NextMarker" in resp
|
||||
|
||||
|
|
@ -1274,7 +1274,7 @@ def test_boto3_list_objects_truncated_response():
|
|||
assert listed_object["Key"] == "three"
|
||||
assert resp["MaxKeys"] == 1
|
||||
assert resp["IsTruncated"] == True
|
||||
assert resp["Prefix"] == "None"
|
||||
assert resp.get("Prefix") is None
|
||||
assert resp["Delimiter"] == "None"
|
||||
assert "NextMarker" in resp
|
||||
|
||||
|
|
@ -1287,7 +1287,7 @@ def test_boto3_list_objects_truncated_response():
|
|||
assert listed_object["Key"] == "two"
|
||||
assert resp["MaxKeys"] == 1
|
||||
assert resp["IsTruncated"] == False
|
||||
assert resp["Prefix"] == "None"
|
||||
assert resp.get("Prefix") is None
|
||||
assert resp["Delimiter"] == "None"
|
||||
assert "NextMarker" not in resp
|
||||
|
||||
|
|
|
|||
|
|
@ -54,9 +54,10 @@ def test_deleting_subscriptions_by_deleting_topic():
|
|||
]["Subscriptions"]
|
||||
subscriptions.should.have.length_of(1)
|
||||
subscription = subscriptions[0]
|
||||
subscription_arn = subscription["SubscriptionArn"]
|
||||
subscription["TopicArn"].should.equal(topic_arn)
|
||||
subscription["Protocol"].should.equal("http")
|
||||
subscription["SubscriptionArn"].should.contain(topic_arn)
|
||||
subscription_arn.should.contain(topic_arn)
|
||||
subscription["Endpoint"].should.equal("http://example.com/")
|
||||
|
||||
# Now delete the topic
|
||||
|
|
@ -67,12 +68,25 @@ def test_deleting_subscriptions_by_deleting_topic():
|
|||
topics = topics_json["ListTopicsResponse"]["ListTopicsResult"]["Topics"]
|
||||
topics.should.have.length_of(0)
|
||||
|
||||
# And there should be zero subscriptions left
|
||||
# And the subscription should still be left
|
||||
subscriptions = conn.get_all_subscriptions()["ListSubscriptionsResponse"][
|
||||
"ListSubscriptionsResult"
|
||||
]["Subscriptions"]
|
||||
subscriptions.should.have.length_of(1)
|
||||
subscription = subscriptions[0]
|
||||
subscription["SubscriptionArn"].should.equal(subscription_arn)
|
||||
|
||||
# Now delete hanging subscription
|
||||
conn.unsubscribe(subscription_arn)
|
||||
|
||||
subscriptions = conn.get_all_subscriptions()["ListSubscriptionsResponse"][
|
||||
"ListSubscriptionsResult"
|
||||
]["Subscriptions"]
|
||||
subscriptions.should.have.length_of(0)
|
||||
|
||||
# Deleting it again should not result in any error
|
||||
conn.unsubscribe(subscription_arn)
|
||||
|
||||
|
||||
@mock_sns_deprecated
|
||||
def test_getting_subscriptions_by_topic():
|
||||
|
|
|
|||
|
|
@ -97,34 +97,48 @@ def test_creating_subscription():
|
|||
|
||||
|
||||
@mock_sns
|
||||
def test_deleting_subscriptions_by_deleting_topic():
|
||||
conn = boto3.client("sns", region_name="us-east-1")
|
||||
conn.create_topic(Name="some-topic")
|
||||
response = conn.list_topics()
|
||||
def test_unsubscribe_from_deleted_topic():
|
||||
client = boto3.client("sns", region_name="us-east-1")
|
||||
client.create_topic(Name="some-topic")
|
||||
response = client.list_topics()
|
||||
topic_arn = response["Topics"][0]["TopicArn"]
|
||||
|
||||
conn.subscribe(TopicArn=topic_arn, Protocol="http", Endpoint="http://example.com/")
|
||||
client.subscribe(
|
||||
TopicArn=topic_arn, Protocol="http", Endpoint="http://example.com/"
|
||||
)
|
||||
|
||||
subscriptions = conn.list_subscriptions()["Subscriptions"]
|
||||
subscriptions = client.list_subscriptions()["Subscriptions"]
|
||||
subscriptions.should.have.length_of(1)
|
||||
subscription = subscriptions[0]
|
||||
subscription_arn = subscription["SubscriptionArn"]
|
||||
subscription["TopicArn"].should.equal(topic_arn)
|
||||
subscription["Protocol"].should.equal("http")
|
||||
subscription["SubscriptionArn"].should.contain(topic_arn)
|
||||
subscription_arn.should.contain(topic_arn)
|
||||
subscription["Endpoint"].should.equal("http://example.com/")
|
||||
|
||||
# Now delete the topic
|
||||
conn.delete_topic(TopicArn=topic_arn)
|
||||
client.delete_topic(TopicArn=topic_arn)
|
||||
|
||||
# And there should now be 0 topics
|
||||
topics_json = conn.list_topics()
|
||||
topics_json = client.list_topics()
|
||||
topics = topics_json["Topics"]
|
||||
topics.should.have.length_of(0)
|
||||
|
||||
# And there should be zero subscriptions left
|
||||
subscriptions = conn.list_subscriptions()["Subscriptions"]
|
||||
# And the subscription should still be left
|
||||
subscriptions = client.list_subscriptions()["Subscriptions"]
|
||||
subscriptions.should.have.length_of(1)
|
||||
subscription = subscriptions[0]
|
||||
subscription["SubscriptionArn"].should.equal(subscription_arn)
|
||||
|
||||
# Now delete hanging subscription
|
||||
client.unsubscribe(SubscriptionArn=subscription_arn)
|
||||
|
||||
subscriptions = client.list_subscriptions()["Subscriptions"]
|
||||
subscriptions.should.have.length_of(0)
|
||||
|
||||
# Deleting it again should not result in any error
|
||||
client.unsubscribe(SubscriptionArn=subscription_arn)
|
||||
|
||||
|
||||
@mock_sns
|
||||
def test_getting_subscriptions_by_topic():
|
||||
|
|
|
|||
|
|
@ -331,7 +331,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 +369,7 @@ def test_get_queue_attributes():
|
|||
"ApproximateNumberOfMessages",
|
||||
"MaximumMessageSize",
|
||||
"QueueArn",
|
||||
"RedrivePolicy",
|
||||
"VisibilityTimeout",
|
||||
],
|
||||
)
|
||||
|
|
@ -366,6 +380,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}
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue