index.rst 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. .. _writing-utility-modules:
  2. ==============================================
  3. Utility Modules - Code Reuse in Custom Modules
  4. ==============================================
  5. .. versionadded:: 2015.5.0
  6. .. versionchanged:: 2016.11.0
  7. These can now be synced to the Master for use in custom Runners, and in
  8. custom execution modules called within Pillar SLS files.
  9. When extending Salt by writing custom (:ref:`state modules
  10. <writing-state-modules>`), :ref:`execution modules
  11. <writing-execution-modules>`, etc., sometimes there is a need for a function to
  12. be available to more than just one kind of custom module. For these cases, Salt
  13. supports what are called "utility modules". These modules are like normal
  14. execution modules, but instead of being invoked in Salt code using
  15. ``__salt__``, the ``__utils__`` prefix is used instead.
  16. For example, assuming the following simple utility module, saved to
  17. ``salt://_utils/foo.py``
  18. .. code-block:: python
  19. # -*- coding: utf-8 -*-
  20. '''
  21. My utils module
  22. ---------------
  23. This module contains common functions for use in my other custom types.
  24. '''
  25. def bar():
  26. return 'baz'
  27. Once synced to a minion, this function would be available to other custom Salt
  28. types like so:
  29. .. code-block:: python
  30. # -*- coding: utf-8 -*-
  31. '''
  32. My awesome execution module
  33. ---------------------------
  34. '''
  35. def observe_the_awesomeness():
  36. '''
  37. Prints information from my utility module
  38. CLI Example:
  39. .. code-block:: bash
  40. salt '*' mymodule.observe_the_awesomeness
  41. '''
  42. return __utils__['foo.bar']()
  43. Utility modules, like any other kind of Salt extension, support using a
  44. :ref:`__virtual__ function <modules-virtual-name>` to conditionally load them,
  45. or load them under a different namespace. For instance, if the utility module
  46. above were named ``salt://_utils/mymodule.py`` it could be made to be loaded as
  47. the ``foo`` utility module with a ``__virtual__`` function.
  48. .. code-block:: python
  49. # -*- coding: utf-8 -*-
  50. '''
  51. My utils module
  52. ---------------
  53. This module contains common functions for use in my other custom types.
  54. '''
  55. def __virtual__():
  56. '''
  57. Load as a different name
  58. '''
  59. return 'foo'
  60. def bar():
  61. return 'baz'
  62. .. versionadded:: 2018.3.0
  63. Instantiating objects from classes declared in util modules works with
  64. Master side modules, such as Runners, Outputters, etc.
  65. Also you could even write your utility modules in object oriented fashion:
  66. .. code-block:: python
  67. # -*- coding: utf-8 -*-
  68. '''
  69. My OOP-style utils module
  70. -------------------------
  71. This module contains common functions for use in my other custom types.
  72. '''
  73. class Foo(object):
  74. def __init__(self):
  75. pass
  76. def bar(self):
  77. return 'baz'
  78. And import them into other custom modules:
  79. .. code-block:: python
  80. # -*- coding: utf-8 -*-
  81. '''
  82. My awesome execution module
  83. ---------------------------
  84. '''
  85. import mymodule
  86. def observe_the_awesomeness():
  87. '''
  88. Prints information from my utility module
  89. CLI Example:
  90. .. code-block:: bash
  91. salt '*' mymodule.observe_the_awesomeness
  92. '''
  93. foo = mymodule.Foo()
  94. return foo.bar()
  95. These are, of course, contrived examples, but they should serve to show some of
  96. the possibilities opened up by writing utility modules. Keep in mind though
  97. that states still have access to all of the execution modules, so it is not
  98. necessary to write a utility module to make a function available to both a
  99. state and an execution module. One good use case for utility modules is one
  100. where it is necessary to invoke the same function from a custom :ref:`outputter
  101. <all-salt.output>`/returner, as well as an execution module.
  102. Utility modules placed in ``salt://_utils/`` will be synced to the minions when
  103. a :ref:`highstate <running-highstate>` is run, as well as when any of the
  104. following Salt functions are called:
  105. * :py:func:`saltutil.sync_utils <salt.modules.saltutil.sync_utils>`
  106. * :py:func:`saltutil.sync_all <salt.modules.saltutil.sync_all>`
  107. As of the Fluorine release, as well as 2017.7.7 and 2018.3.2 in their
  108. respective release cycles, the ``sync`` argument to :py:func:`state.apply
  109. <salt.modules.state.apply_>`/:py:func:`state.sls <salt.modules.state.sls>` can
  110. be used to sync custom types when running individual SLS files.
  111. To sync to the Master, use either of the following:
  112. * :py:func:`saltutil.sync_utils <salt.runners.saltutil.sync_utils>`
  113. * :py:func:`saltutil.sync_all <salt.runners.saltutil.sync_all>`