1""" 2Control the state system on the minion. 3 4State Caching 5------------- 6 7When a highstate is called, the minion automatically caches a copy of the last 8high data. If you then run a highstate with cache=True it will use that cached 9highdata and won't hit the fileserver except for ``salt://`` links in the 10states themselves. 11""" 12 13import logging 14import os 15import shutil 16import sys 17import tarfile 18import tempfile 19import time 20 21import salt.config 22import salt.defaults.exitcodes 23import salt.payload 24import salt.state 25import salt.utils.args 26import salt.utils.data 27import salt.utils.event 28import salt.utils.files 29import salt.utils.functools 30import salt.utils.hashutils 31import salt.utils.jid 32import salt.utils.json 33import salt.utils.msgpack 34import salt.utils.platform 35import salt.utils.state 36import salt.utils.stringutils 37import salt.utils.url 38import salt.utils.versions 39from salt.exceptions import CommandExecutionError, SaltInvocationError 40from salt.loader import _format_cached_grains 41from salt.runners.state import orchestrate as _orchestrate 42from salt.utils.odict import OrderedDict 43 44__proxyenabled__ = ["*"] 45 46__outputter__ = { 47 "sls": "highstate", 48 "sls_id": "highstate", 49 "pkg": "highstate", 50 "top": "highstate", 51 "single": "highstate", 52 "highstate": "highstate", 53 "template": "highstate", 54 "template_str": "highstate", 55 "apply_": "highstate", 56 "test": "highstate", 57 "request": "highstate", 58 "check_request": "highstate", 59 "run_request": "highstate", 60} 61 62__func_alias__ = {"apply_": "apply"} 63log = logging.getLogger(__name__) 64 65# Define the module's virtual name 66__virtualname__ = "state" 67 68 69def __virtual__(): 70 """ 71 Set the virtualname 72 """ 73 # Update global namespace with functions that are cloned in this module 74 global _orchestrate 75 _orchestrate = salt.utils.functools.namespaced_function(_orchestrate, globals()) 76 77 return __virtualname__ 78 79 80def _filter_running(runnings): 81 """ 82 Filter out the result: True + no changes data 83 """ 84 ret = { 85 tag: value 86 for tag, value in runnings.items() 87 if not value["result"] or value["changes"] 88 } 89 return ret 90 91 92def _set_retcode(ret, highstate=None): 93 """ 94 Set the return code based on the data back from the state system 95 """ 96 97 # Set default retcode to 0 98 __context__["retcode"] = salt.defaults.exitcodes.EX_OK 99 100 if isinstance(ret, list): 101 __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR 102 return 103 if not __utils__["state.check_result"](ret, highstate=highstate): 104 __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_FAILURE 105 106 107def _get_pillar_errors(kwargs, pillar=None): 108 """ 109 Checks all pillars (external and internal) for errors. 110 Return an error message, if anywhere or None. 111 112 :param kwargs: dictionary of options 113 :param pillar: external pillar 114 :return: None or an error message 115 """ 116 return ( 117 None 118 if kwargs.get("force") 119 else (pillar or {}).get("_errors", __pillar__.get("_errors")) or None 120 ) 121 122 123def _wait(jid): 124 """ 125 Wait for all previously started state jobs to finish running 126 """ 127 if jid is None: 128 jid = salt.utils.jid.gen_jid(__opts__) 129 states = _prior_running_states(jid) 130 while states: 131 time.sleep(1) 132 states = _prior_running_states(jid) 133 134 135def _snapper_pre(opts, jid): 136 """ 137 Create a snapper pre snapshot 138 """ 139 snapper_pre = None 140 try: 141 if not opts["test"] and __opts__.get("snapper_states"): 142 # Run the snapper pre snapshot 143 snapper_pre = __salt__["snapper.create_snapshot"]( 144 config=__opts__.get("snapper_states_config", "root"), 145 snapshot_type="pre", 146 description="Salt State run for jid {}".format(jid), 147 __pub_jid=jid, 148 ) 149 except Exception: # pylint: disable=broad-except 150 log.error("Failed to create snapper pre snapshot for jid: %s", jid) 151 return snapper_pre 152 153 154def _snapper_post(opts, jid, pre_num): 155 """ 156 Create the post states snapshot 157 """ 158 try: 159 if not opts["test"] and __opts__.get("snapper_states") and pre_num: 160 # Run the snapper pre snapshot 161 __salt__["snapper.create_snapshot"]( 162 config=__opts__.get("snapper_states_config", "root"), 163 snapshot_type="post", 164 pre_number=pre_num, 165 description="Salt State run for jid {}".format(jid), 166 __pub_jid=jid, 167 ) 168 except Exception: # pylint: disable=broad-except 169 log.error("Failed to create snapper pre snapshot for jid: %s", jid) 170 171 172def _get_pause(jid, state_id=None): 173 """ 174 Return the pause information for a given jid 175 """ 176 pause_dir = os.path.join(__opts__["cachedir"], "state_pause") 177 pause_path = os.path.join(pause_dir, jid) 178 if not os.path.exists(pause_dir): 179 try: 180 os.makedirs(pause_dir) 181 except OSError: 182 # File created in the gap 183 pass 184 data = {} 185 if state_id is not None: 186 if state_id not in data: 187 data[state_id] = {} 188 if os.path.exists(pause_path): 189 with salt.utils.files.fopen(pause_path, "rb") as fp_: 190 data = salt.utils.msgpack.loads(fp_.read()) 191 return data, pause_path 192 193 194def get_pauses(jid=None): 195 """ 196 Get a report on all of the currently paused state runs and pause 197 run settings. 198 Optionally send in a jid if you only desire to see a single pause 199 data set. 200 """ 201 ret = {} 202 active = __salt__["saltutil.is_running"]("state.*") 203 pause_dir = os.path.join(__opts__["cachedir"], "state_pause") 204 if not os.path.exists(pause_dir): 205 return ret 206 if jid is None: 207 jids = os.listdir(pause_dir) 208 elif isinstance(jid, list): 209 jids = salt.utils.data.stringify(jid) 210 else: 211 jids = [str(jid)] 212 for scan_jid in jids: 213 is_active = False 214 for active_data in active: 215 if active_data["jid"] == scan_jid: 216 is_active = True 217 if not is_active: 218 try: 219 pause_path = os.path.join(pause_dir, scan_jid) 220 os.remove(pause_path) 221 except OSError: 222 # Already gone 223 pass 224 continue 225 data, pause_path = _get_pause(scan_jid) 226 ret[scan_jid] = data 227 return ret 228 229 230def soft_kill(jid, state_id=None): 231 """ 232 Set up a state run to die before executing the given state id, 233 this instructs a running state to safely exit at a given 234 state id. This needs to pass in the jid of the running state. 235 If a state_id is not passed then the jid referenced will be safely exited 236 at the beginning of the next state run. 237 238 The given state id is the id got a given state execution, so given a state 239 that looks like this: 240 241 .. code-block:: yaml 242 243 vim: 244 pkg.installed: [] 245 246 The state_id to pass to `soft_kill` is `vim` 247 248 CLI Examples: 249 250 .. code-block:: bash 251 252 salt '*' state.soft_kill 20171130110407769519 253 salt '*' state.soft_kill 20171130110407769519 vim 254 """ 255 jid = str(jid) 256 if state_id is None: 257 state_id = "__all__" 258 data, pause_path = _get_pause(jid, state_id) 259 data[state_id]["kill"] = True 260 with salt.utils.files.fopen(pause_path, "wb") as fp_: 261 fp_.write(salt.utils.msgpack.dumps(data)) 262 263 264def pause(jid, state_id=None, duration=None): 265 """ 266 Set up a state id pause, this instructs a running state to pause at a given 267 state id. This needs to pass in the jid of the running state and can 268 optionally pass in a duration in seconds. If a state_id is not passed then 269 the jid referenced will be paused at the beginning of the next state run. 270 271 The given state id is the id got a given state execution, so given a state 272 that looks like this: 273 274 .. code-block:: yaml 275 276 vim: 277 pkg.installed: [] 278 279 The state_id to pass to `pause` is `vim` 280 281 CLI Examples: 282 283 .. code-block:: bash 284 285 salt '*' state.pause 20171130110407769519 286 salt '*' state.pause 20171130110407769519 vim 287 salt '*' state.pause 20171130110407769519 vim 20 288 """ 289 jid = str(jid) 290 if state_id is None: 291 state_id = "__all__" 292 data, pause_path = _get_pause(jid, state_id) 293 if duration: 294 data[state_id]["duration"] = int(duration) 295 with salt.utils.files.fopen(pause_path, "wb") as fp_: 296 fp_.write(salt.utils.msgpack.dumps(data)) 297 298 299def resume(jid, state_id=None): 300 """ 301 Remove a pause from a jid, allowing it to continue. If the state_id is 302 not specified then the a general pause will be resumed. 303 304 The given state_id is the id got a given state execution, so given a state 305 that looks like this: 306 307 .. code-block:: yaml 308 309 vim: 310 pkg.installed: [] 311 312 The state_id to pass to `rm_pause` is `vim` 313 314 CLI Examples: 315 316 .. code-block:: bash 317 318 salt '*' state.resume 20171130110407769519 319 salt '*' state.resume 20171130110407769519 vim 320 """ 321 jid = str(jid) 322 if state_id is None: 323 state_id = "__all__" 324 data, pause_path = _get_pause(jid, state_id) 325 if state_id in data: 326 data.pop(state_id) 327 if state_id == "__all__": 328 data = {} 329 with salt.utils.files.fopen(pause_path, "wb") as fp_: 330 fp_.write(salt.utils.msgpack.dumps(data)) 331 332 333def orchestrate( 334 mods, saltenv="base", test=None, exclude=None, pillar=None, pillarenv=None 335): 336 """ 337 .. versionadded:: 2016.11.0 338 339 Execute the orchestrate runner from a masterless minion. 340 341 .. seealso:: More Orchestrate documentation 342 343 * :ref:`Full Orchestrate Tutorial <orchestrate-runner>` 344 * Docs for the salt state module :py:mod:`salt.states.saltmod` 345 346 CLI Examples: 347 348 .. code-block:: bash 349 350 salt-call --local state.orchestrate webserver 351 salt-call --local state.orchestrate webserver saltenv=dev test=True 352 salt-call --local state.orchestrate webserver saltenv=dev pillarenv=aws 353 """ 354 return _orchestrate( 355 mods=mods, 356 saltenv=saltenv, 357 test=test, 358 exclude=exclude, 359 pillar=pillar, 360 pillarenv=pillarenv, 361 ) 362 363 364def running(concurrent=False): 365 """ 366 Return a list of strings that contain state return data if a state function 367 is already running. This function is used to prevent multiple state calls 368 from being run at the same time. 369 370 CLI Example: 371 372 .. code-block:: bash 373 374 salt '*' state.running 375 """ 376 ret = [] 377 if concurrent: 378 return ret 379 active = __salt__["saltutil.is_running"]("state.*") 380 for data in active: 381 err = ( 382 'The function "{}" is running as PID {} and was started at {} ' 383 "with jid {}".format( 384 data["fun"], 385 data["pid"], 386 salt.utils.jid.jid_to_time(data["jid"]), 387 data["jid"], 388 ) 389 ) 390 ret.append(err) 391 return ret 392 393 394def _prior_running_states(jid): 395 """ 396 Return a list of dicts of prior calls to state functions. This function is 397 used to queue state calls so only one is run at a time. 398 """ 399 400 ret = [] 401 active = __salt__["saltutil.is_running"]("state.*") 402 for data in active: 403 try: 404 data_jid = int(data["jid"]) 405 except ValueError: 406 continue 407 if data_jid < int(jid): 408 ret.append(data) 409 return ret 410 411 412def _check_queue(queue, kwargs): 413 """ 414 Utility function to queue the state run if requested 415 and to check for conflicts in currently running states 416 """ 417 if queue: 418 _wait(kwargs.get("__pub_jid")) 419 else: 420 conflict = running(concurrent=kwargs.get("concurrent", False)) 421 if conflict: 422 __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR 423 return conflict 424 425 426def _get_initial_pillar(opts): 427 return ( 428 __pillar__.value() 429 if __opts__.get("__cli", None) == "salt-call" 430 and opts["pillarenv"] == __opts__["pillarenv"] 431 else None 432 ) 433 434 435def low(data, queue=False, **kwargs): 436 """ 437 Execute a single low data call 438 439 This function is mostly intended for testing the state system and is not 440 likely to be needed in everyday usage. 441 442 CLI Example: 443 444 .. code-block:: bash 445 446 salt '*' state.low '{"state": "pkg", "fun": "installed", "name": "vi"}' 447 """ 448 conflict = _check_queue(queue, kwargs) 449 if conflict is not None: 450 return conflict 451 try: 452 st_ = salt.state.State(__opts__, proxy=__proxy__) 453 except NameError: 454 st_ = salt.state.State(__opts__) 455 err = st_.verify_data(data) 456 if err: 457 __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR 458 return err 459 ret = st_.call(data) 460 if isinstance(ret, list): 461 __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR 462 if __utils__["state.check_result"](ret): 463 __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_FAILURE 464 return ret 465 466 467def _get_test_value(test=None, **kwargs): 468 """ 469 Determine the correct value for the test flag. 470 """ 471 ret = True 472 if test is None: 473 if salt.utils.args.test_mode(test=test, **kwargs): 474 ret = True 475 elif __salt__["config.get"]("test", omit_opts=True) is True: 476 ret = True 477 else: 478 ret = __opts__.get("test", None) 479 else: 480 ret = test 481 return ret 482 483 484def high(data, test=None, queue=False, **kwargs): 485 """ 486 Execute the compound calls stored in a single set of high data 487 488 This function is mostly intended for testing the state system and is not 489 likely to be needed in everyday usage. 490 491 CLI Example: 492 493 .. code-block:: bash 494 495 salt '*' state.high '{"vim": {"pkg": ["installed"]}}' 496 """ 497 conflict = _check_queue(queue, kwargs) 498 if conflict is not None: 499 return conflict 500 opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) 501 502 opts["test"] = _get_test_value(test, **kwargs) 503 504 pillar_override = kwargs.get("pillar") 505 pillar_enc = kwargs.get("pillar_enc") 506 if ( 507 pillar_enc is None 508 and pillar_override is not None 509 and not isinstance(pillar_override, dict) 510 ): 511 raise SaltInvocationError( 512 "Pillar data must be formatted as a dictionary, unless pillar_enc " 513 "is specified." 514 ) 515 try: 516 st_ = salt.state.State( 517 opts, 518 pillar_override, 519 pillar_enc=pillar_enc, 520 proxy=dict(__proxy__), 521 context=dict(__context__), 522 initial_pillar=_get_initial_pillar(opts), 523 ) 524 except NameError: 525 st_ = salt.state.State( 526 opts, 527 pillar_override, 528 pillar_enc=pillar_enc, 529 initial_pillar=_get_initial_pillar(opts), 530 ) 531 532 ret = st_.call_high(data) 533 _set_retcode(ret, highstate=data) 534 return ret 535 536 537def template(tem, queue=False, **kwargs): 538 """ 539 Execute the information stored in a template file on the minion. 540 541 This function does not ask a master for a SLS file to render but 542 instead directly processes the file at the provided path on the minion. 543 544 CLI Example: 545 546 .. code-block:: bash 547 548 salt '*' state.template '<Path to template on the minion>' 549 """ 550 if "env" in kwargs: 551 # "env" is not supported; Use "saltenv". 552 kwargs.pop("env") 553 554 conflict = _check_queue(queue, kwargs) 555 if conflict is not None: 556 return conflict 557 558 opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) 559 try: 560 st_ = salt.state.HighState( 561 opts, 562 context=dict(__context__), 563 proxy=dict(__proxy__), 564 initial_pillar=_get_initial_pillar(opts), 565 ) 566 except NameError: 567 st_ = salt.state.HighState( 568 opts, context=dict(__context__), initial_pillar=_get_initial_pillar(opts) 569 ) 570 571 with st_: 572 errors = _get_pillar_errors(kwargs, pillar=st_.opts["pillar"]) 573 if errors: 574 __context__["retcode"] = salt.defaults.exitcodes.EX_PILLAR_FAILURE 575 raise CommandExecutionError("Pillar failed to render", info=errors) 576 577 if not tem.endswith(".sls"): 578 tem = "{sls}.sls".format(sls=tem) 579 high_state, errors = st_.render_state( 580 tem, kwargs.get("saltenv", ""), "", None, local=True 581 ) 582 if errors: 583 __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR 584 return errors 585 ret = st_.state.call_high(high_state) 586 _set_retcode(ret, highstate=high_state) 587 return ret 588 589 590def template_str(tem, queue=False, **kwargs): 591 """ 592 Execute the information stored in a string from an sls template 593 594 CLI Example: 595 596 .. code-block:: bash 597 598 salt '*' state.template_str '<Template String>' 599 """ 600 conflict = _check_queue(queue, kwargs) 601 if conflict is not None: 602 return conflict 603 604 opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) 605 606 try: 607 st_ = salt.state.State( 608 opts, proxy=__proxy__, initial_pillar=_get_initial_pillar(opts) 609 ) 610 except NameError: 611 st_ = salt.state.State(opts, initial_pillar=_get_initial_pillar(opts)) 612 ret = st_.call_template_str(tem) 613 _set_retcode(ret) 614 return ret 615 616 617def apply_(mods=None, **kwargs): 618 """ 619 .. versionadded:: 2015.5.0 620 621 This function will call :mod:`state.highstate 622 <salt.modules.state.highstate>` or :mod:`state.sls 623 <salt.modules.state.sls>` based on the arguments passed to this function. 624 It exists as a more intuitive way of applying states. 625 626 .. rubric:: APPLYING ALL STATES CONFIGURED IN TOP.SLS (A.K.A. :ref:`HIGHSTATE <running-highstate>`) 627 628 To apply all configured states, simply run ``state.apply``: 629 630 .. code-block:: bash 631 632 salt '*' state.apply 633 634 The following additional arguments are also accepted when applying all 635 states configured in top.sls: 636 637 test 638 Run states in test-only (dry-run) mode 639 640 mock 641 The mock option allows for the state run to execute without actually 642 calling any states. This then returns a mocked return which will show 643 the requisite ordering as well as fully validate the state run. 644 645 .. versionadded:: 2015.8.4 646 647 pillar 648 Custom Pillar values, passed as a dictionary of key-value pairs 649 650 .. code-block:: bash 651 652 salt '*' state.apply stuff pillar='{"foo": "bar"}' 653 654 .. note:: 655 Values passed this way will override Pillar values set via 656 ``pillar_roots`` or an external Pillar source. 657 658 exclude 659 Exclude specific states from execution. Accepts a list of sls names, a 660 comma-separated string of sls names, or a list of dictionaries 661 containing ``sls`` or ``id`` keys. Glob-patterns may be used to match 662 multiple states. 663 664 .. code-block:: bash 665 666 salt '*' state.apply exclude=bar,baz 667 salt '*' state.apply exclude=foo* 668 salt '*' state.apply exclude="[{'id': 'id_to_exclude'}, {'sls': 'sls_to_exclude'}]" 669 670 queue : False 671 Instead of failing immediately when another state run is in progress, 672 queue the new state run to begin running once the other has finished. 673 674 This option starts a new thread for each queued state run, so use this 675 option sparingly. 676 677 localconfig 678 Optionally, instead of using the minion config, load minion opts from 679 the file specified by this argument, and then merge them with the 680 options from the minion config. This functionality allows for specific 681 states to be run with their own custom minion configuration, including 682 different pillars, file_roots, etc. 683 684 .. code-block:: bash 685 686 salt '*' state.apply localconfig=/path/to/minion.yml 687 688 689 .. rubric:: APPLYING INDIVIDUAL SLS FILES (A.K.A. :py:func:`STATE.SLS <salt.modules.state.sls>`) 690 691 To apply individual SLS files, pass them as a comma-separated list: 692 693 .. code-block:: bash 694 695 # Run the states configured in salt://stuff.sls (or salt://stuff/init.sls) 696 salt '*' state.apply stuff 697 698 # Run the states configured in salt://stuff.sls (or salt://stuff/init.sls) 699 # and salt://pkgs.sls (or salt://pkgs/init.sls). 700 salt '*' state.apply stuff,pkgs 701 702 # Run the states configured in a more deeply nested directory such as salt://my/organized/stuff.sls (or salt://my/organized/stuff/init.sls) 703 salt '*' state.apply my.organized.stuff 704 705 The following additional arguments are also accepted when applying 706 individual SLS files: 707 708 test 709 Run states in test-only (dry-run) mode 710 711 mock 712 The mock option allows for the state run to execute without actually 713 calling any states. This then returns a mocked return which will show 714 the requisite ordering as well as fully validate the state run. 715 716 .. versionadded:: 2015.8.4 717 718 pillar 719 Custom Pillar values, passed as a dictionary of key-value pairs 720 721 .. code-block:: bash 722 723 salt '*' state.apply stuff pillar='{"foo": "bar"}' 724 725 .. note:: 726 Values passed this way will override Pillar values set via 727 ``pillar_roots`` or an external Pillar source. 728 729 queue : False 730 Instead of failing immediately when another state run is in progress, 731 queue the new state run to begin running once the other has finished. 732 733 This option starts a new thread for each queued state run, so use this 734 option sparingly. 735 736 concurrent : False 737 Execute state runs concurrently instead of serially 738 739 .. warning:: 740 741 This flag is potentially dangerous. It is designed for use when 742 multiple state runs can safely be run at the same time. Do *not* 743 use this flag for performance optimization. 744 745 saltenv 746 Specify a salt fileserver environment to be used when applying states 747 748 .. versionchanged:: 0.17.0 749 Argument name changed from ``env`` to ``saltenv`` 750 751 .. versionchanged:: 2014.7.0 752 If no saltenv is specified, the minion config will be checked for an 753 ``environment`` parameter and if found, it will be used. If none is 754 found, ``base`` will be used. In prior releases, the minion config 755 was not checked and ``base`` would always be assumed when the 756 saltenv was not explicitly set. 757 758 pillarenv 759 Specify a Pillar environment to be used when applying states. This 760 can also be set in the minion config file using the 761 :conf_minion:`pillarenv` option. When neither the 762 :conf_minion:`pillarenv` minion config option nor this CLI argument is 763 used, all Pillar environments will be merged together. 764 765 localconfig 766 Optionally, instead of using the minion config, load minion opts from 767 the file specified by this argument, and then merge them with the 768 options from the minion config. This functionality allows for specific 769 states to be run with their own custom minion configuration, including 770 different pillars, file_roots, etc. 771 772 .. code-block:: bash 773 774 salt '*' state.apply stuff localconfig=/path/to/minion.yml 775 776 sync_mods 777 If specified, the desired custom module types will be synced prior to 778 running the SLS files: 779 780 .. code-block:: bash 781 782 salt '*' state.apply stuff sync_mods=states,modules 783 salt '*' state.apply stuff sync_mods=all 784 785 .. note:: 786 This option is ignored when no SLS files are specified, as a 787 :ref:`highstate <running-highstate>` automatically syncs all custom 788 module types. 789 790 .. versionadded:: 2017.7.8,2018.3.3,2019.2.0 791 """ 792 if mods: 793 return sls(mods, **kwargs) 794 return highstate(**kwargs) 795 796 797def test(*args, **kwargs): 798 """ 799 .. versionadded:: 3001 800 801 Alias for `state.apply` with the kwarg `test` forced to `True`. 802 803 This is a nicety to avoid the need to type out `test=True` and the possibility of 804 a typo causing changes you do not intend. 805 """ 806 kwargs["test"] = True 807 ret = apply_(*args, **kwargs) 808 809 return ret 810 811 812def request(mods=None, **kwargs): 813 """ 814 .. versionadded:: 2015.5.0 815 816 Request that the local admin execute a state run via 817 `salt-call state.run_request`. 818 All arguments match those of state.apply. 819 820 CLI Example: 821 822 .. code-block:: bash 823 824 salt '*' state.request 825 salt '*' state.request stuff 826 salt '*' state.request stuff,pkgs 827 """ 828 kwargs["test"] = True 829 ret = apply_(mods, **kwargs) 830 notify_path = os.path.join(__opts__["cachedir"], "req_state.p") 831 req = check_request() 832 req.update( 833 { 834 kwargs.get("name", "default"): { 835 "test_run": ret, 836 "mods": mods, 837 "kwargs": kwargs, 838 } 839 } 840 ) 841 with salt.utils.files.set_umask(0o077): 842 try: 843 if salt.utils.platform.is_windows(): 844 # Make sure cache file isn't read-only 845 __salt__["cmd.run"]('attrib -R "{}"'.format(notify_path)) 846 with salt.utils.files.fopen(notify_path, "w+b") as fp_: 847 salt.payload.dump(req, fp_) 848 except OSError: 849 log.error( 850 "Unable to write state request file %s. Check permission.", notify_path 851 ) 852 return ret 853 854 855def check_request(name=None): 856 """ 857 .. versionadded:: 2015.5.0 858 859 Return the state request information, if any 860 861 CLI Example: 862 863 .. code-block:: bash 864 865 salt '*' state.check_request 866 """ 867 notify_path = os.path.join(__opts__["cachedir"], "req_state.p") 868 if os.path.isfile(notify_path): 869 with salt.utils.files.fopen(notify_path, "rb") as fp_: 870 req = salt.payload.load(fp_) 871 if name: 872 return req[name] 873 return req 874 return {} 875 876 877def clear_request(name=None): 878 """ 879 .. versionadded:: 2015.5.0 880 881 Clear out the state execution request without executing it 882 883 CLI Example: 884 885 .. code-block:: bash 886 887 salt '*' state.clear_request 888 """ 889 notify_path = os.path.join(__opts__["cachedir"], "req_state.p") 890 if not os.path.isfile(notify_path): 891 return True 892 if not name: 893 try: 894 os.remove(notify_path) 895 except OSError: 896 pass 897 else: 898 req = check_request() 899 if name in req: 900 req.pop(name) 901 else: 902 return False 903 with salt.utils.files.set_umask(0o077): 904 try: 905 if salt.utils.platform.is_windows(): 906 # Make sure cache file isn't read-only 907 __salt__["cmd.run"]('attrib -R "{}"'.format(notify_path)) 908 with salt.utils.files.fopen(notify_path, "w+b") as fp_: 909 salt.payload.dump(req, fp_) 910 except OSError: 911 log.error( 912 "Unable to write state request file %s. Check permission.", 913 notify_path, 914 ) 915 return True 916 917 918def run_request(name="default", **kwargs): 919 """ 920 .. versionadded:: 2015.5.0 921 922 Execute the pending state request 923 924 CLI Example: 925 926 .. code-block:: bash 927 928 salt '*' state.run_request 929 """ 930 req = check_request() 931 if name not in req: 932 return {} 933 n_req = req[name] 934 if "mods" not in n_req or "kwargs" not in n_req: 935 return {} 936 req[name]["kwargs"].update(kwargs) 937 if "test" in n_req["kwargs"]: 938 n_req["kwargs"].pop("test") 939 if req: 940 ret = apply_(n_req["mods"], **n_req["kwargs"]) 941 try: 942 os.remove(os.path.join(__opts__["cachedir"], "req_state.p")) 943 except OSError: 944 pass 945 return ret 946 return {} 947 948 949def highstate(test=None, queue=False, **kwargs): 950 """ 951 Retrieve the state data from the salt master for this minion and execute it 952 953 test 954 Run states in test-only (dry-run) mode 955 956 pillar 957 Custom Pillar values, passed as a dictionary of key-value pairs 958 959 .. code-block:: bash 960 961 salt '*' state.highstate stuff pillar='{"foo": "bar"}' 962 963 .. note:: 964 Values passed this way will override Pillar values set via 965 ``pillar_roots`` or an external Pillar source. 966 967 .. versionchanged:: 2016.3.0 968 GPG-encrypted CLI Pillar data is now supported via the GPG 969 renderer. See :ref:`here <encrypted-cli-pillar-data>` for details. 970 971 pillar_enc 972 Specify which renderer to use to decrypt encrypted data located within 973 the ``pillar`` value. Currently, only ``gpg`` is supported. 974 975 .. versionadded:: 2016.3.0 976 977 exclude 978 Exclude specific states from execution. Accepts a list of sls names, a 979 comma-separated string of sls names, or a list of dictionaries 980 containing ``sls`` or ``id`` keys. Glob-patterns may be used to match 981 multiple states. 982 983 .. code-block:: bash 984 985 salt '*' state.highstate exclude=bar,baz 986 salt '*' state.highstate exclude=foo* 987 salt '*' state.highstate exclude="[{'id': 'id_to_exclude'}, {'sls': 'sls_to_exclude'}]" 988 989 saltenv 990 Specify a salt fileserver environment to be used when applying states 991 992 .. versionchanged:: 0.17.0 993 Argument name changed from ``env`` to ``saltenv``. 994 995 .. versionchanged:: 2014.7.0 996 If no saltenv is specified, the minion config will be checked for a 997 ``saltenv`` parameter and if found, it will be used. If none is 998 found, ``base`` will be used. In prior releases, the minion config 999 was not checked and ``base`` would always be assumed when the 1000 saltenv was not explicitly set. 1001 1002 pillarenv 1003 Specify a Pillar environment to be used when applying states. This 1004 can also be set in the minion config file using the 1005 :conf_minion:`pillarenv` option. When neither the 1006 :conf_minion:`pillarenv` minion config option nor this CLI argument is 1007 used, all Pillar environments will be merged together. 1008 1009 queue : False 1010 Instead of failing immediately when another state run is in progress, 1011 queue the new state run to begin running once the other has finished. 1012 1013 This option starts a new thread for each queued state run, so use this 1014 option sparingly. 1015 1016 localconfig 1017 Optionally, instead of using the minion config, load minion opts from 1018 the file specified by this argument, and then merge them with the 1019 options from the minion config. This functionality allows for specific 1020 states to be run with their own custom minion configuration, including 1021 different pillars, file_roots, etc. 1022 1023 mock 1024 The mock option allows for the state run to execute without actually 1025 calling any states. This then returns a mocked return which will show 1026 the requisite ordering as well as fully validate the state run. 1027 1028 .. versionadded:: 2015.8.4 1029 1030 CLI Examples: 1031 1032 .. code-block:: bash 1033 1034 salt '*' state.highstate 1035 1036 salt '*' state.highstate whitelist=sls1_to_run,sls2_to_run 1037 salt '*' state.highstate exclude=sls_to_exclude 1038 salt '*' state.highstate exclude="[{'id': 'id_to_exclude'}, {'sls': 'sls_to_exclude'}]" 1039 1040 salt '*' state.highstate pillar="{foo: 'Foo!', bar: 'Bar!'}" 1041 """ 1042 if _disabled(["highstate"]): 1043 log.debug( 1044 "Salt highstate run is disabled. To re-enable, run state.enable highstate" 1045 ) 1046 ret = { 1047 "name": ( 1048 "Salt highstate run is disabled. To re-enable, run state.enable" 1049 " highstate" 1050 ), 1051 "result": "False", 1052 "comment": "Disabled", 1053 } 1054 return ret 1055 1056 conflict = _check_queue(queue, kwargs) 1057 if conflict is not None: 1058 return conflict 1059 1060 orig_test = __opts__.get("test", None) 1061 opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) 1062 opts["test"] = _get_test_value(test, **kwargs) 1063 1064 if "env" in kwargs: 1065 # "env" is not supported; Use "saltenv". 1066 kwargs.pop("env") 1067 1068 if "saltenv" in kwargs: 1069 opts["saltenv"] = kwargs["saltenv"] 1070 1071 if "pillarenv" in kwargs: 1072 opts["pillarenv"] = kwargs["pillarenv"] 1073 1074 pillar_override = kwargs.get("pillar") 1075 pillar_enc = kwargs.get("pillar_enc") 1076 if ( 1077 pillar_enc is None 1078 and pillar_override is not None 1079 and not isinstance(pillar_override, dict) 1080 ): 1081 raise SaltInvocationError( 1082 "Pillar data must be formatted as a dictionary, unless pillar_enc " 1083 "is specified." 1084 ) 1085 1086 try: 1087 st_ = salt.state.HighState( 1088 opts, 1089 pillar_override, 1090 kwargs.get("__pub_jid"), 1091 pillar_enc=pillar_enc, 1092 proxy=dict(__proxy__), 1093 context=dict(__context__), 1094 mocked=kwargs.get("mock", False), 1095 initial_pillar=_get_initial_pillar(opts), 1096 ) 1097 except NameError: 1098 st_ = salt.state.HighState( 1099 opts, 1100 pillar_override, 1101 kwargs.get("__pub_jid"), 1102 pillar_enc=pillar_enc, 1103 mocked=kwargs.get("mock", False), 1104 initial_pillar=_get_initial_pillar(opts), 1105 ) 1106 1107 with st_: 1108 errors = _get_pillar_errors(kwargs, st_.opts["pillar"]) 1109 if errors: 1110 __context__["retcode"] = salt.defaults.exitcodes.EX_PILLAR_FAILURE 1111 return ["Pillar failed to render with the following messages:"] + errors 1112 1113 st_.push_active() 1114 orchestration_jid = kwargs.get("orchestration_jid") 1115 snapper_pre = _snapper_pre(opts, kwargs.get("__pub_jid", "called localy")) 1116 try: 1117 ret = st_.call_highstate( 1118 exclude=kwargs.get("exclude", []), 1119 cache=kwargs.get("cache", None), 1120 cache_name=kwargs.get("cache_name", "highstate"), 1121 force=kwargs.get("force", False), 1122 whitelist=kwargs.get("whitelist"), 1123 orchestration_jid=orchestration_jid, 1124 ) 1125 finally: 1126 st_.pop_active() 1127 1128 if isinstance(ret, dict) and ( 1129 __salt__["config.option"]("state_data", "") == "terse" 1130 or kwargs.get("terse") 1131 ): 1132 ret = _filter_running(ret) 1133 1134 _set_retcode(ret, highstate=st_.building_highstate) 1135 _snapper_post(opts, kwargs.get("__pub_jid", "called localy"), snapper_pre) 1136 1137 # Work around Windows multiprocessing bug, set __opts__['test'] back to 1138 # value from before this function was run. 1139 __opts__["test"] = orig_test 1140 1141 return ret 1142 1143 1144def sls(mods, test=None, exclude=None, queue=False, sync_mods=None, **kwargs): 1145 """ 1146 Execute the states in one or more SLS files 1147 1148 test 1149 Run states in test-only (dry-run) mode 1150 1151 pillar 1152 Custom Pillar values, passed as a dictionary of key-value pairs 1153 1154 .. code-block:: bash 1155 1156 salt '*' state.sls stuff pillar='{"foo": "bar"}' 1157 1158 .. note:: 1159 Values passed this way will override existing Pillar values set via 1160 ``pillar_roots`` or an external Pillar source. Pillar values that 1161 are not included in the kwarg will not be overwritten. 1162 1163 .. versionchanged:: 2016.3.0 1164 GPG-encrypted CLI Pillar data is now supported via the GPG 1165 renderer. See :ref:`here <encrypted-cli-pillar-data>` for details. 1166 1167 pillar_enc 1168 Specify which renderer to use to decrypt encrypted data located within 1169 the ``pillar`` value. Currently, only ``gpg`` is supported. 1170 1171 .. versionadded:: 2016.3.0 1172 1173 exclude 1174 Exclude specific states from execution. Accepts a list of sls names, a 1175 comma-separated string of sls names, or a list of dictionaries 1176 containing ``sls`` or ``id`` keys. Glob-patterns may be used to match 1177 multiple states. 1178 1179 .. code-block:: bash 1180 1181 salt '*' state.sls foo,bar,baz exclude=bar,baz 1182 salt '*' state.sls foo,bar,baz exclude=ba* 1183 salt '*' state.sls foo,bar,baz exclude="[{'id': 'id_to_exclude'}, {'sls': 'sls_to_exclude'}]" 1184 1185 queue : False 1186 Instead of failing immediately when another state run is in progress, 1187 queue the new state run to begin running once the other has finished. 1188 1189 This option starts a new thread for each queued state run, so use this 1190 option sparingly. 1191 1192 concurrent : False 1193 Execute state runs concurrently instead of serially 1194 1195 .. warning:: 1196 1197 This flag is potentially dangerous. It is designed for use when 1198 multiple state runs can safely be run at the same time. Do *not* 1199 use this flag for performance optimization. 1200 1201 saltenv 1202 Specify a salt fileserver environment to be used when applying states 1203 1204 .. versionchanged:: 0.17.0 1205 Argument name changed from ``env`` to ``saltenv``. 1206 1207 .. versionchanged:: 2014.7.0 1208 If no saltenv is specified, the minion config will be checked for an 1209 ``environment`` parameter and if found, it will be used. If none is 1210 found, ``base`` will be used. In prior releases, the minion config 1211 was not checked and ``base`` would always be assumed when the 1212 saltenv was not explicitly set. 1213 1214 pillarenv 1215 Specify a Pillar environment to be used when applying states. This 1216 can also be set in the minion config file using the 1217 :conf_minion:`pillarenv` option. When neither the 1218 :conf_minion:`pillarenv` minion config option nor this CLI argument is 1219 used, all Pillar environments will be merged together. 1220 1221 localconfig 1222 Optionally, instead of using the minion config, load minion opts from 1223 the file specified by this argument, and then merge them with the 1224 options from the minion config. This functionality allows for specific 1225 states to be run with their own custom minion configuration, including 1226 different pillars, file_roots, etc. 1227 1228 mock 1229 The mock option allows for the state run to execute without actually 1230 calling any states. This then returns a mocked return which will show 1231 the requisite ordering as well as fully validate the state run. 1232 1233 .. versionadded:: 2015.8.4 1234 1235 sync_mods 1236 If specified, the desired custom module types will be synced prior to 1237 running the SLS files: 1238 1239 .. code-block:: bash 1240 1241 salt '*' state.sls stuff sync_mods=states,modules 1242 salt '*' state.sls stuff sync_mods=all 1243 1244 .. versionadded:: 2017.7.8,2018.3.3,2019.2.0 1245 1246 CLI Example: 1247 1248 .. code-block:: bash 1249 1250 # Run the states configured in salt://example.sls (or salt://example/init.sls) 1251 salt '*' state.apply example 1252 1253 # Run the states configured in salt://core.sls (or salt://core/init.sls) 1254 # and salt://edit/vim.sls (or salt://edit/vim/init.sls) 1255 salt '*' state.sls core,edit.vim 1256 1257 # Run the states configured in a more deeply nested directory such as salt://my/nested/state.sls (or salt://my/nested/state/init.sls) 1258 salt '*' state.sls my.nested.state 1259 1260 salt '*' state.sls core exclude="[{'id': 'id_to_exclude'}, {'sls': 'sls_to_exclude'}]" 1261 salt '*' state.sls myslsfile pillar="{foo: 'Foo!', bar: 'Bar!'}" 1262 """ 1263 concurrent = kwargs.get("concurrent", False) 1264 if "env" in kwargs: 1265 # "env" is not supported; Use "saltenv". 1266 kwargs.pop("env") 1267 1268 # Modification to __opts__ lost after this if-else 1269 if queue: 1270 _wait(kwargs.get("__pub_jid")) 1271 else: 1272 conflict = running(concurrent) 1273 if conflict: 1274 __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR 1275 return conflict 1276 1277 if isinstance(mods, list): 1278 disabled = _disabled(mods) 1279 else: 1280 disabled = _disabled([mods]) 1281 1282 if disabled: 1283 for state in disabled: 1284 log.debug( 1285 "Salt state %s is disabled. To re-enable, run state.enable %s", 1286 state, 1287 state, 1288 ) 1289 __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR 1290 return disabled 1291 1292 orig_test = __opts__.get("test", None) 1293 opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) 1294 1295 opts["test"] = _get_test_value(test, **kwargs) 1296 1297 # Since this is running a specific SLS file (or files), fall back to the 1298 # 'base' saltenv if none is configured and none was passed. 1299 if opts["saltenv"] is None: 1300 opts["saltenv"] = "base" 1301 1302 pillar_override = kwargs.get("pillar") 1303 pillar_enc = kwargs.get("pillar_enc") 1304 if ( 1305 pillar_enc is None 1306 and pillar_override is not None 1307 and not isinstance(pillar_override, dict) 1308 ): 1309 raise SaltInvocationError( 1310 "Pillar data must be formatted as a dictionary, unless pillar_enc " 1311 "is specified." 1312 ) 1313 1314 cfn = os.path.join( 1315 __opts__["cachedir"], 1316 "{}.cache.p".format(kwargs.get("cache_name", "highstate")), 1317 ) 1318 1319 if sync_mods is True: 1320 sync_mods = ["all"] 1321 if sync_mods is not None: 1322 sync_mods = salt.utils.args.split_input(sync_mods) 1323 else: 1324 sync_mods = [] 1325 1326 if "all" in sync_mods and sync_mods != ["all"]: 1327 # Prevent unnecessary extra syncing 1328 sync_mods = ["all"] 1329 1330 for module_type in sync_mods: 1331 try: 1332 __salt__["saltutil.sync_{}".format(module_type)](saltenv=opts["saltenv"]) 1333 except KeyError: 1334 log.warning("Invalid custom module type '%s', ignoring", module_type) 1335 1336 try: 1337 st_ = salt.state.HighState( 1338 opts, 1339 pillar_override, 1340 kwargs.get("__pub_jid"), 1341 pillar_enc=pillar_enc, 1342 proxy=dict(__proxy__), 1343 context=dict(__context__), 1344 mocked=kwargs.get("mock", False), 1345 initial_pillar=_get_initial_pillar(opts), 1346 ) 1347 except NameError: 1348 st_ = salt.state.HighState( 1349 opts, 1350 pillar_override, 1351 kwargs.get("__pub_jid"), 1352 pillar_enc=pillar_enc, 1353 mocked=kwargs.get("mock", False), 1354 initial_pillar=_get_initial_pillar(opts), 1355 ) 1356 1357 with st_: 1358 errors = _get_pillar_errors(kwargs, pillar=st_.opts["pillar"]) 1359 if errors: 1360 __context__["retcode"] = salt.defaults.exitcodes.EX_PILLAR_FAILURE 1361 return ["Pillar failed to render with the following messages:"] + errors 1362 1363 orchestration_jid = kwargs.get("orchestration_jid") 1364 with salt.utils.files.set_umask(0o077): 1365 if kwargs.get("cache"): 1366 if os.path.isfile(cfn): 1367 with salt.utils.files.fopen(cfn, "rb") as fp_: 1368 high_ = salt.payload.load(fp_) 1369 return st_.state.call_high(high_, orchestration_jid) 1370 1371 # If the state file is an integer, convert to a string then to unicode 1372 if isinstance(mods, int): 1373 mods = salt.utils.stringutils.to_unicode(str(mods)) 1374 1375 mods = salt.utils.args.split_input(mods) 1376 1377 st_.push_active() 1378 try: 1379 high_, errors = st_.render_highstate({opts["saltenv"]: mods}) 1380 1381 if errors: 1382 __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR 1383 return errors 1384 1385 if exclude: 1386 exclude = salt.utils.args.split_input(exclude) 1387 if "__exclude__" in high_: 1388 high_["__exclude__"].extend(exclude) 1389 else: 1390 high_["__exclude__"] = exclude 1391 snapper_pre = _snapper_pre(opts, kwargs.get("__pub_jid", "called localy")) 1392 ret = st_.state.call_high(high_, orchestration_jid) 1393 finally: 1394 st_.pop_active() 1395 if __salt__["config.option"]("state_data", "") == "terse" or kwargs.get("terse"): 1396 ret = _filter_running(ret) 1397 cache_file = os.path.join(__opts__["cachedir"], "sls.p") 1398 with salt.utils.files.set_umask(0o077): 1399 try: 1400 if salt.utils.platform.is_windows(): 1401 # Make sure cache file isn't read-only 1402 __salt__["cmd.run"](["attrib", "-R", cache_file], python_shell=False) 1403 with salt.utils.files.fopen(cache_file, "w+b") as fp_: 1404 salt.payload.dump(ret, fp_) 1405 except OSError: 1406 log.error( 1407 "Unable to write to SLS cache file %s. Check permission.", cache_file 1408 ) 1409 _set_retcode(ret, high_) 1410 # Work around Windows multiprocessing bug, set __opts__['test'] back to 1411 # value from before this function was run. 1412 __opts__["test"] = orig_test 1413 1414 try: 1415 with salt.utils.files.fopen(cfn, "w+b") as fp_: 1416 try: 1417 salt.payload.dump(high_, fp_) 1418 except TypeError: 1419 # Can't serialize pydsl 1420 pass 1421 except OSError: 1422 log.error( 1423 "Unable to write to highstate cache file %s. Do you have permissions?", 1424 cfn, 1425 ) 1426 1427 _snapper_post(opts, kwargs.get("__pub_jid", "called localy"), snapper_pre) 1428 return ret 1429 1430 1431def top(topfn, test=None, queue=False, **kwargs): 1432 """ 1433 Execute a specific top file instead of the default. This is useful to apply 1434 configurations from a different environment (for example, dev or prod), without 1435 modifying the default top file. 1436 1437 queue : False 1438 Instead of failing immediately when another state run is in progress, 1439 queue the new state run to begin running once the other has finished. 1440 1441 This option starts a new thread for each queued state run, so use this 1442 option sparingly. 1443 1444 saltenv 1445 Specify a salt fileserver environment to be used when applying states 1446 1447 pillarenv 1448 Specify a Pillar environment to be used when applying states. This 1449 can also be set in the minion config file using the 1450 :conf_minion:`pillarenv` option. When neither the 1451 :conf_minion:`pillarenv` minion config option nor this CLI argument is 1452 used, all Pillar environments will be merged together. 1453 1454 .. versionadded:: 2017.7.0 1455 1456 CLI Example: 1457 1458 .. code-block:: bash 1459 1460 salt '*' state.top reverse_top.sls 1461 salt '*' state.top prod_top.sls exclude=sls_to_exclude 1462 salt '*' state.top dev_top.sls exclude="[{'id': 'id_to_exclude'}, {'sls': 'sls_to_exclude'}]" 1463 """ 1464 conflict = _check_queue(queue, kwargs) 1465 if conflict is not None: 1466 return conflict 1467 orig_test = __opts__.get("test", None) 1468 opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) 1469 opts["test"] = _get_test_value(test, **kwargs) 1470 1471 pillar_override = kwargs.get("pillar") 1472 pillar_enc = kwargs.get("pillar_enc") 1473 if ( 1474 pillar_enc is None 1475 and pillar_override is not None 1476 and not isinstance(pillar_override, dict) 1477 ): 1478 raise SaltInvocationError( 1479 "Pillar data must be formatted as a dictionary, unless pillar_enc " 1480 "is specified." 1481 ) 1482 try: 1483 st_ = salt.state.HighState( 1484 opts, 1485 pillar_override, 1486 pillar_enc=pillar_enc, 1487 context=dict(__context__), 1488 proxy=dict(__proxy__), 1489 initial_pillar=_get_initial_pillar(opts), 1490 ) 1491 except NameError: 1492 st_ = salt.state.HighState( 1493 opts, 1494 pillar_override, 1495 pillar_enc=pillar_enc, 1496 context=dict(__context__), 1497 initial_pillar=_get_initial_pillar(opts), 1498 ) 1499 1500 with st_: 1501 errors = _get_pillar_errors(kwargs, pillar=st_.opts["pillar"]) 1502 if errors: 1503 __context__["retcode"] = salt.defaults.exitcodes.EX_PILLAR_FAILURE 1504 return ["Pillar failed to render with the following messages:"] + errors 1505 1506 st_.push_active() 1507 st_.opts["state_top"] = salt.utils.url.create(topfn) 1508 ret = {} 1509 orchestration_jid = kwargs.get("orchestration_jid") 1510 if "saltenv" in kwargs: 1511 st_.opts["state_top_saltenv"] = kwargs["saltenv"] 1512 try: 1513 snapper_pre = _snapper_pre(opts, kwargs.get("__pub_jid", "called localy")) 1514 ret = st_.call_highstate( 1515 exclude=kwargs.get("exclude", []), 1516 cache=kwargs.get("cache", None), 1517 cache_name=kwargs.get("cache_name", "highstate"), 1518 orchestration_jid=orchestration_jid, 1519 ) 1520 finally: 1521 st_.pop_active() 1522 1523 _set_retcode(ret, highstate=st_.building_highstate) 1524 # Work around Windows multiprocessing bug, set __opts__['test'] back to 1525 # value from before this function was run. 1526 _snapper_post(opts, kwargs.get("__pub_jid", "called localy"), snapper_pre) 1527 __opts__["test"] = orig_test 1528 return ret 1529 1530 1531def show_highstate(queue=False, **kwargs): 1532 """ 1533 Retrieve the highstate data from the salt master and display it 1534 1535 Custom Pillar data can be passed with the ``pillar`` kwarg. 1536 1537 CLI Example: 1538 1539 .. code-block:: bash 1540 1541 salt '*' state.show_highstate 1542 """ 1543 conflict = _check_queue(queue, kwargs) 1544 if conflict is not None: 1545 return conflict 1546 pillar_override = kwargs.get("pillar") 1547 pillar_enc = kwargs.get("pillar_enc") 1548 if ( 1549 pillar_enc is None 1550 and pillar_override is not None 1551 and not isinstance(pillar_override, dict) 1552 ): 1553 raise SaltInvocationError( 1554 "Pillar data must be formatted as a dictionary, unless pillar_enc " 1555 "is specified." 1556 ) 1557 1558 opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) 1559 try: 1560 st_ = salt.state.HighState( 1561 opts, 1562 pillar_override, 1563 pillar_enc=pillar_enc, 1564 proxy=__proxy__, 1565 initial_pillar=_get_initial_pillar(opts), 1566 ) 1567 except NameError: 1568 st_ = salt.state.HighState( 1569 opts, 1570 pillar_override, 1571 pillar_enc=pillar_enc, 1572 initial_pillar=_get_initial_pillar(opts), 1573 ) 1574 1575 with st_: 1576 errors = _get_pillar_errors(kwargs, pillar=st_.opts["pillar"]) 1577 if errors: 1578 __context__["retcode"] = salt.defaults.exitcodes.EX_PILLAR_FAILURE 1579 raise CommandExecutionError("Pillar failed to render", info=errors) 1580 1581 st_.push_active() 1582 try: 1583 ret = st_.compile_highstate() 1584 finally: 1585 st_.pop_active() 1586 _set_retcode(ret) 1587 return ret 1588 1589 1590def show_lowstate(queue=False, **kwargs): 1591 """ 1592 List out the low data that will be applied to this minion 1593 1594 CLI Example: 1595 1596 .. code-block:: bash 1597 1598 salt '*' state.show_lowstate 1599 """ 1600 conflict = _check_queue(queue, kwargs) 1601 if conflict is not None: 1602 assert False 1603 return conflict 1604 1605 opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) 1606 try: 1607 st_ = salt.state.HighState( 1608 opts, proxy=__proxy__, initial_pillar=_get_initial_pillar(opts) 1609 ) 1610 except NameError: 1611 st_ = salt.state.HighState(opts, initial_pillar=_get_initial_pillar(opts)) 1612 1613 with st_: 1614 errors = _get_pillar_errors(kwargs, pillar=st_.opts["pillar"]) 1615 if errors: 1616 __context__["retcode"] = salt.defaults.exitcodes.EX_PILLAR_FAILURE 1617 raise CommandExecutionError("Pillar failed to render", info=errors) 1618 1619 st_.push_active() 1620 try: 1621 ret = st_.compile_low_chunks() 1622 finally: 1623 st_.pop_active() 1624 return ret 1625 1626 1627def show_state_usage(queue=False, **kwargs): 1628 """ 1629 Retrieve the highstate data from the salt master to analyse used and unused states 1630 1631 Custom Pillar data can be passed with the ``pillar`` kwarg. 1632 1633 CLI Example: 1634 1635 .. code-block:: bash 1636 1637 salt '*' state.show_state_usage 1638 """ 1639 conflict = _check_queue(queue, kwargs) 1640 if conflict is not None: 1641 return conflict 1642 pillar = kwargs.get("pillar") 1643 pillar_enc = kwargs.get("pillar_enc") 1644 if pillar_enc is None and pillar is not None and not isinstance(pillar, dict): 1645 raise SaltInvocationError( 1646 "Pillar data must be formatted as a dictionary, unless pillar_enc " 1647 "is specified." 1648 ) 1649 1650 with salt.state.HighState(__opts__, pillar, pillar_enc=pillar_enc) as st_: 1651 st_.push_active() 1652 1653 try: 1654 ret = st_.compile_state_usage() 1655 finally: 1656 st_.pop_active() 1657 _set_retcode(ret) 1658 return ret 1659 1660 1661def show_states(queue=False, **kwargs): 1662 """ 1663 Returns the list of states that will be applied on highstate. 1664 1665 CLI Example: 1666 1667 .. code-block:: bash 1668 1669 salt '*' state.show_states 1670 1671 .. versionadded:: 2019.2.0 1672 1673 """ 1674 conflict = _check_queue(queue, kwargs) 1675 if conflict is not None: 1676 assert False 1677 return conflict 1678 1679 opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) 1680 try: 1681 st_ = salt.state.HighState( 1682 opts, proxy=__proxy__, initial_pillar=_get_initial_pillar(opts) 1683 ) 1684 except NameError: 1685 st_ = salt.state.HighState(opts, initial_pillar=_get_initial_pillar(opts)) 1686 1687 with st_: 1688 errors = _get_pillar_errors(kwargs, pillar=st_.opts["pillar"]) 1689 if errors: 1690 __context__["retcode"] = salt.defaults.exitcodes.EX_PILLAR_FAILURE 1691 raise CommandExecutionError("Pillar failed to render", info=errors) 1692 1693 st_.push_active() 1694 states = OrderedDict() 1695 try: 1696 result = st_.compile_low_chunks() 1697 1698 if not isinstance(result, list): 1699 raise Exception(result) 1700 1701 for s in result: 1702 if not isinstance(s, dict): 1703 _set_retcode(result) 1704 return result 1705 states[s["__sls__"]] = True 1706 finally: 1707 st_.pop_active() 1708 1709 return list(states.keys()) 1710 1711 1712def sls_id(id_, mods, test=None, queue=False, **kwargs): 1713 """ 1714 Call a single ID from the named module(s) and handle all requisites 1715 1716 The state ID comes *before* the module ID(s) on the command line. 1717 1718 id 1719 ID to call 1720 1721 mods 1722 Comma-delimited list of modules to search for given id and its requisites 1723 1724 .. versionadded:: 2014.7.0 1725 1726 saltenv : base 1727 Specify a salt fileserver environment to be used when applying states 1728 1729 pillarenv 1730 Specify a Pillar environment to be used when applying states. This 1731 can also be set in the minion config file using the 1732 :conf_minion:`pillarenv` option. When neither the 1733 :conf_minion:`pillarenv` minion config option nor this CLI argument is 1734 used, all Pillar environments will be merged together. 1735 1736 pillar 1737 Custom Pillar values, passed as a dictionary of key-value pairs 1738 1739 .. code-block:: bash 1740 1741 salt '*' state.sls_id my_state my_module pillar='{"foo": "bar"}' 1742 1743 .. note:: 1744 Values passed this way will override existing Pillar values set via 1745 ``pillar_roots`` or an external Pillar source. Pillar values that 1746 are not included in the kwarg will not be overwritten. 1747 1748 .. versionadded:: 2018.3.0 1749 1750 CLI Example: 1751 1752 .. code-block:: bash 1753 1754 salt '*' state.sls_id my_state my_module 1755 1756 salt '*' state.sls_id my_state my_module,a_common_module 1757 """ 1758 conflict = _check_queue(queue, kwargs) 1759 if conflict is not None: 1760 return conflict 1761 orig_test = __opts__.get("test", None) 1762 opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) 1763 opts["test"] = _get_test_value(test, **kwargs) 1764 1765 # Since this is running a specific ID within a specific SLS file, fall back 1766 # to the 'base' saltenv if none is configured and none was passed. 1767 if opts["saltenv"] is None: 1768 opts["saltenv"] = "base" 1769 1770 pillar_override = kwargs.get("pillar") 1771 pillar_enc = kwargs.get("pillar_enc") 1772 if ( 1773 pillar_enc is None 1774 and pillar_override is not None 1775 and not isinstance(pillar_override, dict) 1776 ): 1777 raise SaltInvocationError( 1778 "Pillar data must be formatted as a dictionary, unless pillar_enc " 1779 "is specified." 1780 ) 1781 1782 try: 1783 st_ = salt.state.HighState( 1784 opts, 1785 pillar_override, 1786 pillar_enc=pillar_enc, 1787 proxy=__proxy__, 1788 initial_pillar=_get_initial_pillar(opts), 1789 ) 1790 except NameError: 1791 st_ = salt.state.HighState( 1792 opts, 1793 pillar_override, 1794 pillar_enc=pillar_enc, 1795 initial_pillar=_get_initial_pillar(opts), 1796 ) 1797 1798 with st_: 1799 errors = _get_pillar_errors(kwargs, pillar=st_.opts["pillar"]) 1800 if errors: 1801 __context__["retcode"] = salt.defaults.exitcodes.EX_PILLAR_FAILURE 1802 return ["Pillar failed to render with the following messages:"] + errors 1803 1804 split_mods = salt.utils.args.split_input(mods) 1805 st_.push_active() 1806 try: 1807 high_, errors = st_.render_highstate({opts["saltenv"]: split_mods}) 1808 finally: 1809 st_.pop_active() 1810 errors += st_.state.verify_high(high_) 1811 # Apply requisites to high data 1812 high_, req_in_errors = st_.state.requisite_in(high_) 1813 if req_in_errors: 1814 # This if statement should not be necessary if there were no errors, 1815 # but it is required to get the unit tests to pass. 1816 errors.extend(req_in_errors) 1817 if errors: 1818 __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR 1819 return errors 1820 chunks = st_.state.compile_high_data(high_) 1821 ret = {} 1822 for chunk in chunks: 1823 if chunk.get("__id__", "") == id_: 1824 ret.update(st_.state.call_chunk(chunk, {}, chunks)) 1825 1826 _set_retcode(ret, highstate=highstate) 1827 # Work around Windows multiprocessing bug, set __opts__['test'] back to 1828 # value from before this function was run. 1829 __opts__["test"] = orig_test 1830 if not ret: 1831 raise SaltInvocationError( 1832 "No matches for ID '{}' found in SLS '{}' within saltenv '{}'".format( 1833 id_, mods, opts["saltenv"] 1834 ) 1835 ) 1836 return ret 1837 1838 1839def show_low_sls(mods, test=None, queue=False, **kwargs): 1840 """ 1841 Display the low data from a specific sls. The default environment is 1842 ``base``, use ``saltenv`` to specify a different environment. 1843 1844 saltenv 1845 Specify a salt fileserver environment to be used when applying states 1846 1847 pillar 1848 Custom Pillar values, passed as a dictionary of key-value pairs 1849 1850 .. code-block:: bash 1851 1852 salt '*' state.show_low_sls stuff pillar='{"foo": "bar"}' 1853 1854 .. note:: 1855 Values passed this way will override Pillar values set via 1856 ``pillar_roots`` or an external Pillar source. 1857 1858 pillarenv 1859 Specify a Pillar environment to be used when applying states. This 1860 can also be set in the minion config file using the 1861 :conf_minion:`pillarenv` option. When neither the 1862 :conf_minion:`pillarenv` minion config option nor this CLI argument is 1863 used, all Pillar environments will be merged together. 1864 1865 CLI Example: 1866 1867 .. code-block:: bash 1868 1869 salt '*' state.show_low_sls foo 1870 salt '*' state.show_low_sls foo saltenv=dev 1871 """ 1872 if "env" in kwargs: 1873 # "env" is not supported; Use "saltenv". 1874 kwargs.pop("env") 1875 1876 conflict = _check_queue(queue, kwargs) 1877 if conflict is not None: 1878 return conflict 1879 orig_test = __opts__.get("test", None) 1880 opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) 1881 opts["test"] = _get_test_value(test, **kwargs) 1882 1883 # Since this is dealing with a specific SLS file (or files), fall back to 1884 # the 'base' saltenv if none is configured and none was passed. 1885 if opts["saltenv"] is None: 1886 opts["saltenv"] = "base" 1887 1888 pillar_override = kwargs.get("pillar") 1889 pillar_enc = kwargs.get("pillar_enc") 1890 if ( 1891 pillar_enc is None 1892 and pillar_override is not None 1893 and not isinstance(pillar_override, dict) 1894 ): 1895 raise SaltInvocationError( 1896 "Pillar data must be formatted as a dictionary, unless pillar_enc " 1897 "is specified." 1898 ) 1899 1900 try: 1901 st_ = salt.state.HighState( 1902 opts, 1903 pillar_override, 1904 proxy=__proxy__, 1905 initial_pillar=_get_initial_pillar(opts), 1906 ) 1907 except NameError: 1908 st_ = salt.state.HighState( 1909 opts, pillar_override, initial_pillar=_get_initial_pillar(opts) 1910 ) 1911 1912 with st_: 1913 errors = _get_pillar_errors(kwargs, pillar=st_.opts["pillar"]) 1914 if errors: 1915 __context__["retcode"] = salt.defaults.exitcodes.EX_PILLAR_FAILURE 1916 raise CommandExecutionError("Pillar failed to render", info=errors) 1917 1918 mods = salt.utils.args.split_input(mods) 1919 st_.push_active() 1920 try: 1921 high_, errors = st_.render_highstate({opts["saltenv"]: mods}) 1922 finally: 1923 st_.pop_active() 1924 errors += st_.state.verify_high(high_) 1925 if errors: 1926 __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR 1927 return errors 1928 ret = st_.state.compile_high_data(high_) 1929 # Work around Windows multiprocessing bug, set __opts__['test'] back to 1930 # value from before this function was run. 1931 __opts__["test"] = orig_test 1932 return ret 1933 1934 1935def show_sls(mods, test=None, queue=False, **kwargs): 1936 """ 1937 Display the state data from a specific sls or list of sls files on the 1938 master. The default environment is ``base``, use ``saltenv`` to specify a 1939 different environment. 1940 1941 This function does not support topfiles. For ``top.sls`` please use 1942 ``show_top`` instead. 1943 1944 Custom Pillar data can be passed with the ``pillar`` kwarg. 1945 1946 saltenv 1947 Specify a salt fileserver environment to be used when applying states 1948 1949 pillarenv 1950 Specify a Pillar environment to be used when applying states. This 1951 can also be set in the minion config file using the 1952 :conf_minion:`pillarenv` option. When neither the 1953 :conf_minion:`pillarenv` minion config option nor this CLI argument is 1954 used, all Pillar environments will be merged together. 1955 1956 CLI Example: 1957 1958 .. code-block:: bash 1959 1960 salt '*' state.show_sls core,edit.vim saltenv=dev 1961 """ 1962 if "env" in kwargs: 1963 # "env" is not supported; Use "saltenv". 1964 kwargs.pop("env") 1965 1966 conflict = _check_queue(queue, kwargs) 1967 if conflict is not None: 1968 return conflict 1969 orig_test = __opts__.get("test", None) 1970 opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) 1971 1972 opts["test"] = _get_test_value(test, **kwargs) 1973 1974 # Since this is dealing with a specific SLS file (or files), fall back to 1975 # the 'base' saltenv if none is configured and none was passed. 1976 if opts["saltenv"] is None: 1977 opts["saltenv"] = "base" 1978 1979 pillar_override = kwargs.get("pillar") 1980 pillar_enc = kwargs.get("pillar_enc") 1981 if ( 1982 pillar_enc is None 1983 and pillar_override is not None 1984 and not isinstance(pillar_override, dict) 1985 ): 1986 raise SaltInvocationError( 1987 "Pillar data must be formatted as a dictionary, unless pillar_enc " 1988 "is specified." 1989 ) 1990 1991 try: 1992 st_ = salt.state.HighState( 1993 opts, 1994 pillar_override, 1995 pillar_enc=pillar_enc, 1996 proxy=__proxy__, 1997 initial_pillar=_get_initial_pillar(opts), 1998 ) 1999 except NameError: 2000 st_ = salt.state.HighState( 2001 opts, 2002 pillar_override, 2003 pillar_enc=pillar_enc, 2004 initial_pillar=_get_initial_pillar(opts), 2005 ) 2006 2007 with st_: 2008 errors = _get_pillar_errors(kwargs, pillar=st_.opts["pillar"]) 2009 if errors: 2010 __context__["retcode"] = salt.defaults.exitcodes.EX_PILLAR_FAILURE 2011 raise CommandExecutionError("Pillar failed to render", info=errors) 2012 2013 mods = salt.utils.args.split_input(mods) 2014 st_.push_active() 2015 try: 2016 high_, errors = st_.render_highstate({opts["saltenv"]: mods}) 2017 finally: 2018 st_.pop_active() 2019 errors += st_.state.verify_high(high_) 2020 # Work around Windows multiprocessing bug, set __opts__['test'] back to 2021 # value from before this function was run. 2022 __opts__["test"] = orig_test 2023 if errors: 2024 __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR 2025 return errors 2026 return high_ 2027 2028 2029def sls_exists(mods, test=None, queue=False, **kwargs): 2030 """ 2031 Tests for the existence the of a specific SLS or list of SLS files on the 2032 master. Similar to :py:func:`state.show_sls <salt.modules.state.show_sls>`, 2033 rather than returning state details, returns True or False. The default 2034 environment is ``base``, use ``saltenv`` to specify a different environment. 2035 2036 .. versionadded:: 2019.2.0 2037 2038 saltenv 2039 Specify a salt fileserver environment from which to look for the SLS files 2040 specified in the ``mods`` argument 2041 2042 CLI Example: 2043 2044 .. code-block:: bash 2045 2046 salt '*' state.sls_exists core,edit.vim saltenv=dev 2047 """ 2048 return isinstance(show_sls(mods, test=test, queue=queue, **kwargs), dict) 2049 2050 2051def id_exists(ids, mods, test=None, queue=False, **kwargs): 2052 """ 2053 Tests for the existence of a specific ID or list of IDs within the 2054 specified SLS file(s). Similar to :py:func:`state.sls_exists 2055 <salt.modules.state.sls_exists>`, returns True or False. The default 2056 environment is base``, use ``saltenv`` to specify a different environment. 2057 2058 .. versionadded:: 2019.2.0 2059 2060 saltenv 2061 Specify a salt fileserver environment from which to look for the SLS files 2062 specified in the ``mods`` argument 2063 2064 CLI Example: 2065 2066 .. code-block:: bash 2067 2068 salt '*' state.id_exists create_myfile,update_template filestate saltenv=dev 2069 """ 2070 ids = salt.utils.args.split_input(ids) 2071 ids = set(ids) 2072 sls_ids = { 2073 x["__id__"] for x in show_low_sls(mods, test=test, queue=queue, **kwargs) 2074 } 2075 return ids.issubset(sls_ids) 2076 2077 2078def show_top(queue=False, **kwargs): 2079 """ 2080 Return the top data that the minion will use for a highstate 2081 2082 CLI Example: 2083 2084 .. code-block:: bash 2085 2086 salt '*' state.show_top 2087 """ 2088 if "env" in kwargs: 2089 # "env" is not supported; Use "saltenv". 2090 kwargs.pop("env") 2091 2092 conflict = _check_queue(queue, kwargs) 2093 if conflict is not None: 2094 return conflict 2095 2096 opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) 2097 try: 2098 st_ = salt.state.HighState( 2099 opts, proxy=__proxy__, initial_pillar=_get_initial_pillar(opts) 2100 ) 2101 except NameError: 2102 st_ = salt.state.HighState(opts, initial_pillar=_get_initial_pillar(opts)) 2103 2104 with st_: 2105 errors = _get_pillar_errors(kwargs, pillar=st_.opts["pillar"]) 2106 if errors: 2107 __context__["retcode"] = salt.defaults.exitcodes.EX_PILLAR_FAILURE 2108 raise CommandExecutionError("Pillar failed to render", info=errors) 2109 2110 errors = [] 2111 top_ = st_.get_top() 2112 errors += st_.verify_tops(top_) 2113 if errors: 2114 __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR 2115 return errors 2116 matches = st_.top_matches(top_) 2117 return matches 2118 2119 2120def single(fun, name, test=None, queue=False, **kwargs): 2121 """ 2122 Execute a single state function with the named kwargs, returns False if 2123 insufficient data is sent to the command 2124 2125 By default, the values of the kwargs will be parsed as YAML. So, you can 2126 specify lists values, or lists of single entry key-value maps, as you 2127 would in a YAML salt file. Alternatively, JSON format of keyword values 2128 is also supported. 2129 2130 CLI Example: 2131 2132 .. code-block:: bash 2133 2134 salt '*' state.single pkg.installed name=vim 2135 2136 """ 2137 conflict = _check_queue(queue, kwargs) 2138 if conflict is not None: 2139 return conflict 2140 comps = fun.split(".") 2141 if len(comps) < 2: 2142 __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR 2143 return "Invalid function passed" 2144 kwargs.update({"state": comps[0], "fun": comps[1], "__id__": name, "name": name}) 2145 orig_test = __opts__.get("test", None) 2146 opts = salt.utils.state.get_sls_opts(__opts__, **kwargs) 2147 opts["test"] = _get_test_value(test, **kwargs) 2148 2149 pillar_override = kwargs.get("pillar") 2150 pillar_enc = kwargs.get("pillar_enc") 2151 if ( 2152 pillar_enc is None 2153 and pillar_override is not None 2154 and not isinstance(pillar_override, dict) 2155 ): 2156 raise SaltInvocationError( 2157 "Pillar data must be formatted as a dictionary, unless pillar_enc " 2158 "is specified." 2159 ) 2160 2161 try: 2162 st_ = salt.state.State( 2163 opts, 2164 pillar_override, 2165 pillar_enc=pillar_enc, 2166 proxy=__proxy__, 2167 initial_pillar=_get_initial_pillar(opts), 2168 ) 2169 except NameError: 2170 st_ = salt.state.State( 2171 opts, 2172 pillar_override, 2173 pillar_enc=pillar_enc, 2174 initial_pillar=_get_initial_pillar(opts), 2175 ) 2176 err = st_.verify_data(kwargs) 2177 if err: 2178 __context__["retcode"] = salt.defaults.exitcodes.EX_STATE_COMPILER_ERROR 2179 return err 2180 2181 st_._mod_init(kwargs) 2182 snapper_pre = _snapper_pre(opts, kwargs.get("__pub_jid", "called localy")) 2183 ret = { 2184 "{0[state]}_|-{0[__id__]}_|-{0[name]}_|-{0[fun]}".format(kwargs): st_.call( 2185 kwargs 2186 ) 2187 } 2188 _set_retcode(ret) 2189 # Work around Windows multiprocessing bug, set __opts__['test'] back to 2190 # value from before this function was run. 2191 _snapper_post(opts, kwargs.get("__pub_jid", "called localy"), snapper_pre) 2192 __opts__["test"] = orig_test 2193 return ret 2194 2195 2196def clear_cache(): 2197 """ 2198 Clear out cached state files, forcing even cache runs to refresh the cache 2199 on the next state execution. 2200 2201 Remember that the state cache is completely disabled by default, this 2202 execution only applies if cache=True is used in states 2203 2204 CLI Example: 2205 2206 .. code-block:: bash 2207 2208 salt '*' state.clear_cache 2209 """ 2210 ret = [] 2211 for fn_ in os.listdir(__opts__["cachedir"]): 2212 if fn_.endswith(".cache.p"): 2213 path = os.path.join(__opts__["cachedir"], fn_) 2214 if not os.path.isfile(path): 2215 continue 2216 os.remove(path) 2217 ret.append(fn_) 2218 return ret 2219 2220 2221def pkg(pkg_path, pkg_sum, hash_type, test=None, **kwargs): 2222 """ 2223 Execute a packaged state run, the packaged state run will exist in a 2224 tarball available locally. This packaged state 2225 can be generated using salt-ssh. 2226 2227 CLI Example: 2228 2229 .. code-block:: bash 2230 2231 salt '*' state.pkg /tmp/salt_state.tgz 760a9353810e36f6d81416366fc426dc md5 2232 """ 2233 # TODO - Add ability to download from salt master or other source 2234 popts = salt.utils.state.get_sls_opts(__opts__, **kwargs) 2235 if not os.path.isfile(pkg_path): 2236 return {} 2237 if not salt.utils.hashutils.get_hash(pkg_path, hash_type) == pkg_sum: 2238 return {} 2239 root = tempfile.mkdtemp() 2240 s_pkg = tarfile.open(pkg_path, "r:gz") 2241 # Verify that the tarball does not extract outside of the intended root 2242 members = s_pkg.getmembers() 2243 for member in members: 2244 if salt.utils.stringutils.to_unicode(member.path).startswith( 2245 (os.sep, "..{}".format(os.sep)) 2246 ): 2247 return {} 2248 elif "..{}".format(os.sep) in salt.utils.stringutils.to_unicode(member.path): 2249 return {} 2250 s_pkg.extractall(root) 2251 s_pkg.close() 2252 lowstate_json = os.path.join(root, "lowstate.json") 2253 with salt.utils.files.fopen(lowstate_json, "r") as fp_: 2254 lowstate = salt.utils.json.load(fp_) 2255 # Check for errors in the lowstate 2256 for chunk in lowstate: 2257 if not isinstance(chunk, dict): 2258 return lowstate 2259 pillar_json = os.path.join(root, "pillar.json") 2260 if os.path.isfile(pillar_json): 2261 with salt.utils.files.fopen(pillar_json, "r") as fp_: 2262 pillar_override = salt.utils.json.load(fp_) 2263 else: 2264 pillar_override = None 2265 2266 roster_grains_json = os.path.join(root, "roster_grains.json") 2267 if os.path.isfile(roster_grains_json): 2268 with salt.utils.files.fopen(roster_grains_json, "r") as fp_: 2269 roster_grains = _format_cached_grains(salt.utils.json.load(fp_)) 2270 2271 if os.path.isfile(roster_grains_json): 2272 popts["grains"] = roster_grains 2273 popts["fileclient"] = "local" 2274 popts["file_roots"] = {} 2275 popts["test"] = _get_test_value(test, **kwargs) 2276 envs = os.listdir(root) 2277 for fn_ in envs: 2278 full = os.path.join(root, fn_) 2279 if not os.path.isdir(full): 2280 continue 2281 popts["file_roots"][fn_] = [full] 2282 st_ = salt.state.State(popts, pillar_override=pillar_override) 2283 snapper_pre = _snapper_pre(popts, kwargs.get("__pub_jid", "called localy")) 2284 ret = st_.call_chunks(lowstate) 2285 ret = st_.call_listen(lowstate, ret) 2286 try: 2287 shutil.rmtree(root) 2288 except OSError: 2289 pass 2290 _set_retcode(ret) 2291 _snapper_post(popts, kwargs.get("__pub_jid", "called localy"), snapper_pre) 2292 return ret 2293 2294 2295def disable(states): 2296 """ 2297 Disable state runs. 2298 2299 CLI Example: 2300 2301 .. code-block:: bash 2302 2303 salt '*' state.disable highstate 2304 2305 salt '*' state.disable highstate,test.succeed_without_changes 2306 2307 .. note:: 2308 To disable a state file from running provide the same name that would 2309 be passed in a state.sls call. 2310 2311 salt '*' state.disable bind.config 2312 2313 """ 2314 ret = {"res": True, "msg": ""} 2315 2316 states = salt.utils.args.split_input(states) 2317 2318 msg = [] 2319 _disabled_state_runs = __salt__["grains.get"]("state_runs_disabled") 2320 if not isinstance(_disabled_state_runs, list): 2321 _disabled_state_runs = [] 2322 2323 _changed = False 2324 for _state in states: 2325 if _state in _disabled_state_runs: 2326 msg.append("Info: {} state already disabled.".format(_state)) 2327 else: 2328 msg.append("Info: {} state disabled.".format(_state)) 2329 _disabled_state_runs.append(_state) 2330 _changed = True 2331 2332 if _changed: 2333 __salt__["grains.setval"]("state_runs_disabled", _disabled_state_runs) 2334 2335 ret["msg"] = "\n".join(msg) 2336 2337 # refresh the grains 2338 __salt__["saltutil.refresh_modules"]() 2339 2340 return ret 2341 2342 2343def enable(states): 2344 """ 2345 Enable state function or sls run 2346 2347 CLI Example: 2348 2349 .. code-block:: bash 2350 2351 salt '*' state.enable highstate 2352 2353 salt '*' state.enable test.succeed_without_changes 2354 2355 .. note:: 2356 To enable a state file from running provide the same name that would 2357 be passed in a state.sls call. 2358 2359 salt '*' state.disable bind.config 2360 2361 """ 2362 ret = {"res": True, "msg": ""} 2363 2364 states = salt.utils.args.split_input(states) 2365 log.debug("states %s", states) 2366 2367 msg = [] 2368 _disabled_state_runs = __salt__["grains.get"]("state_runs_disabled") 2369 if not isinstance(_disabled_state_runs, list): 2370 _disabled_state_runs = [] 2371 2372 _changed = False 2373 for _state in states: 2374 log.debug("_state %s", _state) 2375 if _state not in _disabled_state_runs: 2376 msg.append("Info: {} state already enabled.".format(_state)) 2377 else: 2378 msg.append("Info: {} state enabled.".format(_state)) 2379 _disabled_state_runs.remove(_state) 2380 _changed = True 2381 2382 if _changed: 2383 __salt__["grains.setval"]("state_runs_disabled", _disabled_state_runs) 2384 2385 ret["msg"] = "\n".join(msg) 2386 2387 # refresh the grains 2388 __salt__["saltutil.refresh_modules"]() 2389 2390 return ret 2391 2392 2393def list_disabled(): 2394 """ 2395 List the states which are currently disabled 2396 2397 CLI Example: 2398 2399 .. code-block:: bash 2400 2401 salt '*' state.list_disabled 2402 """ 2403 return __salt__["grains.get"]("state_runs_disabled") 2404 2405 2406def _disabled(funs): 2407 """ 2408 Return messages for disabled states 2409 that match state functions in funs. 2410 """ 2411 ret = [] 2412 _disabled_state_runs = __salt__["grains.get"]("state_runs_disabled") 2413 if not isinstance(_disabled_state_runs, list): 2414 _disabled_state_runs = [] 2415 for state in funs: 2416 for _state in _disabled_state_runs: 2417 if ".*" in _state: 2418 target_state = _state.split(".")[0] 2419 target_state = ( 2420 target_state + "." 2421 if not target_state.endswith(".") 2422 else target_state 2423 ) 2424 if state.startswith(target_state): 2425 err = ( 2426 'The state file "{0}" is currently disabled by "{1}", ' 2427 "to re-enable, run state.enable {1}.".format( 2428 state, 2429 _state, 2430 ) 2431 ) 2432 ret.append(err) 2433 continue 2434 else: 2435 if _state == state: 2436 err = ( 2437 'The state file "{0}" is currently disabled, ' 2438 "to re-enable, run state.enable {0}.".format( 2439 _state, 2440 ) 2441 ) 2442 ret.append(err) 2443 continue 2444 return ret 2445 2446 2447def event( 2448 tagmatch="*", count=-1, quiet=False, sock_dir=None, pretty=False, node="minion" 2449): 2450 r""" 2451 Watch Salt's event bus and block until the given tag is matched 2452 2453 .. versionadded:: 2016.3.0 2454 .. versionchanged:: 2019.2.0 2455 ``tagmatch`` can now be either a glob or regular expression. 2456 2457 This is useful for utilizing Salt's event bus from shell scripts or for 2458 taking simple actions directly from the CLI. 2459 2460 Enable debug logging to see ignored events. 2461 2462 :param tagmatch: the event is written to stdout for each tag that matches 2463 this glob or regular expression. 2464 :param count: this number is decremented for each event that matches the 2465 ``tagmatch`` parameter; pass ``-1`` to listen forever. 2466 :param quiet: do not print to stdout; just block 2467 :param sock_dir: path to the Salt master's event socket file. 2468 :param pretty: Output the JSON all on a single line if ``False`` (useful 2469 for shell tools); pretty-print the JSON output if ``True``. 2470 :param node: Watch the minion-side or master-side event bus. 2471 2472 CLI Example: 2473 2474 .. code-block:: bash 2475 2476 salt-call --local state.event pretty=True 2477 """ 2478 with salt.utils.event.get_event( 2479 node, 2480 sock_dir or __opts__["sock_dir"], 2481 __opts__["transport"], 2482 opts=__opts__, 2483 listen=True, 2484 ) as sevent: 2485 2486 while True: 2487 ret = sevent.get_event(full=True, auto_reconnect=True) 2488 if ret is None: 2489 continue 2490 2491 if salt.utils.stringutils.expr_match(ret["tag"], tagmatch): 2492 if not quiet: 2493 salt.utils.stringutils.print_cli( 2494 "{}\t{}".format( 2495 salt.utils.stringutils.to_str(ret["tag"]), 2496 salt.utils.json.dumps( 2497 salt.utils.data.decode(ret["data"]), 2498 sort_keys=pretty, 2499 indent=None if not pretty else 4, 2500 ), 2501 ) 2502 ) 2503 sys.stdout.flush() 2504 2505 if count > 0: 2506 count -= 1 2507 log.debug("Remaining event matches: %s", count) 2508 2509 if count == 0: 2510 break 2511 else: 2512 log.debug("Skipping event tag: %s", ret["tag"]) 2513 continue 2514