Merge "Spec for MuranoPL static actions"

This commit is contained in:
Jenkins 2016-06-24 14:02:14 +00:00 committed by Gerrit Code Review
commit 6bac1d6708
1 changed files with 385 additions and 0 deletions

View File

@ -0,0 +1,385 @@
..
This work is licensed under a Creative Commons Attribution 3.0 Unported
License.
http://creativecommons.org/licenses/by/3.0/legalcode
==============
Static actions
==============
https://blueprints.launchpad.net/murano/+spec/static-actions
Currently Murano provides a way to invoke MuranoPL methods through the
actions API. However it doesn't cover all the use cases where one may want
to expose some MuranoPL code. This specification further improves the idea
of actions.
Problem description
===================
Existing actions approach has a number of limitations:
* Only instance methods can be exposed as actions. In other words you need
to have a class instance in order to call a method on it. And instance means
it has to be a part of object model. This makes impossible to expose MuranoPL
code that doesn't operate on object model or even produces it like factory
methods;
* Actions bring large overhead and complexity for simple methods. For each
action call a database record is created and never deleted then. All action
results are persisted as well;
* No two actions in the same environment can be called simultaneously.
All of above is not a problem for regular application actions that usually
involve deployment steps and can take long time to complete. However it makes
actions a bad choice in case when one just wants to expose some application
code to outside to keep all of his code in MuranoPL in single place.
Proposed change
===============
In order to overcome above issues it is proposed to add ability to expose and
call static MuranoPL methods through new API and engine RPC calls. Because
the methods are static they are not bound to any object model (environment)
and thus can be called simultaneously.
Also because now there are two types of action methods (static and instance)
the fact that method needs to be exposed cannot be expressed with the Usage
attribute of the method (static methods already have `Usage: Static`).
We could introduce yet another usage (e.g. `StaticAction`). But because action
means that regular MuranoPL method need to be exposed to outside and it has
much more to do with a method visibility rather then its usage it is proposed
to introduce another method keyword to declare its scope.
Thus current syntax for the action declaration
::
methodName:
Usage: Action
will become
::
methodName:
Scope: Public
and static actions will be declared as
::
methodName:
Usage: Static
Scope: Public
`Scope` attribute must be one of the two possible values:
* `Session` - regular method that is accessible from anywhere in the current
execution session. This is the default if the attribute is omitted;
* `Public` - accessible anywhere, both within the session and from outside
through the API call (i.e. it is an action in current terminology).
In the future new scopes might be added to further restrict the access
to the method (e.g. `Package`, `Class`)
For backward compatibility `Usage: Action` should remain valid and acceptable
but be deprecated for future format versions. An exception must be raised if
both `Usage: Action` and `Scope: Session` are specified.
Synchronous and asynchronous actions
------------------------------------
Current instance actions are always asynchronous and this is achieved by means
of API with action result being persisted into database. For static methods
that doesn't usually do any deployment and much more suitable for quick
request-response interactions that do not modify object model this would be
an overkill that greatly reduces their performance. However if we make
static actions synchronous this will cause confusion because we get two
completely different usage pattern for method that differ only by the fact
that one is static and another is not. This is especially confusing due to the
fact that one can easily imagine synchronous instance actions and asynchronous
static ones. Thus it is proposed to:
#. On MuranoPL side all actions are synchronous i.e. they are plain methods
that return the result;
#. RPC calls for action execution are always asynchronous. I.e. the call to
invoke the method and call to notify API on the method result are two
different calls rather than single request-response. However the request
may indicate that the response must be sent to specific API instance to
make synchronization on the API without database persistence possible.
#. On python-muranoclient side all actions are asynchronous in terms that you
get a Future object from which one can get result later as well as check for
its readiness. For synchronous call the result becomes available immediately.
However from the user's perspective all methods are asynchronous.
Current python-muranoclient method for action execution returns action ID
that can be later provided to another method rather that a Future object.
For consistency it is proposed to change that method to return Future
instead. For backward compatibility the method that accepted action ID
must accept task Future too.
#. It is the API who decides if the method is going to be executed
synchronously or not. In the former case API does RPC request to the engine
without creating database records and instead waits for response that
must be sent to that API instance. As soon as result is available it is
returned to the caller (python-muranoclient). For now the API is going
to do synchronous execution for static actions and asynchronous for
instance actions. However in the future we may consider making it
configurable or introduce some level of automation when API can wait for
some time and then switch to asynchronous mode (create database record
and so on) if there is still no result.
Alternatives
============
* Use actions instead for cases where static methods will be more appropriate;
* Declare static actions with yet another Usage value or make Usage be a list
([Static, Action])
* Use Meta to declare actions
Data model impact
=================
None
REST API impact
===============
**POST /actions**
Execute static MuranoPL method. Method must have a Public scope.
*Request*
+----------+----------------------------------+----------------------------------+
| Method | URI | Description |
+==========+==================================+==================================+
| POST | /actions | Execute static action |
+----------+----------------------------------+----------------------------------+
Body:
::
{
"className": "my.class.fqn",
"methodName": "myMethod",
"packageName": "optional.package.fqn",
"classVersion": "1.2.3",
"parameters": {
"arg1": "value1",
"arg2": "value2"
}
}
packageName is optional. If provided the class must be in that package.
classVersion is optional. If provided it may contain either full SemVer version
or version spec (e.g. ">1.2"). If omitted "=0" is assumed.
*Response*
JSON-serialized method response or exception is returned.
HTTP codes:
+----------------+-----------------------------------------------------------+
| Code | Description |
+================+===========================================================+
| 200 | OK. Action was executed successfully |
+----------------+-----------------------------------------------------------+
| 400 | Bad request. Either the format of the body is invalid or |
| | parameters doesn't match the contracts |
+----------------+-----------------------------------------------------------+
| 403 | User is not allowed to execute the action |
+----------------+-----------------------------------------------------------+
| 404 | Not found. Specified class or method doesn't exist |
| | or not exposed |
+----------------+-----------------------------------------------------------+
| 503 | Unhandled exception in the action |
+----------------+-----------------------------------------------------------+
Versioning impact
=================
None
Other end user impact
=====================
python-muranoclient must be updated to provide method for the new API call.
Deployer impact
===============
None
Developer impact
================
Existing MuranoPL applications shouldn't be affected by the change.
For the next package format version old syntax of action declaration
should still work but produce a deprecation warning.
Murano-dashboard / Horizon impact
=================================
None
Implementation
==============
Assignee(s)
-----------
Stan Lagun <istalker2>
Work Items
----------
* Update DSL to make use Scope method attribute
* Update code that inspects if method is an action for the new syntax
(including object model serializer)
* Implement new RPC call in murano-engine
* Implement API call
* Implement method in python-muranoclient
Dependencies
============
None
Testing
=======
RPC call implementation can be tested by unit tests alone.
However to test the new API several tempest tests need to be added:
* Test that executes sample MuranoPL static action (hello world)
* Test that executes method that throws an exception
* Test that executes method with invalid parameters
Documentation Impact
====================
* Documentation for the actions need to be updated
* Developer's guide need to be extended with static actions info
* REST API specification need to be updated with new call info
References
==========
None
Versioning impact
-----------------
None
Other end user impact
---------------------
python-muranoclient must be updated to provide method for the new API call.
Deployer impact
---------------
None
Developer impact
----------------
Existing MuranoPL applications shouldn't be affected by the change.
For the next package format version old syntax of action declaration
should still work but produce a deprecation warning.
Murano-dashboard / Horizon impact
---------------------------------
None
Implementation
==============
Assignee(s)
-----------
Stan Lagun <istalker2>
Work Items
----------
* Update DSL to make use Scope method attribute
* Update code that inspects if method is an action for the new syntax
(including object model serializer)
* Implement new RPC call in murano-engine
* Implement API call
* Implement method in python-muranoclient
Dependencies
============
None
Testing
=======
RPC call implementation can be tested by unit tests alone.
However to test the new API several tempest tests need to be added:
* Test that executes sample MuranoPL static action (hello world)
* Test that executes method that throws an exception
* Test that executes method with invalid parameters
Documentation Impact
====================
* Documentation for the actions need to be updated
* Developer's guide need to be extended with static actions info
* REST API specification need to be updated with new call info
References
==========
None