Add list_open_workflow_executions endpoint
This commit is contained in:
parent
129b4faff8
commit
93120927f7
@ -61,6 +61,21 @@ class SWFBackend(BaseBackend):
|
|||||||
domains = reversed(domains)
|
domains = reversed(domains)
|
||||||
return domains
|
return domains
|
||||||
|
|
||||||
|
def list_open_workflow_executions(self, domain_name, start_time_filter,
|
||||||
|
maximum_page_size, reverse_order,
|
||||||
|
**kwargs):
|
||||||
|
self._process_timeouts()
|
||||||
|
domain = self._get_domain(domain_name)
|
||||||
|
if domain.status == "DEPRECATED":
|
||||||
|
raise SWFDomainDeprecatedFault(domain_name)
|
||||||
|
open_wfes = [
|
||||||
|
wfe for wfe in domain.workflow_executions
|
||||||
|
if wfe.execution_status == 'OPEN'
|
||||||
|
]
|
||||||
|
if reverse_order:
|
||||||
|
open_wfes = reversed(open_wfes)
|
||||||
|
return open_wfes[0:maximum_page_size]
|
||||||
|
|
||||||
def register_domain(self, name, workflow_execution_retention_period_in_days,
|
def register_domain(self, name, workflow_execution_retention_period_in_days,
|
||||||
description=None):
|
description=None):
|
||||||
if self._get_domain(name, ignore_empty=True):
|
if self._get_domain(name, ignore_empty=True):
|
||||||
|
@ -146,6 +146,27 @@ class WorkflowExecution(object):
|
|||||||
hsh["latestActivityTaskTimestamp"] = self.latest_activity_task_timestamp
|
hsh["latestActivityTaskTimestamp"] = self.latest_activity_task_timestamp
|
||||||
return hsh
|
return hsh
|
||||||
|
|
||||||
|
def to_list_dict(self):
|
||||||
|
hsh = {
|
||||||
|
'execution': {
|
||||||
|
'workflowId': self.workflow_id,
|
||||||
|
'runId': self.run_id,
|
||||||
|
},
|
||||||
|
'workflowType': self.workflow_type.to_short_dict(),
|
||||||
|
'startTimestamp': self.start_timestamp,
|
||||||
|
'executionStatus': self.execution_status,
|
||||||
|
'cancelRequested': self.cancel_requested,
|
||||||
|
}
|
||||||
|
if self.tag_list:
|
||||||
|
hsh['tagList'] = self.tag_list
|
||||||
|
if self.parent:
|
||||||
|
hsh['parent'] = self.parent
|
||||||
|
if self.close_status:
|
||||||
|
hsh['closeStatus'] = self.close_status
|
||||||
|
if self.close_timestamp:
|
||||||
|
hsh['closeTimestamp'] = self.close_timestamp
|
||||||
|
return hsh
|
||||||
|
|
||||||
def _process_timeouts(self):
|
def _process_timeouts(self):
|
||||||
"""
|
"""
|
||||||
SWF timeouts can happen on different objects (workflow executions,
|
SWF timeouts can happen on different objects (workflow executions,
|
||||||
|
@ -3,7 +3,7 @@ import six
|
|||||||
|
|
||||||
from moto.core.responses import BaseResponse
|
from moto.core.responses import BaseResponse
|
||||||
|
|
||||||
from .exceptions import SWFSerializationException
|
from .exceptions import SWFSerializationException, SWFValidationException
|
||||||
from .models import swf_backends
|
from .models import swf_backends
|
||||||
|
|
||||||
|
|
||||||
@ -18,6 +18,10 @@ class SWFResponse(BaseResponse):
|
|||||||
def _params(self):
|
def _params(self):
|
||||||
return json.loads(self.body.decode("utf-8"))
|
return json.loads(self.body.decode("utf-8"))
|
||||||
|
|
||||||
|
def _check_int(self, parameter):
|
||||||
|
if not isinstance(parameter, int):
|
||||||
|
raise SWFSerializationException(parameter)
|
||||||
|
|
||||||
def _check_none_or_string(self, parameter):
|
def _check_none_or_string(self, parameter):
|
||||||
if parameter is not None:
|
if parameter is not None:
|
||||||
self._check_string(parameter)
|
self._check_string(parameter)
|
||||||
@ -37,6 +41,18 @@ class SWFResponse(BaseResponse):
|
|||||||
if not isinstance(i, six.string_types):
|
if not isinstance(i, six.string_types):
|
||||||
raise SWFSerializationException(parameter)
|
raise SWFSerializationException(parameter)
|
||||||
|
|
||||||
|
def _check_exclusivity(self, **kwargs):
|
||||||
|
if kwargs.values().count(None) >= len(kwargs) - 1:
|
||||||
|
return
|
||||||
|
keys = kwargs.keys()
|
||||||
|
if len(keys) == 2:
|
||||||
|
message = 'Cannot specify both a {0} and a {1}'.format(keys[0],
|
||||||
|
keys[1])
|
||||||
|
else:
|
||||||
|
message = 'Cannot specify more than one exclusive filters in the' \
|
||||||
|
' same query: {0}'.format(keys)
|
||||||
|
raise SWFValidationException(message)
|
||||||
|
|
||||||
def _list_types(self, kind):
|
def _list_types(self, kind):
|
||||||
domain_name = self._params["domain"]
|
domain_name = self._params["domain"]
|
||||||
status = self._params["registrationStatus"]
|
status = self._params["registrationStatus"]
|
||||||
@ -81,6 +97,43 @@ class SWFResponse(BaseResponse):
|
|||||||
"domainInfos": [domain.to_short_dict() for domain in domains]
|
"domainInfos": [domain.to_short_dict() for domain in domains]
|
||||||
})
|
})
|
||||||
|
|
||||||
|
def list_open_workflow_executions(self):
|
||||||
|
domain = self._params['domain']
|
||||||
|
start_time_filter = self._params['startTimeFilter']
|
||||||
|
execution_filter = self._params.get('executionFilter', None)
|
||||||
|
workflow_id = execution_filter['workflowId'] if execution_filter else None
|
||||||
|
maximum_page_size = self._params.get('maximumPageSize', 1000)
|
||||||
|
reverse_order = self._params.get('reverseOrder', None)
|
||||||
|
tag_filter = self._params.get('tagFilter', None)
|
||||||
|
type_filter = self._params.get('typeFilter', None)
|
||||||
|
|
||||||
|
self._check_string(domain)
|
||||||
|
self._check_none_or_string(workflow_id)
|
||||||
|
self._check_exclusivity(executionFilter=execution_filter,
|
||||||
|
typeFilter=type_filter,
|
||||||
|
tagFilter=tag_filter)
|
||||||
|
if tag_filter:
|
||||||
|
self._check_string(tag_filter['tag'])
|
||||||
|
if type_filter:
|
||||||
|
self._check_string(type_filter['name'])
|
||||||
|
self._check_string(type_filter['version'])
|
||||||
|
self._check_int(maximum_page_size)
|
||||||
|
|
||||||
|
workflow_executions = self.swf_backend.list_open_workflow_executions(
|
||||||
|
domain_name=domain,
|
||||||
|
start_time_filter=start_time_filter,
|
||||||
|
execution_filter=execution_filter,
|
||||||
|
tag_filter=tag_filter,
|
||||||
|
type_filter=type_filter,
|
||||||
|
maximum_page_size=maximum_page_size,
|
||||||
|
reverse_order=reverse_order,
|
||||||
|
workflow_id=workflow_id
|
||||||
|
)
|
||||||
|
|
||||||
|
return json.dumps({
|
||||||
|
'executionInfos': [wfe.to_list_dict() for wfe in workflow_executions]
|
||||||
|
})
|
||||||
|
|
||||||
def register_domain(self):
|
def register_domain(self):
|
||||||
name = self._params["name"]
|
name = self._params["name"]
|
||||||
retention = self._params["workflowExecutionRetentionPeriodInDays"]
|
retention = self._params["workflowExecutionRetentionPeriodInDays"]
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
from freezegun import freeze_time
|
from freezegun import freeze_time
|
||||||
|
import sure # noqa
|
||||||
|
|
||||||
from moto.swf.models import (
|
from moto.swf.models import (
|
||||||
ActivityType,
|
ActivityType,
|
||||||
@ -141,6 +142,26 @@ def test_workflow_execution_full_dict_representation():
|
|||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
|
def test_workflow_execution_list_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')
|
||||||
|
|
||||||
|
ld = wfe.to_list_dict()
|
||||||
|
ld['workflowType']['version'].should.equal('v1.0')
|
||||||
|
ld['workflowType']['name'].should.equal('test-workflow')
|
||||||
|
ld['executionStatus'].should.equal('OPEN')
|
||||||
|
ld['execution']['workflowId'].should.equal('ab1234')
|
||||||
|
ld['execution'].should.contain('runId')
|
||||||
|
ld['cancelRequested'].should.be.false
|
||||||
|
ld.should.contain('startTimestamp')
|
||||||
|
|
||||||
|
|
||||||
def test_workflow_execution_schedule_decision_task():
|
def test_workflow_execution_schedule_decision_task():
|
||||||
wfe = make_workflow_execution()
|
wfe = make_workflow_execution()
|
||||||
wfe.open_counts["openDecisionTasks"].should.equal(0)
|
wfe.open_counts["openDecisionTasks"].should.equal(0)
|
||||||
|
@ -1,10 +1,13 @@
|
|||||||
import boto
|
import boto
|
||||||
from boto.swf.exceptions import SWFResponseError
|
from boto.swf.exceptions import SWFResponseError
|
||||||
|
from datetime import datetime, timedelta
|
||||||
|
|
||||||
|
import sure # noqa
|
||||||
# Ensure 'assert_raises' context manager support for Python 2.6
|
# Ensure 'assert_raises' context manager support for Python 2.6
|
||||||
import tests.backport_assert_raises # noqa
|
import tests.backport_assert_raises # noqa
|
||||||
|
|
||||||
from moto import mock_swf
|
from moto import mock_swf
|
||||||
|
from moto.core.utils import iso_8601_datetime_with_milliseconds
|
||||||
|
|
||||||
|
|
||||||
# Utils
|
# Utils
|
||||||
@ -105,6 +108,50 @@ def test_get_workflow_execution_history_on_non_existent_workflow_execution():
|
|||||||
).should.throw(SWFResponseError)
|
).should.throw(SWFResponseError)
|
||||||
|
|
||||||
|
|
||||||
|
# ListOpenWorkflowExecutions endpoint
|
||||||
|
@mock_swf
|
||||||
|
def test_list_open_workflow_executions():
|
||||||
|
conn = setup_swf_environment()
|
||||||
|
conn.start_workflow_execution(
|
||||||
|
'test-domain', 'uid-abcd1234', 'test-workflow', 'v1.0'
|
||||||
|
)
|
||||||
|
|
||||||
|
yesterday = datetime.now() - timedelta(days=1)
|
||||||
|
oldest_date = iso_8601_datetime_with_milliseconds(yesterday)
|
||||||
|
response = conn.list_open_workflow_executions('test-domain',
|
||||||
|
oldest_date,
|
||||||
|
workflow_id='test-workflow')
|
||||||
|
execution_infos = response['executionInfos']
|
||||||
|
len(execution_infos).should.equal(1)
|
||||||
|
open_workflow = execution_infos[0]
|
||||||
|
open_workflow['workflowType'].should.equal({'version': 'v1.0',
|
||||||
|
'name': 'test-workflow'})
|
||||||
|
open_workflow.should.contain('startTimestamp')
|
||||||
|
open_workflow['execution']['workflowId'].should.equal('uid-abcd1234')
|
||||||
|
open_workflow['execution'].should.contain('runId')
|
||||||
|
open_workflow['cancelRequested'].should.be(False)
|
||||||
|
open_workflow['executionStatus'].should.equal('OPEN')
|
||||||
|
|
||||||
|
|
||||||
|
@mock_swf
|
||||||
|
def test_list_open_workflow_executions_does_not_show_closed():
|
||||||
|
conn = setup_swf_environment()
|
||||||
|
run_id = conn.start_workflow_execution(
|
||||||
|
'test-domain', 'uid-abcd1234', 'test-workflow', 'v1.0'
|
||||||
|
)['runId']
|
||||||
|
conn.terminate_workflow_execution('test-domain', 'uid-abcd1234',
|
||||||
|
details='some details',
|
||||||
|
reason='a more complete reason',
|
||||||
|
run_id=run_id)
|
||||||
|
|
||||||
|
yesterday = datetime.now() - timedelta(days=1)
|
||||||
|
oldest_date = iso_8601_datetime_with_milliseconds(yesterday)
|
||||||
|
response = conn.list_open_workflow_executions('test-domain',
|
||||||
|
oldest_date,
|
||||||
|
workflow_id='test-workflow')
|
||||||
|
response['executionInfos'].should.be.empty
|
||||||
|
|
||||||
|
|
||||||
# TerminateWorkflowExecution endpoint
|
# TerminateWorkflowExecution endpoint
|
||||||
@mock_swf
|
@mock_swf
|
||||||
def test_terminate_workflow_execution():
|
def test_terminate_workflow_execution():
|
||||||
|
Loading…
x
Reference in New Issue
Block a user