394 lines
17 KiB
Python
394 lines
17 KiB
Python
from __future__ import unicode_literals
|
|
|
|
import boto3
|
|
import sure # noqa
|
|
import datetime
|
|
|
|
from datetime import datetime
|
|
from botocore.exceptions import ClientError
|
|
from nose.tools import assert_raises
|
|
|
|
from moto import mock_sts, mock_stepfunctions
|
|
|
|
|
|
region = 'us-east-1'
|
|
simple_definition = '{"Comment": "An example of the Amazon States Language using a choice state.",' \
|
|
'"StartAt": "DefaultState",' \
|
|
'"States": ' \
|
|
'{"DefaultState": {"Type": "Fail","Error": "DefaultStateError","Cause": "No Matches!"}}}'
|
|
account_id = None
|
|
|
|
|
|
@mock_stepfunctions
|
|
@mock_sts
|
|
def test_state_machine_creation_succeeds():
|
|
client = boto3.client('stepfunctions', region_name=region)
|
|
name = 'example_step_function'
|
|
#
|
|
response = client.create_state_machine(name=name,
|
|
definition=str(simple_definition),
|
|
roleArn=_get_default_role())
|
|
#
|
|
response['ResponseMetadata']['HTTPStatusCode'].should.equal(200)
|
|
response['creationDate'].should.be.a(datetime)
|
|
response['stateMachineArn'].should.equal('arn:aws:states:' + region + ':123456789012:stateMachine:' + name)
|
|
|
|
|
|
@mock_stepfunctions
|
|
def test_state_machine_creation_fails_with_invalid_names():
|
|
client = boto3.client('stepfunctions', region_name=region)
|
|
invalid_names = [
|
|
'with space',
|
|
'with<bracket', 'with>bracket', 'with{bracket', 'with}bracket', 'with[bracket', 'with]bracket',
|
|
'with?wildcard', 'with*wildcard',
|
|
'special"char', 'special#char', 'special%char', 'special\\char', 'special^char', 'special|char',
|
|
'special~char', 'special`char', 'special$char', 'special&char', 'special,char', 'special;char',
|
|
'special:char', 'special/char',
|
|
u'uni\u0000code', u'uni\u0001code', u'uni\u0002code', u'uni\u0003code', u'uni\u0004code',
|
|
u'uni\u0005code', u'uni\u0006code', u'uni\u0007code', u'uni\u0008code', u'uni\u0009code',
|
|
u'uni\u000Acode', u'uni\u000Bcode', u'uni\u000Ccode',
|
|
u'uni\u000Dcode', u'uni\u000Ecode', u'uni\u000Fcode',
|
|
u'uni\u0010code', u'uni\u0011code', u'uni\u0012code', u'uni\u0013code', u'uni\u0014code',
|
|
u'uni\u0015code', u'uni\u0016code', u'uni\u0017code', u'uni\u0018code', u'uni\u0019code',
|
|
u'uni\u001Acode', u'uni\u001Bcode', u'uni\u001Ccode',
|
|
u'uni\u001Dcode', u'uni\u001Ecode', u'uni\u001Fcode',
|
|
u'uni\u007Fcode',
|
|
u'uni\u0080code', u'uni\u0081code', u'uni\u0082code', u'uni\u0083code', u'uni\u0084code',
|
|
u'uni\u0085code', u'uni\u0086code', u'uni\u0087code', u'uni\u0088code', u'uni\u0089code',
|
|
u'uni\u008Acode', u'uni\u008Bcode', u'uni\u008Ccode',
|
|
u'uni\u008Dcode', u'uni\u008Ecode', u'uni\u008Fcode',
|
|
u'uni\u0090code', u'uni\u0091code', u'uni\u0092code', u'uni\u0093code', u'uni\u0094code',
|
|
u'uni\u0095code', u'uni\u0096code', u'uni\u0097code', u'uni\u0098code', u'uni\u0099code',
|
|
u'uni\u009Acode', u'uni\u009Bcode', u'uni\u009Ccode',
|
|
u'uni\u009Dcode', u'uni\u009Ecode', u'uni\u009Fcode']
|
|
#
|
|
|
|
for invalid_name in invalid_names:
|
|
with assert_raises(ClientError) as exc:
|
|
client.create_state_machine(name=invalid_name,
|
|
definition=str(simple_definition),
|
|
roleArn=_get_default_role())
|
|
|
|
|
|
@mock_stepfunctions
|
|
def test_state_machine_creation_requires_valid_role_arn():
|
|
client = boto3.client('stepfunctions', region_name=region)
|
|
name = 'example_step_function'
|
|
#
|
|
with assert_raises(ClientError) as exc:
|
|
client.create_state_machine(name=name,
|
|
definition=str(simple_definition),
|
|
roleArn='arn:aws:iam::1234:role/unknown_role')
|
|
|
|
|
|
@mock_stepfunctions
|
|
def test_state_machine_list_returns_empty_list_by_default():
|
|
client = boto3.client('stepfunctions', region_name=region)
|
|
#
|
|
list = client.list_state_machines()
|
|
list['stateMachines'].should.be.empty
|
|
|
|
|
|
@mock_stepfunctions
|
|
@mock_sts
|
|
def test_state_machine_list_returns_created_state_machines():
|
|
client = boto3.client('stepfunctions', region_name=region)
|
|
#
|
|
machine2 = client.create_state_machine(name='name2',
|
|
definition=str(simple_definition),
|
|
roleArn=_get_default_role())
|
|
machine1 = client.create_state_machine(name='name1',
|
|
definition=str(simple_definition),
|
|
roleArn=_get_default_role(),
|
|
tags=[{'key': 'tag_key', 'value': 'tag_value'}])
|
|
list = client.list_state_machines()
|
|
#
|
|
list['ResponseMetadata']['HTTPStatusCode'].should.equal(200)
|
|
list['stateMachines'].should.have.length_of(2)
|
|
list['stateMachines'][0]['creationDate'].should.be.a(datetime)
|
|
list['stateMachines'][0]['creationDate'].should.equal(machine1['creationDate'])
|
|
list['stateMachines'][0]['name'].should.equal('name1')
|
|
list['stateMachines'][0]['stateMachineArn'].should.equal(machine1['stateMachineArn'])
|
|
list['stateMachines'][1]['creationDate'].should.be.a(datetime)
|
|
list['stateMachines'][1]['creationDate'].should.equal(machine2['creationDate'])
|
|
list['stateMachines'][1]['name'].should.equal('name2')
|
|
list['stateMachines'][1]['stateMachineArn'].should.equal(machine2['stateMachineArn'])
|
|
|
|
|
|
@mock_stepfunctions
|
|
@mock_sts
|
|
def test_state_machine_creation_is_idempotent_by_name():
|
|
client = boto3.client('stepfunctions', region_name=region)
|
|
#
|
|
client.create_state_machine(name='name', definition=str(simple_definition), roleArn=_get_default_role())
|
|
sm_list = client.list_state_machines()
|
|
sm_list['stateMachines'].should.have.length_of(1)
|
|
#
|
|
client.create_state_machine(name='name', definition=str(simple_definition), roleArn=_get_default_role())
|
|
sm_list = client.list_state_machines()
|
|
sm_list['stateMachines'].should.have.length_of(1)
|
|
#
|
|
client.create_state_machine(name='diff_name', definition=str(simple_definition), roleArn=_get_default_role())
|
|
sm_list = client.list_state_machines()
|
|
sm_list['stateMachines'].should.have.length_of(2)
|
|
|
|
|
|
@mock_stepfunctions
|
|
@mock_sts
|
|
def test_state_machine_creation_can_be_described():
|
|
client = boto3.client('stepfunctions', region_name=region)
|
|
#
|
|
sm = client.create_state_machine(name='name', definition=str(simple_definition), roleArn=_get_default_role())
|
|
desc = client.describe_state_machine(stateMachineArn=sm['stateMachineArn'])
|
|
desc['ResponseMetadata']['HTTPStatusCode'].should.equal(200)
|
|
desc['creationDate'].should.equal(sm['creationDate'])
|
|
desc['definition'].should.equal(str(simple_definition))
|
|
desc['name'].should.equal('name')
|
|
desc['roleArn'].should.equal(_get_default_role())
|
|
desc['stateMachineArn'].should.equal(sm['stateMachineArn'])
|
|
desc['status'].should.equal('ACTIVE')
|
|
|
|
|
|
@mock_stepfunctions
|
|
@mock_sts
|
|
def test_state_machine_throws_error_when_describing_unknown_machine():
|
|
client = boto3.client('stepfunctions', region_name=region)
|
|
#
|
|
with assert_raises(ClientError) as exc:
|
|
unknown_state_machine = 'arn:aws:states:' + region + ':' + _get_account_id() + ':stateMachine:unknown'
|
|
client.describe_state_machine(stateMachineArn=unknown_state_machine)
|
|
|
|
|
|
@mock_stepfunctions
|
|
@mock_sts
|
|
def test_state_machine_throws_error_when_describing_machine_in_different_account():
|
|
client = boto3.client('stepfunctions', region_name=region)
|
|
#
|
|
with assert_raises(ClientError) as exc:
|
|
unknown_state_machine = 'arn:aws:states:' + region + ':000000000000:stateMachine:unknown'
|
|
client.describe_state_machine(stateMachineArn=unknown_state_machine)
|
|
|
|
|
|
@mock_stepfunctions
|
|
@mock_sts
|
|
def test_state_machine_can_be_deleted():
|
|
client = boto3.client('stepfunctions', region_name=region)
|
|
sm = client.create_state_machine(name='name', definition=str(simple_definition), roleArn=_get_default_role())
|
|
#
|
|
response = client.delete_state_machine(stateMachineArn=sm['stateMachineArn'])
|
|
response['ResponseMetadata']['HTTPStatusCode'].should.equal(200)
|
|
#
|
|
sm_list = client.list_state_machines()
|
|
sm_list['stateMachines'].should.have.length_of(0)
|
|
|
|
|
|
@mock_stepfunctions
|
|
@mock_sts
|
|
def test_state_machine_can_deleted_nonexisting_machine():
|
|
client = boto3.client('stepfunctions', region_name=region)
|
|
#
|
|
unknown_state_machine = 'arn:aws:states:' + region + ':123456789012:stateMachine:unknown'
|
|
response = client.delete_state_machine(stateMachineArn=unknown_state_machine)
|
|
response['ResponseMetadata']['HTTPStatusCode'].should.equal(200)
|
|
#
|
|
sm_list = client.list_state_machines()
|
|
sm_list['stateMachines'].should.have.length_of(0)
|
|
|
|
|
|
@mock_stepfunctions
|
|
@mock_sts
|
|
def test_state_machine_list_tags_for_created_machine():
|
|
client = boto3.client('stepfunctions', region_name=region)
|
|
#
|
|
machine = client.create_state_machine(name='name1',
|
|
definition=str(simple_definition),
|
|
roleArn=_get_default_role(),
|
|
tags=[{'key': 'tag_key', 'value': 'tag_value'}])
|
|
response = client.list_tags_for_resource(resourceArn=machine['stateMachineArn'])
|
|
tags = response['tags']
|
|
tags.should.have.length_of(1)
|
|
tags[0].should.equal({'key': 'tag_key', 'value': 'tag_value'})
|
|
|
|
|
|
@mock_stepfunctions
|
|
@mock_sts
|
|
def test_state_machine_list_tags_for_machine_without_tags():
|
|
client = boto3.client('stepfunctions', region_name=region)
|
|
#
|
|
machine = client.create_state_machine(name='name1',
|
|
definition=str(simple_definition),
|
|
roleArn=_get_default_role())
|
|
response = client.list_tags_for_resource(resourceArn=machine['stateMachineArn'])
|
|
tags = response['tags']
|
|
tags.should.have.length_of(0)
|
|
|
|
|
|
@mock_stepfunctions
|
|
@mock_sts
|
|
def test_state_machine_list_tags_for_nonexisting_machine():
|
|
client = boto3.client('stepfunctions', region_name=region)
|
|
#
|
|
non_existing_state_machine = 'arn:aws:states:' + region + ':' + _get_account_id() + ':stateMachine:unknown'
|
|
response = client.list_tags_for_resource(resourceArn=non_existing_state_machine)
|
|
tags = response['tags']
|
|
tags.should.have.length_of(0)
|
|
|
|
|
|
@mock_stepfunctions
|
|
@mock_sts
|
|
def test_state_machine_start_execution():
|
|
client = boto3.client('stepfunctions', region_name=region)
|
|
#
|
|
sm = client.create_state_machine(name='name', definition=str(simple_definition), roleArn=_get_default_role())
|
|
execution = client.start_execution(stateMachineArn=sm['stateMachineArn'])
|
|
#
|
|
execution['ResponseMetadata']['HTTPStatusCode'].should.equal(200)
|
|
uuid_regex = '[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}'
|
|
expected_exec_name = 'arn:aws:states:' + region + ':' + _get_account_id() + ':execution:name:' + uuid_regex
|
|
execution['executionArn'].should.match(expected_exec_name)
|
|
execution['startDate'].should.be.a(datetime)
|
|
|
|
|
|
@mock_stepfunctions
|
|
@mock_sts
|
|
def test_state_machine_start_execution_with_custom_name():
|
|
client = boto3.client('stepfunctions', region_name=region)
|
|
#
|
|
sm = client.create_state_machine(name='name', definition=str(simple_definition), roleArn=_get_default_role())
|
|
execution = client.start_execution(stateMachineArn=sm['stateMachineArn'], name='execution_name')
|
|
#
|
|
execution['ResponseMetadata']['HTTPStatusCode'].should.equal(200)
|
|
expected_exec_name = 'arn:aws:states:' + region + ':' + _get_account_id() + ':execution:name:execution_name'
|
|
execution['executionArn'].should.equal(expected_exec_name)
|
|
execution['startDate'].should.be.a(datetime)
|
|
|
|
|
|
@mock_stepfunctions
|
|
@mock_sts
|
|
def test_state_machine_list_executions():
|
|
client = boto3.client('stepfunctions', region_name=region)
|
|
#
|
|
sm = client.create_state_machine(name='name', definition=str(simple_definition), roleArn=_get_default_role())
|
|
execution = client.start_execution(stateMachineArn=sm['stateMachineArn'])
|
|
execution_arn = execution['executionArn']
|
|
execution_name = execution_arn[execution_arn.rindex(':')+1:]
|
|
executions = client.list_executions(stateMachineArn=sm['stateMachineArn'])
|
|
#
|
|
executions['ResponseMetadata']['HTTPStatusCode'].should.equal(200)
|
|
executions['executions'].should.have.length_of(1)
|
|
executions['executions'][0]['executionArn'].should.equal(execution_arn)
|
|
executions['executions'][0]['name'].should.equal(execution_name)
|
|
executions['executions'][0]['startDate'].should.equal(execution['startDate'])
|
|
executions['executions'][0]['stateMachineArn'].should.equal(sm['stateMachineArn'])
|
|
executions['executions'][0]['status'].should.equal('RUNNING')
|
|
executions['executions'][0].shouldnt.have('stopDate')
|
|
|
|
|
|
@mock_stepfunctions
|
|
@mock_sts
|
|
def test_state_machine_list_executions_when_none_exist():
|
|
client = boto3.client('stepfunctions', region_name=region)
|
|
#
|
|
sm = client.create_state_machine(name='name', definition=str(simple_definition), roleArn=_get_default_role())
|
|
executions = client.list_executions(stateMachineArn=sm['stateMachineArn'])
|
|
#
|
|
executions['ResponseMetadata']['HTTPStatusCode'].should.equal(200)
|
|
executions['executions'].should.have.length_of(0)
|
|
|
|
|
|
@mock_stepfunctions
|
|
@mock_sts
|
|
def test_state_machine_describe_execution():
|
|
client = boto3.client('stepfunctions', region_name=region)
|
|
#
|
|
sm = client.create_state_machine(name='name', definition=str(simple_definition), roleArn=_get_default_role())
|
|
execution = client.start_execution(stateMachineArn=sm['stateMachineArn'])
|
|
description = client.describe_execution(executionArn=execution['executionArn'])
|
|
#
|
|
description['ResponseMetadata']['HTTPStatusCode'].should.equal(200)
|
|
description['executionArn'].should.equal(execution['executionArn'])
|
|
description['input'].should.equal("{}")
|
|
description['name'].shouldnt.be.empty
|
|
description['startDate'].should.equal(execution['startDate'])
|
|
description['stateMachineArn'].should.equal(sm['stateMachineArn'])
|
|
description['status'].should.equal('RUNNING')
|
|
description.shouldnt.have('stopDate')
|
|
|
|
|
|
@mock_stepfunctions
|
|
@mock_sts
|
|
def test_state_machine_throws_error_when_describing_unknown_machine():
|
|
client = boto3.client('stepfunctions', region_name=region)
|
|
#
|
|
with assert_raises(ClientError) as exc:
|
|
unknown_execution = 'arn:aws:states:' + region + ':' + _get_account_id() + ':execution:unknown'
|
|
client.describe_execution(executionArn=unknown_execution)
|
|
|
|
|
|
@mock_stepfunctions
|
|
@mock_sts
|
|
def test_state_machine_can_be_described_by_execution():
|
|
client = boto3.client('stepfunctions', region_name=region)
|
|
#
|
|
sm = client.create_state_machine(name='name', definition=str(simple_definition), roleArn=_get_default_role())
|
|
execution = client.start_execution(stateMachineArn=sm['stateMachineArn'])
|
|
desc = client.describe_state_machine_for_execution(executionArn=execution['executionArn'])
|
|
desc['ResponseMetadata']['HTTPStatusCode'].should.equal(200)
|
|
desc['definition'].should.equal(str(simple_definition))
|
|
desc['name'].should.equal('name')
|
|
desc['roleArn'].should.equal(_get_default_role())
|
|
desc['stateMachineArn'].should.equal(sm['stateMachineArn'])
|
|
|
|
|
|
@mock_stepfunctions
|
|
@mock_sts
|
|
def test_state_machine_throws_error_when_describing_unknown_execution():
|
|
client = boto3.client('stepfunctions', region_name=region)
|
|
#
|
|
with assert_raises(ClientError) as exc:
|
|
unknown_execution = 'arn:aws:states:' + region + ':' + _get_account_id() + ':execution:unknown'
|
|
client.describe_state_machine_for_execution(executionArn=unknown_execution)
|
|
|
|
|
|
@mock_stepfunctions
|
|
@mock_sts
|
|
def test_state_machine_stop_execution():
|
|
client = boto3.client('stepfunctions', region_name=region)
|
|
#
|
|
sm = client.create_state_machine(name='name', definition=str(simple_definition), roleArn=_get_default_role())
|
|
start = client.start_execution(stateMachineArn=sm['stateMachineArn'])
|
|
stop = client.stop_execution(executionArn=start['executionArn'])
|
|
#
|
|
stop['ResponseMetadata']['HTTPStatusCode'].should.equal(200)
|
|
stop['stopDate'].should.be.a(datetime)
|
|
|
|
|
|
@mock_stepfunctions
|
|
@mock_sts
|
|
def test_state_machine_describe_execution_after_stoppage():
|
|
account_id
|
|
client = boto3.client('stepfunctions', region_name=region)
|
|
#
|
|
sm = client.create_state_machine(name='name', definition=str(simple_definition), roleArn=_get_default_role())
|
|
execution = client.start_execution(stateMachineArn=sm['stateMachineArn'])
|
|
client.stop_execution(executionArn=execution['executionArn'])
|
|
description = client.describe_execution(executionArn=execution['executionArn'])
|
|
#
|
|
description['ResponseMetadata']['HTTPStatusCode'].should.equal(200)
|
|
description['status'].should.equal('SUCCEEDED')
|
|
description['stopDate'].should.be.a(datetime)
|
|
|
|
|
|
def _get_account_id():
|
|
global account_id
|
|
if account_id:
|
|
return account_id
|
|
sts = boto3.client("sts")
|
|
identity = sts.get_caller_identity()
|
|
account_id = identity['Account']
|
|
return account_id
|
|
|
|
|
|
def _get_default_role():
|
|
return 'arn:aws:iam::' + _get_account_id() + ':role/unknown_sf_role'
|