Utility Modules - Code Reuse in Custom Modules

New in version 2015.5.0.

Changed in version 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 (state modules), 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

# -*- 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:

# -*- 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 __virtual__ function 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.

# -*- 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'

New in version 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:

# -*- 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:

# -*- 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 outputter/returner, as well as an execution module.

Utility modules placed in salt://_utils/ will be synced to the minions when a highstate is run, as well as when any of the following Salt functions are called:

As of the Fluorine release, as well as 2017.7.7 and 2018.3.2 in their respective release cycles, the sync argument to state.apply/state.sls can be used to sync custom types when running individual SLS files.

To sync to the Master, use either of the following: