Add basic get_execution_history implementation for Step Functions (#3507)

* Add format command to makefile

* Refactor executions to be a attribute of StateMachine

* Begin to add tests for execution history

* Add tests for failed and successful event histories, with implementations

* Add failure case to environment var check

* Skip test if in server mode and update implementation coverage

* Add conditional import for mock to cover python 2

* Refactor stop execution logic into StateMachine

* Refactor event history environment variable into settings.py

* Remove typing and os import
This commit is contained in:
Ciaran Evans 2020-12-03 18:32:06 +00:00 committed by GitHub
commit 48df5bd5af
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 383 additions and 46 deletions

View file

@ -2,15 +2,23 @@ from __future__ import unicode_literals
import boto3
import json
import os
import sure # noqa
import sys
from datetime import datetime
from dateutil.tz import tzlocal
from botocore.exceptions import ClientError
import pytest
from moto import mock_cloudformation, mock_sts, mock_stepfunctions
from moto.core import ACCOUNT_ID
if sys.version_info[0] < 3:
import mock
from unittest import SkipTest
else:
from unittest import SkipTest, mock
region = "us-east-1"
simple_definition = (
'{"Comment": "An example of the Amazon States Language using a choice state.",'
@ -799,10 +807,30 @@ def test_state_machine_stop_execution():
@mock_stepfunctions
@mock_sts
def test_state_machine_describe_execution_after_stoppage():
account_id
def test_state_machine_stop_raises_error_when_unknown_execution():
client = boto3.client("stepfunctions", region_name=region)
client.create_state_machine(
name="test-state-machine",
definition=str(simple_definition),
roleArn=_get_default_role(),
)
with pytest.raises(ClientError) as ex:
unknown_execution = (
"arn:aws:states:"
+ region
+ ":"
+ _get_account_id()
+ ":execution:test-state-machine:unknown"
)
client.stop_execution(executionArn=unknown_execution)
ex.value.response["Error"]["Code"].should.equal("ExecutionDoesNotExist")
ex.value.response["Error"]["Message"].should.contain("Execution Does Not Exist:")
@mock_stepfunctions
@mock_sts
def test_state_machine_describe_execution_after_stoppage():
client = boto3.client("stepfunctions", region_name=region)
#
sm = client.create_state_machine(
name="name", definition=str(simple_definition), roleArn=_get_default_role()
)
@ -815,6 +843,146 @@ def test_state_machine_describe_execution_after_stoppage():
description["stopDate"].should.be.a(datetime)
@mock_stepfunctions
@mock_sts
def test_state_machine_get_execution_history_throws_error_with_unknown_execution():
client = boto3.client("stepfunctions", region_name=region)
client.create_state_machine(
name="test-state-machine",
definition=str(simple_definition),
roleArn=_get_default_role(),
)
with pytest.raises(ClientError) as ex:
unknown_execution = (
"arn:aws:states:"
+ region
+ ":"
+ _get_account_id()
+ ":execution:test-state-machine:unknown"
)
client.get_execution_history(executionArn=unknown_execution)
ex.value.response["Error"]["Code"].should.equal("ExecutionDoesNotExist")
ex.value.response["Error"]["Message"].should.contain("Execution Does Not Exist:")
@mock_stepfunctions
@mock_sts
def test_state_machine_get_execution_history_contains_expected_success_events_when_started():
expected_events = [
{
"timestamp": datetime(2020, 1, 1, 0, 0, 0, tzinfo=tzlocal()),
"type": "ExecutionStarted",
"id": 1,
"previousEventId": 0,
"executionStartedEventDetails": {
"input": "{}",
"inputDetails": {"truncated": False},
"roleArn": _get_default_role(),
},
},
{
"timestamp": datetime(2020, 1, 1, 0, 0, 10, tzinfo=tzlocal()),
"type": "PassStateEntered",
"id": 2,
"previousEventId": 0,
"stateEnteredEventDetails": {
"name": "A State",
"input": "{}",
"inputDetails": {"truncated": False},
},
},
{
"timestamp": datetime(2020, 1, 1, 0, 0, 10, tzinfo=tzlocal()),
"type": "PassStateExited",
"id": 3,
"previousEventId": 2,
"stateExitedEventDetails": {
"name": "A State",
"output": "An output",
"outputDetails": {"truncated": False},
},
},
{
"timestamp": datetime(2020, 1, 1, 0, 0, 20, tzinfo=tzlocal()),
"type": "ExecutionSucceeded",
"id": 4,
"previousEventId": 3,
"executionSucceededEventDetails": {
"output": "An output",
"outputDetails": {"truncated": False},
},
},
]
client = boto3.client("stepfunctions", region_name=region)
sm = client.create_state_machine(
name="test-state-machine",
definition=simple_definition,
roleArn=_get_default_role(),
)
execution = client.start_execution(stateMachineArn=sm["stateMachineArn"])
execution_history = client.get_execution_history(
executionArn=execution["executionArn"]
)
execution_history["events"].should.have.length_of(4)
execution_history["events"].should.equal(expected_events)
@mock_stepfunctions
@mock_sts
@mock.patch.dict(os.environ, {"SF_EXECUTION_HISTORY_TYPE": "FAILURE"})
def test_state_machine_get_execution_history_contains_expected_failure_events_when_started():
if os.environ.get("TEST_SERVER_MODE", "false").lower() == "true":
raise SkipTest("Cant pass environment variable in server mode")
expected_events = [
{
"timestamp": datetime(2020, 1, 1, 0, 0, 0, tzinfo=tzlocal()),
"type": "ExecutionStarted",
"id": 1,
"previousEventId": 0,
"executionStartedEventDetails": {
"input": "{}",
"inputDetails": {"truncated": False},
"roleArn": _get_default_role(),
},
},
{
"timestamp": datetime(2020, 1, 1, 0, 0, 10, tzinfo=tzlocal()),
"type": "FailStateEntered",
"id": 2,
"previousEventId": 0,
"stateEnteredEventDetails": {
"name": "A State",
"input": "{}",
"inputDetails": {"truncated": False},
},
},
{
"timestamp": datetime(2020, 1, 1, 0, 0, 10, tzinfo=tzlocal()),
"type": "ExecutionFailed",
"id": 3,
"previousEventId": 2,
"executionFailedEventDetails": {
"error": "AnError",
"cause": "An error occurred!",
},
},
]
client = boto3.client("stepfunctions", region_name=region)
sm = client.create_state_machine(
name="test-state-machine",
definition=simple_definition,
roleArn=_get_default_role(),
)
execution = client.start_execution(stateMachineArn=sm["stateMachineArn"])
execution_history = client.get_execution_history(
executionArn=execution["executionArn"]
)
execution_history["events"].should.have.length_of(3)
execution_history["events"].should.equal(expected_events)
@mock_stepfunctions
@mock_cloudformation
def test_state_machine_cloudformation():