test_matcher.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. # -*- coding: utf-8 -*-
  2. from __future__ import absolute_import
  3. import time
  4. import pytest
  5. import salt.utils.files
  6. import salt.utils.yaml
  7. from tests.support.case import ShellCase
  8. from tests.support.helpers import dedent, flaky
  9. from tests.support.mixins import ShellCaseCommonTestsMixin
  10. from tests.support.unit import skipIf
  11. def minion_in_returns(minion, lines):
  12. return bool([True for line in lines if line == "{0}:".format(minion)])
  13. @pytest.mark.windows_whitelisted
  14. class MatchTest(ShellCase, ShellCaseCommonTestsMixin):
  15. """
  16. Test salt matchers
  17. """
  18. _call_binary_ = "salt"
  19. @skipIf(True, "SLOWTEST skip")
  20. def test_list(self):
  21. """
  22. test salt -L matcher
  23. """
  24. data = self.run_salt("-L minion test.ping")
  25. data = "\n".join(data)
  26. self.assertIn("minion", data)
  27. self.assertNotIn("sub_minion", data)
  28. data = self.run_salt("-L minion,sub_minion test.ping")
  29. data = "\n".join(data)
  30. self.assertIn("minion", data)
  31. self.assertIn("sub_minion", data)
  32. # compound matcher tests: 12
  33. @skipIf(True, "SLOWTEST skip")
  34. def test_compound_min_with_grain(self):
  35. """
  36. test salt compound matcher
  37. """
  38. data = self.run_salt('-C "min* and G@test_grain:cheese" test.ping')
  39. assert minion_in_returns("minion", data) is True
  40. assert minion_in_returns("sub_minion", data) is False
  41. @skipIf(True, "SLOWTEST skip")
  42. def test_compound_and_not_grain(self):
  43. data = self.run_salt('-C "min* and not G@test_grain:foo" test.ping')
  44. assert minion_in_returns("minion", data) is True
  45. assert minion_in_returns("sub_minion", data) is False
  46. @skipIf(True, "SLOWTEST skip")
  47. def test_compound_not_grain(self):
  48. data = self.run_salt('-C "min* not G@test_grain:foo" test.ping')
  49. assert minion_in_returns("minion", data) is True
  50. assert minion_in_returns("sub_minion", data) is False
  51. @skipIf(True, "SLOWTEST skip")
  52. def test_compound_pcre_grain_and_grain(self):
  53. match = "P@test_grain:^cheese$ and * and G@test_grain:cheese"
  54. data = self.run_salt('-t 1 -C "{0}" test.ping'.format(match))
  55. assert minion_in_returns("minion", data) is True
  56. assert minion_in_returns("sub_minion", data) is False
  57. @skipIf(True, "SLOWTEST skip")
  58. def test_compound_list_and_pcre_minion(self):
  59. match = "L@sub_minion and E@.*"
  60. data = self.run_salt('-t 1 -C "{0}" test.ping'.format(match))
  61. assert minion_in_returns("sub_minion", data) is True
  62. assert minion_in_returns("minion", data) is False
  63. @skipIf(True, "SLOWTEST skip")
  64. def test_compound_not_sub_minion(self):
  65. data = self.run_salt('-C "not sub_minion" test.ping')
  66. assert minion_in_returns("minion", data) is True
  67. assert minion_in_returns("sub_minion", data) is False
  68. @skipIf(True, "SLOWTEST skip")
  69. def test_compound_all_and_not_grains(self):
  70. data = self.run_salt('-C "* and ( not G@test_grain:cheese )" test.ping')
  71. assert minion_in_returns("minion", data) is False
  72. assert minion_in_returns("sub_minion", data) is True
  73. @skipIf(True, "SLOWTEST skip")
  74. def test_compound_grain_regex(self):
  75. data = self.run_salt('-C "G%@planets%merc*" test.ping')
  76. assert minion_in_returns("minion", data) is True
  77. assert minion_in_returns("sub_minion", data) is False
  78. @skipIf(True, "SLOWTEST skip")
  79. def test_coumpound_pcre_grain_regex(self):
  80. data = self.run_salt('-C "P%@planets%^(mercury|saturn)$" test.ping')
  81. assert minion_in_returns("minion", data) is True
  82. assert minion_in_returns("sub_minion", data) is True
  83. @skipIf(True, "This test is unreliable. Need to investigate why more deeply.")
  84. @flaky
  85. def test_compound_pillar(self):
  86. data = self.run_salt("-C 'I%@companions%three%sarah*' test.ping")
  87. assert minion_in_returns("minion", data) is True
  88. assert minion_in_returns("sub_minion", data) is True
  89. @skipIf(True, "This test is unreliable. Need to investigate why more deeply.")
  90. @flaky
  91. def test_compound_pillar_pcre(self):
  92. data = self.run_salt("-C 'J%@knights%^(Lancelot|Galahad)$' test.ping")
  93. self.assertTrue(minion_in_returns("minion", data))
  94. self.assertTrue(minion_in_returns("sub_minion", data))
  95. def test_compound_nodegroup(self):
  96. data = self.run_salt('-C "N@multiline_nodegroup" test.ping')
  97. self.assertTrue(minion_in_returns("minion", data))
  98. self.assertTrue(minion_in_returns("sub_minion", data))
  99. data = self.run_salt('-C "N@multiline_nodegroup not sub_minion" test.ping')
  100. self.assertTrue(minion_in_returns("minion", data))
  101. self.assertFalse(minion_in_returns("sub_minion", data))
  102. data = self.run_salt(
  103. '-C "N@multiline_nodegroup not @fakenodegroup not sub_minion" test.ping'
  104. )
  105. self.assertTrue(minion_in_returns("minion", data))
  106. self.assertFalse(minion_in_returns("sub_minion", data))
  107. @skipIf(True, "SLOWTEST skip")
  108. def test_nodegroup(self):
  109. """
  110. test salt nodegroup matcher
  111. """
  112. data = self.run_salt("-N min test.ping")
  113. self.assertTrue(minion_in_returns("minion", data))
  114. self.assertFalse(minion_in_returns("sub_minion", data))
  115. time.sleep(2)
  116. data = self.run_salt("-N sub_min test.ping")
  117. self.assertFalse(minion_in_returns("minion", data))
  118. self.assertTrue(minion_in_returns("sub_minion", data))
  119. time.sleep(2)
  120. data = self.run_salt("-N mins test.ping")
  121. self.assertTrue(minion_in_returns("minion", data))
  122. self.assertTrue(minion_in_returns("sub_minion", data))
  123. time.sleep(2)
  124. data = self.run_salt("-N unknown_nodegroup test.ping")
  125. self.assertFalse(minion_in_returns("minion", data))
  126. self.assertFalse(minion_in_returns("sub_minion", data))
  127. time.sleep(2)
  128. data = self.run_salt("-N redundant_minions test.ping")
  129. self.assertTrue(minion_in_returns("minion", data))
  130. self.assertTrue(minion_in_returns("sub_minion", data))
  131. time.sleep(2)
  132. data = "\n".join(self.run_salt("-N nodegroup_loop_a test.ping"))
  133. self.assertIn("No minions matched", data)
  134. time.sleep(2)
  135. data = self.run_salt("-N multiline_nodegroup test.ping")
  136. self.assertTrue(minion_in_returns("minion", data))
  137. self.assertTrue(minion_in_returns("sub_minion", data))
  138. @skipIf(True, "SLOWTEST skip")
  139. def test_nodegroup_list(self):
  140. data = self.run_salt("-N list_group test.ping")
  141. self.assertTrue(minion_in_returns("minion", data))
  142. self.assertTrue(minion_in_returns("sub_minion", data))
  143. data = self.run_salt("-N list_group2 test.ping")
  144. self.assertTrue(minion_in_returns("minion", data))
  145. self.assertTrue(minion_in_returns("sub_minion", data))
  146. data = self.run_salt("-N one_list_group test.ping")
  147. self.assertTrue(minion_in_returns("minion", data))
  148. self.assertFalse(minion_in_returns("sub_minion", data))
  149. data = self.run_salt("-N one_minion_list test.ping")
  150. self.assertTrue(minion_in_returns("minion", data))
  151. self.assertFalse(minion_in_returns("sub_minion", data))
  152. @skipIf(True, "SLOWTEST skip")
  153. def test_glob(self):
  154. """
  155. test salt glob matcher
  156. """
  157. data = self.run_salt("minion test.ping")
  158. data = "\n".join(data)
  159. self.assertIn("minion", data)
  160. self.assertNotIn("sub_minion", data)
  161. data = self.run_salt('"*" test.ping')
  162. data = "\n".join(data)
  163. self.assertIn("minion", data)
  164. self.assertIn("sub_minion", data)
  165. @skipIf(True, "SLOWTEST skip")
  166. def test_regex(self):
  167. """
  168. test salt regex matcher
  169. """
  170. data = self.run_salt('-E "^minion$" test.ping')
  171. data = "\n".join(data)
  172. self.assertIn("minion", data)
  173. self.assertNotIn("sub_minion", data)
  174. data = self.run_salt('-E ".*" test.ping')
  175. data = "\n".join(data)
  176. self.assertIn("minion", data)
  177. self.assertIn("sub_minion", data)
  178. @skipIf(True, "SLOWTEST skip")
  179. def test_grain(self):
  180. """
  181. test salt grain matcher
  182. """
  183. # Sync grains
  184. self.run_salt('-t1 "*" saltutil.sync_grains')
  185. # First-level grain (string value)
  186. data = self.run_salt('-t 1 -G "test_grain:cheese" test.ping')
  187. data = "\n".join(data)
  188. self.assertIn("minion", data)
  189. self.assertNotIn("sub_minion", data)
  190. data = self.run_salt('-G "test_grain:spam" test.ping')
  191. data = "\n".join(data)
  192. self.assertIn("sub_minion", data)
  193. self.assertNotIn("minion", data.replace("sub_minion", "stub"))
  194. # Custom grain
  195. data = self.run_salt('-t 1 -G "match:maker" test.ping')
  196. data = "\n".join(data)
  197. self.assertIn("minion", data)
  198. self.assertIn("sub_minion", data)
  199. # First-level grain (list member)
  200. data = self.run_salt('-t 1 -G "planets:earth" test.ping')
  201. data = "\n".join(data)
  202. self.assertIn("minion", data)
  203. self.assertNotIn("sub_minion", data)
  204. data = self.run_salt('-G "planets:saturn" test.ping')
  205. data = "\n".join(data)
  206. self.assertIn("sub_minion", data)
  207. self.assertNotIn("minion", data.replace("sub_minion", "stub"))
  208. data = self.run_salt('-G "planets:pluto" test.ping')
  209. expect = None
  210. if self.master_opts["transport"] in ("zeromq", "tcp"):
  211. expect = (
  212. "No minions matched the target. "
  213. "No command was sent, no jid was "
  214. "assigned."
  215. )
  216. self.assertEqual("".join(data), expect)
  217. # Nested grain (string value)
  218. data = self.run_salt('-t 1 -G "level1:level2:foo" test.ping')
  219. data = "\n".join(data)
  220. self.assertIn("minion", data)
  221. self.assertNotIn("sub_minion", data)
  222. data = self.run_salt('-G "level1:level2:bar" test.ping')
  223. data = "\n".join(data)
  224. self.assertIn("sub_minion", data)
  225. self.assertNotIn("minion", data.replace("sub_minion", "stub"))
  226. # Nested grain (list member)
  227. data = self.run_salt('-t 1 -G "companions:one:ian" test.ping')
  228. data = "\n".join(data)
  229. self.assertIn("minion", data)
  230. self.assertNotIn("sub_minion", data)
  231. data = self.run_salt('-G "companions:two:jamie" test.ping')
  232. data = "\n".join(data)
  233. self.assertIn("sub_minion", data)
  234. self.assertNotIn("minion", data.replace("sub_minion", "stub"))
  235. # Test for issue: https://github.com/saltstack/salt/issues/19651
  236. data = self.run_salt('-G "companions:*:susan" test.ping')
  237. data = "\n".join(data)
  238. self.assertIn("minion:", data)
  239. self.assertNotIn("sub_minion", data)
  240. # Test to ensure wildcard at end works correctly
  241. data = self.run_salt('-G "companions:one:*" test.ping')
  242. data = "\n".join(data)
  243. self.assertIn("minion:", data)
  244. self.assertNotIn("sub_minion", data)
  245. # Test to ensure multiple wildcards works correctly
  246. data = self.run_salt('-G "companions:*:*" test.ping')
  247. data = "\n".join(data)
  248. self.assertIn("minion:", data)
  249. self.assertIn("sub_minion", data)
  250. @skipIf(True, "SLOWTEST skip")
  251. def test_regrain(self):
  252. """
  253. test salt grain matcher
  254. """
  255. data = self.run_salt('-t 1 --grain-pcre "test_grain:^cheese$" test.ping')
  256. data = "\n".join(data)
  257. self.assertIn("minion", data)
  258. self.assertNotIn("sub_minion", data)
  259. data = self.run_salt('--grain-pcre "test_grain:.*am$" test.ping')
  260. data = "\n".join(data)
  261. self.assertIn("sub_minion", data)
  262. self.assertNotIn("minion", data.replace("sub_minion", "stub"))
  263. @skipIf(True, "SLOWTEST skip")
  264. def test_pillar(self):
  265. """
  266. test pillar matcher
  267. """
  268. # First-level pillar (string value)
  269. data = self.run_salt('-I "monty:python" test.ping')
  270. data = "\n".join(data)
  271. self.assertIn("minion", data)
  272. self.assertIn("sub_minion", data)
  273. # First-level pillar (string value, only in sub_minion)
  274. data = self.run_salt('-I "sub:sub_minion" test.ping')
  275. data = "\n".join(data)
  276. self.assertIn("sub_minion", data)
  277. self.assertNotIn("minion", data.replace("sub_minion", "stub"))
  278. # First-level pillar (list member)
  279. data = self.run_salt('-I "knights:Bedevere" test.ping')
  280. data = "\n".join(data)
  281. self.assertIn("minion", data)
  282. self.assertIn("sub_minion", data)
  283. # Nested pillar (string value)
  284. data = self.run_salt('-I "level1:level2:foo" test.ping')
  285. data = "\n".join(data)
  286. self.assertIn("minion", data)
  287. self.assertIn("sub_minion", data)
  288. # Nested pillar (list member)
  289. data = self.run_salt('-I "companions:three:sarah jane" test.ping')
  290. data = "\n".join(data)
  291. self.assertIn("minion", data)
  292. self.assertIn("sub_minion", data)
  293. @skipIf(True, "SLOWTEST skip")
  294. def test_repillar(self):
  295. """
  296. test salt pillar PCRE matcher
  297. """
  298. data = self.run_salt('-J "monty:^(python|hall)$" test.ping')
  299. data = "\n".join(data)
  300. self.assertIn("minion", data)
  301. self.assertIn("sub_minion", data)
  302. data = self.run_salt('--pillar-pcre "knights:^(Robin|Lancelot)$" test.ping')
  303. data = "\n".join(data)
  304. self.assertIn("sub_minion", data)
  305. self.assertIn("minion", data.replace("sub_minion", "stub"))
  306. @skipIf(True, "SLOWTEST skip")
  307. def test_ipcidr(self):
  308. subnets_data = self.run_salt('--out yaml "*" network.subnets')
  309. yaml_data = salt.utils.yaml.safe_load("\n".join(subnets_data))
  310. # We're just after the first defined subnet from 'minion'
  311. subnet = yaml_data["minion"][0]
  312. data = self.run_salt("-S {0} test.ping".format(subnet))
  313. data = "\n".join(data)
  314. self.assertIn("minion", data)
  315. self.assertIn("sub_minion", data)
  316. @skipIf(True, "SLOWTEST skip")
  317. def test_static(self):
  318. """
  319. test salt static call
  320. """
  321. data = self.run_salt("minion test.ping --static")
  322. data = "\n".join(data)
  323. self.assertIn("minion", data)
  324. @skipIf(True, "SLOWTEST skip")
  325. def test_salt_documentation(self):
  326. """
  327. Test to see if we're supporting --doc
  328. """
  329. expect_to_find = "test.ping:"
  330. stdout, stderr = self.run_salt('-d "*" test', catch_stderr=True)
  331. error_msg = dedent(
  332. """
  333. Failed to find \'{expected}\' in output
  334. {sep}
  335. --- STDOUT -----
  336. {stdout}
  337. {sep}
  338. --- STDERR -----
  339. {stderr}
  340. {sep}
  341. """.format(
  342. sep="-" * 80,
  343. expected=expect_to_find,
  344. stdout="\n".join(stdout).strip(),
  345. stderr="\n".join(stderr).strip(),
  346. )
  347. )
  348. self.assertIn(expect_to_find, stdout, msg=error_msg)
  349. @skipIf(True, "SLOWTEST skip")
  350. def test_salt_documentation_too_many_arguments(self):
  351. """
  352. Test to see if passing additional arguments shows an error
  353. """
  354. data = self.run_salt(
  355. '-d minion salt ldap.search "filter=ou=People"', catch_stderr=True
  356. )
  357. self.assertIn(
  358. "You can only get documentation for one method at one time",
  359. "\n".join(data[1]),
  360. )