The writing styles at few places were not in compliance with the OpenStack writing style as mentioned in http://docs.openstack.org/contributor-guide/writing-style /general-writing-guidelines.html. This patch changes the heading styles and adds a few other minor changes in the documents. Change-Id: I0d90ba32ddcef0427b1dc4358206210f166e798a Partial-Implements: blueprint mistral-doc
5.2 KiB
How to extend YAQL with a new function
Tutorial
- Create a new Python project, an empty folder, containing a basic
setup.py
file.
$ mkdir my_project
$ cd my_project
$ vim setup.py
try:
from setuptools import setup, find_packages
except ImportError:
from distutils.core import setup, find_packages
setup(="project_name",
name="0.1.0",
version=find_packages(),
packages=["mistral", "yaql"],
install_requires={
entry_points"mistral.yaql_functions": [
"random_uuid = my_package.sub_package.yaql:random_uuid_"
]
} )
Publish the random_uuid_
function in the
entry_points
section, in the
mistral.yaql_functions
namespace in setup.py
.
This function will be defined later.
Note that the package name will be used in Pip and must not overlap
with other packages installed. project_name
may be replaced
by something else. The package name (my_package
here) may
overlap with other packages, but module paths (.py
files)
may not.
For example, it is possible to have a mistral
package
(though not recommended), but there must not be a
mistral/version.py
file, which would overlap with the file
existing in the original mistral
package.
yaql
and mistral
are the required packages.
mistral
is necessary in this example only because calls to
the Mistral Python DB API are made.
For each entry point, the syntax is:
"<name_of_YAQL_expression> = <path.to.module>:<function_name>"
stevedore
will detect all the entry points and make them
available to all Python applications needing them. Using this feature,
there is no need to modify Mistral's core code.
- Create a package folder.
A package folder is directory with a __init__.py
file.
Create a file that will contain the custom YAQL functions. There are no
restrictions on the paths or file names used.
$ mkdir -p my_package/sub_package
$ touch my_package/__init__.py
$ touch my_package/sub_package/__init__.py
- Write a function in
yaql.py
.
That function might have context
as first argument to
have the current YAQL context available inside the function.
$ cd my_package/sub_package
$ vim yaql.py
from uuid import uuid5, UUID
from time import time
def random_uuid_(context):
"""generate a UUID using the execution ID and the clock"""
# fetch the current workflow execution ID found in the context
= context['__execution']['id']
execution_id
= str(time())
time_str = UUID(execution_id)
execution_uuid return uuid5(execution_uuid, time_str)
This function returns a random UUID using the current workflow execution ID as a namespace.
The context
argument will be passed by Mistral YAQL
engine to the function. It is invisble to the user. It contains
variables from the current task execution scope, such as
__execution
which is a dictionary with information about
the current workflow execution such as its id
.
Note that errors can be raised and will be displayed in the task execution state information in case they are raised. Any valid Python primitives may be returned.
The context
argument is optional. There can be as many
arguments as wanted, even list arguments such as *args
or
dictionary arguments such as **kwargs
can be used as
function arguments.
For more information about YAQL, read the official YAQL documentation.
- Install
pip
andsetuptools
.
$ curl https://bootstrap.pypa.io/get-pip.py | python
$ pip install --upgrade setuptools
$ cd -
- Install the package (note that there is a dot
.
at the end of the line).
$ pip install .
- The YAQL function can be called in Mistral using its name
random_uuid
.
The function name in Python random_uuid_
does not
matter, only the entry point name random_uuid
does.
my_workflow:
tasks:
my_action_task:
action: std.echo
publish:
random_id: <% random_uuid() %>
input:
output: "hello world"
Updating changes
After any new created functions or any modification in the code,
re-run pip install .
and restart Mistral.
Development
While developing, it is sufficient to add the root source folder (the
parent folder of my_package
) to the PYTHONPATH
environment variable and the line
random_uuid = my_package.sub_package.yaql:random_uuid_
in
the Mistral entry points in the mistral.yaql_functions
namespace. If the path to the parent folder of my_package
is /path/to/my_project
.
$ export PYTHONPATH=$PYTHONPATH:/path/to/my_project
$ vim $(find / -name "mistral.*egg-info*")/entry_points.txt
[entry_points]
mistral.yaql_functions =
random_uuid = my_package.sub_package.yaql:random_uuid_