Adding new plugins#
Plugins provide functions that can be called from the DSL. This is the primary mechanism to interface Python code with the orchestration model at compile time. For Example, this mechanism is also used for std::template and std::file. In addition to this, Inmanta also registers all plugins with the template engine (Jinja2) to use as filters.
A plugin is a python function, registered with the platform with the
decorator. This plugin accepts arguments when called from the DSL and can return a value. Both the
arguments and the return value must by annotated with the allowed types from the orchestration model.
Type annotations are provided as a string (Python3 style argument annotation).
any is a special
type that effectively disables type validation.
Through the arguments of the function, the Python code in the plugin can navigate the orchestration model. The compiler takes care of scheduling the execution at the correct point in the model evaluation.
A module’s Python code lives in the
A simple plugin that accepts no arguments, prints out “hello world” and returns no value requires the following code:
1from inmanta.plugins import plugin 2 3@plugin 4def hello(): 5 print("Hello world!")
If the code above is placed in the plugins directory of the example module
examples/plugins/__init__.py) the plugin can be invoked from the orchestration model as
import example example::hello()
The plugin decorator accepts an argument name. This can be used to change the name of the plugin in
the DSL. This can be used to create plugins that use python reserved names such as
1from inmanta.plugins import plugin 2 3@plugin("print") 4def printf(): 5 """ 6 Prints inmanta 7 """ 8 print("inmanta")
A more complex plugin accepts arguments and returns a value. Regular arguments and keyword-only arguments are both supported. The following example creates a plugin that converts a string to uppercase:
1from inmanta.plugins import plugin 2 3@plugin 4def upper(value: "string") -> "string": 5 return value.upper()
This plugin can be tested with:
import example std::print(example::upper("hello world"))
Argument type annotations are strings that refer to Inmanta primitive types or to entities. If an entity is passed to a plugin, the python code of the plugin can navigate relations throughout the orchestration model to access attributes of other entities.
A base exception for plugins is provided in
inmanta.plugins.PluginException. Exceptions raised
from a plugin should be of a subtype of this base exception.
1from inmanta.plugins import plugin, PluginException 2 3@plugin 4def raise_exception(message: "string"): 5 raise PluginException(message)
If your plugin requires external libraries, add them as dependencies of the module. For more details on how to add dependencies see Understanding Modules.
To deprecate a plugin the
deprecated() decorator can be used in combination with the
decorator. Using this decorator will log a warning message when the function is called. This decorator also accepts an
replaced_by which can be used to potentially improve the warning message by telling which other
plugin should be used in the place of the current one.
for example if the plugin below is called:
1from inmanta.plugins import plugin, deprecated 2 3@deprecated(replaced_by="my_new_plugin") 4@plugin 5def printf(): 6 """ 7 Prints inmanta 8 """ 9 print("inmanta")
it will give following warning:
Plugin 'printf' in module 'inmanta_plugins.<module_name>' is deprecated. It should be replaced by 'my_new_plugin'
Should the replace_by argument be omitted, the warning would look like this:
Plugin 'printf' in module 'inmanta_plugins.<module_name>' is deprecated.
If you want your module to stay compatible with older versions of inmanta you will also need to add a little piece of code that changes how
deprecated() is imported as it does not exist in all versions.
The previous example would then look like this. For older inmanta versions, replace the decorator with a no-op.
1from inmanta.plugins import plugin 2 3try: 4 from inmanta.plugins import deprecated 5except ImportError: 6 deprecated = lambda function=None, **kwargs: function if function is not None else deprecated 7 8 9@deprecated(replaced_by="my_new_plugin") 10@plugin 11def printf(): 12 """ 13 Prints inmanta 14 """ 15 print("inmanta")