1
0

test_saltutil.py 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  1. # -*- coding: utf-8 -*-
  2. """
  3. Integration tests for the saltutil module.
  4. """
  5. from __future__ import absolute_import, print_function, unicode_literals
  6. import os
  7. import shutil
  8. import textwrap
  9. import threading
  10. import time
  11. import pytest
  12. import salt.config
  13. import salt.defaults.events
  14. import salt.utils.event
  15. import salt.utils.files
  16. import salt.utils.stringutils
  17. from tests.support.case import ModuleCase
  18. from tests.support.helpers import flaky, slowTest
  19. from tests.support.runtests import RUNTIME_VARS
  20. from tests.support.unit import skipIf
  21. @pytest.mark.windows_whitelisted
  22. @pytest.mark.usefixtures("salt_sub_minion")
  23. class SaltUtilModuleTest(ModuleCase):
  24. """
  25. Testcase for the saltutil execution module
  26. """
  27. @classmethod
  28. def setUpClass(cls):
  29. # Whell functions, on a minion, must run with the master running
  30. # along side the minion.
  31. # We copy the master config to the minion's configuration directory just
  32. # for this test since the test suite master and minion(s) do not share the
  33. # same configuration directory
  34. src = os.path.join(RUNTIME_VARS.TMP_CONF_DIR, "master")
  35. dst = os.path.join(RUNTIME_VARS.TMP_MINION_CONF_DIR, "master")
  36. cls.copied_master_config_file = None
  37. if not os.path.exists(dst):
  38. shutil.copyfile(src, dst)
  39. cls.copied_master_config_file = dst
  40. @classmethod
  41. def tearDownClass(cls):
  42. if cls.copied_master_config_file and os.path.exists(
  43. cls.copied_master_config_file
  44. ):
  45. os.unlink(cls.copied_master_config_file)
  46. cls.copied_master_config_file = None
  47. def setUp(self):
  48. self.run_function("saltutil.refresh_pillar")
  49. # Tests for the wheel function
  50. @slowTest
  51. def test_wheel_just_function(self):
  52. """
  53. Tests using the saltutil.wheel function when passing only a function.
  54. """
  55. # Wait for the pillar refresh to kick in, so that grains are ready to go
  56. time.sleep(3)
  57. ret = self.run_function("saltutil.wheel", ["minions.connected"])
  58. self.assertIn("minion", ret["return"])
  59. self.assertIn("sub_minion", ret["return"])
  60. @slowTest
  61. def test_wheel_with_arg(self):
  62. """
  63. Tests using the saltutil.wheel function when passing a function and an arg.
  64. """
  65. ret = self.run_function("saltutil.wheel", ["key.list", "minion"])
  66. self.assertEqual(ret["return"], {})
  67. @slowTest
  68. def test_wheel_no_arg_raise_error(self):
  69. """
  70. Tests using the saltutil.wheel function when passing a function that requires
  71. an arg, but one isn't supplied.
  72. """
  73. self.assertRaises(TypeError, "saltutil.wheel", ["key.list"])
  74. @slowTest
  75. def test_wheel_with_kwarg(self):
  76. """
  77. Tests using the saltutil.wheel function when passing a function and a kwarg.
  78. This function just generates a key pair, but doesn't do anything with it. We
  79. just need this for testing purposes.
  80. """
  81. ret = self.run_function("saltutil.wheel", ["key.gen"], keysize=1024)
  82. self.assertIn("pub", ret["return"])
  83. self.assertIn("priv", ret["return"])
  84. @pytest.mark.windows_whitelisted
  85. class SyncGrainsTest(ModuleCase):
  86. @slowTest
  87. def test_sync_grains(self):
  88. ret = self.run_function("saltutil.sync_grains")
  89. self.assertEqual(ret, [])
  90. @pytest.mark.windows_whitelisted
  91. class SaltUtilSyncModuleTest(ModuleCase):
  92. """
  93. Testcase for the saltutil sync execution module
  94. """
  95. def setUp(self):
  96. whitelist = {
  97. "modules": [],
  98. }
  99. self.run_function("saltutil.sync_all", extmod_whitelist=whitelist)
  100. def tearDown(self):
  101. self.run_function("saltutil.sync_all")
  102. @slowTest
  103. def test_sync_all(self):
  104. """
  105. Test syncing all ModuleCase
  106. """
  107. expected_return = {
  108. "engines": [],
  109. "clouds": [],
  110. "grains": [],
  111. "beacons": [],
  112. "utils": [],
  113. "returners": [],
  114. "modules": [
  115. "modules.depends_versioned",
  116. "modules.depends_versionless",
  117. "modules.mantest",
  118. "modules.override_test",
  119. "modules.runtests_decorators",
  120. "modules.runtests_helpers",
  121. "modules.salttest",
  122. ],
  123. "renderers": [],
  124. "log_handlers": [],
  125. "matchers": [],
  126. "states": [],
  127. "sdb": [],
  128. "proxymodules": [],
  129. "executors": [],
  130. "output": [],
  131. "thorium": [],
  132. "serializers": [],
  133. }
  134. ret = self.run_function("saltutil.sync_all")
  135. self.assertEqual(ret, expected_return)
  136. @slowTest
  137. def test_sync_all_whitelist(self):
  138. """
  139. Test syncing all ModuleCase with whitelist
  140. """
  141. expected_return = {
  142. "engines": [],
  143. "clouds": [],
  144. "grains": [],
  145. "beacons": [],
  146. "utils": [],
  147. "returners": [],
  148. "modules": ["modules.salttest"],
  149. "renderers": [],
  150. "log_handlers": [],
  151. "matchers": [],
  152. "states": [],
  153. "sdb": [],
  154. "proxymodules": [],
  155. "executors": [],
  156. "output": [],
  157. "thorium": [],
  158. "serializers": [],
  159. }
  160. ret = self.run_function(
  161. "saltutil.sync_all", extmod_whitelist={"modules": ["salttest"]}
  162. )
  163. self.assertEqual(ret, expected_return)
  164. @slowTest
  165. def test_sync_all_blacklist(self):
  166. """
  167. Test syncing all ModuleCase with blacklist
  168. """
  169. expected_return = {
  170. "engines": [],
  171. "clouds": [],
  172. "grains": [],
  173. "beacons": [],
  174. "utils": [],
  175. "returners": [],
  176. "modules": [
  177. "modules.mantest",
  178. "modules.override_test",
  179. "modules.runtests_helpers",
  180. "modules.salttest",
  181. ],
  182. "renderers": [],
  183. "log_handlers": [],
  184. "matchers": [],
  185. "states": [],
  186. "sdb": [],
  187. "proxymodules": [],
  188. "executors": [],
  189. "output": [],
  190. "thorium": [],
  191. "serializers": [],
  192. }
  193. ret = self.run_function(
  194. "saltutil.sync_all",
  195. extmod_blacklist={
  196. "modules": [
  197. "runtests_decorators",
  198. "depends_versioned",
  199. "depends_versionless",
  200. ]
  201. },
  202. )
  203. self.assertEqual(ret, expected_return)
  204. @slowTest
  205. def test_sync_all_blacklist_and_whitelist(self):
  206. """
  207. Test syncing all ModuleCase with whitelist and blacklist
  208. """
  209. expected_return = {
  210. "engines": [],
  211. "clouds": [],
  212. "grains": [],
  213. "beacons": [],
  214. "utils": [],
  215. "returners": [],
  216. "executors": [],
  217. "modules": [],
  218. "renderers": [],
  219. "log_handlers": [],
  220. "matchers": [],
  221. "states": [],
  222. "sdb": [],
  223. "proxymodules": [],
  224. "output": [],
  225. "thorium": [],
  226. "serializers": [],
  227. }
  228. ret = self.run_function(
  229. "saltutil.sync_all",
  230. extmod_whitelist={"modules": ["runtests_decorators"]},
  231. extmod_blacklist={"modules": ["runtests_decorators"]},
  232. )
  233. self.assertEqual(ret, expected_return)
  234. @skipIf(True, "Pillar refresh test is flaky. Skipping for now.")
  235. @pytest.mark.windows_whitelisted
  236. class SaltUtilSyncPillarTest(ModuleCase):
  237. """
  238. Testcase for the saltutil sync pillar module
  239. """
  240. class WaitForEvent(threading.Thread):
  241. def __init__(self, opts, event_tag):
  242. self.__eventer = salt.utils.event.get_event(
  243. "minion", opts=opts, listen=True
  244. )
  245. self.__event_tag = event_tag
  246. self.__event_complete = False
  247. threading.Thread.__init__(self)
  248. def run(self):
  249. if self.__eventer.get_event(tag=self.__event_tag, wait=30):
  250. self.__event_complete = True
  251. def is_complete(self):
  252. return self.__event_complete
  253. @flaky
  254. def test_pillar_refresh(self):
  255. """
  256. test pillar refresh module
  257. """
  258. pillar_key = "itworked"
  259. pre_pillar = self.run_function("pillar.raw")
  260. self.assertNotIn(pillar_key, pre_pillar.get(pillar_key, "didnotwork"))
  261. with salt.utils.files.fopen(
  262. os.path.join(RUNTIME_VARS.TMP_PILLAR_TREE, "add_pillar.sls"), "w"
  263. ) as fp:
  264. fp.write(salt.utils.stringutils.to_str("{0}: itworked".format(pillar_key)))
  265. with salt.utils.files.fopen(
  266. os.path.join(RUNTIME_VARS.TMP_PILLAR_TREE, "top.sls"), "w"
  267. ) as fp:
  268. fp.write(
  269. textwrap.dedent(
  270. """\
  271. base:
  272. '*':
  273. - add_pillar
  274. """
  275. )
  276. )
  277. self.run_function("saltutil.refresh_pillar")
  278. pillar = False
  279. timeout = time.time() + 30
  280. while not pillar:
  281. post_pillar = self.run_function("pillar.raw")
  282. try:
  283. self.assertIn(pillar_key, post_pillar.get(pillar_key, "didnotwork"))
  284. pillar = True
  285. except AssertionError:
  286. if time.time() > timeout:
  287. self.assertIn(pillar_key, post_pillar.get(pillar_key, "didnotwork"))
  288. continue
  289. post_pillar = self.run_function("pillar.raw")
  290. self.assertIn(pillar_key, post_pillar.get(pillar_key, "didnotwork"))
  291. def test_pillar_refresh_sync(self):
  292. """
  293. test pillar refresh module with sync enabled
  294. """
  295. pillar_key = "itworked_sync"
  296. pre_pillar = self.run_function("pillar.raw")
  297. self.assertNotIn(pillar_key, pre_pillar.get(pillar_key, "didnotwork_sync"))
  298. with salt.utils.files.fopen(
  299. os.path.join(RUNTIME_VARS.TMP_PILLAR_TREE, "add_pillar_sync.sls"), "w"
  300. ) as fp:
  301. fp.write(
  302. salt.utils.stringutils.to_str("{0}: itworked_sync".format(pillar_key))
  303. )
  304. with salt.utils.files.fopen(
  305. os.path.join(RUNTIME_VARS.TMP_PILLAR_TREE, "top.sls"), "w"
  306. ) as fp:
  307. fp.write(
  308. textwrap.dedent(
  309. """\
  310. base:
  311. '*':
  312. - add_pillar_sync
  313. """
  314. )
  315. )
  316. opts = self.run_function("test.get_opts")
  317. wait = self.WaitForEvent(
  318. opts, salt.defaults.events.MINION_PILLAR_REFRESH_COMPLETE
  319. )
  320. wait.start()
  321. self.run_function("saltutil.refresh_pillar", wait=True)
  322. while wait.is_alive():
  323. time.sleep(1)
  324. self.assertTrue(wait.is_complete())
  325. pillar = False
  326. timeout = time.time() + 30
  327. while not pillar:
  328. post_pillar = self.run_function("pillar.raw")
  329. try:
  330. self.assertIn(
  331. pillar_key, post_pillar.get(pillar_key, "didnotwork_sync")
  332. )
  333. pillar = True
  334. except AssertionError:
  335. if time.time() > timeout:
  336. self.assertIn(
  337. pillar_key, post_pillar.get(pillar_key, "didnotwork_sync")
  338. )
  339. continue
  340. post_pillar = self.run_function("pillar.raw")
  341. self.assertIn(pillar_key, post_pillar.get(pillar_key, "didnotwork_sync"))
  342. def tearDown(self):
  343. for filename in os.listdir(RUNTIME_VARS.TMP_PILLAR_TREE):
  344. os.remove(os.path.join(RUNTIME_VARS.TMP_PILLAR_TREE, filename))