test_mine.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. # -*- coding: utf-8 -*-
  2. """
  3. Test the salt mine system
  4. """
  5. from __future__ import absolute_import, print_function, unicode_literals
  6. import pprint
  7. import time
  8. import pytest
  9. import salt.utils.platform
  10. from tests.support.case import ModuleCase, ShellCase
  11. from tests.support.runtests import RUNTIME_VARS
  12. @pytest.mark.windows_whitelisted
  13. @pytest.mark.usefixtures("salt_sub_minion")
  14. class MineTest(ModuleCase, ShellCase):
  15. """
  16. Test the mine system
  17. """
  18. def setUp(self):
  19. self.tgt = r"\*"
  20. if salt.utils.platform.is_windows():
  21. self.tgt = "*"
  22. self.wait_for_all_jobs()
  23. @pytest.mark.slow_test(seconds=60) # Test takes >30 and <=60 seconds
  24. def test_get(self):
  25. """
  26. test mine.get and mine.update
  27. """
  28. assert self.run_function("mine.update", minion_tgt="minion")
  29. assert self.run_function("mine.update", minion_tgt="sub_minion")
  30. # Since the minion has mine_functions defined in its configuration,
  31. # mine.update will return True
  32. self.assertTrue(self.run_function("mine.get", ["minion", "test.ping"]))
  33. @pytest.mark.slow_test(seconds=120) # Test takes >60 and <=120 seconds
  34. def test_get_allow_tgt(self):
  35. """
  36. test mine.get and mine.update using allow_tgt
  37. """
  38. assert self.run_function("mine.update", minion_tgt="minion")
  39. assert self.run_function("mine.update", minion_tgt="sub_minion")
  40. # sub_minion should be able to view test.arg data
  41. sub_min_ret = self.run_call(
  42. "mine.get {0} test.arg".format(self.tgt),
  43. config_dir=RUNTIME_VARS.TMP_SUB_MINION_CONF_DIR,
  44. )
  45. assert " - isn't" in sub_min_ret
  46. # minion should not be able to view test.arg data
  47. min_ret = self.run_call("mine.get {0} test.arg".format(self.tgt))
  48. assert " - isn't" not in min_ret
  49. @pytest.mark.slow_test(seconds=120) # Test takes >60 and <=120 seconds
  50. def test_send_allow_tgt(self):
  51. """
  52. test mine.send with allow_tgt set
  53. """
  54. mine_name = "test_this"
  55. for minion in ["sub_minion", "minion"]:
  56. assert self.run_function(
  57. "mine.send",
  58. [mine_name, "mine_function=test.arg_clean", "one"],
  59. allow_tgt="sub_minion",
  60. minion_tgt=minion,
  61. )
  62. min_ret = self.run_call("mine.get {0} {1}".format(self.tgt, mine_name))
  63. sub_ret = self.run_call(
  64. "mine.get {0} {1}".format(self.tgt, mine_name),
  65. config_dir=RUNTIME_VARS.TMP_SUB_MINION_CONF_DIR,
  66. )
  67. # ensure we did get the mine_name mine function for sub_minion
  68. assert " - one" in sub_ret
  69. # ensure we did not get the mine_name mine function for minion
  70. assert " - one" not in min_ret
  71. @pytest.mark.slow_test(seconds=120) # Test takes >60 and <=120 seconds
  72. def test_send_allow_tgt_compound(self):
  73. """
  74. test mine.send with allow_tgt set
  75. and using compound targeting
  76. """
  77. mine_name = "test_this_comp"
  78. for minion in ["sub_minion", "minion"]:
  79. assert self.run_function(
  80. "mine.send",
  81. [mine_name, "mine_function=test.arg_clean", "one"],
  82. allow_tgt="L@minion,sub_minion",
  83. allow_tgt_type="compound",
  84. minion_tgt=minion,
  85. )
  86. min_ret = self.run_call("mine.get {0} {1}".format(self.tgt, mine_name))
  87. sub_ret = self.run_call(
  88. "mine.get {0} {1}".format(self.tgt, mine_name),
  89. config_dir=RUNTIME_VARS.TMP_SUB_MINION_CONF_DIR,
  90. )
  91. # ensure we get the mine_name mine function for both minions
  92. for ret in [min_ret, sub_ret]:
  93. assert " - one" in ret
  94. @pytest.mark.slow_test(seconds=120) # Test takes >60 and <=120 seconds
  95. def test_send_allow_tgt_doesnotexist(self):
  96. """
  97. test mine.send with allow_tgt set when
  98. the minion defined in allow_tgt does
  99. not exist
  100. """
  101. mine_name = "mine_doesnotexist"
  102. for minion in ["sub_minion", "minion"]:
  103. assert self.run_function(
  104. "mine.send",
  105. [mine_name, "mine_function=test.arg_clean", "one"],
  106. allow_tgt="doesnotexist",
  107. minion_tgt=minion,
  108. )
  109. min_ret = self.run_call("mine.get {0} {1}".format(self.tgt, mine_name))
  110. sub_ret = self.run_call(
  111. "mine.get {0} {1}".format(self.tgt, mine_name),
  112. config_dir=RUNTIME_VARS.TMP_SUB_MINION_CONF_DIR,
  113. )
  114. # ensure we did not get the mine_name mine function for both minions
  115. for ret in [sub_ret, min_ret]:
  116. assert " - one" not in ret
  117. @pytest.mark.slow_test(seconds=120) # Test takes >60 and <=120 seconds
  118. def test_send(self):
  119. """
  120. test mine.send
  121. """
  122. self.assertFalse(self.run_function("mine.send", ["foo.__spam_and_cheese"]))
  123. self.assertTrue(
  124. self.run_function("mine.send", ["grains.items"], minion_tgt="minion",)
  125. )
  126. self.assertTrue(
  127. self.run_function("mine.send", ["grains.items"], minion_tgt="sub_minion",)
  128. )
  129. ret = self.run_function("mine.get", ["sub_minion", "grains.items"])
  130. self.assertEqual(ret["sub_minion"]["id"], "sub_minion")
  131. ret = self.run_function(
  132. "mine.get", ["minion", "grains.items"], minion_tgt="sub_minion"
  133. )
  134. self.assertEqual(ret["minion"]["id"], "minion")
  135. @pytest.mark.slow_test(seconds=120) # Test takes >60 and <=120 seconds
  136. def test_mine_flush(self):
  137. """
  138. Test mine.flush
  139. """
  140. # TODO The calls to sleep were added in an attempt to make this tests
  141. # less flaky. If we still see it fail we need to look for a more robust
  142. # solution.
  143. for minion_id in ("minion", "sub_minion"):
  144. self.assertTrue(
  145. self.run_function("mine.send", ["grains.items"], minion_tgt=minion_id)
  146. )
  147. time.sleep(1)
  148. for minion_id in ("minion", "sub_minion"):
  149. ret = self.run_function(
  150. "mine.get", [minion_id, "grains.items"], minion_tgt=minion_id
  151. )
  152. self.assertEqual(ret[minion_id]["id"], minion_id)
  153. time.sleep(1)
  154. self.assertTrue(self.run_function("mine.flush", minion_tgt="minion"))
  155. time.sleep(1)
  156. ret_flushed = self.run_function("mine.get", ["*", "grains.items"])
  157. self.assertEqual(ret_flushed.get("minion", None), None)
  158. self.assertEqual(ret_flushed["sub_minion"]["id"], "sub_minion")
  159. @pytest.mark.slow_test(seconds=240) # Test takes >120 and <=240 seconds
  160. def test_mine_delete(self):
  161. """
  162. Test mine.delete
  163. """
  164. self.assertTrue(
  165. self.run_function("mine.send", ["grains.items"], minion_tgt="minion")
  166. )
  167. self.wait_for_all_jobs(minions=("minion",))
  168. attempts = 10
  169. ret_grains = None
  170. while True:
  171. if ret_grains:
  172. break
  173. # Smoke testing that grains should now exist in the mine
  174. ret_grains = self.run_function(
  175. "mine.get", ["minion", "grains.items"], minion_tgt="minion"
  176. )
  177. if ret_grains and "minion" in ret_grains:
  178. break
  179. if attempts:
  180. attempts -= 1
  181. if attempts:
  182. time.sleep(1.5)
  183. continue
  184. self.fail(
  185. "'minion' was not found as a key of the 'mine.get' 'grains.items' call. Full return: {}".format(
  186. pprint.pformat(ret_grains)
  187. )
  188. )
  189. self.assertEqual(
  190. ret_grains["minion"]["id"],
  191. "minion",
  192. msg="{} != minion, full return payload: {}".format(
  193. ret_grains["minion"]["id"], pprint.pformat(ret_grains)
  194. ),
  195. )
  196. self.assertTrue(
  197. self.run_function(
  198. "mine.send",
  199. ["test.arg", "foo=bar", "fnord=roscivs"],
  200. minion_tgt="minion",
  201. )
  202. )
  203. self.wait_for_all_jobs(minions=("minion",))
  204. ret_args = self.run_function("mine.get", ["minion", "test.arg"])
  205. expected = {
  206. "minion": {"args": [], "kwargs": {"fnord": "roscivs", "foo": "bar"}},
  207. }
  208. # Smoke testing that test.arg exists in the mine
  209. self.assertDictEqual(ret_args, expected)
  210. self.assertTrue(
  211. self.run_function("mine.send", ["test.echo", "foo"], minion_tgt="minion")
  212. )
  213. self.wait_for_all_jobs(minions=("minion",))
  214. ret_echo = self.run_function(
  215. "mine.get", ["minion", "test.echo"], minion_tgt="minion"
  216. )
  217. # Smoke testing that we were also able to set test.echo in the mine
  218. self.assertEqual(ret_echo["minion"], "foo")
  219. self.assertTrue(
  220. self.run_function("mine.delete", ["test.arg"], minion_tgt="minion")
  221. )
  222. self.wait_for_all_jobs(minions=("minion",))
  223. ret_arg_deleted = self.run_function(
  224. "mine.get", ["minion", "test.arg"], minion_tgt="minion"
  225. )
  226. # Now comes the real test - did we obliterate test.arg from the mine?
  227. # We could assert this a different way, but there shouldn't be any
  228. # other tests that are setting this mine value, so this should
  229. # definitely avoid any race conditions.
  230. self.assertFalse(
  231. ret_arg_deleted.get("minion", {}).get("kwargs", {}).get("fnord", None)
  232. == "roscivs",
  233. '{} contained "fnord":"roscivs", which should be gone'.format(
  234. ret_arg_deleted,
  235. ),
  236. )
  237. ret_echo_stays = self.run_function(
  238. "mine.get", ["minion", "test.echo"], minion_tgt="minion"
  239. )
  240. # Of course, one more health check - we want targeted removal.
  241. # This isn't horseshoes or hand grenades - test.arg should go away
  242. # but test.echo should still be available.
  243. self.assertEqual(ret_echo_stays["minion"], "foo")