123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161 |
- .. _writing-utility-modules:
- ==============================================
- Utility Modules - Code Reuse in Custom Modules
- ==============================================
- .. versionadded:: 2015.5.0
- .. versionchanged:: 2016.11.0
- These can now be synced to the Master for use in custom Runners, and in
- custom execution modules called within Pillar SLS files.
- When extending Salt by writing custom (:ref:`state modules
- <writing-state-modules>`), :ref:`execution modules
- <writing-execution-modules>`, etc., sometimes there is a need for a function to
- be available to more than just one kind of custom module. For these cases, Salt
- supports what are called "utility modules". These modules are like normal
- execution modules, but instead of being invoked in Salt code using
- ``__salt__``, the ``__utils__`` prefix is used instead.
- For example, assuming the following simple utility module, saved to
- ``salt://_utils/foo.py``
- .. code-block:: python
- # -*- coding: utf-8 -*-
- """
- My utils module
- ---------------
- This module contains common functions for use in my other custom types.
- """
- def bar():
- return "baz"
- Once synced to a minion, this function would be available to other custom Salt
- types like so:
- .. code-block:: python
- # -*- coding: utf-8 -*-
- """
- My awesome execution module
- ---------------------------
- """
- def observe_the_awesomeness():
- """
- Prints information from my utility module
- CLI Example:
- .. code-block:: bash
- salt '*' mymodule.observe_the_awesomeness
- """
- return __utils__["foo.bar"]()
- Utility modules, like any other kind of Salt extension, support using a
- :ref:`__virtual__ function <modules-virtual-name>` to conditionally load them,
- or load them under a different namespace. For instance, if the utility module
- above were named ``salt://_utils/mymodule.py`` it could be made to be loaded as
- the ``foo`` utility module with a ``__virtual__`` function.
- .. code-block:: python
- # -*- coding: utf-8 -*-
- """
- My utils module
- ---------------
- This module contains common functions for use in my other custom types.
- """
- def __virtual__():
- """
- Load as a different name
- """
- return "foo"
- def bar():
- return "baz"
- .. versionadded:: 2018.3.0
- Instantiating objects from classes declared in util modules works with
- Master side modules, such as Runners, Outputters, etc.
- Also you could even write your utility modules in object oriented fashion:
- .. code-block:: python
- # -*- coding: utf-8 -*-
- """
- My OOP-style utils module
- -------------------------
- This module contains common functions for use in my other custom types.
- """
- class Foo(object):
- def __init__(self):
- pass
- def bar(self):
- return "baz"
- And import them into other custom modules:
- .. code-block:: python
- # -*- coding: utf-8 -*-
- """
- My awesome execution module
- ---------------------------
- """
- import mymodule
- def observe_the_awesomeness():
- """
- Prints information from my utility module
- CLI Example:
- .. code-block:: bash
- salt '*' mymodule.observe_the_awesomeness
- """
- foo = mymodule.Foo()
- return foo.bar()
- These are, of course, contrived examples, but they should serve to show some of
- the possibilities opened up by writing utility modules. Keep in mind though
- that states still have access to all of the execution modules, so it is not
- necessary to write a utility module to make a function available to both a
- state and an execution module. One good use case for utility modules is one
- where it is necessary to invoke the same function from a custom :ref:`outputter
- <all-salt.output>`/returner, as well as an execution module.
- Utility modules placed in ``salt://_utils/`` will be synced to the minions when
- a :ref:`highstate <running-highstate>` is run, as well as when any of the
- following Salt functions are called:
- * :py:func:`saltutil.sync_utils <salt.modules.saltutil.sync_utils>`
- * :py:func:`saltutil.sync_all <salt.modules.saltutil.sync_all>`
- As of the 2019.2.0 release, as well as 2017.7.7 and 2018.3.2 in their
- respective release cycles, the ``sync`` argument to :py:func:`state.apply
- <salt.modules.state.apply_>`/:py:func:`state.sls <salt.modules.state.sls>` can
- be used to sync custom types when running individual SLS files.
- To sync to the Master, use either of the following:
- * :py:func:`saltutil.sync_utils <salt.runners.saltutil.sync_utils>`
- * :py:func:`saltutil.sync_all <salt.runners.saltutil.sync_all>`
|