Add SWF endpoint: DescribeWorkflowExecution
This commit is contained in:
parent
a589dc08b5
commit
2878252816
@ -84,6 +84,17 @@ class Domain(object):
|
|||||||
raise SWFWorkflowExecutionAlreadyStartedFault()
|
raise SWFWorkflowExecutionAlreadyStartedFault()
|
||||||
self.workflow_executions[_id] = workflow_execution
|
self.workflow_executions[_id] = workflow_execution
|
||||||
|
|
||||||
|
def get_workflow_execution(self, run_id, workflow_id):
|
||||||
|
wfe = self.workflow_executions.get(workflow_id)
|
||||||
|
if not wfe or wfe.run_id != run_id:
|
||||||
|
raise SWFUnknownResourceFault(
|
||||||
|
"execution",
|
||||||
|
"WorkflowExecution=[workflowId={}, runId={}]".format(
|
||||||
|
workflow_id, run_id
|
||||||
|
)
|
||||||
|
)
|
||||||
|
return wfe
|
||||||
|
|
||||||
|
|
||||||
class GenericType(object):
|
class GenericType(object):
|
||||||
def __init__(self, name, version, **kwargs):
|
def __init__(self, name, version, **kwargs):
|
||||||
@ -177,12 +188,68 @@ class WorkflowExecution(object):
|
|||||||
self.workflow_type = workflow_type
|
self.workflow_type = workflow_type
|
||||||
self.workflow_id = workflow_id
|
self.workflow_id = workflow_id
|
||||||
self.run_id = uuid.uuid4().hex
|
self.run_id = uuid.uuid4().hex
|
||||||
|
self.execution_status = "OPEN"
|
||||||
|
self.cancel_requested = False
|
||||||
|
#config
|
||||||
for key, value in kwargs.iteritems():
|
for key, value in kwargs.iteritems():
|
||||||
self.__setattr__(key, value)
|
self.__setattr__(key, value)
|
||||||
|
#counters
|
||||||
|
self.open_counts = {
|
||||||
|
"openTimers": 0,
|
||||||
|
"openDecisionTasks": 0,
|
||||||
|
"openActivityTasks": 0,
|
||||||
|
"openChildWorkflowExecutions": 0,
|
||||||
|
}
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "WorkflowExecution(run_id: {})".format(self.run_id)
|
return "WorkflowExecution(run_id: {})".format(self.run_id)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def _configuration_keys(self):
|
||||||
|
return [
|
||||||
|
"executionStartToCloseTimeout",
|
||||||
|
"childPolicy",
|
||||||
|
"taskPriority",
|
||||||
|
"taskStartToCloseTimeout",
|
||||||
|
]
|
||||||
|
|
||||||
|
def to_short_dict(self):
|
||||||
|
return {
|
||||||
|
"workflowId": self.workflow_id,
|
||||||
|
"runId": self.run_id
|
||||||
|
}
|
||||||
|
|
||||||
|
def to_medium_dict(self):
|
||||||
|
hsh = {
|
||||||
|
"execution": self.to_short_dict(),
|
||||||
|
"workflowType": self.workflow_type.to_short_dict(),
|
||||||
|
"startTimestamp": 1420066800.123,
|
||||||
|
"executionStatus": self.execution_status,
|
||||||
|
"cancelRequested": self.cancel_requested,
|
||||||
|
}
|
||||||
|
if hasattr(self, "tag_list"):
|
||||||
|
hsh["tagList"] = self.tag_list
|
||||||
|
return hsh
|
||||||
|
|
||||||
|
def to_full_dict(self):
|
||||||
|
hsh = {
|
||||||
|
"executionInfo": self.to_medium_dict(),
|
||||||
|
"executionConfiguration": {}
|
||||||
|
}
|
||||||
|
#configuration
|
||||||
|
if hasattr(self, "task_list"):
|
||||||
|
hsh["executionConfiguration"]["taskList"] = {"name": self.task_list}
|
||||||
|
for key in self._configuration_keys:
|
||||||
|
attr = camelcase_to_underscores(key)
|
||||||
|
if not hasattr(self, attr):
|
||||||
|
continue
|
||||||
|
if not getattr(self, attr):
|
||||||
|
continue
|
||||||
|
hsh["executionConfiguration"][key] = getattr(self, attr)
|
||||||
|
#counters
|
||||||
|
hsh["openCounts"] = self.open_counts
|
||||||
|
return hsh
|
||||||
|
|
||||||
|
|
||||||
class SWFBackend(BaseBackend):
|
class SWFBackend(BaseBackend):
|
||||||
def __init__(self, region_name):
|
def __init__(self, region_name):
|
||||||
@ -318,6 +385,13 @@ class SWFBackend(BaseBackend):
|
|||||||
|
|
||||||
return wfe
|
return wfe
|
||||||
|
|
||||||
|
def describe_workflow_execution(self, domain_name, run_id, workflow_id):
|
||||||
|
self._check_string(domain_name)
|
||||||
|
self._check_string(run_id)
|
||||||
|
self._check_string(workflow_id)
|
||||||
|
domain = self._get_domain(domain_name)
|
||||||
|
return domain.get_workflow_execution(run_id, workflow_id)
|
||||||
|
|
||||||
|
|
||||||
swf_backends = {}
|
swf_backends = {}
|
||||||
for region in boto.swf.regions():
|
for region in boto.swf.regions():
|
||||||
|
@ -139,7 +139,6 @@ class SWFResponse(BaseResponse):
|
|||||||
def describe_activity_type(self):
|
def describe_activity_type(self):
|
||||||
return self._describe_type("activity")
|
return self._describe_type("activity")
|
||||||
|
|
||||||
# TODO: refactor with list_activity_types()
|
|
||||||
def list_workflow_types(self):
|
def list_workflow_types(self):
|
||||||
return self._list_types("workflow")
|
return self._list_types("workflow")
|
||||||
|
|
||||||
@ -201,3 +200,12 @@ class SWFResponse(BaseResponse):
|
|||||||
return json.dumps({
|
return json.dumps({
|
||||||
"runId": wfe.run_id
|
"runId": wfe.run_id
|
||||||
})
|
})
|
||||||
|
|
||||||
|
def describe_workflow_execution(self):
|
||||||
|
domain_name = self._params["domain"]
|
||||||
|
_workflow_execution = self._params["execution"]
|
||||||
|
run_id = _workflow_execution["runId"]
|
||||||
|
workflow_id = _workflow_execution["workflowId"]
|
||||||
|
|
||||||
|
wfe = self.swf_backend.describe_workflow_execution(domain_name, run_id, workflow_id)
|
||||||
|
return json.dumps(wfe.to_full_dict())
|
||||||
|
@ -3,6 +3,7 @@ from sure import expect
|
|||||||
from moto.swf.models import (
|
from moto.swf.models import (
|
||||||
Domain,
|
Domain,
|
||||||
GenericType,
|
GenericType,
|
||||||
|
WorkflowType,
|
||||||
WorkflowExecution,
|
WorkflowExecution,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -89,3 +90,44 @@ def test_workflow_execution_generates_a_random_run_id():
|
|||||||
wfe1 = WorkflowExecution("workflow_type_whatever", "ab1234")
|
wfe1 = WorkflowExecution("workflow_type_whatever", "ab1234")
|
||||||
wfe2 = WorkflowExecution("workflow_type_whatever", "ab1235")
|
wfe2 = WorkflowExecution("workflow_type_whatever", "ab1235")
|
||||||
wfe1.run_id.should_not.equal(wfe2.run_id)
|
wfe1.run_id.should_not.equal(wfe2.run_id)
|
||||||
|
|
||||||
|
def test_workflow_execution_short_dict_representation():
|
||||||
|
wf_type = WorkflowType("test-workflow", "v1.0")
|
||||||
|
wfe = WorkflowExecution(wf_type, "ab1234")
|
||||||
|
|
||||||
|
sd = wfe.to_short_dict()
|
||||||
|
sd["workflowId"].should.equal("ab1234")
|
||||||
|
sd.should.contain("runId")
|
||||||
|
|
||||||
|
def test_workflow_execution_medium_dict_representation():
|
||||||
|
wf_type = WorkflowType("test-workflow", "v1.0")
|
||||||
|
wfe = WorkflowExecution(wf_type, "ab1234")
|
||||||
|
|
||||||
|
md = wfe.to_medium_dict()
|
||||||
|
md["execution"].should.equal(wfe.to_short_dict())
|
||||||
|
md["workflowType"].should.equal(wf_type.to_short_dict())
|
||||||
|
md["startTimestamp"].should.be.a('float')
|
||||||
|
md["executionStatus"].should.equal("OPEN")
|
||||||
|
md["cancelRequested"].should.equal(False)
|
||||||
|
md.should_not.contain("tagList")
|
||||||
|
|
||||||
|
wfe.tag_list = ["foo", "bar", "baz"]
|
||||||
|
md = wfe.to_medium_dict()
|
||||||
|
md["tagList"].should.equal(["foo", "bar", "baz"])
|
||||||
|
|
||||||
|
def test_workflow_execution_full_dict_representation():
|
||||||
|
wf_type = WorkflowType("test-workflow", "v1.0")
|
||||||
|
wfe = WorkflowExecution(wf_type, "ab1234")
|
||||||
|
|
||||||
|
fd = wfe.to_full_dict()
|
||||||
|
fd["executionInfo"].should.equal(wfe.to_medium_dict())
|
||||||
|
fd["openCounts"]["openTimers"].should.equal(0)
|
||||||
|
fd["openCounts"]["openDecisionTasks"].should.equal(0)
|
||||||
|
fd["openCounts"]["openActivityTasks"].should.equal(0)
|
||||||
|
fd["executionConfiguration"].should.equal({})
|
||||||
|
|
||||||
|
wfe.task_list = "special"
|
||||||
|
wfe.task_start_to_close_timeout = "45"
|
||||||
|
fd = wfe.to_full_dict()
|
||||||
|
fd["executionConfiguration"]["taskList"]["name"].should.equal("special")
|
||||||
|
fd["executionConfiguration"]["taskStartToCloseTimeout"].should.equal("45")
|
||||||
|
@ -6,6 +6,7 @@ from moto import mock_swf
|
|||||||
from moto.swf.exceptions import (
|
from moto.swf.exceptions import (
|
||||||
SWFWorkflowExecutionAlreadyStartedFault,
|
SWFWorkflowExecutionAlreadyStartedFault,
|
||||||
SWFTypeDeprecatedFault,
|
SWFTypeDeprecatedFault,
|
||||||
|
SWFUnknownResourceFault,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@ -57,3 +58,30 @@ def test_start_workflow_execution_on_deprecated_type():
|
|||||||
"__type": "com.amazonaws.swf.base.model#TypeDeprecatedFault",
|
"__type": "com.amazonaws.swf.base.model#TypeDeprecatedFault",
|
||||||
"message": "WorkflowType=[name=test-workflow, version=v1.0]"
|
"message": "WorkflowType=[name=test-workflow, version=v1.0]"
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
# DescribeWorkflowExecution endpoint
|
||||||
|
@mock_swf
|
||||||
|
def test_describe_workflow_execution():
|
||||||
|
conn = setup_swf_environment()
|
||||||
|
hsh = conn.start_workflow_execution("test-domain", "uid-abcd1234", "test-workflow", "v1.0")
|
||||||
|
run_id = hsh["runId"]
|
||||||
|
|
||||||
|
wfe = conn.describe_workflow_execution("test-domain", run_id, "uid-abcd1234")
|
||||||
|
wfe["executionInfo"]["execution"]["workflowId"].should.equal("uid-abcd1234")
|
||||||
|
wfe["executionInfo"]["executionStatus"].should.equal("OPEN")
|
||||||
|
|
||||||
|
@mock_swf
|
||||||
|
def test_describe_non_existent_workflow_execution():
|
||||||
|
conn = setup_swf_environment()
|
||||||
|
|
||||||
|
with assert_raises(SWFUnknownResourceFault) as err:
|
||||||
|
conn.describe_workflow_execution("test-domain", "wrong-run-id", "wrong-workflow-id")
|
||||||
|
|
||||||
|
ex = err.exception
|
||||||
|
ex.status.should.equal(400)
|
||||||
|
ex.error_code.should.equal("UnknownResourceFault")
|
||||||
|
ex.body.should.equal({
|
||||||
|
"__type": "com.amazonaws.swf.base.model#UnknownResourceFault",
|
||||||
|
"message": "Unknown execution: WorkflowExecution=[workflowId=wrong-workflow-id, runId=wrong-run-id]"
|
||||||
|
})
|
||||||
|
Loading…
x
Reference in New Issue
Block a user