"Fossies" - the Fresh Open Source Software Archive

Member "salt-3002.2/tests/unit/test_pillar.py" (18 Nov 2020, 49743 Bytes) of package /linux/misc/salt-3002.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Python source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "test_pillar.py": 3002.1_vs_3002.2.

    1 """
    2     :codeauthor: Pedro Algarvio (pedro@algarvio.me)
    3     :codeauthor: Alexandru Bleotu (alexandru.bleotu@morganstanley.com)
    4 
    5     tests.unit.pillar_test
    6     ~~~~~~~~~~~~~~~~~~~~~~
    7 """
    8 
    9 
   10 import logging
   11 import os
   12 import shutil
   13 import tempfile
   14 import textwrap
   15 
   16 import salt.config
   17 import salt.exceptions
   18 import salt.fileclient
   19 import salt.utils.stringutils
   20 from salt.utils.files import fopen
   21 from tests.support.helpers import with_tempdir
   22 from tests.support.mock import MagicMock, patch
   23 from tests.support.runtests import RUNTIME_VARS
   24 from tests.support.unit import TestCase
   25 
   26 log = logging.getLogger(__name__)
   27 
   28 
   29 class MockFileclient:
   30     def __init__(self, cache_file=None, get_state=None, list_states=None):
   31         if cache_file is not None:
   32             self.cache_file = lambda *x, **y: cache_file
   33         if get_state is not None:
   34             self.get_state = lambda sls, env: get_state[sls]
   35         if list_states is not None:
   36             self.list_states = lambda *x, **y: list_states
   37 
   38     # pylint: disable=unused-argument,no-method-argument,method-hidden
   39     def cache_file(*args, **kwargs):
   40         raise NotImplementedError()
   41 
   42     def get_state(*args, **kwargs):
   43         raise NotImplementedError()
   44 
   45     def list_states(*args, **kwargs):
   46         raise NotImplementedError()
   47 
   48     # pylint: enable=unused-argument,no-method-argument,method-hidden
   49 
   50 
   51 class PillarTestCase(TestCase):
   52     def tearDown(self):
   53         for attrname in (
   54             "generic_file",
   55             "generic_minion_file",
   56             "ssh_file",
   57             "ssh_minion_file",
   58             "top_file",
   59         ):
   60             try:
   61                 delattr(self, attrname)
   62             except AttributeError:
   63                 continue
   64 
   65     def test_pillarenv_from_saltenv(self):
   66         with patch("salt.pillar.compile_template") as compile_template:
   67             opts = {
   68                 "optimization_order": [0, 1, 2],
   69                 "renderer": "json",
   70                 "renderer_blacklist": [],
   71                 "renderer_whitelist": [],
   72                 "state_top": "",
   73                 "pillar_roots": {"dev": [], "base": []},
   74                 "file_roots": {"dev": [], "base": []},
   75                 "extension_modules": "",
   76                 "pillarenv_from_saltenv": True,
   77             }
   78             grains = {
   79                 "os": "Ubuntu",
   80             }
   81             pillar = salt.pillar.Pillar(opts, grains, "mocked-minion", "dev")
   82             self.assertEqual(pillar.opts["saltenv"], "dev")
   83             self.assertEqual(pillar.opts["pillarenv"], "dev")
   84 
   85     def test_ext_pillar_no_extra_minion_data_val_dict(self):
   86         opts = {
   87             "optimization_order": [0, 1, 2],
   88             "renderer": "json",
   89             "renderer_blacklist": [],
   90             "renderer_whitelist": [],
   91             "state_top": "",
   92             "pillar_roots": {"dev": [], "base": []},
   93             "file_roots": {"dev": [], "base": []},
   94             "extension_modules": "",
   95             "pillarenv_from_saltenv": True,
   96         }
   97         mock_ext_pillar_func = MagicMock()
   98         with patch(
   99             "salt.loader.pillars",
  100             MagicMock(return_value={"fake_ext_pillar": mock_ext_pillar_func}),
  101         ):
  102             pillar = salt.pillar.Pillar(opts, {}, "mocked-minion", "dev")
  103         # ext pillar function doesn't have the extra_minion_data arg
  104         with patch(
  105             "salt.utils.args.get_function_argspec",
  106             MagicMock(return_value=MagicMock(args=[])),
  107         ):
  108             pillar._external_pillar_data(
  109                 "fake_pillar", {"arg": "foo"}, "fake_ext_pillar"
  110             )
  111         mock_ext_pillar_func.assert_called_once_with(
  112             "mocked-minion", "fake_pillar", arg="foo"
  113         )
  114         # ext pillar function has the extra_minion_data arg
  115         mock_ext_pillar_func.reset_mock()
  116         with patch(
  117             "salt.utils.args.get_function_argspec",
  118             MagicMock(return_value=MagicMock(args=["extra_minion_data"])),
  119         ):
  120             pillar._external_pillar_data(
  121                 "fake_pillar", {"arg": "foo"}, "fake_ext_pillar"
  122             )
  123         mock_ext_pillar_func.assert_called_once_with(
  124             "mocked-minion", "fake_pillar", arg="foo"
  125         )
  126 
  127     def test_ext_pillar_no_extra_minion_data_val_list(self):
  128         opts = {
  129             "optimization_order": [0, 1, 2],
  130             "renderer": "json",
  131             "renderer_blacklist": [],
  132             "renderer_whitelist": [],
  133             "state_top": "",
  134             "pillar_roots": {"dev": [], "base": []},
  135             "file_roots": {"dev": [], "base": []},
  136             "extension_modules": "",
  137             "pillarenv_from_saltenv": True,
  138         }
  139         mock_ext_pillar_func = MagicMock()
  140         with patch(
  141             "salt.loader.pillars",
  142             MagicMock(return_value={"fake_ext_pillar": mock_ext_pillar_func}),
  143         ):
  144             pillar = salt.pillar.Pillar(opts, {}, "mocked-minion", "dev")
  145         # ext pillar function doesn't have the extra_minion_data arg
  146         with patch(
  147             "salt.utils.args.get_function_argspec",
  148             MagicMock(return_value=MagicMock(args=[])),
  149         ):
  150             pillar._external_pillar_data("fake_pillar", ["foo"], "fake_ext_pillar")
  151         mock_ext_pillar_func.assert_called_once_with(
  152             "mocked-minion", "fake_pillar", "foo"
  153         )
  154         # ext pillar function has the extra_minion_data arg
  155         mock_ext_pillar_func.reset_mock()
  156         with patch(
  157             "salt.utils.args.get_function_argspec",
  158             MagicMock(return_value=MagicMock(args=["extra_minion_data"])),
  159         ):
  160             pillar._external_pillar_data("fake_pillar", ["foo"], "fake_ext_pillar")
  161         mock_ext_pillar_func.assert_called_once_with(
  162             "mocked-minion", "fake_pillar", "foo"
  163         )
  164 
  165     def test_ext_pillar_no_extra_minion_data_val_elem(self):
  166         opts = {
  167             "optimization_order": [0, 1, 2],
  168             "renderer": "json",
  169             "renderer_blacklist": [],
  170             "renderer_whitelist": [],
  171             "state_top": "",
  172             "pillar_roots": {"dev": [], "base": []},
  173             "file_roots": {"dev": [], "base": []},
  174             "extension_modules": "",
  175             "pillarenv_from_saltenv": True,
  176         }
  177         mock_ext_pillar_func = MagicMock()
  178         with patch(
  179             "salt.loader.pillars",
  180             MagicMock(return_value={"fake_ext_pillar": mock_ext_pillar_func}),
  181         ):
  182             pillar = salt.pillar.Pillar(opts, {}, "mocked-minion", "dev")
  183         # ext pillar function doesn't have the extra_minion_data arg
  184         with patch(
  185             "salt.utils.args.get_function_argspec",
  186             MagicMock(return_value=MagicMock(args=[])),
  187         ):
  188             pillar._external_pillar_data("fake_pillar", "fake_val", "fake_ext_pillar")
  189         mock_ext_pillar_func.assert_called_once_with(
  190             "mocked-minion", "fake_pillar", "fake_val"
  191         )
  192         # ext pillar function has the extra_minion_data arg
  193         mock_ext_pillar_func.reset_mock()
  194         with patch(
  195             "salt.utils.args.get_function_argspec",
  196             MagicMock(return_value=MagicMock(args=["extra_minion_data"])),
  197         ):
  198             pillar._external_pillar_data("fake_pillar", "fake_val", "fake_ext_pillar")
  199         mock_ext_pillar_func.assert_called_once_with(
  200             "mocked-minion", "fake_pillar", "fake_val"
  201         )
  202 
  203     def test_ext_pillar_with_extra_minion_data_val_dict(self):
  204         opts = {
  205             "optimization_order": [0, 1, 2],
  206             "renderer": "json",
  207             "renderer_blacklist": [],
  208             "renderer_whitelist": [],
  209             "state_top": "",
  210             "pillar_roots": {"dev": [], "base": []},
  211             "file_roots": {"dev": [], "base": []},
  212             "extension_modules": "",
  213             "pillarenv_from_saltenv": True,
  214         }
  215         mock_ext_pillar_func = MagicMock()
  216         with patch(
  217             "salt.loader.pillars",
  218             MagicMock(return_value={"fake_ext_pillar": mock_ext_pillar_func}),
  219         ):
  220             pillar = salt.pillar.Pillar(
  221                 opts, {}, "mocked-minion", "dev", extra_minion_data={"fake_key": "foo"}
  222             )
  223         # ext pillar function doesn't have the extra_minion_data arg
  224         with patch(
  225             "salt.utils.args.get_function_argspec",
  226             MagicMock(return_value=MagicMock(args=[])),
  227         ):
  228             pillar._external_pillar_data(
  229                 "fake_pillar", {"arg": "foo"}, "fake_ext_pillar"
  230             )
  231         mock_ext_pillar_func.assert_called_once_with(
  232             "mocked-minion", "fake_pillar", arg="foo"
  233         )
  234         # ext pillar function has the extra_minion_data arg
  235         mock_ext_pillar_func.reset_mock()
  236         with patch(
  237             "salt.utils.args.get_function_argspec",
  238             MagicMock(return_value=MagicMock(args=["extra_minion_data"])),
  239         ):
  240             pillar._external_pillar_data(
  241                 "fake_pillar", {"arg": "foo"}, "fake_ext_pillar"
  242             )
  243         mock_ext_pillar_func.assert_called_once_with(
  244             "mocked-minion",
  245             "fake_pillar",
  246             arg="foo",
  247             extra_minion_data={"fake_key": "foo"},
  248         )
  249 
  250     def test_ext_pillar_with_extra_minion_data_val_list(self):
  251         opts = {
  252             "optimization_order": [0, 1, 2],
  253             "renderer": "json",
  254             "renderer_blacklist": [],
  255             "renderer_whitelist": [],
  256             "state_top": "",
  257             "pillar_roots": {"dev": [], "base": []},
  258             "file_roots": {"dev": [], "base": []},
  259             "extension_modules": "",
  260             "pillarenv_from_saltenv": True,
  261         }
  262         mock_ext_pillar_func = MagicMock()
  263         with patch(
  264             "salt.loader.pillars",
  265             MagicMock(return_value={"fake_ext_pillar": mock_ext_pillar_func}),
  266         ):
  267             pillar = salt.pillar.Pillar(
  268                 opts, {}, "mocked-minion", "dev", extra_minion_data={"fake_key": "foo"}
  269             )
  270         # ext pillar function doesn't have the extra_minion_data arg
  271         with patch(
  272             "salt.utils.args.get_function_argspec",
  273             MagicMock(return_value=MagicMock(args=[])),
  274         ):
  275             pillar._external_pillar_data("fake_pillar", ["bar"], "fake_ext_pillar")
  276         mock_ext_pillar_func.assert_called_once_with(
  277             "mocked-minion", "fake_pillar", "bar"
  278         )
  279         # ext pillar function has the extra_minion_data arg
  280         mock_ext_pillar_func.reset_mock()
  281         with patch(
  282             "salt.utils.args.get_function_argspec",
  283             MagicMock(return_value=MagicMock(args=["extra_minion_data"])),
  284         ):
  285             pillar._external_pillar_data("fake_pillar", ["bar"], "fake_ext_pillar")
  286         mock_ext_pillar_func.assert_called_once_with(
  287             "mocked-minion", "fake_pillar", "bar", extra_minion_data={"fake_key": "foo"}
  288         )
  289 
  290     def test_ext_pillar_with_extra_minion_data_val_elem(self):
  291         opts = {
  292             "optimization_order": [0, 1, 2],
  293             "renderer": "json",
  294             "renderer_blacklist": [],
  295             "renderer_whitelist": [],
  296             "state_top": "",
  297             "pillar_roots": {"dev": [], "base": []},
  298             "file_roots": {"dev": [], "base": []},
  299             "extension_modules": "",
  300             "pillarenv_from_saltenv": True,
  301         }
  302         mock_ext_pillar_func = MagicMock()
  303         with patch(
  304             "salt.loader.pillars",
  305             MagicMock(return_value={"fake_ext_pillar": mock_ext_pillar_func}),
  306         ):
  307             pillar = salt.pillar.Pillar(
  308                 opts, {}, "mocked-minion", "dev", extra_minion_data={"fake_key": "foo"}
  309             )
  310         # ext pillar function doesn't have the extra_minion_data arg
  311         with patch(
  312             "salt.utils.args.get_function_argspec",
  313             MagicMock(return_value=MagicMock(args=[])),
  314         ):
  315             pillar._external_pillar_data("fake_pillar", "bar", "fake_ext_pillar")
  316         mock_ext_pillar_func.assert_called_once_with(
  317             "mocked-minion", "fake_pillar", "bar"
  318         )
  319         # ext pillar function has the extra_minion_data arg
  320         mock_ext_pillar_func.reset_mock()
  321         with patch(
  322             "salt.utils.args.get_function_argspec",
  323             MagicMock(return_value=MagicMock(args=["extra_minion_data"])),
  324         ):
  325             pillar._external_pillar_data("fake_pillar", "bar", "fake_ext_pillar")
  326         mock_ext_pillar_func.assert_called_once_with(
  327             "mocked-minion", "fake_pillar", "bar", extra_minion_data={"fake_key": "foo"}
  328         )
  329 
  330     def test_ext_pillar_first(self):
  331         """
  332         test when using ext_pillar and ext_pillar_first
  333         """
  334         opts = {
  335             "optimization_order": [0, 1, 2],
  336             "renderer": "yaml",
  337             "renderer_blacklist": [],
  338             "renderer_whitelist": [],
  339             "state_top": "",
  340             "pillar_roots": [],
  341             "extension_modules": "",
  342             "saltenv": "base",
  343             "file_roots": [],
  344             "ext_pillar_first": True,
  345         }
  346         grains = {
  347             "os": "Ubuntu",
  348             "os_family": "Debian",
  349             "oscodename": "raring",
  350             "osfullname": "Ubuntu",
  351             "osrelease": "13.04",
  352             "kernel": "Linux",
  353         }
  354 
  355         tempdir = tempfile.mkdtemp(dir=RUNTIME_VARS.TMP)
  356         try:
  357             sls_files = self._setup_test_topfile_sls_pillar_match(tempdir,)
  358             fc_mock = MockFileclient(
  359                 cache_file=sls_files["top"]["dest"],
  360                 list_states=["top", "ssh", "ssh.minion", "generic", "generic.minion"],
  361                 get_state=sls_files,
  362             )
  363             with patch.object(
  364                 salt.fileclient, "get_file_client", MagicMock(return_value=fc_mock)
  365             ), patch(
  366                 "salt.pillar.Pillar.ext_pillar",
  367                 MagicMock(
  368                     return_value=(
  369                         {"id": "minion", "phase": "alpha", "role": "database"},
  370                         [],
  371                     )
  372                 ),
  373             ):
  374                 pillar = salt.pillar.Pillar(opts, grains, "mocked-minion", "base")
  375                 self.assertEqual(pillar.compile_pillar()["generic"]["key1"], "value1")
  376         finally:
  377             shutil.rmtree(tempdir, ignore_errors=True)
  378 
  379     def test_dynamic_pillarenv(self):
  380         opts = {
  381             "optimization_order": [0, 1, 2],
  382             "renderer": "json",
  383             "renderer_blacklist": [],
  384             "renderer_whitelist": [],
  385             "state_top": "",
  386             "pillar_roots": {
  387                 "__env__": ["/srv/pillar/__env__"],
  388                 "base": ["/srv/pillar/base"],
  389             },
  390             "file_roots": {"base": ["/srv/salt/base"], "dev": ["/svr/salt/dev"]},
  391             "extension_modules": "",
  392         }
  393         pillar = salt.pillar.Pillar(opts, {}, "mocked-minion", "base", pillarenv="dev")
  394         self.assertEqual(
  395             pillar.opts["pillar_roots"],
  396             {"base": ["/srv/pillar/base"], "dev": ["/srv/pillar/__env__"]},
  397         )
  398 
  399     def test_ignored_dynamic_pillarenv(self):
  400         opts = {
  401             "optimization_order": [0, 1, 2],
  402             "renderer": "json",
  403             "renderer_blacklist": [],
  404             "renderer_whitelist": [],
  405             "state_top": "",
  406             "pillar_roots": {
  407                 "__env__": ["/srv/pillar/__env__"],
  408                 "base": ["/srv/pillar/base"],
  409             },
  410             "file_roots": {"base": ["/srv/salt/base"], "dev": ["/svr/salt/dev"]},
  411             "extension_modules": "",
  412         }
  413         pillar = salt.pillar.Pillar(opts, {}, "mocked-minion", "base", pillarenv="base")
  414         self.assertEqual(pillar.opts["pillar_roots"], {"base": ["/srv/pillar/base"]})
  415 
  416     @patch("salt.fileclient.Client.list_states")
  417     def test_malformed_pillar_sls(self, mock_list_states):
  418         with patch("salt.pillar.compile_template") as compile_template:
  419             opts = {
  420                 "optimization_order": [0, 1, 2],
  421                 "renderer": "json",
  422                 "renderer_blacklist": [],
  423                 "renderer_whitelist": [],
  424                 "state_top": "",
  425                 "pillar_roots": [],
  426                 "file_roots": [],
  427                 "extension_modules": "",
  428             }
  429             grains = {
  430                 "os": "Ubuntu",
  431                 "os_family": "Debian",
  432                 "oscodename": "raring",
  433                 "osfullname": "Ubuntu",
  434                 "osrelease": "13.04",
  435                 "kernel": "Linux",
  436             }
  437 
  438             mock_list_states.return_value = ["foo", "blah"]
  439             pillar = salt.pillar.Pillar(opts, grains, "mocked-minion", "base")
  440             # Mock getting the proper template files
  441             pillar.client.get_state = MagicMock(
  442                 return_value={
  443                     "dest": "/path/to/pillar/files/foo.sls",
  444                     "source": "salt://foo.sls",
  445                 }
  446             )
  447 
  448             # Template compilation returned a string
  449             compile_template.return_value = "BAHHH"
  450             self.assertEqual(
  451                 pillar.render_pillar({"base": ["foo.sls"]}),
  452                 ({}, ["SLS 'foo.sls' does not render to a dictionary"]),
  453             )
  454 
  455             # Template compilation returned a list
  456             compile_template.return_value = ["BAHHH"]
  457             self.assertEqual(
  458                 pillar.render_pillar({"base": ["foo.sls"]}),
  459                 ({}, ["SLS 'foo.sls' does not render to a dictionary"]),
  460             )
  461 
  462             # Template compilation returned a dictionary, which is what's expected
  463             compile_template.return_value = {"foo": "bar"}
  464             self.assertEqual(
  465                 pillar.render_pillar({"base": ["foo.sls"]}), ({"foo": "bar"}, [])
  466             )
  467 
  468             # Test improper includes
  469             compile_template.side_effect = [
  470                 {"foo": "bar", "include": "blah"},
  471                 {"foo2": "bar2"},
  472             ]
  473             self.assertEqual(
  474                 pillar.render_pillar({"base": ["foo.sls"]}),
  475                 (
  476                     {"foo": "bar", "include": "blah"},
  477                     ["Include Declaration in SLS 'foo.sls' is not formed as a list"],
  478                 ),
  479             )
  480 
  481             # Test includes as a list, which is what's expected
  482             compile_template.side_effect = [
  483                 {"foo": "bar", "include": ["blah"]},
  484                 {"foo2": "bar2"},
  485             ]
  486             self.assertEqual(
  487                 pillar.render_pillar({"base": ["foo.sls"]}),
  488                 ({"foo": "bar", "foo2": "bar2"}, []),
  489             )
  490 
  491             # Test includes as a list overriding data
  492             compile_template.side_effect = [
  493                 {"foo": "bar", "include": ["blah"]},
  494                 {"foo": "bar2"},
  495             ]
  496             self.assertEqual(
  497                 pillar.render_pillar({"base": ["foo.sls"]}), ({"foo": "bar"}, [])
  498             )
  499 
  500             # Test includes using empty key directive
  501             compile_template.side_effect = [
  502                 {"foo": "bar", "include": [{"blah": {"key": ""}}]},
  503                 {"foo": "bar2"},
  504             ]
  505             self.assertEqual(
  506                 pillar.render_pillar({"base": ["foo.sls"]}), ({"foo": "bar"}, [])
  507             )
  508 
  509             # Test includes using simple non-nested key
  510             compile_template.side_effect = [
  511                 {"foo": "bar", "include": [{"blah": {"key": "nested"}}]},
  512                 {"foo": "bar2"},
  513             ]
  514             self.assertEqual(
  515                 pillar.render_pillar({"base": ["foo.sls"]}),
  516                 ({"foo": "bar", "nested": {"foo": "bar2"}}, []),
  517             )
  518 
  519             # Test includes using nested key
  520             compile_template.side_effect = [
  521                 {"foo": "bar", "include": [{"blah": {"key": "nested:level"}}]},
  522                 {"foo": "bar2"},
  523             ]
  524             self.assertEqual(
  525                 pillar.render_pillar({"base": ["foo.sls"]}),
  526                 ({"foo": "bar", "nested": {"level": {"foo": "bar2"}}}, []),
  527             )
  528 
  529     def test_includes_override_sls(self):
  530         opts = {
  531             "optimization_order": [0, 1, 2],
  532             "renderer": "json",
  533             "renderer_blacklist": [],
  534             "renderer_whitelist": [],
  535             "state_top": "",
  536             "pillar_roots": {},
  537             "file_roots": {},
  538             "extension_modules": "",
  539         }
  540         grains = {
  541             "os": "Ubuntu",
  542             "os_family": "Debian",
  543             "oscodename": "raring",
  544             "osfullname": "Ubuntu",
  545             "osrelease": "13.04",
  546             "kernel": "Linux",
  547         }
  548         with patch("salt.pillar.compile_template") as compile_template, patch.object(
  549             salt.pillar.Pillar,
  550             "_Pillar__gather_avail",
  551             MagicMock(return_value={"base": ["blah", "foo"]}),
  552         ):
  553 
  554             # Test with option set to True
  555             opts["pillar_includes_override_sls"] = True
  556             pillar = salt.pillar.Pillar(opts, grains, "mocked-minion", "base")
  557             # Mock getting the proper template files
  558             pillar.client.get_state = MagicMock(
  559                 return_value={
  560                     "dest": "/path/to/pillar/files/foo.sls",
  561                     "source": "salt://foo.sls",
  562                 }
  563             )
  564 
  565             compile_template.side_effect = [
  566                 {"foo": "bar", "include": ["blah"]},
  567                 {"foo": "bar2"},
  568             ]
  569             self.assertEqual(
  570                 pillar.render_pillar({"base": ["foo.sls"]}), ({"foo": "bar2"}, [])
  571             )
  572 
  573             # Test with option set to False
  574             opts["pillar_includes_override_sls"] = False
  575             pillar = salt.pillar.Pillar(opts, grains, "mocked-minion", "base")
  576             # Mock getting the proper template files
  577             pillar.client.get_state = MagicMock(
  578                 return_value={
  579                     "dest": "/path/to/pillar/files/foo.sls",
  580                     "source": "salt://foo.sls",
  581                 }
  582             )
  583 
  584             compile_template.side_effect = [
  585                 {"foo": "bar", "include": ["blah"]},
  586                 {"foo": "bar2"},
  587             ]
  588             self.assertEqual(
  589                 pillar.render_pillar({"base": ["foo.sls"]}), ({"foo": "bar"}, [])
  590             )
  591 
  592     def test_topfile_order(self):
  593         opts = {
  594             "optimization_order": [0, 1, 2],
  595             "renderer": "yaml",
  596             "renderer_blacklist": [],
  597             "renderer_whitelist": [],
  598             "state_top": "",
  599             "pillar_roots": [],
  600             "extension_modules": "",
  601             "saltenv": "base",
  602             "file_roots": [],
  603         }
  604         grains = {
  605             "os": "Ubuntu",
  606             "os_family": "Debian",
  607             "oscodename": "raring",
  608             "osfullname": "Ubuntu",
  609             "osrelease": "13.04",
  610             "kernel": "Linux",
  611         }
  612 
  613         def _run_test(nodegroup_order, glob_order, expected):
  614             tempdir = tempfile.mkdtemp(dir=RUNTIME_VARS.TMP)
  615             try:
  616                 sls_files = self._setup_test_topfile_sls(
  617                     tempdir, nodegroup_order, glob_order
  618                 )
  619                 fc_mock = MockFileclient(
  620                     cache_file=sls_files["top"]["dest"],
  621                     list_states=[
  622                         "top",
  623                         "ssh",
  624                         "ssh.minion",
  625                         "generic",
  626                         "generic.minion",
  627                     ],
  628                     get_state=sls_files,
  629                 )
  630                 with patch.object(
  631                     salt.fileclient, "get_file_client", MagicMock(return_value=fc_mock)
  632                 ):
  633                     pillar = salt.pillar.Pillar(opts, grains, "mocked-minion", "base")
  634                     # Make sure that confirm_top.confirm_top returns True
  635                     pillar.matchers["confirm_top.confirm_top"] = lambda *x, **y: True
  636                     self.assertEqual(pillar.compile_pillar()["ssh"], expected)
  637             finally:
  638                 shutil.rmtree(tempdir, ignore_errors=True)
  639 
  640         # test case where glob match happens second and therefore takes
  641         # precedence over nodegroup match.
  642         _run_test(nodegroup_order=1, glob_order=2, expected="bar")
  643         # test case where nodegroup match happens second and therefore takes
  644         # precedence over glob match.
  645         _run_test(nodegroup_order=2, glob_order=1, expected="foo")
  646 
  647     def _setup_test_topfile_sls_pillar_match(self, tempdir):
  648         # Write a simple topfile and two pillar state files
  649         top_file = tempfile.NamedTemporaryFile(dir=tempdir, delete=False)
  650         s = """
  651 base:
  652   'phase:alpha':
  653     - match: pillar
  654     - generic
  655 """
  656         top_file.write(salt.utils.stringutils.to_bytes(s))
  657         top_file.flush()
  658         generic_file = tempfile.NamedTemporaryFile(dir=tempdir, delete=False)
  659         generic_file.write(
  660             b"""
  661 generic:
  662     key1: value1
  663 """
  664         )
  665         generic_file.flush()
  666         return {
  667             "top": {"path": "", "dest": top_file.name},
  668             "generic": {"path": "", "dest": generic_file.name},
  669         }
  670 
  671     def _setup_test_topfile_sls(self, tempdir, nodegroup_order, glob_order):
  672         # Write a simple topfile and two pillar state files
  673         top_file = tempfile.NamedTemporaryFile(dir=tempdir, delete=False)
  674         s = """
  675 base:
  676     group:
  677         - match: nodegroup
  678         - order: {nodegroup_order}
  679         - ssh
  680         - generic
  681     '*':
  682         - generic
  683     minion:
  684         - order: {glob_order}
  685         - ssh.minion
  686         - generic.minion
  687 """.format(
  688             nodegroup_order=nodegroup_order, glob_order=glob_order
  689         )
  690         top_file.write(salt.utils.stringutils.to_bytes(s))
  691         top_file.flush()
  692         ssh_file = tempfile.NamedTemporaryFile(dir=tempdir, delete=False)
  693         ssh_file.write(
  694             b"""
  695 ssh:
  696     foo
  697 """
  698         )
  699         ssh_file.flush()
  700         ssh_minion_file = tempfile.NamedTemporaryFile(dir=tempdir, delete=False)
  701         ssh_minion_file.write(
  702             b"""
  703 ssh:
  704     bar
  705 """
  706         )
  707         ssh_minion_file.flush()
  708         generic_file = tempfile.NamedTemporaryFile(dir=tempdir, delete=False)
  709         generic_file.write(
  710             b"""
  711 generic:
  712     key1:
  713       - value1
  714       - value2
  715     key2:
  716         sub_key1: []
  717 """
  718         )
  719         generic_file.flush()
  720         generic_minion_file = tempfile.NamedTemporaryFile(dir=tempdir, delete=False)
  721         generic_minion_file.write(
  722             b"""
  723 generic:
  724     key1:
  725       - value3
  726     key2:
  727         sub_key2: []
  728 """
  729         )
  730         generic_minion_file.flush()
  731 
  732         return {
  733             "top": {"path": "", "dest": top_file.name},
  734             "ssh": {"path": "", "dest": ssh_file.name},
  735             "ssh.minion": {"path": "", "dest": ssh_minion_file.name},
  736             "generic": {"path": "", "dest": generic_file.name},
  737             "generic.minion": {"path": "", "dest": generic_minion_file.name},
  738         }
  739 
  740     @with_tempdir()
  741     def test_include(self, tempdir):
  742         opts = {
  743             "optimization_order": [0, 1, 2],
  744             "renderer": "yaml",
  745             "renderer_blacklist": [],
  746             "renderer_whitelist": [],
  747             "state_top": "",
  748             "pillar_roots": [],
  749             "extension_modules": "",
  750             "saltenv": "base",
  751             "file_roots": [],
  752         }
  753         grains = {
  754             "os": "Ubuntu",
  755             "os_family": "Debian",
  756             "oscodename": "raring",
  757             "osfullname": "Ubuntu",
  758             "osrelease": "13.04",
  759             "kernel": "Linux",
  760         }
  761         sls_files = self._setup_test_include_sls(tempdir)
  762         fc_mock = MockFileclient(
  763             cache_file=sls_files["top"]["dest"],
  764             get_state=sls_files,
  765             list_states=[
  766                 "top",
  767                 "test.init",
  768                 "test.sub1",
  769                 "test.sub2",
  770                 "test.sub_wildcard_1",
  771                 "test.sub_with_init_dot",
  772                 "test.sub.with.slashes",
  773             ],
  774         )
  775         with patch.object(
  776             salt.fileclient, "get_file_client", MagicMock(return_value=fc_mock)
  777         ):
  778             pillar = salt.pillar.Pillar(opts, grains, "minion", "base")
  779             # Make sure that confirm_top.confirm_top returns True
  780             pillar.matchers["confirm_top.confirm_top"] = lambda *x, **y: True
  781             compiled_pillar = pillar.compile_pillar()
  782             self.assertEqual(compiled_pillar["foo_wildcard"], "bar_wildcard")
  783             self.assertEqual(compiled_pillar["foo1"], "bar1")
  784             self.assertEqual(compiled_pillar["foo2"], "bar2")
  785             self.assertEqual(compiled_pillar["sub_with_slashes"], "sub_slashes_worked")
  786             self.assertEqual(
  787                 compiled_pillar["sub_init_dot"], "sub_with_init_dot_worked"
  788             )
  789 
  790     def _setup_test_include_sls(self, tempdir):
  791         top_file = tempfile.NamedTemporaryFile(dir=tempdir, delete=False)
  792         top_file.write(
  793             b"""
  794 base:
  795     '*':
  796         - order: 1
  797         - test.sub2
  798     minion:
  799         - order: 2
  800         - test
  801 """
  802         )
  803         top_file.flush()
  804         init_sls = tempfile.NamedTemporaryFile(dir=tempdir, delete=False)
  805         init_sls.write(
  806             b"""
  807 include:
  808    - test.sub1
  809    - test.sub_wildcard*
  810    - .test.sub_with_init_dot
  811    - test/sub/with/slashes
  812 """
  813         )
  814         init_sls.flush()
  815         sub1_sls = tempfile.NamedTemporaryFile(dir=tempdir, delete=False)
  816         sub1_sls.write(
  817             b"""
  818 foo1:
  819   bar1
  820 """
  821         )
  822         sub1_sls.flush()
  823         sub2_sls = tempfile.NamedTemporaryFile(dir=tempdir, delete=False)
  824         sub2_sls.write(
  825             b"""
  826 foo2:
  827   bar2
  828 """
  829         )
  830         sub2_sls.flush()
  831 
  832         sub_wildcard_1_sls = tempfile.NamedTemporaryFile(dir=tempdir, delete=False)
  833         sub_wildcard_1_sls.write(
  834             b"""
  835 foo_wildcard:
  836    bar_wildcard
  837 """
  838         )
  839         sub_wildcard_1_sls.flush()
  840 
  841         sub_with_init_dot_sls = tempfile.NamedTemporaryFile(dir=tempdir, delete=False)
  842         sub_with_init_dot_sls.write(
  843             b"""
  844 sub_init_dot:
  845   sub_with_init_dot_worked
  846 """
  847         )
  848         sub_with_init_dot_sls.flush()
  849 
  850         sub_with_slashes_sls = tempfile.NamedTemporaryFile(dir=tempdir, delete=False)
  851         sub_with_slashes_sls.write(
  852             b"""
  853 sub_with_slashes:
  854   sub_slashes_worked
  855 """
  856         )
  857         sub_with_slashes_sls.flush()
  858 
  859         return {
  860             "top": {"path": "", "dest": top_file.name},
  861             "test": {"path": "", "dest": init_sls.name},
  862             "test.sub1": {"path": "", "dest": sub1_sls.name},
  863             "test.sub2": {"path": "", "dest": sub2_sls.name},
  864             "test.sub_wildcard_1": {"path": "", "dest": sub_wildcard_1_sls.name},
  865             "test.sub_with_init_dot": {"path": "", "dest": sub_with_init_dot_sls.name},
  866             "test.sub.with.slashes": {"path": "", "dest": sub_with_slashes_sls.name},
  867         }
  868 
  869     @with_tempdir()
  870     def test_relative_include(self, tempdir):
  871         join = os.path.join
  872         with fopen(join(tempdir, "top.sls"), "w") as f:
  873             print(
  874                 textwrap.dedent(
  875                     """
  876                     base:
  877                       '*':
  878                         - includer
  879                         - simple_includer
  880                         - includes.with.more.depth
  881                 """
  882                 ),
  883                 file=f,
  884             )
  885         includer_dir = join(tempdir, "includer")
  886         os.makedirs(includer_dir)
  887         with fopen(join(includer_dir, "init.sls"), "w") as f:
  888             print(
  889                 textwrap.dedent(
  890                     """
  891                     include:
  892                       - .this
  893                       - includer.that
  894                 """
  895                 ),
  896                 file=f,
  897             )
  898         with fopen(join(includer_dir, "this.sls"), "w") as f:
  899             print(
  900                 textwrap.dedent(
  901                     """
  902                     this:
  903                         is all good
  904                 """
  905                 ),
  906                 file=f,
  907             )
  908         with fopen(join(includer_dir, "that.sls"), "w") as f:
  909             print(
  910                 textwrap.dedent(
  911                     """
  912                     that:
  913                         is also all good
  914                 """
  915                 ),
  916                 file=f,
  917             )
  918 
  919         with fopen(join(tempdir, "simple_includer.sls"), "w") as simpleincluder:
  920             print(
  921                 textwrap.dedent(
  922                     """
  923                     include:
  924                       - .simple
  925                       - super_simple
  926                 """
  927                 ),
  928                 file=simpleincluder,
  929             )
  930         with fopen(join(tempdir, "simple.sls"), "w") as f:
  931             print(
  932                 textwrap.dedent(
  933                     """
  934                     simple:
  935                       simon
  936                 """
  937                 ),
  938                 file=f,
  939             )
  940         with fopen(join(tempdir, "super_simple.sls"), "w") as f:
  941             print(
  942                 textwrap.dedent(
  943                     """
  944                     super simple:
  945                       a caveman
  946                 """
  947                 ),
  948                 file=f,
  949             )
  950 
  951         depth_dir = join(tempdir, "includes", "with", "more")
  952         os.makedirs(depth_dir)
  953         with fopen(join(depth_dir, "depth.sls"), "w") as f:
  954             print(
  955                 textwrap.dedent(
  956                     """
  957                     include:
  958                       - .ramble
  959                       - includes.with.more.doors
  960 
  961                     mordor:
  962                         has dark depths
  963                 """
  964                 ),
  965                 file=f,
  966             )
  967 
  968         with fopen(join(depth_dir, "ramble.sls"), "w") as f:
  969             print(
  970                 textwrap.dedent(
  971                     """
  972                     found:
  973                         my precious
  974                 """
  975                 ),
  976                 file=f,
  977             )
  978 
  979         with fopen(join(depth_dir, "doors.sls"), "w") as f:
  980             print(
  981                 textwrap.dedent(
  982                     """
  983                     mojo:
  984                         bad risin'
  985                 """
  986                 ),
  987                 file=f,
  988             )
  989         opts = {
  990             "optimization_order": [0, 1, 2],
  991             "renderer": "yaml",
  992             "renderer_blacklist": [],
  993             "renderer_whitelist": [],
  994             "state_top": "top.sls",
  995             "pillar_roots": {"base": [tempdir]},
  996             "extension_modules": "",
  997             "saltenv": "base",
  998             "file_roots": [],
  999             "file_ignore_regex": None,
 1000             "file_ignore_glob": None,
 1001         }
 1002         grains = {
 1003             "os": "Ubuntu",
 1004             "os_family": "Debian",
 1005             "oscodename": "raring",
 1006             "osfullname": "Ubuntu",
 1007             "osrelease": "13.04",
 1008             "kernel": "Linux",
 1009         }
 1010         pillar = salt.pillar.Pillar(opts, grains, "minion", "base")
 1011         # Make sure that confirm_top.confirm_top returns True
 1012         pillar.matchers["confirm_top.confirm_top"] = lambda *x, **y: True
 1013 
 1014         # Act
 1015         compiled_pillar = pillar.compile_pillar()
 1016 
 1017         # Assert
 1018         self.assertEqual(compiled_pillar["this"], "is all good")
 1019         self.assertEqual(compiled_pillar["that"], "is also all good")
 1020         self.assertEqual(compiled_pillar["simple"], "simon")
 1021         self.assertEqual(compiled_pillar["super simple"], "a caveman")
 1022         self.assertEqual(compiled_pillar["mordor"], "has dark depths")
 1023         self.assertEqual(compiled_pillar["found"], "my precious")
 1024         self.assertEqual(compiled_pillar["mojo"], "bad risin'")
 1025 
 1026     @with_tempdir()
 1027     def test_missing_include(self, tempdir):
 1028         opts = {
 1029             "optimization_order": [0, 1, 2],
 1030             "renderer": "yaml",
 1031             "renderer_blacklist": [],
 1032             "renderer_whitelist": [],
 1033             "state_top": "top.sls",
 1034             "pillar_roots": {"base": [tempdir]},
 1035             "extension_modules": "",
 1036             "saltenv": "base",
 1037             "file_roots": [],
 1038             "file_ignore_regex": None,
 1039             "file_ignore_glob": None,
 1040         }
 1041         grains = {
 1042             "os": "Ubuntu",
 1043             "os_family": "Debian",
 1044             "oscodename": "raring",
 1045             "osfullname": "Ubuntu",
 1046             "osrelease": "13.04",
 1047             "kernel": "Linux",
 1048         }
 1049 
 1050         join = os.path.join
 1051         with fopen(join(tempdir, "top.sls"), "w") as f:
 1052             print(
 1053                 textwrap.dedent(
 1054                     """
 1055                     base:
 1056                       '*':
 1057                         - simple_include
 1058                 """
 1059                 ),
 1060                 file=f,
 1061             )
 1062         include_dir = join(tempdir, "simple_include")
 1063         os.makedirs(include_dir)
 1064         with fopen(join(include_dir, "init.sls"), "w") as f:
 1065             print(
 1066                 textwrap.dedent(
 1067                     """
 1068                     include:
 1069                       - simple_include.missing_include
 1070                     simple_include: is ok
 1071                     """
 1072                 ),
 1073                 file=f,
 1074             )
 1075 
 1076         pillar = salt.pillar.Pillar(opts, grains, "minion", "base")
 1077         # Make sure that confirm_top.confirm_top returns True
 1078         pillar.matchers["confirm_top.confirm_top"] = lambda *x, **y: True
 1079 
 1080         # Act
 1081         compiled_pillar = pillar.compile_pillar()
 1082 
 1083         # Assert
 1084         self.assertEqual(compiled_pillar["simple_include"], "is ok")
 1085         self.assertTrue("_errors" in compiled_pillar)
 1086         self.assertTrue(
 1087             "simple_include.missing_include" in compiled_pillar["_errors"][0]
 1088         )
 1089 
 1090 
 1091 @patch("salt.transport.client.ReqChannel.factory", MagicMock())
 1092 class RemotePillarTestCase(TestCase):
 1093     """
 1094     Tests for instantiating a RemotePillar in salt.pillar
 1095     """
 1096 
 1097     def setUp(self):
 1098         self.grains = {}
 1099 
 1100     def tearDown(self):
 1101         for attr in ("grains",):
 1102             try:
 1103                 delattr(self, attr)
 1104             except AttributeError:
 1105                 continue
 1106 
 1107     def test_get_opts_in_pillar_override_call(self):
 1108         mock_get_extra_minion_data = MagicMock(return_value={})
 1109         with patch(
 1110             "salt.pillar.RemotePillarMixin.get_ext_pillar_extra_minion_data",
 1111             mock_get_extra_minion_data,
 1112         ):
 1113 
 1114             salt.pillar.RemotePillar({}, self.grains, "mocked-minion", "dev")
 1115         mock_get_extra_minion_data.assert_called_once_with({"saltenv": "dev"})
 1116 
 1117     def test_multiple_keys_in_opts_added_to_pillar(self):
 1118         opts = {
 1119             "renderer": "json",
 1120             "path_to_add": "fake_data",
 1121             "path_to_add2": {"fake_data2": ["fake_data3", "fake_data4"]},
 1122             "pass_to_ext_pillars": ["path_to_add", "path_to_add2"],
 1123         }
 1124         pillar = salt.pillar.RemotePillar(opts, self.grains, "mocked-minion", "dev")
 1125         self.assertEqual(
 1126             pillar.extra_minion_data,
 1127             {
 1128                 "path_to_add": "fake_data",
 1129                 "path_to_add2": {"fake_data2": ["fake_data3", "fake_data4"]},
 1130             },
 1131         )
 1132 
 1133     def test_subkey_in_opts_added_to_pillar(self):
 1134         opts = {
 1135             "renderer": "json",
 1136             "path_to_add": "fake_data",
 1137             "path_to_add2": {
 1138                 "fake_data5": "fake_data6",
 1139                 "fake_data2": ["fake_data3", "fake_data4"],
 1140             },
 1141             "pass_to_ext_pillars": ["path_to_add2:fake_data5"],
 1142         }
 1143         pillar = salt.pillar.RemotePillar(opts, self.grains, "mocked-minion", "dev")
 1144         self.assertEqual(
 1145             pillar.extra_minion_data, {"path_to_add2": {"fake_data5": "fake_data6"}}
 1146         )
 1147 
 1148     def test_non_existent_leaf_opt_in_add_to_pillar(self):
 1149         opts = {
 1150             "renderer": "json",
 1151             "path_to_add": "fake_data",
 1152             "path_to_add2": {
 1153                 "fake_data5": "fake_data6",
 1154                 "fake_data2": ["fake_data3", "fake_data4"],
 1155             },
 1156             "pass_to_ext_pillars": ["path_to_add2:fake_data_non_exist"],
 1157         }
 1158         pillar = salt.pillar.RemotePillar(opts, self.grains, "mocked-minion", "dev")
 1159         self.assertEqual(pillar.pillar_override, {})
 1160 
 1161     def test_non_existent_intermediate_opt_in_add_to_pillar(self):
 1162         opts = {
 1163             "renderer": "json",
 1164             "path_to_add": "fake_data",
 1165             "path_to_add2": {
 1166                 "fake_data5": "fake_data6",
 1167                 "fake_data2": ["fake_data3", "fake_data4"],
 1168             },
 1169             "pass_to_ext_pillars": ["path_to_add_no_exist"],
 1170         }
 1171         pillar = salt.pillar.RemotePillar(opts, self.grains, "mocked-minion", "dev")
 1172         self.assertEqual(pillar.pillar_override, {})
 1173 
 1174     def test_malformed_add_to_pillar(self):
 1175         opts = {
 1176             "renderer": "json",
 1177             "path_to_add": "fake_data",
 1178             "path_to_add2": {
 1179                 "fake_data5": "fake_data6",
 1180                 "fake_data2": ["fake_data3", "fake_data4"],
 1181             },
 1182             "pass_to_ext_pillars": MagicMock(),
 1183         }
 1184         with self.assertRaises(salt.exceptions.SaltClientError) as excinfo:
 1185             salt.pillar.RemotePillar(opts, self.grains, "mocked-minion", "dev")
 1186         self.assertEqual(
 1187             excinfo.exception.strerror, "'pass_to_ext_pillars' config is malformed."
 1188         )
 1189 
 1190     def test_pillar_send_extra_minion_data_from_config(self):
 1191         opts = {
 1192             "renderer": "json",
 1193             "pillarenv": "fake_pillar_env",
 1194             "path_to_add": "fake_data",
 1195             "path_to_add2": {
 1196                 "fake_data5": "fake_data6",
 1197                 "fake_data2": ["fake_data3", "fake_data4"],
 1198             },
 1199             "pass_to_ext_pillars": ["path_to_add"],
 1200         }
 1201         mock_channel = MagicMock(
 1202             crypted_transfer_decode_dictentry=MagicMock(return_value={})
 1203         )
 1204         with patch(
 1205             "salt.transport.client.ReqChannel.factory",
 1206             MagicMock(return_value=mock_channel),
 1207         ):
 1208             pillar = salt.pillar.RemotePillar(
 1209                 opts, self.grains, "mocked_minion", "fake_env"
 1210             )
 1211 
 1212         ret = pillar.compile_pillar()
 1213         self.assertEqual(pillar.channel, mock_channel)
 1214         mock_channel.crypted_transfer_decode_dictentry.assert_called_once_with(
 1215             {
 1216                 "cmd": "_pillar",
 1217                 "ver": "2",
 1218                 "id": "mocked_minion",
 1219                 "grains": {},
 1220                 "saltenv": "fake_env",
 1221                 "pillarenv": "fake_pillar_env",
 1222                 "pillar_override": {},
 1223                 "extra_minion_data": {"path_to_add": "fake_data"},
 1224             },
 1225             dictkey="pillar",
 1226         )
 1227 
 1228     def test_pillar_file_client_master_remote(self):
 1229         """
 1230         Test condition where local file_client and use_master_when_local option
 1231         returns a remote file client.
 1232         """
 1233         mocked_minion = MagicMock()
 1234         opts = {
 1235             "file_client": "local",
 1236             "use_master_when_local": True,
 1237             "pillar_cache": None,
 1238         }
 1239         pillar = salt.pillar.get_pillar(opts, self.grains, mocked_minion)
 1240         self.assertEqual(type(pillar), salt.pillar.RemotePillar)
 1241         self.assertNotEqual(type(pillar), salt.pillar.PillarCache)
 1242 
 1243 
 1244 @patch("salt.transport.client.AsyncReqChannel.factory", MagicMock())
 1245 class AsyncRemotePillarTestCase(TestCase):
 1246     """
 1247     Tests for instantiating a AsyncRemotePillar in salt.pillar
 1248     """
 1249 
 1250     def setUp(self):
 1251         self.grains = {}
 1252 
 1253     def tearDown(self):
 1254         for attr in ("grains",):
 1255             try:
 1256                 delattr(self, attr)
 1257             except AttributeError:
 1258                 continue
 1259 
 1260     def test_get_opts_in_pillar_override_call(self):
 1261         mock_get_extra_minion_data = MagicMock(return_value={})
 1262         with patch(
 1263             "salt.pillar.RemotePillarMixin.get_ext_pillar_extra_minion_data",
 1264             mock_get_extra_minion_data,
 1265         ):
 1266 
 1267             salt.pillar.RemotePillar({}, self.grains, "mocked-minion", "dev")
 1268         mock_get_extra_minion_data.assert_called_once_with({"saltenv": "dev"})
 1269 
 1270     def test_pillar_send_extra_minion_data_from_config(self):
 1271         opts = {
 1272             "renderer": "json",
 1273             "pillarenv": "fake_pillar_env",
 1274             "path_to_add": "fake_data",
 1275             "path_to_add2": {
 1276                 "fake_data5": "fake_data6",
 1277                 "fake_data2": ["fake_data3", "fake_data4"],
 1278             },
 1279             "pass_to_ext_pillars": ["path_to_add"],
 1280         }
 1281         mock_channel = MagicMock(
 1282             crypted_transfer_decode_dictentry=MagicMock(return_value={})
 1283         )
 1284         with patch(
 1285             "salt.transport.client.AsyncReqChannel.factory",
 1286             MagicMock(return_value=mock_channel),
 1287         ):
 1288             pillar = salt.pillar.RemotePillar(
 1289                 opts, self.grains, "mocked_minion", "fake_env"
 1290             )
 1291 
 1292         ret = pillar.compile_pillar()
 1293         mock_channel.crypted_transfer_decode_dictentry.assert_called_once_with(
 1294             {
 1295                 "cmd": "_pillar",
 1296                 "ver": "2",
 1297                 "id": "mocked_minion",
 1298                 "grains": {},
 1299                 "saltenv": "fake_env",
 1300                 "pillarenv": "fake_pillar_env",
 1301                 "pillar_override": {},
 1302                 "extra_minion_data": {"path_to_add": "fake_data"},
 1303             },
 1304             dictkey="pillar",
 1305         )
 1306 
 1307 
 1308 @patch("salt.transport.client.ReqChannel.factory", MagicMock())
 1309 class PillarCacheTestCase(TestCase):
 1310     """
 1311     Tests for instantiating a PillarCache in salt.pillar
 1312     """
 1313 
 1314     def setUp(self):
 1315         self.grains = {}
 1316 
 1317     @classmethod
 1318     def setUpClass(cls):
 1319         cls.mock_master_default_opts = salt.config.DEFAULT_MASTER_OPTS.copy()
 1320         cls.mock_master_default_opts["cachedir"] = tempfile.mkdtemp(
 1321             dir=RUNTIME_VARS.TMP
 1322         )
 1323 
 1324     def tearDown(self):
 1325         for attr in ("grains",):
 1326             try:
 1327                 delattr(self, attr)
 1328             except AttributeError:
 1329                 continue
 1330 
 1331     def test_compile_pillar_disk_cache(self):
 1332         self.mock_master_default_opts.update(
 1333             {"pillar_cache_backend": "disk", "pillar_cache_ttl": 3600}
 1334         )
 1335 
 1336         pillar = salt.pillar.PillarCache(
 1337             self.mock_master_default_opts,
 1338             self.grains,
 1339             "mocked_minion",
 1340             "fake_env",
 1341             pillarenv="base",
 1342         )
 1343 
 1344         with patch("salt.utils.cache.CacheDisk._write", MagicMock()):
 1345             with patch(
 1346                 "salt.pillar.PillarCache.fetch_pillar",
 1347                 side_effect=[{"foo": "bar"}, {"foo": "baz"}],
 1348             ):
 1349                 # Run once for pillarenv base
 1350                 ret = pillar.compile_pillar()
 1351                 expected_cache = {"mocked_minion": {"base": {"foo": "bar"}}}
 1352                 self.assertEqual(pillar.cache._dict, expected_cache)
 1353 
 1354                 # Run a second time for pillarenv base
 1355                 ret = pillar.compile_pillar()
 1356                 expected_cache = {"mocked_minion": {"base": {"foo": "bar"}}}
 1357                 self.assertEqual(pillar.cache._dict, expected_cache)
 1358 
 1359                 # Change the pillarenv
 1360                 pillar.pillarenv = "dev"
 1361 
 1362                 # Run once for pillarenv dev
 1363                 ret = pillar.compile_pillar()
 1364                 expected_cache = {
 1365                     "mocked_minion": {"base": {"foo": "bar"}, "dev": {"foo": "baz"}}
 1366                 }
 1367                 self.assertEqual(pillar.cache._dict, expected_cache)
 1368 
 1369                 # Run a second time for pillarenv dev
 1370                 ret = pillar.compile_pillar()
 1371                 expected_cache = {
 1372                     "mocked_minion": {"base": {"foo": "bar"}, "dev": {"foo": "baz"}}
 1373                 }
 1374                 self.assertEqual(pillar.cache._dict, expected_cache)
 1375 
 1376     def test_compile_pillar_memory_cache(self):
 1377         self.mock_master_default_opts.update(
 1378             {"pillar_cache_backend": "memory", "pillar_cache_ttl": 3600}
 1379         )
 1380 
 1381         pillar = salt.pillar.PillarCache(
 1382             self.mock_master_default_opts,
 1383             self.grains,
 1384             "mocked_minion",
 1385             "fake_env",
 1386             pillarenv="base",
 1387         )
 1388 
 1389         with patch(
 1390             "salt.pillar.PillarCache.fetch_pillar",
 1391             side_effect=[{"foo": "bar"}, {"foo": "baz"}],
 1392         ):
 1393             # Run once for pillarenv base
 1394             ret = pillar.compile_pillar()
 1395             expected_cache = {"base": {"foo": "bar"}}
 1396             self.assertIn("mocked_minion", pillar.cache)
 1397             self.assertEqual(pillar.cache["mocked_minion"], expected_cache)
 1398 
 1399             # Run a second time for pillarenv base
 1400             ret = pillar.compile_pillar()
 1401             expected_cache = {"base": {"foo": "bar"}}
 1402             self.assertIn("mocked_minion", pillar.cache)
 1403             self.assertEqual(pillar.cache["mocked_minion"], expected_cache)
 1404 
 1405             # Change the pillarenv
 1406             pillar.pillarenv = "dev"
 1407 
 1408             # Run once for pillarenv dev
 1409             ret = pillar.compile_pillar()
 1410             expected_cache = {"base": {"foo": "bar"}, "dev": {"foo": "baz"}}
 1411             self.assertIn("mocked_minion", pillar.cache)
 1412             self.assertEqual(pillar.cache["mocked_minion"], expected_cache)
 1413 
 1414             # Run a second time for pillarenv dev
 1415             ret = pillar.compile_pillar()
 1416             expected_cache = {"base": {"foo": "bar"}, "dev": {"foo": "baz"}}
 1417             self.assertIn("mocked_minion", pillar.cache)
 1418             self.assertEqual(pillar.cache["mocked_minion"], expected_cache)