1""" 2This runner makes Salt's 3execution modules available 4on the salt master. 5 6.. versionadded:: 2016.11.0 7 8.. _salt_salt_runner: 9 10Salt's execution modules are normally available 11on the salt minion. Use this runner to call 12execution modules on the salt master. 13Salt :ref:`execution modules <writing-execution-modules>` 14are the functions called by the ``salt`` command. 15 16Execution modules can be called with ``salt-run``: 17 18.. code-block:: bash 19 20 salt-run salt.cmd test.ping 21 # call functions with arguments and keyword arguments 22 salt-run salt.cmd test.arg 1 2 3 key=value a=1 23 24Execution modules are also available to salt runners: 25 26.. code-block:: python 27 28 __salt__['salt.cmd'](fun=fun, args=args, kwargs=kwargs) 29 30""" 31 32import copy 33import logging 34 35import salt.client 36import salt.loader 37import salt.pillar 38import salt.utils.args 39from salt.exceptions import SaltClientError 40 41log = logging.getLogger(__name__) 42 43 44def cmd(fun, *args, **kwargs): 45 """ 46 .. versionchanged:: 2018.3.0 47 Added ``with_pillar`` argument 48 49 Execute ``fun`` with the given ``args`` and ``kwargs``. Parameter ``fun`` 50 should be the string :ref:`name <all-salt.modules>` of the execution module 51 to call. 52 53 .. note:: 54 Execution modules will be loaded *every time* this function is called. 55 Additionally, keep in mind that since runners execute on the master, 56 custom execution modules will need to be synced to the master using 57 :py:func:`salt-run saltutil.sync_modules 58 <salt.runners.saltutil.sync_modules>`, otherwise they will not be 59 available. 60 61 with_pillar : False 62 If ``True``, pillar data will be compiled for the master 63 64 .. note:: 65 To target the master in the pillar top file, keep in mind that the 66 default ``id`` for the master is ``<hostname>_master``. This can be 67 overridden by setting an ``id`` configuration parameter in the 68 master config file. 69 70 CLI Example: 71 72 .. code-block:: bash 73 74 salt-run salt.cmd test.ping 75 # call functions with arguments and keyword arguments 76 salt-run salt.cmd test.arg 1 2 3 a=1 77 salt-run salt.cmd mymod.myfunc with_pillar=True 78 """ 79 log.debug("Called salt.cmd runner with minion function %s", fun) 80 81 kwargs = salt.utils.args.clean_kwargs(**kwargs) 82 with_pillar = kwargs.pop("with_pillar", False) 83 84 opts = copy.deepcopy(__opts__) 85 opts["grains"] = salt.loader.grains(opts) 86 87 if with_pillar: 88 opts["pillar"] = salt.pillar.get_pillar( 89 opts, 90 opts["grains"], 91 opts["id"], 92 saltenv=opts["saltenv"], 93 pillarenv=opts.get("pillarenv"), 94 ).compile_pillar() 95 else: 96 opts["pillar"] = {} 97 98 functions = salt.loader.minion_mods( 99 opts, utils=salt.loader.utils(opts), context=__context__ 100 ) 101 102 return ( 103 functions[fun](*args, **kwargs) 104 if fun in functions 105 else "'{}' is not available.".format(fun) 106 ) 107 108 109def execute( 110 tgt, 111 fun, 112 arg=(), 113 timeout=None, 114 tgt_type="glob", 115 ret="", 116 jid="", 117 kwarg=None, 118 **kwargs 119): 120 """ 121 .. versionadded:: 2017.7.0 122 123 Execute ``fun`` on all minions matched by ``tgt`` and ``tgt_type``. 124 Parameter ``fun`` is the name of execution module function to call. 125 126 This function should mainly be used as a helper for runner modules, 127 in order to avoid redundant code. 128 For example, when inside a runner one needs to execute a certain function 129 on arbitrary groups of minions, only has to: 130 131 .. code-block:: python 132 133 ret1 = __salt__['salt.execute']('*', 'mod.fun') 134 ret2 = __salt__['salt.execute']('my_nodegroup', 'mod2.fun2', tgt_type='nodegroup') 135 136 It can also be used to schedule jobs directly on the master, for example: 137 138 .. code-block:: yaml 139 140 schedule: 141 collect_bgp_stats: 142 function: salt.execute 143 args: 144 - edge-routers 145 - bgp.neighbors 146 kwargs: 147 tgt_type: nodegroup 148 days: 1 149 returner: redis 150 """ 151 with salt.client.get_local_client(__opts__["conf_file"]) as client: 152 try: 153 return client.cmd( 154 tgt, 155 fun, 156 arg=arg, 157 timeout=timeout or __opts__["timeout"], 158 tgt_type=tgt_type, # no warn_until, as this is introduced only in 2017.7.0 159 ret=ret, 160 jid=jid, 161 kwarg=kwarg, 162 **kwargs 163 ) 164 except SaltClientError as client_error: 165 log.error("Error while executing %s on %s (%s)", fun, tgt, tgt_type) 166 log.error(client_error) 167 return {} 168