test_saltutil.py 12 KB

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