test_pillar.py 47 KB

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