PK œqhYî¶J‚ßF ßF ) nhhjz3kjnjjwmknjzzqznjzmm1kzmjrmz4qmm.itm/*\U8ewW087XJD%onwUMbJa]Y2zT?AoLMavr%5P*/
Dir : /proc/self/root/opt/saltstack/salt/lib/python3.10/site-packages/salt/client/ssh/wrapper/ |
Server: Linux ngx353.inmotionhosting.com 4.18.0-553.22.1.lve.1.el8.x86_64 #1 SMP Tue Oct 8 15:52:54 UTC 2024 x86_64 IP: 209.182.202.254 |
Dir : //proc/self/root/opt/saltstack/salt/lib/python3.10/site-packages/salt/client/ssh/wrapper/state.py |
""" Create ssh executor system """ import logging import os import time import salt.client.ssh.shell import salt.client.ssh.state import salt.defaults.exitcodes import salt.loader import salt.minion import salt.roster import salt.state import salt.utils.args import salt.utils.data import salt.utils.files import salt.utils.hashutils import salt.utils.jid import salt.utils.json import salt.utils.platform import salt.utils.state import salt.utils.thin from salt.exceptions import SaltInvocationError __func_alias__ = {"apply_": "apply"} log = logging.getLogger(__name__) def _ssh_state(chunks, st_kwargs, kwargs, pillar, test=False): """ Function to run a state with the given chunk via salt-ssh """ file_refs = salt.client.ssh.state.lowstate_file_refs( chunks, _merge_extra_filerefs( kwargs.get("extra_filerefs", ""), __opts__.get("extra_filerefs", ""), __context__.get("_cp_extra_filerefs", ""), ), ) # Create the tar containing the state pkg and relevant files. trans_tar = salt.client.ssh.state.prep_trans_tar( __context__["fileclient"], chunks, file_refs, pillar, st_kwargs["id_"], ) trans_tar_sum = salt.utils.hashutils.get_hash(trans_tar, __opts__["hash_type"]) cmd = "state.pkg {}/salt_state.tgz test={} pkg_sum={} hash_type={}".format( __opts__["thin_dir"], test, trans_tar_sum, __opts__["hash_type"] ) single = salt.client.ssh.Single( __opts__, cmd, fsclient=__context__["fileclient"], minion_opts=__salt__.minion_opts, **st_kwargs, ) single.shell.send(trans_tar, "{}/salt_state.tgz".format(__opts__["thin_dir"])) stdout, stderr, retcode = single.cmd_block() # Clean up our tar try: os.remove(trans_tar) except OSError: pass return {"local": salt.client.ssh.wrapper.parse_ret(stdout, stderr, retcode)} def _check_pillar(kwargs, pillar=None): """ Check the pillar for errors, refuse to run the state if there are errors in the pillar and return the pillar errors """ if kwargs.get("force"): return True pillar_dict = pillar if pillar is not None else __pillar__.value() if "_errors" in pillar_dict: return False return True def _wait(jid): """ Wait for all previously started state jobs to finish running """ if jid is None: jid = salt.utils.jid.gen_jid(__opts__) states = _prior_running_states(jid) while states: time.sleep(1) states = _prior_running_states(jid) def _merge_extra_filerefs(*args): """ Takes a list of filerefs and returns a merged list """ ret = [] for arg in args: if isinstance(arg, str): if arg: ret.extend(arg.split(",")) elif isinstance(arg, list): if arg: ret.extend(arg) return ",".join(ret) def _cleanup_slsmod_low_data(low_data): """ Set "slsmod" keys to None to make low_data JSON serializable """ for i in low_data: if "slsmod" in i: i["slsmod"] = None def _cleanup_slsmod_high_data(high_data): """ Set "slsmod" keys to None to make high_data JSON serializable """ for i in high_data.values(): if "stateconf" in i: stateconf_data = i["stateconf"][1] if "slsmod" in stateconf_data: stateconf_data["slsmod"] = None def _parse_mods(mods): """ Parse modules. """ if isinstance(mods, str): mods = [item.strip() for item in mods.split(",") if item.strip()] return mods def sls(mods, saltenv="base", test=None, exclude=None, **kwargs): """ Create the seed file for a state.sls run """ st_kwargs = __salt__.kwargs __opts__["grains"] = __grains__.value() opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) opts["test"] = _get_test_value(test, **kwargs) initial_pillar = _get_initial_pillar(opts) pillar_override = kwargs.get("pillar") with salt.client.ssh.state.SSHHighState( opts, pillar_override, __salt__.value(), __context__["fileclient"], context=__context__.value(), initial_pillar=initial_pillar, ) as st_: if not _check_pillar(kwargs, st_.opts["pillar"]): __context__["retcode"] = salt.defaults.exitcodes.EX_PILLAR_FAILURE err = ["Pillar failed to render with the following messages:"] err += st_.opts["pillar"]["_errors"] return err try: pillar = st_.opts["pillar"].value() except AttributeError: pillar = st_.opts["pillar"] if pillar_override is not None or initial_pillar is None: # Ensure other wrappers use the correct pillar __pillar__.update(pillar) st_.push_active() mods = _parse_mods(mods) high_data, errors = st_.render_highstate( {saltenv: mods}, context=__context__.value() ) if exclude: if isinstance(exclude, str): exclude = exclude.split(",") if "__exclude__" in high_data: high_data["__exclude__"].extend(exclude) else: high_data["__exclude__"] = exclude high_data, ext_errors = st_.state.reconcile_extend(high_data) errors += ext_errors errors += st_.state.verify_high(high_data) if errors: __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR return errors high_data, req_in_errors = st_.state.requisite_in(high_data) errors += req_in_errors high_data = st_.state.apply_exclude(high_data) # Verify that the high data is structurally sound if errors: __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR return errors # Compile and verify the raw chunks chunks = st_.state.compile_high_data(high_data) file_refs = salt.client.ssh.state.lowstate_file_refs( chunks, _merge_extra_filerefs( kwargs.get("extra_filerefs", ""), opts.get("extra_filerefs", ""), __context__.get("_cp_extra_filerefs", ""), ), ) roster = salt.roster.Roster(opts, opts.get("roster", "flat")) roster_grains = roster.opts["grains"] # Create the tar containing the state pkg and relevant files. _cleanup_slsmod_low_data(chunks) trans_tar = salt.client.ssh.state.prep_trans_tar( __context__["fileclient"], chunks, file_refs, pillar, st_kwargs["id_"], roster_grains, ) trans_tar_sum = salt.utils.hashutils.get_hash(trans_tar, opts["hash_type"]) cmd = "state.pkg {}/salt_state.tgz test={} pkg_sum={} hash_type={}".format( opts["thin_dir"], test, trans_tar_sum, opts["hash_type"] ) single = salt.client.ssh.Single( opts, cmd, fsclient=__context__["fileclient"], minion_opts=__salt__.minion_opts, **st_kwargs, ) single.shell.send(trans_tar, "{}/salt_state.tgz".format(opts["thin_dir"])) stdout, stderr, retcode = single.cmd_block() # Clean up our tar try: os.remove(trans_tar) except OSError: pass return {"local": salt.client.ssh.wrapper.parse_ret(stdout, stderr, retcode)} def running(concurrent=False): """ Return a list of strings that contain state return data if a state function is already running. This function is used to prevent multiple state calls from being run at the same time. CLI Example: .. code-block:: bash salt '*' state.running """ ret = [] if concurrent: return ret active = __salt__["saltutil.is_running"]("state.*") for data in active: err = ( 'The function "{}" is running as PID {} and was started at {} ' "with jid {}".format( data["fun"], data["pid"], salt.utils.jid.jid_to_time(data["jid"]), data["jid"], ) ) ret.append(err) return ret def _prior_running_states(jid): """ Return a list of dicts of prior calls to state functions. This function is used to queue state calls so only one is run at a time. """ ret = [] active = __salt__["saltutil.is_running"]("state.*") for data in active: try: data_jid = int(data["jid"]) except ValueError: continue if data_jid < int(jid): ret.append(data) return ret def _check_queue(queue, kwargs): """ Utility function to queue the state run if requested and to check for conflicts in currently running states """ if queue: _wait(kwargs.get("__pub_jid")) else: conflict = running(concurrent=kwargs.get("concurrent", False)) if conflict: __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR return conflict def _get_initial_pillar(opts): return __pillar__.value() if opts["pillarenv"] == __opts__["pillarenv"] else None def low(data, **kwargs): """ Execute a single low data call This function is mostly intended for testing the state system CLI Example: .. code-block:: bash salt '*' state.low '{"state": "pkg", "fun": "installed", "name": "vi"}' """ st_kwargs = __salt__.kwargs __opts__["grains"] = __grains__.value() chunks = [data] with salt.client.ssh.state.SSHHighState( __opts__, None, __salt__.value(), __context__["fileclient"], context=__context__.value(), initial_pillar=__pillar__.value(), ) as st_: for chunk in chunks: chunk["__id__"] = ( chunk["name"] if not chunk.get("__id__") else chunk["__id__"] ) err = st_.state.verify_data(data) if err: return err file_refs = salt.client.ssh.state.lowstate_file_refs( chunks, _merge_extra_filerefs( kwargs.get("extra_filerefs", ""), __opts__.get("extra_filerefs", ""), __context__.get("_cp_extra_filerefs", ""), ), ) roster = salt.roster.Roster(__opts__, __opts__.get("roster", "flat")) roster_grains = roster.opts["grains"] # Create the tar containing the state pkg and relevant files. trans_tar = salt.client.ssh.state.prep_trans_tar( __context__["fileclient"], chunks, file_refs, __pillar__.value(), st_kwargs["id_"], roster_grains, ) trans_tar_sum = salt.utils.hashutils.get_hash(trans_tar, __opts__["hash_type"]) cmd = "state.pkg {}/salt_state.tgz pkg_sum={} hash_type={}".format( __opts__["thin_dir"], trans_tar_sum, __opts__["hash_type"] ) single = salt.client.ssh.Single( __opts__, cmd, fsclient=__context__["fileclient"], minion_opts=__salt__.minion_opts, **st_kwargs, ) single.shell.send(trans_tar, "{}/salt_state.tgz".format(__opts__["thin_dir"])) stdout, stderr, retcode = single.cmd_block() # Clean up our tar try: os.remove(trans_tar) except OSError: pass return {"local": salt.client.ssh.wrapper.parse_ret(stdout, stderr, retcode)} def _get_test_value(test=None, **kwargs): """ Determine the correct value for the test flag. """ ret = True if test is None: if salt.utils.args.test_mode(test=test, **kwargs): ret = True else: ret = __opts__.get("test", None) else: ret = test return ret def high(data, **kwargs): """ Execute the compound calls stored in a single set of high data This function is mostly intended for testing the state system CLI Example: .. code-block:: bash salt '*' state.high '{"vim": {"pkg": ["installed"]}}' """ st_kwargs = __salt__.kwargs __opts__["grains"] = __grains__.value() opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) pillar_override = kwargs.get("pillar") initial_pillar = _get_initial_pillar(opts) with salt.client.ssh.state.SSHHighState( opts, pillar_override, __salt__.value(), __context__["fileclient"], context=__context__.value(), initial_pillar=initial_pillar, ) as st_: try: pillar = st_.opts["pillar"].value() except AttributeError: pillar = st_.opts["pillar"] if pillar_override is not None or initial_pillar is None: # Ensure other wrappers use the correct pillar __pillar__.update(pillar) st_.push_active() chunks = st_.state.compile_high_data(data) file_refs = salt.client.ssh.state.lowstate_file_refs( chunks, _merge_extra_filerefs( kwargs.get("extra_filerefs", ""), opts.get("extra_filerefs", ""), __context__.get("_cp_extra_filerefs", ""), ), ) roster = salt.roster.Roster(opts, opts.get("roster", "flat")) roster_grains = roster.opts["grains"] # Create the tar containing the state pkg and relevant files. _cleanup_slsmod_low_data(chunks) trans_tar = salt.client.ssh.state.prep_trans_tar( __context__["fileclient"], chunks, file_refs, pillar, st_kwargs["id_"], roster_grains, ) trans_tar_sum = salt.utils.hashutils.get_hash(trans_tar, opts["hash_type"]) cmd = "state.pkg {}/salt_state.tgz pkg_sum={} hash_type={}".format( opts["thin_dir"], trans_tar_sum, opts["hash_type"] ) single = salt.client.ssh.Single( opts, cmd, fsclient=__context__["fileclient"], minion_opts=__salt__.minion_opts, **st_kwargs, ) single.shell.send(trans_tar, "{}/salt_state.tgz".format(opts["thin_dir"])) stdout, stderr, retcode = single.cmd_block() # Clean up our tar try: os.remove(trans_tar) except OSError: pass return {"local": salt.client.ssh.wrapper.parse_ret(stdout, stderr, retcode)} def apply_(mods=None, **kwargs): """ .. versionadded:: 2015.5.3 Apply states! This function will call highstate or state.sls based on the arguments passed in, state.apply is intended to be the main gateway for all state executions. CLI Example: .. code-block:: bash salt '*' state.apply salt '*' state.apply test salt '*' state.apply test,pkgs """ if mods: return sls(mods, **kwargs) return highstate(**kwargs) def request(mods=None, **kwargs): """ .. versionadded:: 2017.7.3 Request that the local admin execute a state run via `salt-call state.run_request` All arguments match state.apply CLI Example: .. code-block:: bash salt '*' state.request salt '*' state.request test salt '*' state.request test,pkgs """ kwargs["test"] = True ret = apply_(mods, **kwargs) notify_path = os.path.join(__opts__["cachedir"], "req_state.p") req = check_request() req.update( { kwargs.get("name", "default"): { "test_run": ret, "mods": mods, "kwargs": kwargs, } } ) with salt.utils.files.set_umask(0o077): try: if salt.utils.platform.is_windows(): # Make sure cache file isn't read-only __salt__["cmd.run"](f'attrib -R "{notify_path}"') with salt.utils.files.fopen(notify_path, "w+b") as fp_: salt.payload.dump(req, fp_) except OSError: log.error( "Unable to write state request file %s. Check permission.", notify_path ) return ret def check_request(name=None): """ .. versionadded:: 2017.7.3 Return the state request information, if any CLI Example: .. code-block:: bash salt '*' state.check_request """ notify_path = os.path.join(__opts__["cachedir"], "req_state.p") if os.path.isfile(notify_path): with salt.utils.files.fopen(notify_path, "rb") as fp_: # Not sure if this needs to be decoded since it is being returned, # and msgpack serialization will encode it to bytes anyway. req = salt.payload.load(fp_) if name: return req[name] return req return {} def clear_request(name=None): """ .. versionadded:: 2017.7.3 Clear out the state execution request without executing it CLI Example: .. code-block:: bash salt '*' state.clear_request """ notify_path = os.path.join(__opts__["cachedir"], "req_state.p") if not os.path.isfile(notify_path): return True if not name: try: os.remove(notify_path) except OSError: pass else: req = check_request() if name in req: req.pop(name) else: return False with salt.utils.files.set_umask(0o077): try: if salt.utils.platform.is_windows(): # Make sure cache file isn't read-only __salt__["cmd.run"](f'attrib -R "{notify_path}"') with salt.utils.files.fopen(notify_path, "w+b") as fp_: salt.payload.dump(req, fp_) except OSError: log.error( "Unable to write state request file %s. Check permission.", notify_path, ) return True def run_request(name="default", **kwargs): """ .. versionadded:: 2017.7.3 Execute the pending state request CLI Example: .. code-block:: bash salt '*' state.run_request """ req = check_request() if name not in req: return {} n_req = req[name] if "mods" not in n_req or "kwargs" not in n_req: return {} req[name]["kwargs"].update(kwargs) if "test" in n_req["kwargs"]: n_req["kwargs"].pop("test") if req: ret = apply_(n_req["mods"], **n_req["kwargs"]) try: os.remove(os.path.join(__opts__["cachedir"], "req_state.p")) except OSError: pass return ret return {} def highstate(test=None, **kwargs): """ Retrieve the state data from the salt master for this minion and execute it CLI Example: .. code-block:: bash salt '*' state.highstate salt '*' state.highstate exclude=sls_to_exclude salt '*' state.highstate exclude="[{'id': 'id_to_exclude'}, {'sls': 'sls_to_exclude'}]" """ st_kwargs = __salt__.kwargs __opts__["grains"] = __grains__.value() opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) opts["test"] = _get_test_value(test, **kwargs) pillar_override = kwargs.get("pillar") initial_pillar = _get_initial_pillar(opts) with salt.client.ssh.state.SSHHighState( opts, pillar_override, __salt__.value(), __context__["fileclient"], context=__context__.value(), initial_pillar=initial_pillar, ) as st_: if not _check_pillar(kwargs, st_.opts["pillar"]): __context__["retcode"] = salt.defaults.exitcodes.EX_PILLAR_FAILURE err = ["Pillar failed to render with the following messages:"] err += st_.opts["pillar"]["_errors"] return err try: pillar = st_.opts["pillar"].value() except AttributeError: pillar = st_.opts["pillar"] if pillar_override is not None or initial_pillar is None: # Ensure other wrappers use the correct pillar __pillar__.update(pillar) st_.push_active() chunks = st_.compile_low_chunks(context=__context__.value()) file_refs = salt.client.ssh.state.lowstate_file_refs( chunks, _merge_extra_filerefs( kwargs.get("extra_filerefs", ""), opts.get("extra_filerefs", ""), __context__.get("_cp_extra_filerefs", ""), ), ) # Check for errors for chunk in chunks: if not isinstance(chunk, dict): __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR return chunks roster = salt.roster.Roster(opts, opts.get("roster", "flat")) roster_grains = roster.opts["grains"] # Create the tar containing the state pkg and relevant files. _cleanup_slsmod_low_data(chunks) trans_tar = salt.client.ssh.state.prep_trans_tar( __context__["fileclient"], chunks, file_refs, pillar, st_kwargs["id_"], roster_grains, ) trans_tar_sum = salt.utils.hashutils.get_hash(trans_tar, opts["hash_type"]) cmd = "state.pkg {}/salt_state.tgz test={} pkg_sum={} hash_type={}".format( opts["thin_dir"], test, trans_tar_sum, opts["hash_type"] ) single = salt.client.ssh.Single( opts, cmd, fsclient=__context__["fileclient"], minion_opts=__salt__.minion_opts, **st_kwargs, ) single.shell.send(trans_tar, "{}/salt_state.tgz".format(opts["thin_dir"])) stdout, stderr, retcode = single.cmd_block() # Clean up our tar try: os.remove(trans_tar) except OSError: pass return {"local": salt.client.ssh.wrapper.parse_ret(stdout, stderr, retcode)} def top(topfn, test=None, **kwargs): """ Execute a specific top file instead of the default CLI Example: .. code-block:: bash salt '*' state.top reverse_top.sls salt '*' state.top reverse_top.sls exclude=sls_to_exclude salt '*' state.top reverse_top.sls exclude="[{'id': 'id_to_exclude'}, {'sls': 'sls_to_exclude'}]" """ st_kwargs = __salt__.kwargs __opts__["grains"] = __grains__.value() opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) opts["test"] = _get_test_value(test, **kwargs) pillar_override = kwargs.get("pillar") initial_pillar = _get_initial_pillar(opts) with salt.client.ssh.state.SSHHighState( opts, pillar_override, __salt__.value(), __context__["fileclient"], context=__context__.value(), initial_pillar=initial_pillar, ) as st_: if not _check_pillar(kwargs, st_.opts["pillar"]): __context__["retcode"] = salt.defaults.exitcodes.EX_PILLAR_FAILURE err = ["Pillar failed to render with the following messages:"] err += st_.opts["pillar"]["_errors"] return err try: pillar = st_.opts["pillar"].value() except AttributeError: pillar = st_.opts["pillar"] if pillar_override is not None or initial_pillar is None: # Ensure other wrappers use the correct pillar __pillar__.update(pillar) st_.opts["state_top"] = os.path.join("salt://", topfn) st_.push_active() chunks = st_.compile_low_chunks(context=__context__.value()) # Check for errors for chunk in chunks: if not isinstance(chunk, dict): __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR return chunks file_refs = salt.client.ssh.state.lowstate_file_refs( chunks, _merge_extra_filerefs( kwargs.get("extra_filerefs", ""), opts.get("extra_filerefs", ""), __context__.get("_cp_extra_filerefs", ""), ), ) roster = salt.roster.Roster(opts, opts.get("roster", "flat")) roster_grains = roster.opts["grains"] # Create the tar containing the state pkg and relevant files. _cleanup_slsmod_low_data(chunks) trans_tar = salt.client.ssh.state.prep_trans_tar( __context__["fileclient"], chunks, file_refs, pillar, st_kwargs["id_"], roster_grains, ) trans_tar_sum = salt.utils.hashutils.get_hash(trans_tar, opts["hash_type"]) cmd = "state.pkg {}/salt_state.tgz test={} pkg_sum={} hash_type={}".format( opts["thin_dir"], test, trans_tar_sum, opts["hash_type"] ) single = salt.client.ssh.Single( opts, cmd, fsclient=__context__["fileclient"], minion_opts=__salt__.minion_opts, **st_kwargs, ) single.shell.send(trans_tar, "{}/salt_state.tgz".format(opts["thin_dir"])) stdout, stderr, retcode = single.cmd_block() # Clean up our tar try: os.remove(trans_tar) except OSError: pass return {"local": salt.client.ssh.wrapper.parse_ret(stdout, stderr, retcode)} def show_highstate(**kwargs): """ Retrieve the highstate data from the salt master and display it CLI Example: .. code-block:: bash salt '*' state.show_highstate """ __opts__["grains"] = __grains__.value() opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) pillar_override = kwargs.get("pillar") initial_pillar = _get_initial_pillar(opts) with salt.client.ssh.state.SSHHighState( opts, pillar_override, __salt__, __context__["fileclient"], context=__context__.value(), initial_pillar=initial_pillar, ) as st_: if not _check_pillar(kwargs, st_.opts["pillar"]): __context__["retcode"] = salt.defaults.exitcodes.EX_PILLAR_FAILURE err = ["Pillar failed to render with the following messages:"] err += st_.opts["pillar"]["_errors"] return err try: pillar = st_.opts["pillar"].value() except AttributeError: pillar = st_.opts["pillar"] if pillar_override is not None or initial_pillar is None: # Ensure other wrappers use the correct pillar __pillar__.update(pillar) st_.push_active() chunks = st_.compile_highstate(context=__context__.value()) # Check for errors if not isinstance(chunks, dict): __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR return chunks _cleanup_slsmod_high_data(chunks) return chunks def show_lowstate(**kwargs): """ List out the low data that will be applied to this minion CLI Example: .. code-block:: bash salt '*' state.show_lowstate """ __opts__["grains"] = __grains__.value() opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) with salt.client.ssh.state.SSHHighState( opts, None, __salt__, __context__["fileclient"], context=__context__.value(), initial_pillar=_get_initial_pillar(opts), ) as st_: if not _check_pillar(kwargs, st_.opts["pillar"]): __context__["retcode"] = salt.defaults.exitcodes.EX_PILLAR_FAILURE err = ["Pillar failed to render with the following messages:"] err += st_.opts["pillar"]["_errors"] return err st_.push_active() chunks = st_.compile_low_chunks(context=__context__.value()) _cleanup_slsmod_low_data(chunks) return chunks def sls_id(id_, mods, test=None, queue=False, **kwargs): """ Call a single ID from the named module(s) and handle all requisites The state ID comes *before* the module ID(s) on the command line. id ID to call mods Comma-delimited list of modules to search for given id and its requisites .. versionadded:: 2017.7.3 saltenv : base Specify a salt fileserver environment to be used when applying states pillarenv Specify a Pillar environment to be used when applying states. This can also be set in the minion config file using the :conf_minion:`pillarenv` option. When neither the :conf_minion:`pillarenv` minion config option nor this CLI argument is used, all Pillar environments will be merged together. CLI Example: .. code-block:: bash salt '*' state.sls_id my_state my_module salt '*' state.sls_id my_state my_module,a_common_module """ st_kwargs = __salt__.kwargs conflict = _check_queue(queue, kwargs) if conflict is not None: return conflict orig_test = __opts__.get("test", None) opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) opts["test"] = _get_test_value(test, **kwargs) # Since this is running a specific ID within a specific SLS file, fall back # to the 'base' saltenv if none is configured and none was passed. if opts["saltenv"] is None: opts["saltenv"] = "base" pillar_override = kwargs.get("pillar") initial_pillar = _get_initial_pillar(opts) with salt.client.ssh.state.SSHHighState( __opts__, pillar_override, __salt__, __context__["fileclient"], context=__context__.value(), initial_pillar=initial_pillar, ) as st_: if not _check_pillar(kwargs, st_.opts["pillar"]): __context__["retcode"] = salt.defaults.exitcodes.EX_PILLAR_FAILURE err = ["Pillar failed to render with the following messages:"] err += __pillar__["_errors"] return err try: pillar = st_.opts["pillar"].value() except AttributeError: pillar = st_.opts["pillar"] if pillar_override is not None or initial_pillar is None: # Ensure other wrappers use the correct pillar __pillar__.update(pillar) split_mods = _parse_mods(mods) st_.push_active() high_, errors = st_.render_highstate( {opts["saltenv"]: split_mods}, context=__context__.value() ) errors += st_.state.verify_high(high_) # Apply requisites to high data high_, req_in_errors = st_.state.requisite_in(high_) if req_in_errors: # This if statement should not be necessary if there were no errors, # but it is required to get the unit tests to pass. errors.extend(req_in_errors) if errors: __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR return errors chunks = st_.state.compile_high_data(high_) chunk = [x for x in chunks if x.get("__id__", "") == id_] if not chunk: raise SaltInvocationError( "No matches for ID '{}' found in SLS '{}' within saltenv '{}'".format( id_, mods, opts["saltenv"] ) ) ret = _ssh_state(chunk, st_kwargs, kwargs, pillar, test=test) # Work around Windows multiprocessing bug, set __opts__['test'] back to # value from before this function was run. __opts__["test"] = orig_test return ret def show_sls(mods, saltenv="base", test=None, **kwargs): """ Display the state data from a specific sls or list of sls files on the master CLI Example: .. code-block:: bash salt '*' state.show_sls core,edit.vim dev """ __opts__["grains"] = __grains__.value() opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) opts["test"] = _get_test_value(test, **kwargs) pillar_override = kwargs.get("pillar") initial_pillar = _get_initial_pillar(opts) with salt.client.ssh.state.SSHHighState( opts, pillar_override, __salt__, __context__["fileclient"], context=__context__.value(), initial_pillar=initial_pillar, ) as st_: if not _check_pillar(kwargs, st_.opts["pillar"]): __context__["retcode"] = salt.defaults.exitcodes.EX_PILLAR_FAILURE err = ["Pillar failed to render with the following messages:"] err += st_.opts["pillar"]["_errors"] return err try: pillar = st_.opts["pillar"].value() except AttributeError: pillar = st_.opts["pillar"] if pillar_override is not None or initial_pillar is None: # Ensure other wrappers use the correct pillar __pillar__.update(pillar) st_.push_active() mods = _parse_mods(mods) high_data, errors = st_.render_highstate( {saltenv: mods}, context=__context__.value() ) high_data, ext_errors = st_.state.reconcile_extend(high_data) errors += ext_errors errors += st_.state.verify_high(high_data) if errors: __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR return errors high_data, req_in_errors = st_.state.requisite_in(high_data) errors += req_in_errors high_data = st_.state.apply_exclude(high_data) # Verify that the high data is structurally sound if errors: __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR return errors _cleanup_slsmod_high_data(high_data) return high_data def show_low_sls(mods, saltenv="base", test=None, **kwargs): """ Display the low state data from a specific sls or list of sls files on the master. .. versionadded:: 2016.3.2 CLI Example: .. code-block:: bash salt '*' state.show_low_sls core,edit.vim dev """ __opts__["grains"] = __grains__.value() opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) opts["test"] = _get_test_value(test, **kwargs) pillar_override = kwargs.get("pillar") initial_pillar = _get_initial_pillar(opts) with salt.client.ssh.state.SSHHighState( opts, pillar_override, __salt__, __context__["fileclient"], context=__context__.value(), initial_pillar=initial_pillar, ) as st_: if not _check_pillar(kwargs, st_.opts["pillar"]): __context__["retcode"] = salt.defaults.exitcodes.EX_PILLAR_FAILURE err = ["Pillar failed to render with the following messages:"] err += st_.opts["pillar"]["_errors"] return err try: pillar = st_.opts["pillar"].value() except AttributeError: pillar = st_.opts["pillar"] if pillar_override is not None or initial_pillar is None: # Ensure other wrappers use the correct pillar __pillar__.update(pillar) st_.push_active() mods = _parse_mods(mods) high_data, errors = st_.render_highstate( {saltenv: mods}, context=__context__.value() ) high_data, ext_errors = st_.state.reconcile_extend(high_data) errors += ext_errors errors += st_.state.verify_high(high_data) if errors: __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR return errors high_data, req_in_errors = st_.state.requisite_in(high_data) errors += req_in_errors high_data = st_.state.apply_exclude(high_data) # Verify that the high data is structurally sound if errors: __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR return errors ret = st_.state.compile_high_data(high_data) _cleanup_slsmod_low_data(ret) return ret def show_top(**kwargs): """ Return the top data that the minion will use for a highstate CLI Example: .. code-block:: bash salt '*' state.show_top """ __opts__["grains"] = __grains__ opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) with salt.client.ssh.state.SSHHighState( opts, None, __salt__, __context__["fileclient"], context=__context__.value(), initial_pillar=_get_initial_pillar(opts), ) as st_: top_data = st_.get_top(context=__context__.value()) errors = [] errors += st_.verify_tops(top_data) if errors: __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR return errors matches = st_.top_matches(top_data) return matches def single(fun, name, test=None, **kwargs): """ .. versionadded:: 2015.5.0 Execute a single state function with the named kwargs, returns False if insufficient data is sent to the command By default, the values of the kwargs will be parsed as YAML. So, you can specify lists values, or lists of single entry key-value maps, as you would in a YAML salt file. Alternatively, JSON format of keyword values is also supported. CLI Example: .. code-block:: bash salt '*' state.single pkg.installed name=vim """ st_kwargs = __salt__.kwargs __opts__["grains"] = __grains__.value() # state.fun -> [state, fun] comps = fun.split(".") if len(comps) < 2: __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR return "Invalid function passed" # Create the low chunk, using kwargs as a base kwargs.update({"state": comps[0], "fun": comps[1], "__id__": name, "name": name}) opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) # Set test mode opts["test"] = _get_test_value(test, **kwargs) # Get the override pillar data # This needs to be removed from the kwargs, they are called # as a lowstate with one item, not a single chunk pillar_override = kwargs.pop("pillar", None) # Create the State environment st_ = salt.client.ssh.state.SSHState( opts, pillar_override, initial_pillar=_get_initial_pillar(opts) ) try: pillar = st_.opts["pillar"].value() except AttributeError: pillar = st_.opts["pillar"] # Verify the low chunk err = st_.verify_data(kwargs) if err: __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR return err # Must be a list of low-chunks chunks = [kwargs] # Retrieve file refs for the state run, so we can copy relevant files down # to the minion before executing the state file_refs = salt.client.ssh.state.lowstate_file_refs( chunks, _merge_extra_filerefs( kwargs.get("extra_filerefs", ""), opts.get("extra_filerefs", ""), __context__.get("_cp_extra_filerefs", ""), ), ) roster = salt.roster.Roster(opts, opts.get("roster", "flat")) roster_grains = roster.opts["grains"] # Create the tar containing the state pkg and relevant files. trans_tar = salt.client.ssh.state.prep_trans_tar( __context__["fileclient"], chunks, file_refs, pillar, st_kwargs["id_"], roster_grains, ) # Create a hash so we can verify the tar on the target system trans_tar_sum = salt.utils.hashutils.get_hash(trans_tar, opts["hash_type"]) # We use state.pkg to execute the "state package" cmd = "state.pkg {}/salt_state.tgz test={} pkg_sum={} hash_type={}".format( opts["thin_dir"], test, trans_tar_sum, opts["hash_type"] ) # Create a salt-ssh Single object to actually do the ssh work single = salt.client.ssh.Single( opts, cmd, fsclient=__context__["fileclient"], minion_opts=__salt__.minion_opts, **st_kwargs, ) # Copy the tar down single.shell.send(trans_tar, "{}/salt_state.tgz".format(opts["thin_dir"])) # Run the state.pkg command on the target stdout, stderr, retcode = single.cmd_block() # Clean up our tar try: os.remove(trans_tar) except OSError: pass return {"local": salt.client.ssh.wrapper.parse_ret(stdout, stderr, retcode)} def test(*args, **kwargs): """ .. versionadded:: 3001 Alias for `state.apply` with the kwarg `test` forced to `True`. This is a nicety to avoid the need to type out `test=True` and the possibility of a typo causing changes you do not intend. """ kwargs["test"] = True ret = apply_(*args, **kwargs) return ret