724 lines
21 KiB
Python
724 lines
21 KiB
Python
# Copyright 2013 - Mirantis, Inc.
|
|
# Copyright 2018 - Extreme Networks, Inc.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
|
|
import wsme
|
|
from wsme import types as wtypes
|
|
|
|
from mistral.api.controllers import resource
|
|
from mistral.api.controllers.v2 import types
|
|
from mistral import exceptions as exc
|
|
from mistral import utils
|
|
from mistral.workflow import states
|
|
|
|
SCOPE_TYPES = wtypes.Enum(str, 'private', 'public')
|
|
|
|
|
|
class ScopedResource(object):
|
|
"""Utilities for scoped resources"""
|
|
@classmethod
|
|
def validate_scope(cls, scope):
|
|
if scope not in SCOPE_TYPES.values:
|
|
raise exc.InvalidModelException(
|
|
"Scope must be one of the following: %s; actual: "
|
|
"%s" % (SCOPE_TYPES.values, scope)
|
|
)
|
|
|
|
|
|
class Workbook(resource.Resource, ScopedResource):
|
|
"""Workbook resource."""
|
|
|
|
id = wtypes.text
|
|
name = wtypes.text
|
|
namespace = wtypes.text
|
|
|
|
definition = wtypes.text
|
|
"workbook definition in Mistral v2 DSL"
|
|
tags = [wtypes.text]
|
|
scope = SCOPE_TYPES
|
|
"'private' or 'public'"
|
|
project_id = wsme.wsattr(wtypes.text, readonly=True)
|
|
|
|
created_at = wtypes.text
|
|
updated_at = wtypes.text
|
|
|
|
@classmethod
|
|
def sample(cls):
|
|
return cls(id='123e4567-e89b-12d3-a456-426655440000',
|
|
name='book',
|
|
definition='HERE GOES'
|
|
'WORKBOOK DEFINITION IN MISTRAL DSL v2',
|
|
tags=['large', 'expensive'],
|
|
scope='private',
|
|
project_id='a7eb669e9819420ea4bd1453e672c0a7',
|
|
created_at='1970-01-01T00:00:00.000000',
|
|
updated_at='1970-01-01T00:00:00.000000',
|
|
namespace='')
|
|
|
|
|
|
class Workbooks(resource.ResourceList):
|
|
"""A collection of Workbooks."""
|
|
|
|
workbooks = [Workbook]
|
|
|
|
def __init__(self, **kwargs):
|
|
self._type = 'workbooks'
|
|
|
|
super(Workbooks, self).__init__(**kwargs)
|
|
|
|
@classmethod
|
|
def sample(cls):
|
|
return cls(workbooks=[Workbook.sample()])
|
|
|
|
|
|
class Workflow(resource.Resource, ScopedResource):
|
|
"""Workflow resource."""
|
|
|
|
id = wtypes.text
|
|
name = wtypes.text
|
|
namespace = wtypes.text
|
|
input = wtypes.text
|
|
|
|
definition = wtypes.text
|
|
"Workflow definition in Mistral v2 DSL"
|
|
tags = [wtypes.text]
|
|
scope = SCOPE_TYPES
|
|
"'private' or 'public'"
|
|
project_id = wtypes.text
|
|
|
|
created_at = wtypes.text
|
|
updated_at = wtypes.text
|
|
|
|
@classmethod
|
|
def sample(cls):
|
|
return cls(id='123e4567-e89b-12d3-a456-426655440000',
|
|
name='flow',
|
|
input='param1, param2',
|
|
definition='HERE GOES'
|
|
'WORKFLOW DEFINITION IN MISTRAL DSL v2',
|
|
tags=['large', 'expensive'],
|
|
scope='private',
|
|
project_id='a7eb669e9819420ea4bd1453e672c0a7',
|
|
created_at='1970-01-01T00:00:00.000000',
|
|
updated_at='1970-01-01T00:00:00.000000',
|
|
namespace='')
|
|
|
|
@classmethod
|
|
def _set_input(cls, obj, wf_spec):
|
|
input_list = []
|
|
|
|
if wf_spec:
|
|
input = wf_spec.get('input', [])
|
|
|
|
for param in input:
|
|
if isinstance(param, dict):
|
|
for k, v in param.items():
|
|
input_list.append("%s=%s" % (k, v))
|
|
else:
|
|
input_list.append(param)
|
|
|
|
setattr(obj, 'input', ", ".join(input_list) if input_list else '')
|
|
|
|
return obj
|
|
|
|
@classmethod
|
|
def from_dict(cls, d):
|
|
obj = super(Workflow, cls).from_dict(d)
|
|
|
|
return cls._set_input(obj, d.get('spec'))
|
|
|
|
@classmethod
|
|
def from_db_model(cls, db_model):
|
|
obj = super(Workflow, cls).from_db_model(db_model)
|
|
|
|
return cls._set_input(obj, db_model.spec)
|
|
|
|
@classmethod
|
|
def from_tuples(cls, tuple_iterator):
|
|
obj = cls()
|
|
spec = None
|
|
for col_name, col_val in tuple_iterator:
|
|
if hasattr(obj, col_name):
|
|
# Convert all datetime values to strings.
|
|
setattr(obj, col_name, utils.datetime_to_str(col_val))
|
|
if col_name == 'spec':
|
|
spec = col_val
|
|
|
|
if spec:
|
|
obj = cls._set_input(obj, spec)
|
|
|
|
return obj
|
|
|
|
|
|
class Workflows(resource.ResourceList):
|
|
"""A collection of workflows."""
|
|
|
|
workflows = [Workflow]
|
|
|
|
def __init__(self, **kwargs):
|
|
self._type = 'workflows'
|
|
|
|
super(Workflows, self).__init__(**kwargs)
|
|
|
|
@classmethod
|
|
def sample(cls):
|
|
workflows_sample = cls()
|
|
workflows_sample.workflows = [Workflow.sample()]
|
|
workflows_sample.next = ("http://localhost:8989/v2/workflows?"
|
|
"sort_keys=id,name&"
|
|
"sort_dirs=asc,desc&limit=10&"
|
|
"marker=123e4567-e89b-12d3-a456-426655440000")
|
|
|
|
return workflows_sample
|
|
|
|
|
|
class Action(resource.Resource, ScopedResource):
|
|
"""Action resource.
|
|
|
|
NOTE: *name* is immutable. Note that name and description get inferred
|
|
from action definition when Mistral service receives a POST request.
|
|
So they can't be changed in another way.
|
|
|
|
"""
|
|
|
|
id = wtypes.text
|
|
name = wtypes.text
|
|
is_system = bool
|
|
input = wtypes.text
|
|
|
|
description = wtypes.text
|
|
tags = [wtypes.text]
|
|
definition = wtypes.text
|
|
scope = SCOPE_TYPES
|
|
project_id = wsme.wsattr(wtypes.text, readonly=True)
|
|
|
|
created_at = wtypes.text
|
|
updated_at = wtypes.text
|
|
|
|
@classmethod
|
|
def sample(cls):
|
|
return cls(
|
|
id='123e4567-e89b-12d3-a456-426655440000',
|
|
name='flow',
|
|
definition='HERE GOES ACTION DEFINITION IN MISTRAL DSL v2',
|
|
tags=['large', 'expensive'],
|
|
scope='private',
|
|
project_id='a7eb669e9819420ea4bd1453e672c0a7',
|
|
created_at='1970-01-01T00:00:00.000000',
|
|
updated_at='1970-01-01T00:00:00.000000'
|
|
)
|
|
|
|
|
|
class Actions(resource.ResourceList):
|
|
"""A collection of Actions."""
|
|
|
|
actions = [Action]
|
|
|
|
def __init__(self, **kwargs):
|
|
self._type = 'actions'
|
|
|
|
super(Actions, self).__init__(**kwargs)
|
|
|
|
@classmethod
|
|
def sample(cls):
|
|
sample = cls()
|
|
sample.actions = [Action.sample()]
|
|
sample.next = (
|
|
"http://localhost:8989/v2/actions?sort_keys=id,name&"
|
|
"sort_dirs=asc,desc&limit=10&"
|
|
"marker=123e4567-e89b-12d3-a456-426655440000"
|
|
)
|
|
|
|
return sample
|
|
|
|
|
|
class Execution(resource.Resource):
|
|
"""Execution resource."""
|
|
|
|
id = wtypes.text
|
|
"execution ID. It is immutable and auto assigned or determined by the API "
|
|
"client on execution creation. "
|
|
"If it's passed to POST method from a client it'll be assigned to the "
|
|
"newly created execution object, but only if an execution with such ID "
|
|
"doesn't exist. If it exists, then the endpoint will just return "
|
|
"execution properties in JSON."
|
|
|
|
workflow_id = wtypes.text
|
|
"workflow ID"
|
|
|
|
workflow_name = wtypes.text
|
|
"workflow name"
|
|
|
|
workflow_namespace = wtypes.text
|
|
"""Workflow namespace. The workflow namespace is also saved
|
|
under params and passed to all sub-workflow executions. When looking for
|
|
the next sub-workflow to run, The correct workflow will be found by
|
|
name and namespace, where the namespace can be the workflow namespace or
|
|
the default namespace. Workflows in the same namespace as the top workflow
|
|
will be given a higher priority."""
|
|
|
|
description = wtypes.text
|
|
"description of workflow execution"
|
|
|
|
params = types.jsontype
|
|
"""'params' define workflow type specific parameters. Specific parameters
|
|
are:
|
|
'task_name' - the name of the target task. Only for reverse workflows.
|
|
'env' - A string value containing the name of the stored environment
|
|
object or a dictionary with the environment variables used during
|
|
workflow execution and accessible as 'env()' from within expressions
|
|
(YAQL or Jinja) defined in the workflow text.
|
|
'evaluate_env' - If present, controls whether or not Mistral should
|
|
recursively find and evaluate all expressions (YAQL or Jinja) within
|
|
the specified environment (via 'env' parameter). 'True' - evaluate
|
|
all expressions recursively in the environment structure. 'False' -
|
|
don't evaluate expressions. 'True' by default.
|
|
"""
|
|
|
|
task_execution_id = wtypes.text
|
|
"reference to the parent task execution"
|
|
|
|
root_execution_id = wtypes.text
|
|
"reference to the root execution"
|
|
|
|
source_execution_id = wtypes.text
|
|
"""reference to a workflow execution id which will signal the api to
|
|
perform a lookup of a current workflow_execution and create a replica
|
|
based on that workflow inputs and parameters"""
|
|
|
|
state = wtypes.text
|
|
"state can be one of: IDLE, RUNNING, SUCCESS, ERROR, PAUSED"
|
|
|
|
state_info = wtypes.text
|
|
"an optional state information string"
|
|
|
|
input = types.jsontype
|
|
"input is a JSON structure containing workflow input values"
|
|
|
|
output = types.jsontype
|
|
"output is a workflow output"
|
|
|
|
created_at = wtypes.text
|
|
updated_at = wtypes.text
|
|
|
|
project_id = wsme.wsattr(wtypes.text, readonly=True)
|
|
|
|
@classmethod
|
|
def sample(cls):
|
|
return cls(
|
|
id='123e4567-e89b-12d3-a456-426655440000',
|
|
workflow_name='flow',
|
|
workflow_namespace='some_namespace',
|
|
workflow_id='123e4567-e89b-12d3-a456-426655441111',
|
|
description='this is the first execution.',
|
|
project_id='40a908dbddfe48ad80a87fb30fa70a03',
|
|
state='SUCCESS',
|
|
input={},
|
|
output={},
|
|
params={
|
|
'env': {'k1': 'abc', 'k2': 123},
|
|
'notify': [
|
|
{
|
|
'type': 'webhook',
|
|
'url': 'http://endpoint/of/webhook',
|
|
'headers': {
|
|
'Content-Type': 'application/json',
|
|
'X-Auth-Token': '123456789'
|
|
}
|
|
},
|
|
{
|
|
'type': 'queue',
|
|
'topic': 'failover_queue',
|
|
'backend': 'rabbitmq',
|
|
'host': '127.0.0.1',
|
|
'port': 5432
|
|
}
|
|
]
|
|
},
|
|
created_at='1970-01-01T00:00:00.000000',
|
|
updated_at='1970-01-01T00:00:00.000000'
|
|
)
|
|
|
|
|
|
class Executions(resource.ResourceList):
|
|
"""A collection of Execution resources."""
|
|
|
|
executions = [Execution]
|
|
|
|
def __init__(self, **kwargs):
|
|
self._type = 'executions'
|
|
|
|
super(Executions, self).__init__(**kwargs)
|
|
|
|
@classmethod
|
|
def sample(cls):
|
|
sample = cls()
|
|
sample.executions = [Execution.sample()]
|
|
sample.next = (
|
|
"http://localhost:8989/v2/executions?"
|
|
"sort_keys=id,workflow_name&sort_dirs=asc,desc&limit=10&"
|
|
"marker=123e4567-e89b-12d3-a456-426655440000"
|
|
)
|
|
|
|
return sample
|
|
|
|
|
|
class Task(resource.Resource):
|
|
"""Task resource."""
|
|
|
|
id = wtypes.text
|
|
name = wtypes.text
|
|
type = wtypes.text
|
|
|
|
workflow_name = wtypes.text
|
|
workflow_namespace = wtypes.text
|
|
workflow_id = wtypes.text
|
|
workflow_execution_id = wtypes.text
|
|
|
|
state = wtypes.text
|
|
"""state can take one of the following values:
|
|
IDLE, RUNNING, SUCCESS, ERROR, DELAYED"""
|
|
|
|
state_info = wtypes.text
|
|
"an optional state information string"
|
|
|
|
project_id = wsme.wsattr(wtypes.text, readonly=True)
|
|
|
|
runtime_context = types.jsontype
|
|
|
|
result = wtypes.text
|
|
published = types.jsontype
|
|
processed = bool
|
|
|
|
created_at = wtypes.text
|
|
updated_at = wtypes.text
|
|
|
|
started_at = wtypes.text
|
|
finished_at = wtypes.text
|
|
|
|
# Add this param to make Mistral API work with WSME 0.8.0 or higher version
|
|
reset = wsme.wsattr(bool, mandatory=True)
|
|
|
|
env = types.jsontype
|
|
|
|
@classmethod
|
|
def sample(cls):
|
|
return cls(
|
|
id='123e4567-e89b-12d3-a456-426655440000',
|
|
workflow_name='flow',
|
|
workflow_id='123e4567-e89b-12d3-a456-426655441111',
|
|
workflow_execution_id='123e4567-e89b-12d3-a456-426655440000',
|
|
name='task',
|
|
state=states.SUCCESS,
|
|
project_id='40a908dbddfe48ad80a87fb30fa70a03',
|
|
runtime_context={
|
|
'triggered_by': [
|
|
{
|
|
'task_id': '123-123-123',
|
|
'event': 'on-success'
|
|
}
|
|
]
|
|
},
|
|
result='task result',
|
|
published={'key': 'value'},
|
|
processed=True,
|
|
created_at='1970-01-01T00:00:00.000000',
|
|
updated_at='1970-01-01T00:00:00.000000',
|
|
reset=True
|
|
)
|
|
|
|
|
|
class Tasks(resource.ResourceList):
|
|
"""A collection of tasks."""
|
|
|
|
tasks = [Task]
|
|
|
|
def __init__(self, **kwargs):
|
|
self._type = 'tasks'
|
|
|
|
super(Tasks, self).__init__(**kwargs)
|
|
|
|
@classmethod
|
|
def sample(cls):
|
|
return cls(tasks=[Task.sample()])
|
|
|
|
|
|
class ActionExecution(resource.Resource):
|
|
"""ActionExecution resource."""
|
|
|
|
id = wtypes.text
|
|
|
|
workflow_name = wtypes.text
|
|
workflow_namespace = wtypes.text
|
|
task_name = wtypes.text
|
|
task_execution_id = wtypes.text
|
|
|
|
state = wtypes.text
|
|
|
|
state_info = wtypes.text
|
|
tags = [wtypes.text]
|
|
name = wtypes.text
|
|
description = wtypes.text
|
|
project_id = wsme.wsattr(wtypes.text, readonly=True)
|
|
accepted = bool
|
|
input = types.jsontype
|
|
output = types.jsontype
|
|
created_at = wtypes.text
|
|
updated_at = wtypes.text
|
|
params = types.jsontype # TODO(rakhmerov): What is this??
|
|
|
|
@classmethod
|
|
def sample(cls):
|
|
return cls(
|
|
id='123e4567-e89b-12d3-a456-426655440000',
|
|
workflow_name='flow',
|
|
task_name='task1',
|
|
workflow_execution_id='653e4127-e89b-12d3-a456-426655440076',
|
|
task_execution_id='343e45623-e89b-12d3-a456-426655440090',
|
|
state=states.SUCCESS,
|
|
state_info=states.SUCCESS,
|
|
tags=['foo', 'fee'],
|
|
name='std.echo',
|
|
description='My running action',
|
|
project_id='40a908dbddfe48ad80a87fb30fa70a03',
|
|
accepted=True,
|
|
input={'first_name': 'John', 'last_name': 'Doe'},
|
|
output={'some_output': 'Hello, John Doe!'},
|
|
created_at='1970-01-01T00:00:00.000000',
|
|
updated_at='1970-01-01T00:00:00.000000',
|
|
params={'save_result': True, "run_sync": False}
|
|
)
|
|
|
|
|
|
class ActionExecutions(resource.ResourceList):
|
|
"""A collection of action_executions."""
|
|
|
|
action_executions = [ActionExecution]
|
|
|
|
def __init__(self, **kwargs):
|
|
self._type = 'action_executions'
|
|
|
|
super(ActionExecutions, self).__init__(**kwargs)
|
|
|
|
@classmethod
|
|
def sample(cls):
|
|
return cls(action_executions=[ActionExecution.sample()])
|
|
|
|
|
|
class CronTrigger(resource.Resource):
|
|
"""CronTrigger resource."""
|
|
|
|
id = wtypes.text
|
|
name = wtypes.text
|
|
workflow_name = wtypes.text
|
|
workflow_id = wtypes.text
|
|
workflow_input = types.jsontype
|
|
workflow_params = types.jsontype
|
|
project_id = wsme.wsattr(wtypes.text, readonly=True)
|
|
|
|
scope = SCOPE_TYPES
|
|
|
|
pattern = wtypes.text
|
|
remaining_executions = wtypes.IntegerType(minimum=1)
|
|
first_execution_time = wtypes.text
|
|
next_execution_time = wtypes.text
|
|
|
|
created_at = wtypes.text
|
|
updated_at = wtypes.text
|
|
|
|
@classmethod
|
|
def sample(cls):
|
|
return cls(
|
|
id='123e4567-e89b-12d3-a456-426655440000',
|
|
name='my_trigger',
|
|
workflow_name='my_wf',
|
|
workflow_id='123e4567-e89b-12d3-a456-426655441111',
|
|
workflow_input={},
|
|
workflow_params={},
|
|
project_id='40a908dbddfe48ad80a87fb30fa70a03',
|
|
scope='private',
|
|
pattern='* * * * *',
|
|
remaining_executions=42,
|
|
created_at='1970-01-01T00:00:00.000000',
|
|
updated_at='1970-01-01T00:00:00.000000'
|
|
)
|
|
|
|
|
|
class CronTriggers(resource.ResourceList):
|
|
"""A collection of cron triggers."""
|
|
|
|
cron_triggers = [CronTrigger]
|
|
|
|
def __init__(self, **kwargs):
|
|
self._type = 'cron_triggers'
|
|
|
|
super(CronTriggers, self).__init__(**kwargs)
|
|
|
|
@classmethod
|
|
def sample(cls):
|
|
return cls(cron_triggers=[CronTrigger.sample()])
|
|
|
|
|
|
class Environment(resource.Resource):
|
|
"""Environment resource."""
|
|
|
|
id = wtypes.text
|
|
name = wtypes.text
|
|
description = wtypes.text
|
|
variables = types.jsontype
|
|
scope = SCOPE_TYPES
|
|
project_id = wsme.wsattr(wtypes.text, readonly=True)
|
|
created_at = wtypes.text
|
|
updated_at = wtypes.text
|
|
|
|
@classmethod
|
|
def sample(cls):
|
|
return cls(
|
|
id='123e4567-e89b-12d3-a456-426655440000',
|
|
name='sample',
|
|
description='example environment entry',
|
|
variables={
|
|
'server': 'localhost',
|
|
'database': 'temp',
|
|
'timeout': 600,
|
|
'verbose': True
|
|
},
|
|
scope='private',
|
|
project_id='40a908dbddfe48ad80a87fb30fa70a03',
|
|
created_at='1970-01-01T00:00:00.000000',
|
|
updated_at='1970-01-01T00:00:00.000000'
|
|
)
|
|
|
|
|
|
class Environments(resource.ResourceList):
|
|
"""A collection of Environment resources."""
|
|
|
|
environments = [Environment]
|
|
|
|
def __init__(self, **kwargs):
|
|
self._type = 'environments'
|
|
|
|
super(Environments, self).__init__(**kwargs)
|
|
|
|
@classmethod
|
|
def sample(cls):
|
|
return cls(environments=[Environment.sample()])
|
|
|
|
|
|
class Member(resource.Resource):
|
|
id = types.uuid
|
|
resource_id = wtypes.text
|
|
resource_type = wtypes.text
|
|
project_id = wtypes.text
|
|
member_id = wtypes.text
|
|
status = wtypes.Enum(str, 'pending', 'accepted', 'rejected')
|
|
created_at = wtypes.text
|
|
updated_at = wtypes.text
|
|
|
|
@classmethod
|
|
def sample(cls):
|
|
return cls(
|
|
id='123e4567-e89b-12d3-a456-426655440000',
|
|
resource_id='123e4567-e89b-12d3-a456-426655440011',
|
|
resource_type='workflow',
|
|
project_id='40a908dbddfe48ad80a87fb30fa70a03',
|
|
member_id='a7eb669e9819420ea4bd1453e672c0a7',
|
|
status='accepted',
|
|
created_at='1970-01-01T00:00:00.000000',
|
|
updated_at='1970-01-01T00:00:00.000000'
|
|
)
|
|
|
|
|
|
class Members(resource.ResourceList):
|
|
members = [Member]
|
|
|
|
@classmethod
|
|
def sample(cls):
|
|
return cls(members=[Member.sample()])
|
|
|
|
|
|
class Service(resource.Resource):
|
|
"""Service resource."""
|
|
|
|
name = wtypes.text
|
|
|
|
type = wtypes.text
|
|
|
|
@classmethod
|
|
def sample(cls):
|
|
return cls(name='host1_1234', type='executor_group')
|
|
|
|
|
|
class Services(resource.Resource):
|
|
"""A collection of Services."""
|
|
|
|
services = [Service]
|
|
|
|
@classmethod
|
|
def sample(cls):
|
|
return cls(services=[Service.sample()])
|
|
|
|
|
|
class EventTrigger(resource.Resource):
|
|
"""EventTrigger resource."""
|
|
|
|
id = wsme.wsattr(wtypes.text, readonly=True)
|
|
created_at = wsme.wsattr(wtypes.text, readonly=True)
|
|
updated_at = wsme.wsattr(wtypes.text, readonly=True)
|
|
project_id = wsme.wsattr(wtypes.text, readonly=True)
|
|
name = wtypes.text
|
|
workflow_id = types.uuid
|
|
workflow_input = types.jsontype
|
|
workflow_params = types.jsontype
|
|
exchange = wtypes.text
|
|
topic = wtypes.text
|
|
event = wtypes.text
|
|
scope = SCOPE_TYPES
|
|
|
|
@classmethod
|
|
def sample(cls):
|
|
return cls(id='123e4567-e89b-12d3-a456-426655441414',
|
|
created_at='1970-01-01T00:00:00.000000',
|
|
updated_at='1970-01-01T00:00:00.000000',
|
|
project_id='project',
|
|
name='expiration_event_trigger',
|
|
workflow_id='123e4567-e89b-12d3-a456-426655441414',
|
|
workflow_input={},
|
|
workflow_params={},
|
|
exchange='nova',
|
|
topic='notifications',
|
|
event='compute.instance.create.end')
|
|
|
|
|
|
class EventTriggers(resource.ResourceList):
|
|
"""A collection of event triggers."""
|
|
|
|
event_triggers = [EventTrigger]
|
|
|
|
def __init__(self, **kwargs):
|
|
self._type = 'event_triggers'
|
|
|
|
super(EventTriggers, self).__init__(**kwargs)
|
|
|
|
@classmethod
|
|
def sample(cls):
|
|
triggers_sample = cls()
|
|
triggers_sample.event_triggers = [EventTrigger.sample()]
|
|
triggers_sample.next = ("http://localhost:8989/v2/event_triggers?"
|
|
"sort_keys=id,name&"
|
|
"sort_dirs=asc,desc&limit=10&"
|
|
"marker=123e4567-e89b-12d3-a456-426655440000")
|
|
|
|
return triggers_sample
|