From b8390eb84d6c7fd6e241038829b6ab337ab9b8ab Mon Sep 17 00:00:00 2001 From: Dmitri Zimine Date: Sun, 5 Oct 2014 13:25:16 -0700 Subject: [PATCH] Add documentation - part 3 Document REST v2 with autodocs Change-Id: Ib43d2237ebb0f8ef9f8d18e70182d7cc5f2f0828 --- doc/README.md | 24 ++++++ doc/source/conf.py | 2 +- doc/source/developer/webapi/v2.rst | 99 +++++++++++++++++++++++++ mistral/api/controllers/v2/action.py | 10 ++- mistral/api/controllers/v2/execution.py | 26 ++++++- mistral/api/controllers/v2/task.py | 4 +- mistral/api/controllers/v2/workbook.py | 5 +- mistral/api/controllers/v2/workflow.py | 5 +- 8 files changed, 165 insertions(+), 10 deletions(-) create mode 100644 doc/README.md diff --git a/doc/README.md b/doc/README.md new file mode 100644 index 000000000..805b894e4 --- /dev/null +++ b/doc/README.md @@ -0,0 +1,24 @@ +# Sphinx DOC hints + +## Migrating from Openstack Wiki + +* Install pandoc +* Copy wiki code into a file, e.g. `source.mw` +* Convert to .rst + + pandoc --from=mediawiki --to=rst --output=doc/source/dsl/dsl_v1.rst doc/source/dsl/source.mw + +* To make code samples fancy: + + TODO: figure how to make YAML samples look nicer with `code::` directive + +## Using autodoc with sphinxcontrib.pecanwsme.rest and wsmeext.sphinxext plugins + + TODO: why REST URL is not generated with parameters? + +## Running sphinx-audobuild + +[auto-loader](https://pypi.python.org/pypi/sphinx-autobuild/0.2.3) - rules for convenient development https://pypi.python.org/pypi/sphinx-autobuild/0.2.3. install, and run: + + sphinx-autobuild doc/source doc/build + diff --git a/doc/source/conf.py b/doc/source/conf.py index ff808dd48..7495ab146 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -28,7 +28,7 @@ extensions = [ 'wsmeext.sphinxext', ] -wsme_protocols = ['restjson', 'restxml'] +wsme_protocols = ['restjson'] # autodoc generation is a bit aggressive and a nuisance when doing heavy # text edit cycles. diff --git a/doc/source/developer/webapi/v2.rst b/doc/source/developer/webapi/v2.rst index 16a2cbea9..77928120c 100644 --- a/doc/source/developer/webapi/v2.rst +++ b/doc/source/developer/webapi/v2.rst @@ -1,3 +1,102 @@ V2 API ====== +.. warning:: (2014-10-5): API described in this document might slightly change within a short period of time (2-3 weeks) and should be now considered experimental. Mistral team is now actively working on stabilization. + +This API describes the ways of interacting with Mistral service via HTTP protocol using Representational State Transfer concept (ReST). + + +Basics +------- + + +Media Types +^^^^^^^^^^^^ + +Currently this API relies on JSON to represent states of REST resources. + +Error States +^^^^^^^^^^^^ + +The common HTTP Response Status Codes (https://github.com/for-GET/know-your-http-well/blob/master/status-codes.md) are used. + +Application Root [/] +^^^^^^^^^^^^^^^^^^^^^ +Application Root provides links to all possible API methods for Mistral. URLs for other resources described below are relative to Application Root. + +API v2 Root [/v2/] +^^^^^^^^^^^^^^^^^^^ +All API v2 urls are relative to API v2 root. + +Workbooks +---------- + +.. autotype:: mistral.api.controllers.v2.workbook.Workbook + :members: + +`name` is immutable. tags is a list of values associated with a workbook that a user can use to group workbooks by some criteria (deployment workbooks, Big Data processing workbooks etc.). Note that name and tags get inferred from workbook definition when Mistral service receives a POST request. So they can't be changed in another way. + +.. autotype:: mistral.api.controllers.v2.workbook.Workbooks + :members: + +.. rest-controller:: mistral.api.controllers.v2.workbook:WorkbooksController + :webprefix: /v2/workbooks + + +Workflows +---------- + +.. autotype:: mistral.api.controllers.v2.workflow.Workflow + :members: + +`name` is immutable. tags is a list of values associated with a workflow that a user can use to group workflows by some criteria. Note that name and tags get inferred from workflow definition when Mistral service receives a POST request. So they can't be changed in another way. + +.. autotype:: mistral.api.controllers.v2.workflow.Workflows + :members: + +.. rest-controller:: mistral.api.controllers.v2.workflow:WorkflowsController + :webprefix: /v2/workflows + +Actions +-------- + +.. autotype:: mistral.api.controllers.v2.action.Action + :members: + +.. autotype:: mistral.api.controllers.v2.action.Actions + :members: + +.. rest-controller:: mistral.api.controllers.v2.action:ActionsController + :webprefix: /v2/actions + + +Executions +------------ + +.. autotype:: mistral.api.controllers.v2.execution.Execution + :members: + +.. autotype:: mistral.api.controllers.v2.execution.Executions + :members: + +.. rest-controller:: mistral.api.controllers.v2.execution:ExecutionsController + :webprefix: /v2/executions + + +Tasks +------------ + +When a workflow starts Mistral creates an execution. It in turn consists of a set of tasks. So Task is an instance of a task described in a Workflow that belongs to a particular execution. + + +.. autotype:: mistral.api.controllers.v2.task.Task + :members: + +.. autotype:: mistral.api.controllers.v2.task.Tasks + :members: + +.. rest-controller:: mistral.api.controllers.v2.task:TasksController + :webprefix: /v2/tasks + +.. rest-controller:: mistral.api.controllers.v2.task:ExecutionTasksController + :webprefix: /v2/executions \ No newline at end of file diff --git a/mistral/api/controllers/v2/action.py b/mistral/api/controllers/v2/action.py index b1ce78e3f..002f46e76 100644 --- a/mistral/api/controllers/v2/action.py +++ b/mistral/api/controllers/v2/action.py @@ -30,7 +30,13 @@ SCOPE_TYPES = wtypes.Enum(str, 'private', 'public') class Action(resource.Resource): - """Action resource.""" + """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 @@ -49,7 +55,7 @@ class Action(resource.Resource): def sample(cls): return cls(id='123e4567-e89b-12d3-a456-426655440000', name='flow', - definition='---', + definition='HERE GOES ACTION DEFINITION IN MISTRAL DSL v2', tags=['large', 'expensive'], scope='private', created_at='1970-01-01T00:00:00.000000', diff --git a/mistral/api/controllers/v2/execution.py b/mistral/api/controllers/v2/execution.py index f278e55d2..c9f9b8f71 100644 --- a/mistral/api/controllers/v2/execution.py +++ b/mistral/api/controllers/v2/execution.py @@ -34,18 +34,28 @@ class Execution(resource.Resource): """Execution resource.""" id = wtypes.text + "id is immutable and auto assigned." + workflow_name = wtypes.text + "reference to workflow definition" + params = wtypes.text + "params define workflow type specific parameters. For example, reverse \ + workflow takes one parameter 'task_name' that defines a target task." state = wtypes.text - # Context is a JSON object but since WSME doesn't support arbitrary - # dictionaries we have to use text type convert to json and back manually. + "state can be one of: RUNNING, SUCCESS, ERROR, PAUSED" + input = wtypes.text + "input is a JSON structure containing workflow input values." output = wtypes.text + "output is a workflow output." created_at = wtypes.text updated_at = wtypes.text + # Context is a JSON object but since WSME doesn't support arbitrary + # dictionaries we have to use text type convert to json and back manually. def to_dict(self): d = super(Execution, self).to_dict() @@ -110,10 +120,15 @@ class ExecutionsController(rest.RestController): @rest_utils.wrap_wsme_controller_exception @wsme_pecan.wsexpose(Execution, wtypes.text, body=Execution) def put(self, id, execution): - """Update the specified Execution.""" + """Update the specified Execution. + + :param id: execution ID. + :param execution: Execution objects + """ LOG.debug("Update execution [id=%s, execution=%s]" % (id, execution)) + # TODO(dzimine): Why update execution? We must only pause and resume. db_model = db_api.update_execution(id, execution.to_dict()) return Execution.from_dict(db_model.to_dict()) @@ -121,7 +136,10 @@ class ExecutionsController(rest.RestController): @rest_utils.wrap_wsme_controller_exception @wsme_pecan.wsexpose(Execution, body=Execution, status_code=201) def post(self, execution): - """Create a new Execution.""" + """Create a new Execution. + + :param execution: Execution object with input content. + """ LOG.debug("Create execution [execution=%s]" % execution) engine = rpc.get_engine_client() diff --git a/mistral/api/controllers/v2/task.py b/mistral/api/controllers/v2/task.py index 0e5509284..6c20daec5 100644 --- a/mistral/api/controllers/v2/task.py +++ b/mistral/api/controllers/v2/task.py @@ -45,8 +45,10 @@ class Task(resource.Resource): execution_id = wtypes.text state = wtypes.text - result = wtypes.text + "state can take one of the following values: \ + IDLE, RUNNING, SUCCESS, ERROR, DELAYED" + result = wtypes.text input = wtypes.text output = wtypes.text diff --git a/mistral/api/controllers/v2/workbook.py b/mistral/api/controllers/v2/workbook.py index 47ea2fbb4..a255c4063 100644 --- a/mistral/api/controllers/v2/workbook.py +++ b/mistral/api/controllers/v2/workbook.py @@ -35,8 +35,10 @@ class Workbook(resource.Resource): name = wtypes.text definition = wtypes.text + "workbook definition in Mistral v2 DSL" tags = [wtypes.text] scope = SCOPE_TYPES + "'private' or 'public'" created_at = wtypes.text updated_at = wtypes.text @@ -45,7 +47,8 @@ class Workbook(resource.Resource): def sample(cls): return cls(id='123e4567-e89b-12d3-a456-426655440000', name='book', - definition='---', + definition='HERE GOES' + 'WORKBOOK DEFINITION IN MISTRAL DSL v2', tags=['large', 'expensive'], scope='private', created_at='1970-01-01T00:00:00.000000', diff --git a/mistral/api/controllers/v2/workflow.py b/mistral/api/controllers/v2/workflow.py index aa3c7600f..125ed2b52 100644 --- a/mistral/api/controllers/v2/workflow.py +++ b/mistral/api/controllers/v2/workflow.py @@ -36,8 +36,10 @@ class Workflow(resource.Resource): input = wtypes.text definition = wtypes.text + "Workflow definition in Mistral v2 DSL" tags = [wtypes.text] scope = SCOPE_TYPES + "'private' or 'public'" created_at = wtypes.text updated_at = wtypes.text @@ -47,7 +49,8 @@ class Workflow(resource.Resource): return cls(id='123e4567-e89b-12d3-a456-426655440000', name='flow', input='param1, param2', - definition='---', + definition='HERE GOES' + 'WORKFLOW DEFINITION IN MISTRAL DSL v2', tags=['large', 'expensive'], scope='private', created_at='1970-01-01T00:00:00.000000',