1
0

test_pillar.py 45 KB

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