module.py (salt-3002.1) | : | module.py (salt-3002.2) | ||
---|---|---|---|---|
# -*- coding: utf-8 -*- | ||||
r""" | r""" | |||
Execution of Salt modules from within states | Execution of Salt modules from within states | |||
============================================ | ============================================ | |||
.. note:: | .. note:: | |||
There are two styles of calling ``module.run``. **The legacy style will no | There are two styles of calling ``module.run``. **The legacy style will no | |||
longer be available starting in the 3005 release.** To opt-in early to the | longer be available starting in the 3005 release.** To opt-in early to the | |||
new style you must add the following to your ``/etc/salt/minion`` config | new style you must add the following to your ``/etc/salt/minion`` config | |||
file: | file: | |||
skipping to change at line 303 | skipping to change at line 302 | |||
- kwargs: { | - kwargs: { | |||
action_type: 'Execute', | action_type: 'Execute', | |||
cmd: 'c:\netops\scripts\events_viewer.bat', | cmd: 'c:\netops\scripts\events_viewer.bat', | |||
trigger_type: 'Daily', | trigger_type: 'Daily', | |||
start_date: '2017-1-20', | start_date: '2017-1-20', | |||
start_time: '11:59PM' | start_time: '11:59PM' | |||
} | } | |||
.. _file_roots: https://docs.saltstack.com/en/latest/ref/configuration/master.ht ml#file-roots | .. _file_roots: https://docs.saltstack.com/en/latest/ref/configuration/master.ht ml#file-roots | |||
""" | """ | |||
from __future__ import absolute_import, print_function, unicode_literals | ||||
# Import salt libs | ||||
import salt.loader | import salt.loader | |||
import salt.utils.args | import salt.utils.args | |||
import salt.utils.functools | import salt.utils.functools | |||
import salt.utils.jid | import salt.utils.jid | |||
from salt.exceptions import SaltInvocationError | from salt.exceptions import SaltInvocationError | |||
from salt.ext import six | ||||
from salt.ext.six.moves import range | from salt.ext.six.moves import range | |||
from salt.utils.decorators import with_deprecated | from salt.utils.decorators import with_deprecated | |||
def wait(name, **kwargs): | def wait(name, **kwargs): | |||
""" | """ | |||
Run a single module function only if the watch statement calls it | Run a single module function only if the watch statement calls it | |||
``name`` | ``name`` | |||
The module function to execute | The module function to execute | |||
skipping to change at line 427 | skipping to change at line 423 | |||
success = [] | success = [] | |||
for func in functions: | for func in functions: | |||
_func = func.split(":")[0] | _func = func.split(":")[0] | |||
try: | try: | |||
func_ret = _call_function( | func_ret = _call_function( | |||
_func, returner=kwargs.get("returner"), func_args=kwargs.get (func) | _func, returner=kwargs.get("returner"), func_args=kwargs.get (func) | |||
) | ) | |||
if not _get_result(func_ret, ret["changes"].get("ret", {})): | if not _get_result(func_ret, ret["changes"].get("ret", {})): | |||
if isinstance(func_ret, dict): | if isinstance(func_ret, dict): | |||
failures.append( | failures.append( | |||
"'{0}' failed: {1}".format( | "'{}' failed: {}".format( | |||
func, func_ret.get("comment", "(error message N/ A)") | func, func_ret.get("comment", "(error message N/ A)") | |||
) | ) | |||
) | ) | |||
if func_ret is False: | ||||
failures.append("'{}': {}".format(func, func_ret)) | ||||
else: | else: | |||
success.append( | success.append( | |||
"{0}: {1}".format( | "{}: {}".format( | |||
func, | func, | |||
func_ret.get("comment", "Success") | func_ret.get("comment", "Success") | |||
if isinstance(func_ret, dict) | if isinstance(func_ret, dict) | |||
else func_ret, | else func_ret, | |||
) | ) | |||
) | ) | |||
ret["changes"][func] = func_ret | ret["changes"][func] = func_ret | |||
except (SaltInvocationError, TypeError) as ex: | except (SaltInvocationError, TypeError) as ex: | |||
failures.append("'{0}' failed: {1}".format(func, ex)) | failures.append("'{}' failed: {}".format(func, ex)) | |||
ret["comment"] = ", ".join(failures + success) | ret["comment"] = ", ".join(failures + success) | |||
ret["result"] = not bool(failures) | ret["result"] = not bool(failures) | |||
return ret | return ret | |||
def _call_function(name, returner=None, func_args=None, func_kwargs=None): | def _call_function(name, returner=None, func_args=None, func_kwargs=None): | |||
""" | """ | |||
Calls a function from the specified module. | Calls a function from the specified module. | |||
:param str name: module.function of the function to call | :param str name: module.function of the function to call | |||
skipping to change at line 496 | skipping to change at line 494 | |||
The module function to execute | The module function to execute | |||
``returner`` | ``returner`` | |||
Specify the returner to send the return of the module execution to | Specify the returner to send the return of the module execution to | |||
``kwargs`` | ``kwargs`` | |||
Pass any arguments needed to execute the function | Pass any arguments needed to execute the function | |||
""" | """ | |||
ret = {"name": name, "changes": {}, "comment": "", "result": None} | ret = {"name": name, "changes": {}, "comment": "", "result": None} | |||
if name not in __salt__: | if name not in __salt__: | |||
ret["comment"] = "Module function {0} is not available".format(name) | ret["comment"] = "Module function {} is not available".format(name) | |||
ret["result"] = False | ret["result"] = False | |||
return ret | return ret | |||
if __opts__["test"]: | if __opts__["test"]: | |||
ret["comment"] = "Module function {0} is set to execute".format(name) | ret["comment"] = "Module function {} is set to execute".format(name) | |||
return ret | return ret | |||
aspec = salt.utils.args.get_function_argspec(__salt__[name]) | aspec = salt.utils.args.get_function_argspec(__salt__[name]) | |||
args = [] | args = [] | |||
defaults = {} | defaults = {} | |||
arglen = 0 | arglen = 0 | |||
deflen = 0 | deflen = 0 | |||
if isinstance(aspec.args, list): | if isinstance(aspec.args, list): | |||
arglen = len(aspec.args) | arglen = len(aspec.args) | |||
skipping to change at line 559 | skipping to change at line 557 | |||
if rarg not in kwargs and arg not in defaults: | if rarg not in kwargs and arg not in defaults: | |||
missing.add(rarg) | missing.add(rarg) | |||
continue | continue | |||
if arg in defaults: | if arg in defaults: | |||
args.append(defaults[arg]) | args.append(defaults[arg]) | |||
else: | else: | |||
args.append(kwargs.pop(rarg)) | args.append(kwargs.pop(rarg)) | |||
if missing: | if missing: | |||
comment = "The following arguments are missing:" | comment = "The following arguments are missing:" | |||
for arg in missing: | for arg in missing: | |||
comment += " {0}".format(arg) | comment += " {}".format(arg) | |||
ret["comment"] = comment | ret["comment"] = comment | |||
ret["result"] = False | ret["result"] = False | |||
return ret | return ret | |||
if aspec.varargs: | if aspec.varargs: | |||
if aspec.varargs == "name": | if aspec.varargs == "name": | |||
rarg = "m_name" | rarg = "m_name" | |||
elif aspec.varargs == "fun": | elif aspec.varargs == "fun": | |||
rarg = "m_fun" | rarg = "m_fun" | |||
elif aspec.varargs == "names": | elif aspec.varargs == "names": | |||
skipping to change at line 604 | skipping to change at line 602 | |||
ret["comment"] = msg.format(aspec.keywords) | ret["comment"] = msg.format(aspec.keywords) | |||
ret["result"] = False | ret["result"] = False | |||
return ret | return ret | |||
try: | try: | |||
if aspec.keywords: | if aspec.keywords: | |||
mret = __salt__[name](*args, **nkwargs) | mret = __salt__[name](*args, **nkwargs) | |||
else: | else: | |||
mret = __salt__[name](*args) | mret = __salt__[name](*args) | |||
except Exception as e: # pylint: disable=broad-except | except Exception as e: # pylint: disable=broad-except | |||
ret[ | ret["comment"] = "Module function {} threw an exception. Exception: {}". | |||
"comment" | format( | |||
] = "Module function {0} threw an exception. Exception: {1}".format(name | name, e | |||
, e) | ) | |||
ret["result"] = False | ret["result"] = False | |||
return ret | return ret | |||
else: | else: | |||
if mret is not None or mret != {}: | if mret is not None or mret != {}: | |||
ret["changes"]["ret"] = mret | ret["changes"]["ret"] = mret | |||
if "returner" in kwargs: | if "returner" in kwargs: | |||
ret_ret = { | ret_ret = { | |||
"id": __opts__["id"], | "id": __opts__["id"], | |||
"ret": mret, | "ret": mret, | |||
"fun": name, | "fun": name, | |||
"jid": salt.utils.jid.gen_jid(__opts__), | "jid": salt.utils.jid.gen_jid(__opts__), | |||
} | } | |||
returners = salt.loader.returners(__opts__, __salt__) | returners = salt.loader.returners(__opts__, __salt__) | |||
if kwargs["returner"] in returners: | if kwargs["returner"] in returners: | |||
returners[kwargs["returner"]](ret_ret) | returners[kwargs["returner"]](ret_ret) | |||
ret["comment"] = "Module function {0} executed".format(name) | ret["comment"] = "Module function {} executed".format(name) | |||
ret["result"] = _get_result(mret, ret["changes"]) | ret["result"] = _get_result(mret, ret["changes"]) | |||
return ret | return ret | |||
def _get_result(func_ret, changes): | def _get_result(func_ret, changes): | |||
res = True | res = True | |||
# if mret is a dict and there is retcode and its non-zero | # if mret is a dict and there is retcode and its non-zero | |||
if isinstance(func_ret, dict) and func_ret.get("retcode", 0) != 0: | if isinstance(func_ret, dict) and func_ret.get("retcode", 0) != 0: | |||
res = False | res = False | |||
# if its a boolean, return that as the result | # if its a boolean, return that as the result | |||
skipping to change at line 653 | skipping to change at line 651 | |||
# Explore dict in depth to determine if there is a | # Explore dict in depth to determine if there is a | |||
# 'result' key set to False which sets the global | # 'result' key set to False which sets the global | |||
# state result. | # state result. | |||
else: | else: | |||
res = _get_dict_result(changes_ret) | res = _get_dict_result(changes_ret) | |||
return res | return res | |||
def _get_dict_result(node): | def _get_dict_result(node): | |||
ret = True | ret = True | |||
for key, val in six.iteritems(node): | for key, val in node.items(): | |||
if key == "result" and val is False: | if key == "result" and val is False: | |||
ret = False | ret = False | |||
break | break | |||
elif isinstance(val, dict): | elif isinstance(val, dict): | |||
ret = _get_dict_result(val) | ret = _get_dict_result(val) | |||
if ret is False: | if ret is False: | |||
break | break | |||
return ret | return ret | |||
mod_watch = salt.utils.functools.alias_function(run, "mod_watch") | mod_watch = salt.utils.functools.alias_function(run, "mod_watch") | |||
End of changes. 14 change blocks. | ||||
16 lines changed or deleted | 14 lines changed or added |