1
0

test_state.py 96 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580
  1. import logging
  2. import os
  3. import shutil
  4. import sys
  5. import tempfile
  6. import textwrap
  7. import threading
  8. import time
  9. import pytest
  10. import salt.utils.atomicfile
  11. import salt.utils.files
  12. import salt.utils.path
  13. import salt.utils.platform
  14. import salt.utils.stringutils
  15. from salt.ext import six
  16. from salt.modules.virtualenv_mod import KNOWN_BINARY_NAMES
  17. from tests.support.case import ModuleCase
  18. from tests.support.helpers import slowTest, with_tempdir
  19. from tests.support.mixins import SaltReturnAssertsMixin
  20. from tests.support.pytest.helpers import temp_state_file
  21. from tests.support.runtests import RUNTIME_VARS
  22. from tests.support.sminion import create_sminion
  23. from tests.support.unit import skipIf
  24. log = logging.getLogger(__name__)
  25. DEFAULT_ENDING = salt.utils.stringutils.to_bytes(os.linesep)
  26. @pytest.mark.windows_whitelisted
  27. class StateModuleTest(ModuleCase, SaltReturnAssertsMixin):
  28. """
  29. Validate the state module
  30. """
  31. maxDiff = None
  32. @classmethod
  33. def setUpClass(cls):
  34. def _reline(path, ending=DEFAULT_ENDING):
  35. """
  36. Normalize the line endings of a file.
  37. """
  38. with salt.utils.files.fopen(path, "rb") as fhr:
  39. lines = fhr.read().splitlines()
  40. with salt.utils.atomicfile.atomic_open(path, "wb") as fhw:
  41. for line in lines:
  42. fhw.write(line + ending)
  43. destpath = os.path.join(RUNTIME_VARS.BASE_FILES, "testappend", "firstif")
  44. _reline(destpath)
  45. destpath = os.path.join(RUNTIME_VARS.BASE_FILES, "testappend", "secondif")
  46. _reline(destpath)
  47. if salt.utils.platform.is_windows():
  48. cls.TIMEOUT = 600
  49. # Be sure to have everything sync'ed
  50. sminion = create_sminion()
  51. sminion.functions.saltutil.sync_all()
  52. else:
  53. cls.TIMEOUT = 10
  54. @slowTest
  55. def test_show_highstate(self):
  56. """
  57. state.show_highstate
  58. """
  59. high = self.run_function("state.show_highstate")
  60. destpath = os.path.join(RUNTIME_VARS.TMP, "testfile")
  61. self.assertTrue(isinstance(high, dict))
  62. self.assertTrue(destpath in high)
  63. self.assertEqual(high[destpath]["__env__"], "base")
  64. @slowTest
  65. def test_show_lowstate(self):
  66. """
  67. state.show_lowstate
  68. """
  69. low = self.run_function("state.show_lowstate")
  70. self.assertTrue(isinstance(low, list))
  71. self.assertTrue(isinstance(low[0], dict))
  72. @slowTest
  73. def test_show_states(self):
  74. """
  75. state.show_states
  76. """
  77. states = self.run_function("state.show_states")
  78. self.assertTrue(isinstance(states, list))
  79. self.assertTrue(isinstance(states[0], str))
  80. states = self.run_function("state.show_states", sorted=False)
  81. self.assertTrue(isinstance(states, list))
  82. self.assertTrue(isinstance(states[0], str))
  83. @slowTest
  84. def test_show_states_missing_sls(self):
  85. """
  86. Test state.show_states with a sls file
  87. defined in a top file is missing
  88. """
  89. topfile = os.path.join(RUNTIME_VARS.TMP_STATE_TREE, "top.sls")
  90. with salt.utils.files.fopen(topfile, "w") as top_file:
  91. top_file.write(
  92. textwrap.dedent(
  93. """\
  94. base:
  95. '*':
  96. - doesnotexist
  97. """
  98. )
  99. )
  100. states = self.run_function("state.show_states")
  101. assert isinstance(states, list)
  102. assert states == ["No matching sls found for 'doesnotexist' in env 'base'"]
  103. @slowTest
  104. def test_catch_recurse(self):
  105. """
  106. state.show_sls used to catch a recursive ref
  107. """
  108. err = self.run_function("state.sls", mods="recurse_fail")
  109. self.assertIn("recursive", err[0])
  110. @slowTest
  111. def test_no_recurse(self):
  112. """
  113. verify that a sls structure is NOT a recursive ref
  114. """
  115. sls = self.run_function("state.show_sls", mods="recurse_ok")
  116. self.assertIn("snmpd", sls)
  117. @slowTest
  118. def test_no_recurse_two(self):
  119. """
  120. verify that a sls structure is NOT a recursive ref
  121. """
  122. sls = self.run_function("state.show_sls", mods="recurse_ok_two")
  123. self.assertIn("/etc/nagios/nrpe.cfg", sls)
  124. @slowTest
  125. def test_running_dictionary_consistency(self):
  126. """
  127. Test the structure of the running dictionary so we don't change it
  128. without deprecating/documenting the change
  129. """
  130. running_dict_fields = [
  131. "__id__",
  132. "__run_num__",
  133. "__sls__",
  134. "changes",
  135. "comment",
  136. "duration",
  137. "name",
  138. "result",
  139. "start_time",
  140. ]
  141. sls = self.run_function(
  142. "state.single", fun="test.succeed_with_changes", name="gndn"
  143. )
  144. for state, ret in sls.items():
  145. for field in running_dict_fields:
  146. self.assertIn(field, ret)
  147. @slowTest
  148. def test_running_dictionary_key_sls(self):
  149. """
  150. Ensure the __sls__ key is either null or a string
  151. """
  152. sls1 = self.run_function(
  153. "state.single", fun="test.succeed_with_changes", name="gndn"
  154. )
  155. sls2 = self.run_function("state.sls", mods="gndn")
  156. for state, ret in sls1.items():
  157. self.assertTrue(isinstance(ret["__sls__"], type(None)))
  158. for state, ret in sls2.items():
  159. self.assertTrue(isinstance(ret["__sls__"], str))
  160. def _remove_request_cache_file(self):
  161. """
  162. remove minion state request file
  163. """
  164. cache_file = os.path.join(self.get_config("minion")["cachedir"], "req_state.p")
  165. if os.path.exists(cache_file):
  166. os.remove(cache_file)
  167. @slowTest
  168. def test_request(self):
  169. """
  170. verify sending a state request to the minion(s)
  171. """
  172. self._remove_request_cache_file()
  173. ret = self.run_function("state.request", mods="modules.state.requested")
  174. result = ret["cmd_|-count_root_dir_contents_|-ls -a / | wc -l_|-run"]["result"]
  175. self.assertEqual(result, None)
  176. @slowTest
  177. def test_check_request(self):
  178. """
  179. verify checking a state request sent to the minion(s)
  180. """
  181. self._remove_request_cache_file()
  182. self.run_function("state.request", mods="modules.state.requested")
  183. ret = self.run_function("state.check_request")
  184. result = ret["default"]["test_run"][
  185. "cmd_|-count_root_dir_contents_|-ls -a / | wc -l_|-run"
  186. ]["result"]
  187. self.assertEqual(result, None)
  188. @slowTest
  189. def test_clear_request(self):
  190. """
  191. verify clearing a state request sent to the minion(s)
  192. """
  193. self._remove_request_cache_file()
  194. self.run_function("state.request", mods="modules.state.requested")
  195. ret = self.run_function("state.clear_request")
  196. self.assertTrue(ret)
  197. @slowTest
  198. def test_run_request_succeeded(self):
  199. """
  200. verify running a state request sent to the minion(s)
  201. """
  202. self._remove_request_cache_file()
  203. if salt.utils.platform.is_windows():
  204. self.run_function("state.request", mods="modules.state.requested_win")
  205. else:
  206. self.run_function("state.request", mods="modules.state.requested")
  207. ret = self.run_function("state.run_request")
  208. if salt.utils.platform.is_windows():
  209. key = "cmd_|-count_root_dir_contents_|-Get-ChildItem C:\\\\ | Measure-Object | %{$_.Count}_|-run"
  210. else:
  211. key = "cmd_|-count_root_dir_contents_|-ls -a / | wc -l_|-run"
  212. result = ret[key]["result"]
  213. self.assertTrue(result)
  214. @slowTest
  215. def test_run_request_failed_no_request_staged(self):
  216. """
  217. verify not running a state request sent to the minion(s)
  218. """
  219. self._remove_request_cache_file()
  220. self.run_function("state.request", mods="modules.state.requested")
  221. self.run_function("state.clear_request")
  222. ret = self.run_function("state.run_request")
  223. self.assertEqual(ret, {})
  224. @with_tempdir()
  225. @slowTest
  226. def test_issue_1896_file_append_source(self, base_dir):
  227. """
  228. Verify that we can append a file's contents
  229. """
  230. testfile = os.path.join(base_dir, "test.append")
  231. ret = self.run_state("file.touch", name=testfile)
  232. self.assertSaltTrueReturn(ret)
  233. ret = self.run_state(
  234. "file.append", name=testfile, source="salt://testappend/firstif"
  235. )
  236. self.assertSaltTrueReturn(ret)
  237. ret = self.run_state(
  238. "file.append", name=testfile, source="salt://testappend/secondif"
  239. )
  240. self.assertSaltTrueReturn(ret)
  241. with salt.utils.files.fopen(testfile, "r") as fp_:
  242. testfile_contents = salt.utils.stringutils.to_unicode(fp_.read())
  243. contents = textwrap.dedent(
  244. """\
  245. # set variable identifying the chroot you work in (used in the prompt below)
  246. if [ -z "$debian_chroot" ] && [ -r /etc/debian_chroot ]; then
  247. debian_chroot=$(cat /etc/debian_chroot)
  248. fi
  249. # enable bash completion in interactive shells
  250. if [ -f /etc/bash_completion ] && ! shopt -oq posix; then
  251. . /etc/bash_completion
  252. fi
  253. """
  254. )
  255. if salt.utils.platform.is_windows():
  256. new_contents = contents.splitlines()
  257. contents = os.linesep.join(new_contents)
  258. contents += os.linesep
  259. self.assertMultiLineEqual(contents, testfile_contents)
  260. ret = self.run_state(
  261. "file.append", name=testfile, source="salt://testappend/secondif"
  262. )
  263. self.assertSaltTrueReturn(ret)
  264. ret = self.run_state(
  265. "file.append", name=testfile, source="salt://testappend/firstif"
  266. )
  267. self.assertSaltTrueReturn(ret)
  268. with salt.utils.files.fopen(testfile, "r") as fp_:
  269. testfile_contents = salt.utils.stringutils.to_unicode(fp_.read())
  270. self.assertMultiLineEqual(contents, testfile_contents)
  271. @slowTest
  272. def test_issue_1876_syntax_error(self):
  273. """
  274. verify that we catch the following syntax error::
  275. /tmp/salttest/issue-1876:
  276. file:
  277. - managed
  278. - source: salt://testfile
  279. file.append:
  280. - text: foo
  281. """
  282. testfile = os.path.join(RUNTIME_VARS.TMP, "issue-1876")
  283. sls = self.run_function("state.sls", mods="issue-1876")
  284. self.assertIn(
  285. "ID '{}' in SLS 'issue-1876' contains multiple state "
  286. "declarations of the same type".format(testfile),
  287. sls,
  288. )
  289. @slowTest
  290. def test_issue_1879_too_simple_contains_check(self):
  291. expected = textwrap.dedent(
  292. """\
  293. # set variable identifying the chroot you work in (used in the prompt below)
  294. if [ -z "$debian_chroot" ] && [ -r /etc/debian_chroot ]; then
  295. debian_chroot=$(cat /etc/debian_chroot)
  296. fi
  297. # enable bash completion in interactive shells
  298. if [ -f /etc/bash_completion ] && ! shopt -oq posix; then
  299. . /etc/bash_completion
  300. fi
  301. """
  302. )
  303. if salt.utils.platform.is_windows():
  304. new_contents = expected.splitlines()
  305. expected = os.linesep.join(new_contents)
  306. expected += os.linesep
  307. testfile = os.path.join(RUNTIME_VARS.TMP, "issue-1879")
  308. # Delete if exiting
  309. if os.path.isfile(testfile):
  310. os.unlink(testfile)
  311. # Create the file
  312. ret = self.run_function("state.sls", mods="issue-1879", timeout=120)
  313. self.assertSaltTrueReturn(ret)
  314. # The first append
  315. ret = self.run_function("state.sls", mods="issue-1879.step-1", timeout=120)
  316. self.assertSaltTrueReturn(ret)
  317. # The second append
  318. ret = self.run_function("state.sls", mods="issue-1879.step-2", timeout=120)
  319. self.assertSaltTrueReturn(ret)
  320. # Does it match?
  321. try:
  322. with salt.utils.files.fopen(testfile, "r") as fp_:
  323. contents = salt.utils.stringutils.to_unicode(fp_.read())
  324. self.assertMultiLineEqual(expected, contents)
  325. # Make sure we don't re-append existing text
  326. ret = self.run_function("state.sls", mods="issue-1879.step-1", timeout=120)
  327. self.assertSaltTrueReturn(ret)
  328. ret = self.run_function("state.sls", mods="issue-1879.step-2", timeout=120)
  329. self.assertSaltTrueReturn(ret)
  330. with salt.utils.files.fopen(testfile, "r") as fp_:
  331. contents = salt.utils.stringutils.to_unicode(fp_.read())
  332. self.assertMultiLineEqual(expected, contents)
  333. except Exception: # pylint: disable=broad-except
  334. if os.path.exists(testfile):
  335. shutil.copy(testfile, testfile + ".bak")
  336. raise
  337. finally:
  338. if os.path.exists(testfile):
  339. os.unlink(testfile)
  340. @slowTest
  341. def test_include(self):
  342. tempdir = tempfile.mkdtemp(dir=RUNTIME_VARS.TMP)
  343. self.addCleanup(shutil.rmtree, tempdir, ignore_errors=True)
  344. pillar = {}
  345. for path in ("include-test", "to-include-test", "exclude-test"):
  346. pillar[path] = os.path.join(tempdir, path)
  347. ret = self.run_function("state.sls", mods="include-test", pillar=pillar)
  348. self.assertSaltTrueReturn(ret)
  349. self.assertTrue(os.path.isfile(pillar["include-test"]))
  350. self.assertTrue(os.path.isfile(pillar["to-include-test"]))
  351. self.assertFalse(os.path.isfile(pillar["exclude-test"]))
  352. @slowTest
  353. def test_exclude(self):
  354. tempdir = tempfile.mkdtemp(dir=RUNTIME_VARS.TMP)
  355. self.addCleanup(shutil.rmtree, tempdir, ignore_errors=True)
  356. pillar = {}
  357. for path in ("include-test", "exclude-test", "to-include-test"):
  358. pillar[path] = os.path.join(tempdir, path)
  359. ret = self.run_function("state.sls", mods="exclude-test", pillar=pillar)
  360. self.assertSaltTrueReturn(ret)
  361. self.assertTrue(os.path.isfile(pillar["include-test"]))
  362. self.assertTrue(os.path.isfile(pillar["exclude-test"]))
  363. self.assertFalse(os.path.isfile(pillar["to-include-test"]))
  364. @skipIf(
  365. salt.utils.path.which_bin(KNOWN_BINARY_NAMES) is None,
  366. "virtualenv not installed",
  367. )
  368. @slowTest
  369. def test_issue_2068_template_str(self):
  370. venv_dir = os.path.join(RUNTIME_VARS.TMP, "issue-2068-template-str")
  371. try:
  372. ret = self.run_function(
  373. "state.sls", mods="issue-2068-template-str-no-dot", timeout=120
  374. )
  375. self.assertSaltTrueReturn(ret)
  376. finally:
  377. if os.path.isdir(venv_dir):
  378. shutil.rmtree(venv_dir)
  379. # Let's load the template from the filesystem. If running this state
  380. # with state.sls works, so should using state.template_str
  381. template_path = os.path.join(
  382. os.path.dirname(os.path.dirname(__file__)),
  383. "files",
  384. "file",
  385. "base",
  386. "issue-2068-template-str-no-dot.sls",
  387. )
  388. with salt.utils.files.fopen(template_path, "r") as fp_:
  389. template = salt.utils.stringutils.to_unicode(fp_.read())
  390. ret = self.run_function("state.template_str", [template], timeout=120)
  391. self.assertSaltTrueReturn(ret)
  392. # Now using state.template
  393. ret = self.run_function("state.template", [template_path], timeout=120)
  394. self.assertSaltTrueReturn(ret)
  395. # Now the problematic #2068 including dot's
  396. ret = self.run_function(
  397. "state.sls", mods="issue-2068-template-str", timeout=120
  398. )
  399. self.assertSaltTrueReturn(ret)
  400. # Let's load the template from the filesystem. If running this state
  401. # with state.sls works, so should using state.template_str
  402. template_path = os.path.join(
  403. os.path.dirname(os.path.dirname(__file__)),
  404. "files",
  405. "file",
  406. "base",
  407. "issue-2068-template-str.sls",
  408. )
  409. with salt.utils.files.fopen(template_path, "r") as fp_:
  410. template = salt.utils.stringutils.to_unicode(fp_.read())
  411. ret = self.run_function("state.template_str", [template], timeout=120)
  412. self.assertSaltTrueReturn(ret)
  413. # Now using state.template
  414. ret = self.run_function("state.template", [template_path], timeout=120)
  415. self.assertSaltTrueReturn(ret)
  416. @slowTest
  417. def test_template_invalid_items(self):
  418. TEMPLATE = textwrap.dedent(
  419. """\
  420. {0}:
  421. - issue-2068-template-str
  422. /tmp/test-template-invalid-items:
  423. file:
  424. - managed
  425. - source: salt://testfile
  426. """
  427. )
  428. for item in ("include", "exclude", "extends"):
  429. ret = self.run_function("state.template_str", [TEMPLATE.format(item)])
  430. self.assertTrue(isinstance(ret, list))
  431. self.assertNotEqual(ret, [])
  432. self.assertEqual(
  433. [
  434. "The '{}' declaration found on '<template-str>' is "
  435. "invalid when rendering single templates".format(item)
  436. ],
  437. ret,
  438. )
  439. @slowTest
  440. def test_pydsl(self):
  441. """
  442. Test the basics of the pydsl
  443. """
  444. ret = self.run_function("state.sls", mods="pydsl-1")
  445. self.assertSaltTrueReturn(ret)
  446. @slowTest
  447. def test_issues_7905_and_8174_sls_syntax_error(self):
  448. """
  449. Call sls file with yaml syntax error.
  450. Ensure theses errors are detected and presented to the user without
  451. stack traces.
  452. """
  453. ret = self.run_function("state.sls", mods="syntax.badlist")
  454. self.assertEqual(
  455. ret, ["State 'A' in SLS 'syntax.badlist' is not formed as a list"]
  456. )
  457. ret = self.run_function("state.sls", mods="syntax.badlist2")
  458. self.assertEqual(
  459. ret, ["State 'C' in SLS 'syntax.badlist2' is not formed as a list"]
  460. )
  461. @slowTest
  462. def test_requisites_mixed_require_prereq_use(self):
  463. """
  464. Call sls file containing several requisites.
  465. """
  466. expected_simple_result = {
  467. "cmd_|-A_|-echo A_|-run": {
  468. "__run_num__": 2,
  469. "comment": 'Command "echo A" run',
  470. "result": True,
  471. "changes": True,
  472. },
  473. "cmd_|-B_|-echo B_|-run": {
  474. "__run_num__": 1,
  475. "comment": 'Command "echo B" run',
  476. "result": True,
  477. "changes": True,
  478. },
  479. "cmd_|-C_|-echo C_|-run": {
  480. "__run_num__": 0,
  481. "comment": 'Command "echo C" run',
  482. "result": True,
  483. "changes": True,
  484. },
  485. }
  486. expected_result = {
  487. "cmd_|-A_|-echo A fifth_|-run": {
  488. "__run_num__": 4,
  489. "comment": 'Command "echo A fifth" run',
  490. "result": True,
  491. "changes": True,
  492. },
  493. "cmd_|-B_|-echo B third_|-run": {
  494. "__run_num__": 2,
  495. "comment": 'Command "echo B third" run',
  496. "result": True,
  497. "changes": True,
  498. },
  499. "cmd_|-C_|-echo C second_|-run": {
  500. "__run_num__": 1,
  501. "comment": 'Command "echo C second" run',
  502. "result": True,
  503. "changes": True,
  504. },
  505. "cmd_|-D_|-echo D first_|-run": {
  506. "__run_num__": 0,
  507. "comment": 'Command "echo D first" run',
  508. "result": True,
  509. "changes": True,
  510. },
  511. "cmd_|-E_|-echo E fourth_|-run": {
  512. "__run_num__": 3,
  513. "comment": 'Command "echo E fourth" run',
  514. "result": True,
  515. "changes": True,
  516. },
  517. }
  518. expected_req_use_result = {
  519. "cmd_|-A_|-echo A_|-run": {
  520. "__run_num__": 1,
  521. "comment": 'Command "echo A" run',
  522. "result": True,
  523. "changes": True,
  524. },
  525. "cmd_|-B_|-echo B_|-run": {
  526. "__run_num__": 4,
  527. "comment": 'Command "echo B" run',
  528. "result": True,
  529. "changes": True,
  530. },
  531. "cmd_|-C_|-echo C_|-run": {
  532. "__run_num__": 0,
  533. "comment": 'Command "echo C" run',
  534. "result": True,
  535. "changes": True,
  536. },
  537. "cmd_|-D_|-echo D_|-run": {
  538. "__run_num__": 5,
  539. "comment": 'Command "echo D" run',
  540. "result": True,
  541. "changes": True,
  542. },
  543. "cmd_|-E_|-echo E_|-run": {
  544. "__run_num__": 2,
  545. "comment": 'Command "echo E" run',
  546. "result": True,
  547. "changes": True,
  548. },
  549. "cmd_|-F_|-echo F_|-run": {
  550. "__run_num__": 3,
  551. "comment": 'Command "echo F" run',
  552. "result": True,
  553. "changes": True,
  554. },
  555. }
  556. ret = self.run_function("state.sls", mods="requisites.mixed_simple")
  557. result = self.normalize_ret(ret)
  558. self.assertReturnNonEmptySaltType(ret)
  559. self.assertEqual(expected_simple_result, result)
  560. # test Traceback recursion prereq+require #8785
  561. # TODO: this is actually failing badly
  562. # ret = self.run_function('state.sls', mods='requisites.prereq_require_recursion_error2')
  563. # self.assertEqual(
  564. # ret,
  565. # ['A recursive requisite was found, SLS "requisites.prereq_require_recursion_error2" ID "B" ID "A"']
  566. # )
  567. # test Infinite recursion prereq+require #8785 v2
  568. # TODO: this is actually failing badly
  569. # ret = self.run_function('state.sls', mods='requisites.prereq_require_recursion_error3')
  570. # self.assertEqual(
  571. # ret,
  572. # ['A recursive requisite was found, SLS "requisites.prereq_require_recursion_error2" ID "B" ID "A"']
  573. # )
  574. # test Infinite recursion prereq+require #8785 v3
  575. # TODO: this is actually failing badly, and expected result is maybe not a recursion
  576. # ret = self.run_function('state.sls', mods='requisites.prereq_require_recursion_error4')
  577. # self.assertEqual(
  578. # ret,
  579. # ['A recursive requisite was found, SLS "requisites.prereq_require_recursion_error2" ID "B" ID "A"']
  580. # )
  581. # undetected infinite loopS prevents this test from running...
  582. # TODO: this is actually failing badly
  583. # ret = self.run_function('state.sls', mods='requisites.mixed_complex1')
  584. # result = self.normalize_ret(ret)
  585. # self.assertEqual(expected_result, result)
  586. @slowTest
  587. def test_watch_in(self):
  588. """
  589. test watch_in requisite when there is a success
  590. """
  591. ret = self.run_function("state.sls", mods="requisites.watch_in")
  592. changes = "test_|-return_changes_|-return_changes_|-succeed_with_changes"
  593. watch = "test_|-watch_states_|-watch_states_|-succeed_without_changes"
  594. self.assertEqual(ret[changes]["__run_num__"], 0)
  595. self.assertEqual(ret[watch]["__run_num__"], 2)
  596. self.assertEqual("Watch statement fired.", ret[watch]["comment"])
  597. self.assertEqual(
  598. "Something pretended to change", ret[changes]["changes"]["testing"]["new"]
  599. )
  600. @slowTest
  601. def test_watch_in_failure(self):
  602. """
  603. test watch_in requisite when there is a failure
  604. """
  605. ret = self.run_function("state.sls", mods="requisites.watch_in_failure")
  606. fail = "test_|-return_changes_|-return_changes_|-fail_with_changes"
  607. watch = "test_|-watch_states_|-watch_states_|-succeed_without_changes"
  608. self.assertEqual(False, ret[fail]["result"])
  609. self.assertEqual(
  610. "One or more requisite failed: requisites.watch_in_failure.return_changes",
  611. ret[watch]["comment"],
  612. )
  613. def normalize_ret(self, ret):
  614. """
  615. Normalize the return to the format that we'll use for result checking
  616. """
  617. result = {}
  618. for item, descr in ret.items():
  619. result[item] = {
  620. "__run_num__": descr["__run_num__"],
  621. "comment": descr["comment"],
  622. "result": descr["result"],
  623. "changes": descr["changes"] != {}, # whether there where any changes
  624. }
  625. return result
  626. @slowTest
  627. def test_requisites_require_ordering_and_errors(self):
  628. """
  629. Call sls file containing several require_in and require.
  630. Ensure that some of them are failing and that the order is right.
  631. """
  632. expected_result = {
  633. "cmd_|-A_|-echo A fifth_|-run": {
  634. "__run_num__": 4,
  635. "comment": 'Command "echo A fifth" run',
  636. "result": True,
  637. "changes": True,
  638. },
  639. "cmd_|-B_|-echo B second_|-run": {
  640. "__run_num__": 1,
  641. "comment": 'Command "echo B second" run',
  642. "result": True,
  643. "changes": True,
  644. },
  645. "cmd_|-C_|-echo C third_|-run": {
  646. "__run_num__": 2,
  647. "comment": 'Command "echo C third" run',
  648. "result": True,
  649. "changes": True,
  650. },
  651. "cmd_|-D_|-echo D first_|-run": {
  652. "__run_num__": 0,
  653. "comment": 'Command "echo D first" run',
  654. "result": True,
  655. "changes": True,
  656. },
  657. "cmd_|-E_|-echo E fourth_|-run": {
  658. "__run_num__": 3,
  659. "comment": 'Command "echo E fourth" run',
  660. "result": True,
  661. "changes": True,
  662. },
  663. "cmd_|-F_|-echo F_|-run": {
  664. "__run_num__": 5,
  665. "comment": "The following requisites were not found:\n"
  666. + " require:\n"
  667. + " foobar: A\n",
  668. "result": False,
  669. "changes": False,
  670. },
  671. "cmd_|-G_|-echo G_|-run": {
  672. "__run_num__": 6,
  673. "comment": "The following requisites were not found:\n"
  674. + " require:\n"
  675. + " cmd: Z\n",
  676. "result": False,
  677. "changes": False,
  678. },
  679. "cmd_|-H_|-echo H_|-run": {
  680. "__run_num__": 7,
  681. "comment": "The following requisites were not found:\n"
  682. + " require:\n"
  683. + " cmd: Z\n",
  684. "result": False,
  685. "changes": False,
  686. },
  687. }
  688. ret = self.run_function("state.sls", mods="requisites.require")
  689. result = self.normalize_ret(ret)
  690. self.assertReturnNonEmptySaltType(ret)
  691. self.assertEqual(expected_result, result)
  692. ret = self.run_function("state.sls", mods="requisites.require_error1")
  693. self.assertEqual(
  694. ret,
  695. [
  696. "Cannot extend ID 'W' in 'base:requisites.require_error1'. It is not part of the high state.\nThis is likely due to a missing include statement or an incorrectly typed ID.\nEnsure that a state with an ID of 'W' is available\nin environment 'base' and to SLS 'requisites.require_error1'"
  697. ],
  698. )
  699. # issue #8235
  700. # FIXME: Why is require enforcing list syntax while require_in does not?
  701. # And why preventing it?
  702. # Currently this state fails, should return C/B/A
  703. result = {}
  704. ret = self.run_function("state.sls", mods="requisites.require_simple_nolist")
  705. self.assertEqual(
  706. ret,
  707. [
  708. "The require statement in state 'B' in SLS "
  709. + "'requisites.require_simple_nolist' needs to be formed as a list"
  710. ],
  711. )
  712. # commented until a fix is made for issue #8772
  713. # TODO: this test actually fails
  714. # ret = self.run_function('state.sls', mods='requisites.require_error2')
  715. # self.assertEqual(ret, [
  716. # 'Cannot extend state foobar for ID A in "base:requisites.require_error2".'
  717. # + ' It is not part of the high state.'
  718. # ])
  719. ret = self.run_function("state.sls", mods="requisites.require_recursion_error1")
  720. self.assertEqual(
  721. ret,
  722. [
  723. 'A recursive requisite was found, SLS "requisites.require_recursion_error1" ID "B" ID "A"'
  724. ],
  725. )
  726. @slowTest
  727. def test_requisites_require_any(self):
  728. """
  729. Call sls file containing several require_in and require.
  730. Ensure that some of them are failing and that the order is right.
  731. """
  732. expected_result = {
  733. "cmd_|-A_|-echo A_|-run": {
  734. "__run_num__": 3,
  735. "comment": 'Command "echo A" run',
  736. "result": True,
  737. "changes": True,
  738. },
  739. "cmd_|-B_|-echo B_|-run": {
  740. "__run_num__": 0,
  741. "comment": 'Command "echo B" run',
  742. "result": True,
  743. "changes": True,
  744. },
  745. "cmd_|-C_|-$(which false)_|-run": {
  746. "__run_num__": 1,
  747. "comment": 'Command "$(which false)" run',
  748. "result": False,
  749. "changes": True,
  750. },
  751. "cmd_|-D_|-echo D_|-run": {
  752. "__run_num__": 2,
  753. "comment": 'Command "echo D" run',
  754. "result": True,
  755. "changes": True,
  756. },
  757. }
  758. ret = self.run_function("state.sls", mods="requisites.require_any")
  759. result = self.normalize_ret(ret)
  760. self.assertReturnNonEmptySaltType(ret)
  761. self.assertEqual(expected_result, result)
  762. @slowTest
  763. def test_requisites_require_any_fail(self):
  764. """
  765. Call sls file containing several require_in and require.
  766. Ensure that some of them are failing and that the order is right.
  767. """
  768. ret = self.run_function("state.sls", mods="requisites.require_any_fail")
  769. result = self.normalize_ret(ret)
  770. self.assertReturnNonEmptySaltType(ret)
  771. self.assertIn(
  772. "One or more requisite failed", result["cmd_|-D_|-echo D_|-run"]["comment"]
  773. )
  774. @slowTest
  775. def test_requisites_watch_any(self):
  776. """
  777. Call sls file containing several require_in and require.
  778. Ensure that some of them are failing and that the order is right.
  779. """
  780. if salt.utils.platform.is_windows():
  781. cmd_true = "exit"
  782. cmd_false = "exit /B 1"
  783. else:
  784. cmd_true = "true"
  785. cmd_false = "false"
  786. expected_result = {
  787. "cmd_|-A_|-{}_|-wait".format(cmd_true): {
  788. "__run_num__": 4,
  789. "comment": 'Command "{}" run'.format(cmd_true),
  790. "result": True,
  791. "changes": True,
  792. },
  793. "cmd_|-B_|-{}_|-run".format(cmd_true): {
  794. "__run_num__": 0,
  795. "comment": 'Command "{}" run'.format(cmd_true),
  796. "result": True,
  797. "changes": True,
  798. },
  799. "cmd_|-C_|-{}_|-run".format(cmd_false): {
  800. "__run_num__": 1,
  801. "comment": 'Command "{}" run'.format(cmd_false),
  802. "result": False,
  803. "changes": True,
  804. },
  805. "cmd_|-D_|-{}_|-run".format(cmd_true): {
  806. "__run_num__": 2,
  807. "comment": 'Command "{}" run'.format(cmd_true),
  808. "result": True,
  809. "changes": True,
  810. },
  811. "cmd_|-E_|-{}_|-wait".format(cmd_true): {
  812. "__run_num__": 9,
  813. "comment": 'Command "{}" run'.format(cmd_true),
  814. "result": True,
  815. "changes": True,
  816. },
  817. "cmd_|-F_|-{}_|-run".format(cmd_true): {
  818. "__run_num__": 5,
  819. "comment": 'Command "{}" run'.format(cmd_true),
  820. "result": True,
  821. "changes": True,
  822. },
  823. "cmd_|-G_|-{}_|-run".format(cmd_false): {
  824. "__run_num__": 6,
  825. "comment": 'Command "{}" run'.format(cmd_false),
  826. "result": False,
  827. "changes": True,
  828. },
  829. "cmd_|-H_|-{}_|-run".format(cmd_false): {
  830. "__run_num__": 7,
  831. "comment": 'Command "{}" run'.format(cmd_false),
  832. "result": False,
  833. "changes": True,
  834. },
  835. }
  836. ret = self.run_function("state.sls", mods="requisites.watch_any")
  837. result = self.normalize_ret(ret)
  838. self.assertReturnNonEmptySaltType(ret)
  839. self.assertEqual(expected_result, result)
  840. @slowTest
  841. def test_requisites_watch_any_fail(self):
  842. """
  843. Call sls file containing several require_in and require.
  844. Ensure that some of them are failing and that the order is right.
  845. """
  846. ret = self.run_function("state.sls", mods="requisites.watch_any_fail")
  847. result = self.normalize_ret(ret)
  848. self.assertReturnNonEmptySaltType(ret)
  849. self.assertIn(
  850. "One or more requisite failed", result["cmd_|-A_|-true_|-wait"]["comment"]
  851. )
  852. @slowTest
  853. def test_requisites_onchanges_any(self):
  854. """
  855. Call sls file containing several require_in and require.
  856. Ensure that some of them are failing and that the order is right.
  857. """
  858. expected_result = {
  859. 'cmd_|-another_changing_state_|-echo "Changed!"_|-run': {
  860. "__run_num__": 1,
  861. "changes": True,
  862. "comment": 'Command "echo "Changed!"" run',
  863. "result": True,
  864. },
  865. 'cmd_|-changing_state_|-echo "Changed!"_|-run': {
  866. "__run_num__": 0,
  867. "changes": True,
  868. "comment": 'Command "echo "Changed!"" run',
  869. "result": True,
  870. },
  871. 'cmd_|-test_one_changing_states_|-echo "Success!"_|-run': {
  872. "__run_num__": 4,
  873. "changes": True,
  874. "comment": 'Command "echo "Success!"" run',
  875. "result": True,
  876. },
  877. 'cmd_|-test_two_non_changing_states_|-echo "Should not run"_|-run': {
  878. "__run_num__": 5,
  879. "changes": False,
  880. "comment": "State was not run because none of the onchanges reqs changed",
  881. "result": True,
  882. },
  883. "pip_|-another_non_changing_state_|-mock_|-installed": {
  884. "__run_num__": 3,
  885. "changes": False,
  886. "comment": "Python package mock was already installed\nAll specified packages are already installed",
  887. "result": True,
  888. },
  889. "pip_|-non_changing_state_|-mock_|-installed": {
  890. "__run_num__": 2,
  891. "changes": False,
  892. "comment": "Python package mock was already installed\nAll specified packages are already installed",
  893. "result": True,
  894. },
  895. }
  896. ret = self.run_function("state.sls", mods="requisites.onchanges_any")
  897. result = self.normalize_ret(ret)
  898. self.assertReturnNonEmptySaltType(ret)
  899. self.assertEqual(expected_result, result)
  900. @slowTest
  901. def test_requisites_onfail_any(self):
  902. """
  903. Call sls file containing several require_in and require.
  904. Ensure that some of them are failing and that the order is right.
  905. """
  906. expected_result = {
  907. "cmd_|-a_|-exit 0_|-run": {
  908. "__run_num__": 0,
  909. "changes": True,
  910. "comment": 'Command "exit 0" run',
  911. "result": True,
  912. },
  913. "cmd_|-b_|-exit 1_|-run": {
  914. "__run_num__": 1,
  915. "changes": True,
  916. "comment": 'Command "exit 1" run',
  917. "result": False,
  918. },
  919. "cmd_|-c_|-exit 0_|-run": {
  920. "__run_num__": 2,
  921. "changes": True,
  922. "comment": 'Command "exit 0" run',
  923. "result": True,
  924. },
  925. "cmd_|-d_|-echo itworked_|-run": {
  926. "__run_num__": 3,
  927. "changes": True,
  928. "comment": 'Command "echo itworked" run',
  929. "result": True,
  930. },
  931. "cmd_|-e_|-exit 0_|-run": {
  932. "__run_num__": 4,
  933. "changes": True,
  934. "comment": 'Command "exit 0" run',
  935. "result": True,
  936. },
  937. "cmd_|-f_|-exit 0_|-run": {
  938. "__run_num__": 5,
  939. "changes": True,
  940. "comment": 'Command "exit 0" run',
  941. "result": True,
  942. },
  943. "cmd_|-g_|-exit 0_|-run": {
  944. "__run_num__": 6,
  945. "changes": True,
  946. "comment": 'Command "exit 0" run',
  947. "result": True,
  948. },
  949. "cmd_|-h_|-echo itworked_|-run": {
  950. "__run_num__": 7,
  951. "changes": False,
  952. "comment": "State was not run because onfail req did not change",
  953. "result": True,
  954. },
  955. }
  956. ret = self.run_function("state.sls", mods="requisites.onfail_any")
  957. result = self.normalize_ret(ret)
  958. self.assertReturnNonEmptySaltType(ret)
  959. self.assertEqual(expected_result, result)
  960. @slowTest
  961. def test_requisites_onfail_all(self):
  962. """
  963. Call sls file containing several onfail-all
  964. Ensure that some of them are failing and that the order is right.
  965. """
  966. expected_result = {
  967. "cmd_|-a_|-exit 0_|-run": {
  968. "__run_num__": 0,
  969. "changes": True,
  970. "comment": 'Command "exit 0" run',
  971. "result": True,
  972. },
  973. "cmd_|-b_|-exit 0_|-run": {
  974. "__run_num__": 1,
  975. "changes": True,
  976. "comment": 'Command "exit 0" run',
  977. "result": True,
  978. },
  979. "cmd_|-c_|-exit 0_|-run": {
  980. "__run_num__": 2,
  981. "changes": True,
  982. "comment": 'Command "exit 0" run',
  983. "result": True,
  984. },
  985. "cmd_|-d_|-exit 1_|-run": {
  986. "__run_num__": 3,
  987. "changes": True,
  988. "comment": 'Command "exit 1" run',
  989. "result": False,
  990. },
  991. "cmd_|-e_|-exit 1_|-run": {
  992. "__run_num__": 4,
  993. "changes": True,
  994. "comment": 'Command "exit 1" run',
  995. "result": False,
  996. },
  997. "cmd_|-f_|-exit 1_|-run": {
  998. "__run_num__": 5,
  999. "changes": True,
  1000. "comment": 'Command "exit 1" run',
  1001. "result": False,
  1002. },
  1003. "cmd_|-reqs also met_|-echo itonfailed_|-run": {
  1004. "__run_num__": 9,
  1005. "changes": True,
  1006. "comment": 'Command "echo itonfailed" run',
  1007. "result": True,
  1008. },
  1009. "cmd_|-reqs also not met_|-echo italsodidnonfail_|-run": {
  1010. "__run_num__": 7,
  1011. "changes": False,
  1012. "comment": "State was not run because onfail req did not change",
  1013. "result": True,
  1014. },
  1015. "cmd_|-reqs met_|-echo itonfailed_|-run": {
  1016. "__run_num__": 8,
  1017. "changes": True,
  1018. "comment": 'Command "echo itonfailed" run',
  1019. "result": True,
  1020. },
  1021. "cmd_|-reqs not met_|-echo itdidntonfail_|-run": {
  1022. "__run_num__": 6,
  1023. "changes": False,
  1024. "comment": "State was not run because onfail req did not change",
  1025. "result": True,
  1026. },
  1027. }
  1028. ret = self.run_function("state.sls", mods="requisites.onfail_all")
  1029. result = self.normalize_ret(ret)
  1030. self.assertReturnNonEmptySaltType(ret)
  1031. self.assertEqual(expected_result, result)
  1032. @slowTest
  1033. def test_requisites_full_sls(self):
  1034. """
  1035. Teste the sls special command in requisites
  1036. """
  1037. expected_result = {
  1038. "cmd_|-A_|-echo A_|-run": {
  1039. "__run_num__": 2,
  1040. "comment": 'Command "echo A" run',
  1041. "result": True,
  1042. "changes": True,
  1043. },
  1044. "cmd_|-B_|-echo B_|-run": {
  1045. "__run_num__": 0,
  1046. "comment": 'Command "echo B" run',
  1047. "result": True,
  1048. "changes": True,
  1049. },
  1050. "cmd_|-C_|-echo C_|-run": {
  1051. "__run_num__": 1,
  1052. "comment": 'Command "echo C" run',
  1053. "result": True,
  1054. "changes": True,
  1055. },
  1056. }
  1057. ret = self.run_function("state.sls", mods="requisites.fullsls_require")
  1058. self.assertReturnNonEmptySaltType(ret)
  1059. result = self.normalize_ret(ret)
  1060. self.assertEqual(expected_result, result)
  1061. # issue #8233: traceback on prereq sls
  1062. # TODO: not done
  1063. # ret = self.run_function('state.sls', mods='requisites.fullsls_prereq')
  1064. # self.assertEqual(['sls command can only be used with require requisite'], ret)
  1065. @slowTest
  1066. def test_requisites_require_no_state_module(self):
  1067. """
  1068. Call sls file containing several require_in and require.
  1069. Ensure that some of them are failing and that the order is right.
  1070. """
  1071. expected_result = {
  1072. "cmd_|-A_|-echo A fifth_|-run": {
  1073. "__run_num__": 4,
  1074. "comment": 'Command "echo A fifth" run',
  1075. "result": True,
  1076. "changes": True,
  1077. },
  1078. "cmd_|-B_|-echo B second_|-run": {
  1079. "__run_num__": 1,
  1080. "comment": 'Command "echo B second" run',
  1081. "result": True,
  1082. "changes": True,
  1083. },
  1084. "cmd_|-C_|-echo C third_|-run": {
  1085. "__run_num__": 2,
  1086. "comment": 'Command "echo C third" run',
  1087. "result": True,
  1088. "changes": True,
  1089. },
  1090. "cmd_|-D_|-echo D first_|-run": {
  1091. "__run_num__": 0,
  1092. "comment": 'Command "echo D first" run',
  1093. "result": True,
  1094. "changes": True,
  1095. },
  1096. "cmd_|-E_|-echo E fourth_|-run": {
  1097. "__run_num__": 3,
  1098. "comment": 'Command "echo E fourth" run',
  1099. "result": True,
  1100. "changes": True,
  1101. },
  1102. "cmd_|-G_|-echo G_|-run": {
  1103. "__run_num__": 5,
  1104. "comment": "The following requisites were not found:\n"
  1105. + " require:\n"
  1106. + " id: Z\n",
  1107. "result": False,
  1108. "changes": False,
  1109. },
  1110. "cmd_|-H_|-echo H_|-run": {
  1111. "__run_num__": 6,
  1112. "comment": "The following requisites were not found:\n"
  1113. + " require:\n"
  1114. + " id: Z\n",
  1115. "result": False,
  1116. "changes": False,
  1117. },
  1118. }
  1119. ret = self.run_function("state.sls", mods="requisites.require_no_state_module")
  1120. result = self.normalize_ret(ret)
  1121. self.assertReturnNonEmptySaltType(ret)
  1122. self.assertEqual(expected_result, result)
  1123. @slowTest
  1124. def test_requisites_prereq_simple_ordering_and_errors(self):
  1125. """
  1126. Call sls file containing several prereq_in and prereq.
  1127. Ensure that some of them are failing and that the order is right.
  1128. """
  1129. expected_result_simple = {
  1130. "cmd_|-A_|-echo A third_|-run": {
  1131. "__run_num__": 2,
  1132. "comment": 'Command "echo A third" run',
  1133. "result": True,
  1134. "changes": True,
  1135. },
  1136. "cmd_|-B_|-echo B first_|-run": {
  1137. "__run_num__": 0,
  1138. "comment": 'Command "echo B first" run',
  1139. "result": True,
  1140. "changes": True,
  1141. },
  1142. "cmd_|-C_|-echo C second_|-run": {
  1143. "__run_num__": 1,
  1144. "comment": 'Command "echo C second" run',
  1145. "result": True,
  1146. "changes": True,
  1147. },
  1148. "cmd_|-I_|-echo I_|-run": {
  1149. "__run_num__": 3,
  1150. "comment": "The following requisites were not found:\n"
  1151. + " prereq:\n"
  1152. + " cmd: Z\n",
  1153. "result": False,
  1154. "changes": False,
  1155. },
  1156. "cmd_|-J_|-echo J_|-run": {
  1157. "__run_num__": 4,
  1158. "comment": "The following requisites were not found:\n"
  1159. + " prereq:\n"
  1160. + " foobar: A\n",
  1161. "result": False,
  1162. "changes": False,
  1163. },
  1164. }
  1165. expected_result_simple_no_state_module = {
  1166. "cmd_|-A_|-echo A third_|-run": {
  1167. "__run_num__": 2,
  1168. "comment": 'Command "echo A third" run',
  1169. "result": True,
  1170. "changes": True,
  1171. },
  1172. "cmd_|-B_|-echo B first_|-run": {
  1173. "__run_num__": 0,
  1174. "comment": 'Command "echo B first" run',
  1175. "result": True,
  1176. "changes": True,
  1177. },
  1178. "cmd_|-C_|-echo C second_|-run": {
  1179. "__run_num__": 1,
  1180. "comment": 'Command "echo C second" run',
  1181. "result": True,
  1182. "changes": True,
  1183. },
  1184. "cmd_|-I_|-echo I_|-run": {
  1185. "__run_num__": 3,
  1186. "comment": "The following requisites were not found:\n"
  1187. + " prereq:\n"
  1188. + " id: Z\n",
  1189. "result": False,
  1190. "changes": False,
  1191. },
  1192. }
  1193. expected_result_simple2 = {
  1194. "cmd_|-A_|-echo A_|-run": {
  1195. "__run_num__": 1,
  1196. "comment": 'Command "echo A" run',
  1197. "result": True,
  1198. "changes": True,
  1199. },
  1200. "cmd_|-B_|-echo B_|-run": {
  1201. "__run_num__": 2,
  1202. "comment": 'Command "echo B" run',
  1203. "result": True,
  1204. "changes": True,
  1205. },
  1206. "cmd_|-C_|-echo C_|-run": {
  1207. "__run_num__": 0,
  1208. "comment": 'Command "echo C" run',
  1209. "result": True,
  1210. "changes": True,
  1211. },
  1212. "cmd_|-D_|-echo D_|-run": {
  1213. "__run_num__": 3,
  1214. "comment": 'Command "echo D" run',
  1215. "result": True,
  1216. "changes": True,
  1217. },
  1218. "cmd_|-E_|-echo E_|-run": {
  1219. "__run_num__": 4,
  1220. "comment": 'Command "echo E" run',
  1221. "result": True,
  1222. "changes": True,
  1223. },
  1224. }
  1225. expected_result_simple3 = {
  1226. "cmd_|-A_|-echo A first_|-run": {
  1227. "__run_num__": 0,
  1228. "comment": 'Command "echo A first" run',
  1229. "result": True,
  1230. "changes": True,
  1231. },
  1232. "cmd_|-B_|-echo B second_|-run": {
  1233. "__run_num__": 1,
  1234. "comment": 'Command "echo B second" run',
  1235. "result": True,
  1236. "changes": True,
  1237. },
  1238. "cmd_|-C_|-echo C third_|-wait": {
  1239. "__run_num__": 2,
  1240. "comment": "",
  1241. "result": True,
  1242. "changes": False,
  1243. },
  1244. }
  1245. expected_result_complex = {
  1246. "cmd_|-A_|-echo A fourth_|-run": {
  1247. "__run_num__": 3,
  1248. "comment": 'Command "echo A fourth" run',
  1249. "result": True,
  1250. "changes": True,
  1251. },
  1252. "cmd_|-B_|-echo B first_|-run": {
  1253. "__run_num__": 0,
  1254. "comment": 'Command "echo B first" run',
  1255. "result": True,
  1256. "changes": True,
  1257. },
  1258. "cmd_|-C_|-echo C second_|-run": {
  1259. "__run_num__": 1,
  1260. "comment": 'Command "echo C second" run',
  1261. "result": True,
  1262. "changes": True,
  1263. },
  1264. "cmd_|-D_|-echo D third_|-run": {
  1265. "__run_num__": 2,
  1266. "comment": 'Command "echo D third" run',
  1267. "result": True,
  1268. "changes": True,
  1269. },
  1270. }
  1271. ret = self.run_function("state.sls", mods="requisites.prereq_simple")
  1272. self.assertReturnNonEmptySaltType(ret)
  1273. result = self.normalize_ret(ret)
  1274. self.assertEqual(expected_result_simple, result)
  1275. # same test, but not using lists in yaml syntax
  1276. # TODO: issue #8235, prereq ignored when not used in list syntax
  1277. # Currently fails badly with :
  1278. # TypeError encountered executing state.sls: string indices must be integers, not str.
  1279. # expected_result_simple.pop('cmd_|-I_|-echo I_|-run')
  1280. # expected_result_simple.pop('cmd_|-J_|-echo J_|-run')
  1281. # ret = self.run_function('state.sls', mods='requisites.prereq_simple_nolist')
  1282. # result = self.normalize_ret(ret)
  1283. # self.assertEqual(expected_result_simple, result)
  1284. ret = self.run_function("state.sls", mods="requisites.prereq_simple2")
  1285. result = self.normalize_ret(ret)
  1286. self.assertReturnNonEmptySaltType(ret)
  1287. self.assertEqual(expected_result_simple2, result)
  1288. ret = self.run_function("state.sls", mods="requisites.prereq_simple3")
  1289. result = self.normalize_ret(ret)
  1290. self.assertReturnNonEmptySaltType(ret)
  1291. self.assertEqual(expected_result_simple3, result)
  1292. # ret = self.run_function('state.sls', mods='requisites.prereq_error_nolist')
  1293. # self.assertEqual(
  1294. # ret,
  1295. # ['Cannot extend ID Z in "base:requisites.prereq_error_nolist".'
  1296. # + ' It is not part of the high state.']
  1297. # )
  1298. ret = self.run_function("state.sls", mods="requisites.prereq_compile_error1")
  1299. self.assertReturnNonEmptySaltType(ret)
  1300. self.assertEqual(
  1301. ret["cmd_|-B_|-echo B_|-run"]["comment"],
  1302. "The following requisites were not found:\n"
  1303. + " prereq:\n"
  1304. + " foobar: A\n",
  1305. )
  1306. ret = self.run_function("state.sls", mods="requisites.prereq_compile_error2")
  1307. self.assertReturnNonEmptySaltType(ret)
  1308. self.assertEqual(
  1309. ret["cmd_|-B_|-echo B_|-run"]["comment"],
  1310. "The following requisites were not found:\n"
  1311. + " prereq:\n"
  1312. + " foobar: C\n",
  1313. )
  1314. ret = self.run_function("state.sls", mods="requisites.prereq_complex")
  1315. result = self.normalize_ret(ret)
  1316. self.assertEqual(expected_result_complex, result)
  1317. # issue #8210 : prereq recursion undetected
  1318. # TODO: this test fails
  1319. # ret = self.run_function('state.sls', mods='requisites.prereq_recursion_error')
  1320. # self.assertEqual(
  1321. # ret,
  1322. # ['A recursive requisite was found, SLS "requisites.prereq_recursion_error" ID "B" ID "A"']
  1323. # )
  1324. ret = self.run_function(
  1325. "state.sls", mods="requisites.prereq_simple_no_state_module"
  1326. )
  1327. result = self.normalize_ret(ret)
  1328. self.assertEqual(expected_result_simple_no_state_module, result)
  1329. @slowTest
  1330. def test_infinite_recursion_sls_prereq(self):
  1331. ret = self.run_function(
  1332. "state.sls", mods="requisites.prereq_sls_infinite_recursion"
  1333. )
  1334. self.assertSaltTrueReturn(ret)
  1335. @slowTest
  1336. def test_requisites_use(self):
  1337. """
  1338. Call sls file containing several use_in and use.
  1339. """
  1340. # TODO issue #8235 & #8774 some examples are still commented in the test file
  1341. ret = self.run_function("state.sls", mods="requisites.use")
  1342. self.assertReturnNonEmptySaltType(ret)
  1343. for item, descr in ret.items():
  1344. self.assertEqual(descr["comment"], "onlyif condition is false")
  1345. # TODO: issue #8802 : use recursions undetected
  1346. # issue is closed as use does not actually inherit requisites
  1347. # if chain-use is added after #8774 resolution theses tests would maybe become useful
  1348. # ret = self.run_function('state.sls', mods='requisites.use_recursion')
  1349. # self.assertEqual(ret, [
  1350. # 'A recursive requisite was found, SLS "requisites.use_recursion"'
  1351. # + ' ID "B" ID "A"'
  1352. # ])
  1353. # ret = self.run_function('state.sls', mods='requisites.use_recursion2')
  1354. # self.assertEqual(ret, [
  1355. # 'A recursive requisite was found, SLS "requisites.use_recursion2"'
  1356. # + ' ID "C" ID "A"'
  1357. # ])
  1358. # ret = self.run_function('state.sls', mods='requisites.use_auto_recursion')
  1359. # self.assertEqual(ret, [
  1360. # 'A recursive requisite was found, SLS "requisites.use_recursion"'
  1361. # + ' ID "A" ID "A"'
  1362. # ])
  1363. @slowTest
  1364. def test_requisites_use_no_state_module(self):
  1365. """
  1366. Call sls file containing several use_in and use.
  1367. """
  1368. ret = self.run_function("state.sls", mods="requisites.use_no_state_module")
  1369. self.assertReturnNonEmptySaltType(ret)
  1370. for item, descr in ret.items():
  1371. self.assertEqual(descr["comment"], "onlyif condition is false")
  1372. @slowTest
  1373. def test_onlyif_req(self):
  1374. ret = self.run_function(
  1375. "state.single",
  1376. fun="test.succeed_with_changes",
  1377. name="onlyif test",
  1378. onlyif=[{}],
  1379. )["test_|-onlyif test_|-onlyif test_|-succeed_with_changes"]
  1380. self.assertTrue(ret["result"])
  1381. self.assertEqual(ret["comment"], "Success!")
  1382. ret = self.run_function(
  1383. "state.single",
  1384. fun="test.fail_with_changes",
  1385. name="onlyif test",
  1386. onlyif=[{"fun": "test.false"}],
  1387. )["test_|-onlyif test_|-onlyif test_|-fail_with_changes"]
  1388. self.assertTrue(ret["result"])
  1389. self.assertFalse(ret["changes"])
  1390. self.assertEqual(ret["comment"], "onlyif condition is false")
  1391. ret = self.run_function(
  1392. "state.single",
  1393. fun="test.fail_with_changes",
  1394. name="onlyif test",
  1395. onlyif=[{"fun": "test.true"}],
  1396. )["test_|-onlyif test_|-onlyif test_|-fail_with_changes"]
  1397. self.assertFalse(ret["result"])
  1398. self.assertTrue(ret["changes"])
  1399. self.assertEqual(ret["comment"], "Failure!")
  1400. ret = self.run_function(
  1401. "state.single",
  1402. fun="test.succeed_without_changes",
  1403. name="onlyif test",
  1404. onlyif=[{"fun": "test.true"}],
  1405. )["test_|-onlyif test_|-onlyif test_|-succeed_without_changes"]
  1406. self.assertTrue(ret["result"])
  1407. self.assertFalse(ret["changes"])
  1408. self.assertEqual(ret["comment"], "Success!")
  1409. @slowTest
  1410. def test_onlyif_req_retcode(self):
  1411. ret = self.run_function(
  1412. "state.single",
  1413. fun="test.succeed_with_changes",
  1414. name="onlyif test",
  1415. onlyif=[{"fun": "test.retcode"}],
  1416. )["test_|-onlyif test_|-onlyif test_|-succeed_with_changes"]
  1417. self.assertTrue(ret["result"])
  1418. self.assertFalse(ret["changes"])
  1419. self.assertEqual(ret["comment"], "onlyif condition is false")
  1420. ret = self.run_function(
  1421. "state.single",
  1422. fun="test.succeed_with_changes",
  1423. name="onlyif test",
  1424. onlyif=[{"fun": "test.retcode", "code": 0}],
  1425. )["test_|-onlyif test_|-onlyif test_|-succeed_with_changes"]
  1426. self.assertTrue(ret["result"])
  1427. self.assertTrue(ret["changes"])
  1428. self.assertEqual(ret["comment"], "Success!")
  1429. @slowTest
  1430. def test_unless_req(self):
  1431. ret = self.run_function(
  1432. "state.single",
  1433. fun="test.succeed_with_changes",
  1434. name="unless test",
  1435. unless=[{}],
  1436. )["test_|-unless test_|-unless test_|-succeed_with_changes"]
  1437. self.assertTrue(ret["result"])
  1438. self.assertEqual(ret["comment"], "Success!")
  1439. ret = self.run_function(
  1440. "state.single",
  1441. fun="test.fail_with_changes",
  1442. name="unless test",
  1443. unless=[{"fun": "test.true"}],
  1444. )["test_|-unless test_|-unless test_|-fail_with_changes"]
  1445. self.assertTrue(ret["result"])
  1446. self.assertFalse(ret["changes"])
  1447. self.assertEqual(ret["comment"], "unless condition is true")
  1448. ret = self.run_function(
  1449. "state.single",
  1450. fun="test.fail_with_changes",
  1451. name="unless test",
  1452. unless=[{"fun": "test.false"}],
  1453. )["test_|-unless test_|-unless test_|-fail_with_changes"]
  1454. self.assertFalse(ret["result"])
  1455. self.assertTrue(ret["changes"])
  1456. self.assertEqual(ret["comment"], "Failure!")
  1457. ret = self.run_function(
  1458. "state.single",
  1459. fun="test.succeed_without_changes",
  1460. name="unless test",
  1461. unless=[{"fun": "test.false"}],
  1462. )["test_|-unless test_|-unless test_|-succeed_without_changes"]
  1463. self.assertTrue(ret["result"])
  1464. self.assertFalse(ret["changes"])
  1465. self.assertEqual(ret["comment"], "Success!")
  1466. @slowTest
  1467. def test_unless_req_retcode(self):
  1468. ret = self.run_function(
  1469. "state.single",
  1470. fun="test.succeed_with_changes",
  1471. name="unless test",
  1472. unless=[{"fun": "test.retcode"}],
  1473. )["test_|-unless test_|-unless test_|-succeed_with_changes"]
  1474. self.assertTrue(ret["result"])
  1475. self.assertTrue(ret["changes"])
  1476. self.assertEqual(ret["comment"], "Success!")
  1477. ret = self.run_function(
  1478. "state.single",
  1479. fun="test.succeed_with_changes",
  1480. name="unless test",
  1481. unless=[{"fun": "test.retcode", "code": 0}],
  1482. )["test_|-unless test_|-unless test_|-succeed_with_changes"]
  1483. self.assertTrue(ret["result"])
  1484. self.assertFalse(ret["changes"])
  1485. self.assertEqual(ret["comment"], "unless condition is true")
  1486. @slowTest
  1487. @pytest.mark.usefixtures("salt_sub_minion")
  1488. def test_get_file_from_env_in_top_match(self):
  1489. tgt = os.path.join(RUNTIME_VARS.TMP, "prod-cheese-file")
  1490. try:
  1491. ret = self.run_function("state.highstate", minion_tgt="sub_minion")
  1492. self.assertSaltTrueReturn(ret)
  1493. self.assertTrue(os.path.isfile(tgt))
  1494. with salt.utils.files.fopen(tgt, "r") as cheese:
  1495. data = salt.utils.stringutils.to_unicode(cheese.read())
  1496. self.assertIn("Gromit", data)
  1497. self.assertIn("Comte", data)
  1498. finally:
  1499. if os.path.islink(tgt):
  1500. os.unlink(tgt)
  1501. # onchanges tests
  1502. @slowTest
  1503. def test_onchanges_requisite(self):
  1504. """
  1505. Tests a simple state using the onchanges requisite
  1506. """
  1507. # Only run the state once and keep the return data
  1508. state_run = self.run_function("state.sls", mods="requisites.onchanges_simple")
  1509. # First, test the result of the state run when changes are expected to happen
  1510. test_data = state_run['cmd_|-test_changing_state_|-echo "Success!"_|-run'][
  1511. "comment"
  1512. ]
  1513. expected_result = 'Command "echo "Success!"" run'
  1514. self.assertIn(expected_result, test_data)
  1515. # Then, test the result of the state run when changes are not expected to happen
  1516. test_data = state_run[
  1517. 'cmd_|-test_non_changing_state_|-echo "Should not run"_|-run'
  1518. ]["comment"]
  1519. expected_result = "State was not run because none of the onchanges reqs changed"
  1520. self.assertIn(expected_result, test_data)
  1521. @slowTest
  1522. def test_onchanges_requisite_multiple(self):
  1523. """
  1524. Tests a simple state using the onchanges requisite
  1525. """
  1526. # Only run the state once and keep the return data
  1527. state_run = self.run_function("state.sls", mods="requisites.onchanges_multiple")
  1528. # First, test the result of the state run when two changes are expected to happen
  1529. test_data = state_run['cmd_|-test_two_changing_states_|-echo "Success!"_|-run'][
  1530. "comment"
  1531. ]
  1532. expected_result = 'Command "echo "Success!"" run'
  1533. self.assertIn(expected_result, test_data)
  1534. # Then, test the result of the state run when two changes are not expected to happen
  1535. test_data = state_run[
  1536. 'cmd_|-test_two_non_changing_states_|-echo "Should not run"_|-run'
  1537. ]["comment"]
  1538. expected_result = "State was not run because none of the onchanges reqs changed"
  1539. self.assertIn(expected_result, test_data)
  1540. # Finally, test the result of the state run when only one of the onchanges requisites changes.
  1541. test_data = state_run['cmd_|-test_one_changing_state_|-echo "Success!"_|-run'][
  1542. "comment"
  1543. ]
  1544. expected_result = 'Command "echo "Success!"" run'
  1545. self.assertIn(expected_result, test_data)
  1546. @slowTest
  1547. def test_onchanges_in_requisite(self):
  1548. """
  1549. Tests a simple state using the onchanges_in requisite
  1550. """
  1551. # Only run the state once and keep the return data
  1552. state_run = self.run_function(
  1553. "state.sls", mods="requisites.onchanges_in_simple"
  1554. )
  1555. # First, test the result of the state run of when changes are expected to happen
  1556. test_data = state_run['cmd_|-test_changes_expected_|-echo "Success!"_|-run'][
  1557. "comment"
  1558. ]
  1559. expected_result = 'Command "echo "Success!"" run'
  1560. self.assertIn(expected_result, test_data)
  1561. # Then, test the result of the state run when changes are not expected to happen
  1562. test_data = state_run[
  1563. 'cmd_|-test_changes_not_expected_|-echo "Should not run"_|-run'
  1564. ]["comment"]
  1565. expected_result = "State was not run because none of the onchanges reqs changed"
  1566. self.assertIn(expected_result, test_data)
  1567. @slowTest
  1568. def test_onchanges_requisite_no_state_module(self):
  1569. """
  1570. Tests a simple state using the onchanges requisite without state modules
  1571. """
  1572. # Only run the state once and keep the return data
  1573. state_run = self.run_function(
  1574. "state.sls", mods="requisites.onchanges_simple_no_state_module"
  1575. )
  1576. test_data = state_run['cmd_|-test_changing_state_|-echo "Success!"_|-run'][
  1577. "comment"
  1578. ]
  1579. expected_result = 'Command "echo "Success!"" run'
  1580. self.assertIn(expected_result, test_data)
  1581. @slowTest
  1582. def test_onchanges_requisite_with_duration(self):
  1583. """
  1584. Tests a simple state using the onchanges requisite
  1585. the state will not run but results will include duration
  1586. """
  1587. # Only run the state once and keep the return data
  1588. state_run = self.run_function("state.sls", mods="requisites.onchanges_simple")
  1589. # Then, test the result of the state run when changes are not expected to happen
  1590. # and ensure duration is included in the results
  1591. test_data = state_run[
  1592. 'cmd_|-test_non_changing_state_|-echo "Should not run"_|-run'
  1593. ]
  1594. self.assertIn("duration", test_data)
  1595. # onfail tests
  1596. @slowTest
  1597. def test_onfail_requisite(self):
  1598. """
  1599. Tests a simple state using the onfail requisite
  1600. """
  1601. # Only run the state once and keep the return data
  1602. state_run = self.run_function("state.sls", mods="requisites.onfail_simple")
  1603. # First, test the result of the state run when a failure is expected to happen
  1604. test_data = state_run['cmd_|-test_failing_state_|-echo "Success!"_|-run'][
  1605. "comment"
  1606. ]
  1607. expected_result = 'Command "echo "Success!"" run'
  1608. self.assertIn(expected_result, test_data)
  1609. # Then, test the result of the state run when a failure is not expected to happen
  1610. test_data = state_run[
  1611. 'cmd_|-test_non_failing_state_|-echo "Should not run"_|-run'
  1612. ]["comment"]
  1613. expected_result = "State was not run because onfail req did not change"
  1614. self.assertIn(expected_result, test_data)
  1615. @slowTest
  1616. def test_multiple_onfail_requisite(self):
  1617. """
  1618. test to ensure state is run even if only one
  1619. of the onfails fails. This is a test for the issue:
  1620. https://github.com/saltstack/salt/issues/22370
  1621. """
  1622. state_run = self.run_function(
  1623. "state.sls", mods="requisites.onfail_multiple", timeout=self.TIMEOUT
  1624. )
  1625. retcode = state_run["cmd_|-c_|-echo itworked_|-run"]["changes"]["retcode"]
  1626. self.assertEqual(retcode, 0)
  1627. stdout = state_run["cmd_|-c_|-echo itworked_|-run"]["changes"]["stdout"]
  1628. self.assertEqual(stdout, "itworked")
  1629. @slowTest
  1630. def test_onfail_in_requisite(self):
  1631. """
  1632. Tests a simple state using the onfail_in requisite
  1633. """
  1634. # Only run the state once and keep the return data
  1635. state_run = self.run_function("state.sls", mods="requisites.onfail_in_simple")
  1636. # First, test the result of the state run when a failure is expected to happen
  1637. test_data = state_run['cmd_|-test_failing_state_|-echo "Success!"_|-run'][
  1638. "comment"
  1639. ]
  1640. expected_result = 'Command "echo "Success!"" run'
  1641. self.assertIn(expected_result, test_data)
  1642. # Then, test the result of the state run when a failure is not expected to happen
  1643. test_data = state_run[
  1644. 'cmd_|-test_non_failing_state_|-echo "Should not run"_|-run'
  1645. ]["comment"]
  1646. expected_result = "State was not run because onfail req did not change"
  1647. self.assertIn(expected_result, test_data)
  1648. @slowTest
  1649. def test_onfail_requisite_no_state_module(self):
  1650. """
  1651. Tests a simple state using the onfail requisite
  1652. """
  1653. # Only run the state once and keep the return data
  1654. state_run = self.run_function(
  1655. "state.sls", mods="requisites.onfail_simple_no_state_module"
  1656. )
  1657. # First, test the result of the state run when a failure is expected to happen
  1658. test_data = state_run['cmd_|-test_failing_state_|-echo "Success!"_|-run'][
  1659. "comment"
  1660. ]
  1661. expected_result = 'Command "echo "Success!"" run'
  1662. self.assertIn(expected_result, test_data)
  1663. # Then, test the result of the state run when a failure is not expected to happen
  1664. test_data = state_run[
  1665. 'cmd_|-test_non_failing_state_|-echo "Should not run"_|-run'
  1666. ]["comment"]
  1667. expected_result = "State was not run because onfail req did not change"
  1668. self.assertIn(expected_result, test_data)
  1669. @slowTest
  1670. def test_onfail_requisite_with_duration(self):
  1671. """
  1672. Tests a simple state using the onfail requisite
  1673. """
  1674. # Only run the state once and keep the return data
  1675. state_run = self.run_function("state.sls", mods="requisites.onfail_simple")
  1676. # Then, test the result of the state run when a failure is not expected to happen
  1677. test_data = state_run[
  1678. 'cmd_|-test_non_failing_state_|-echo "Should not run"_|-run'
  1679. ]
  1680. self.assertIn("duration", test_data)
  1681. @slowTest
  1682. def test_multiple_onfail_requisite_with_required(self):
  1683. """
  1684. test to ensure multiple states are run
  1685. when specified as onfails for a single state.
  1686. This is a test for the issue:
  1687. https://github.com/saltstack/salt/issues/46552
  1688. """
  1689. state_run = self.run_function(
  1690. "state.sls", mods="requisites.onfail_multiple_required"
  1691. )
  1692. retcode = state_run["cmd_|-b_|-echo b_|-run"]["changes"]["retcode"]
  1693. self.assertEqual(retcode, 0)
  1694. retcode = state_run["cmd_|-c_|-echo c_|-run"]["changes"]["retcode"]
  1695. self.assertEqual(retcode, 0)
  1696. retcode = state_run["cmd_|-d_|-echo d_|-run"]["changes"]["retcode"]
  1697. self.assertEqual(retcode, 0)
  1698. stdout = state_run["cmd_|-b_|-echo b_|-run"]["changes"]["stdout"]
  1699. self.assertEqual(stdout, "b")
  1700. stdout = state_run["cmd_|-c_|-echo c_|-run"]["changes"]["stdout"]
  1701. self.assertEqual(stdout, "c")
  1702. stdout = state_run["cmd_|-d_|-echo d_|-run"]["changes"]["stdout"]
  1703. self.assertEqual(stdout, "d")
  1704. comment = state_run["cmd_|-e_|-echo e_|-run"]["comment"]
  1705. self.assertEqual(comment, "State was not run because onfail req did not change")
  1706. stdout = state_run["cmd_|-f_|-echo f_|-run"]["changes"]["stdout"]
  1707. self.assertEqual(stdout, "f")
  1708. @slowTest
  1709. def test_multiple_onfail_requisite_with_required_no_run(self):
  1710. """
  1711. test to ensure multiple states are not run
  1712. when specified as onfails for a single state
  1713. which fails.
  1714. This is a test for the issue:
  1715. https://github.com/saltstack/salt/issues/46552
  1716. """
  1717. state_run = self.run_function(
  1718. "state.sls", mods="requisites.onfail_multiple_required_no_run"
  1719. )
  1720. expected = "State was not run because onfail req did not change"
  1721. stdout = state_run["cmd_|-b_|-echo b_|-run"]["comment"]
  1722. self.assertEqual(stdout, expected)
  1723. stdout = state_run["cmd_|-c_|-echo c_|-run"]["comment"]
  1724. self.assertEqual(stdout, expected)
  1725. stdout = state_run["cmd_|-d_|-echo d_|-run"]["comment"]
  1726. self.assertEqual(stdout, expected)
  1727. # listen tests
  1728. @slowTest
  1729. def test_listen_requisite(self):
  1730. """
  1731. Tests a simple state using the listen requisite
  1732. """
  1733. # Only run the state once and keep the return data
  1734. state_run = self.run_function("state.sls", mods="requisites.listen_simple")
  1735. # First, test the result of the state run when a listener is expected to trigger
  1736. listener_state = 'cmd_|-listener_test_listening_change_state_|-echo "Listening State"_|-mod_watch'
  1737. self.assertIn(listener_state, state_run)
  1738. # Then, test the result of the state run when a listener should not trigger
  1739. absent_state = 'cmd_|-listener_test_listening_non_changing_state_|-echo "Only run once"_|-mod_watch'
  1740. self.assertNotIn(absent_state, state_run)
  1741. @slowTest
  1742. def test_listen_in_requisite(self):
  1743. """
  1744. Tests a simple state using the listen_in requisite
  1745. """
  1746. # Only run the state once and keep the return data
  1747. state_run = self.run_function("state.sls", mods="requisites.listen_in_simple")
  1748. # First, test the result of the state run when a listener is expected to trigger
  1749. listener_state = 'cmd_|-listener_test_listening_change_state_|-echo "Listening State"_|-mod_watch'
  1750. self.assertIn(listener_state, state_run)
  1751. # Then, test the result of the state run when a listener should not trigger
  1752. absent_state = 'cmd_|-listener_test_listening_non_changing_state_|-echo "Only run once"_|-mod_watch'
  1753. self.assertNotIn(absent_state, state_run)
  1754. @slowTest
  1755. def test_listen_in_requisite_resolution(self):
  1756. """
  1757. Verify listen_in requisite lookups use ID declaration to check for changes
  1758. """
  1759. # Only run the state once and keep the return data
  1760. state_run = self.run_function("state.sls", mods="requisites.listen_in_simple")
  1761. # Test the result of the state run when a listener is expected to trigger
  1762. listener_state = 'cmd_|-listener_test_listen_in_resolution_|-echo "Successful listen_in resolution"_|-mod_watch'
  1763. self.assertIn(listener_state, state_run)
  1764. @slowTest
  1765. def test_listen_requisite_resolution(self):
  1766. """
  1767. Verify listen requisite lookups use ID declaration to check for changes
  1768. """
  1769. # Only run the state once and keep the return data
  1770. state_run = self.run_function("state.sls", mods="requisites.listen_simple")
  1771. # Both listeners are expected to trigger
  1772. listener_state = 'cmd_|-listener_test_listening_resolution_one_|-echo "Successful listen resolution"_|-mod_watch'
  1773. self.assertIn(listener_state, state_run)
  1774. listener_state = 'cmd_|-listener_test_listening_resolution_two_|-echo "Successful listen resolution"_|-mod_watch'
  1775. self.assertIn(listener_state, state_run)
  1776. @slowTest
  1777. def test_listen_requisite_no_state_module(self):
  1778. """
  1779. Tests a simple state using the listen requisite
  1780. """
  1781. # Only run the state once and keep the return data
  1782. state_run = self.run_function(
  1783. "state.sls", mods="requisites.listen_simple_no_state_module"
  1784. )
  1785. # First, test the result of the state run when a listener is expected to trigger
  1786. listener_state = 'cmd_|-listener_test_listening_change_state_|-echo "Listening State"_|-mod_watch'
  1787. self.assertIn(listener_state, state_run)
  1788. # Then, test the result of the state run when a listener should not trigger
  1789. absent_state = 'cmd_|-listener_test_listening_non_changing_state_|-echo "Only run once"_|-mod_watch'
  1790. self.assertNotIn(absent_state, state_run)
  1791. @slowTest
  1792. def test_listen_in_requisite_resolution_names(self):
  1793. """
  1794. Verify listen_in requisite lookups use ID declaration to check for changes
  1795. and resolves magic names state variable
  1796. """
  1797. # Only run the state once and keep the return data
  1798. state_run = self.run_function("state.sls", mods="requisites.listen_in_names")
  1799. self.assertIn("test_|-listener_service_|-nginx_|-mod_watch", state_run)
  1800. self.assertIn("test_|-listener_service_|-crond_|-mod_watch", state_run)
  1801. @slowTest
  1802. def test_listen_requisite_resolution_names(self):
  1803. """
  1804. Verify listen requisite lookups use ID declaration to check for changes
  1805. and resolves magic names state variable
  1806. """
  1807. # Only run the state once and keep the return data
  1808. state_run = self.run_function(
  1809. "state.sls", mods="requisites.listen_names", timeout=self.TIMEOUT
  1810. )
  1811. self.assertIn("test_|-listener_service_|-nginx_|-mod_watch", state_run)
  1812. self.assertIn("test_|-listener_service_|-crond_|-mod_watch", state_run)
  1813. @slowTest
  1814. def test_issue_30820_requisite_in_match_by_name(self):
  1815. """
  1816. This tests the case where a requisite_in matches by name instead of ID
  1817. See https://github.com/saltstack/salt/issues/30820 for more info
  1818. """
  1819. state_run = self.run_function(
  1820. "state.sls", mods="requisites.requisite_in_match_by_name"
  1821. )
  1822. bar_state = "cmd_|-bar state_|-echo bar_|-wait"
  1823. self.assertIn(bar_state, state_run)
  1824. self.assertEqual(state_run[bar_state]["comment"], 'Command "echo bar" run')
  1825. @slowTest
  1826. def test_retry_option_defaults(self):
  1827. """
  1828. test the retry option on a simple state with defaults
  1829. ensure comment is as expected
  1830. ensure state duration is greater than default retry_interval (30 seconds)
  1831. """
  1832. state_run = self.run_function("state.sls", mods="retry.retry_defaults")
  1833. retry_state = "file_|-file_test_|-/path/to/a/non-existent/file.txt_|-exists"
  1834. expected_comment = (
  1835. 'Attempt 1: Returned a result of "False", with the following '
  1836. 'comment: "Specified path /path/to/a/non-existent/file.txt does not exist"\n'
  1837. "Specified path /path/to/a/non-existent/file.txt does not exist"
  1838. )
  1839. self.assertEqual(state_run[retry_state]["comment"], expected_comment)
  1840. self.assertTrue(state_run[retry_state]["duration"] > 30)
  1841. self.assertEqual(state_run[retry_state]["result"], False)
  1842. @slowTest
  1843. def test_retry_option_custom(self):
  1844. """
  1845. test the retry option on a simple state with custom retry values
  1846. ensure comment is as expected
  1847. ensure state duration is greater than custom defined interval * (retries - 1)
  1848. """
  1849. state_run = self.run_function("state.sls", mods="retry.retry_custom")
  1850. retry_state = "file_|-file_test_|-/path/to/a/non-existent/file.txt_|-exists"
  1851. expected_comment = (
  1852. 'Attempt 1: Returned a result of "False", with the following '
  1853. 'comment: "Specified path /path/to/a/non-existent/file.txt does not exist"\n'
  1854. 'Attempt 2: Returned a result of "False", with the following comment: "Specified'
  1855. ' path /path/to/a/non-existent/file.txt does not exist"\nAttempt 3: Returned'
  1856. ' a result of "False", with the following comment: "Specified path'
  1857. ' /path/to/a/non-existent/file.txt does not exist"\nAttempt 4: Returned a'
  1858. ' result of "False", with the following comment: "Specified path'
  1859. ' /path/to/a/non-existent/file.txt does not exist"\nSpecified path'
  1860. " /path/to/a/non-existent/file.txt does not exist"
  1861. )
  1862. self.assertEqual(state_run[retry_state]["comment"], expected_comment)
  1863. self.assertTrue(state_run[retry_state]["duration"] > 40)
  1864. self.assertEqual(state_run[retry_state]["result"], False)
  1865. @slowTest
  1866. def test_retry_option_success(self):
  1867. """
  1868. test a state with the retry option that should return True immedietly (i.e. no retries)
  1869. """
  1870. testfile = os.path.join(RUNTIME_VARS.TMP, "retry_file_option_success")
  1871. state_run = self.run_function("state.sls", mods="retry.retry_success")
  1872. os.unlink(testfile)
  1873. retry_state = "file_|-file_test_|-{}_|-exists".format(testfile)
  1874. self.assertNotIn("Attempt", state_run[retry_state]["comment"])
  1875. def run_create(self, testfile):
  1876. """
  1877. helper function to wait 30 seconds and then create the temp retry file
  1878. """
  1879. # Wait for the requisite stae 'file_test_a' to complete before creating
  1880. # test_file
  1881. while True:
  1882. if os.path.exists(testfile + "_a"):
  1883. break
  1884. time.sleep(1)
  1885. time.sleep(30)
  1886. with salt.utils.files.fopen(testfile, "a"):
  1887. pass
  1888. @slowTest
  1889. def test_retry_option_eventual_success(self):
  1890. """
  1891. test a state with the retry option that should return True after at least 4 retry attmempt
  1892. but never run 15 attempts
  1893. """
  1894. testfile = os.path.join(RUNTIME_VARS.TMP, "retry_file_eventual_success")
  1895. assert not os.path.exists(testfile + "_a")
  1896. assert not os.path.exists(testfile)
  1897. create_thread = threading.Thread(target=self.run_create, args=(testfile,))
  1898. create_thread.start()
  1899. state_run = self.run_function("state.sls", mods="retry.retry_success2")
  1900. retry_state = "file_|-file_test_b_|-{}_|-exists".format(testfile)
  1901. self.assertIn("Attempt 1:", state_run[retry_state]["comment"])
  1902. self.assertIn("Attempt 2:", state_run[retry_state]["comment"])
  1903. self.assertIn("Attempt 3:", state_run[retry_state]["comment"])
  1904. self.assertIn("Attempt 4:", state_run[retry_state]["comment"])
  1905. self.assertNotIn("Attempt 15:", state_run[retry_state]["comment"])
  1906. self.assertEqual(state_run[retry_state]["result"], True)
  1907. @slowTest
  1908. def test_issue_38683_require_order_failhard_combination(self):
  1909. """
  1910. This tests the case where require, order, and failhard are all used together in a state definition.
  1911. Previously, the order option, which used in tandem with require and failhard, would cause the state
  1912. compiler to stacktrace. This exposed a logic error in the ``check_failhard`` function of the state
  1913. compiler. With the logic error resolved, this test should now pass.
  1914. See https://github.com/saltstack/salt/issues/38683 for more information.
  1915. """
  1916. state_run = self.run_function(
  1917. "state.sls", mods="requisites.require_order_failhard_combo"
  1918. )
  1919. state_id = "test_|-b_|-b_|-fail_with_changes"
  1920. self.assertIn(state_id, state_run)
  1921. self.assertEqual(state_run[state_id]["comment"], "Failure!")
  1922. self.assertFalse(state_run[state_id]["result"])
  1923. @slowTest
  1924. def test_issue_46762_prereqs_on_a_state_with_unfulfilled_requirements(self):
  1925. """
  1926. This tests the case where state C requires state A, which fails.
  1927. State C is a pre-required state for State B.
  1928. Since state A fails, state C will not run because the requisite failed,
  1929. therefore state B will not run because state C failed to run.
  1930. See https://github.com/saltstack/salt/issues/46762 for
  1931. more information.
  1932. """
  1933. state_run = self.run_function("state.sls", mods="issue-46762")
  1934. state_id = "test_|-a_|-a_|-fail_without_changes"
  1935. self.assertIn(state_id, state_run)
  1936. self.assertEqual(state_run[state_id]["comment"], "Failure!")
  1937. self.assertFalse(state_run[state_id]["result"])
  1938. state_id = "test_|-b_|-b_|-nop"
  1939. self.assertIn(state_id, state_run)
  1940. self.assertEqual(
  1941. state_run[state_id]["comment"],
  1942. "One or more requisite failed: issue-46762.c",
  1943. )
  1944. self.assertFalse(state_run[state_id]["result"])
  1945. state_id = "test_|-c_|-c_|-nop"
  1946. self.assertIn(state_id, state_run)
  1947. self.assertEqual(
  1948. state_run[state_id]["comment"],
  1949. "One or more requisite failed: issue-46762.a",
  1950. )
  1951. self.assertFalse(state_run[state_id]["result"])
  1952. @slowTest
  1953. def test_state_nonbase_environment(self):
  1954. """
  1955. test state.sls with saltenv using a nonbase environment
  1956. with a salt source
  1957. """
  1958. filename = os.path.join(RUNTIME_VARS.TMP, "nonbase_env")
  1959. try:
  1960. ret = self.run_function("state.sls", mods="non-base-env", saltenv="prod")
  1961. ret = ret[next(iter(ret))]
  1962. assert ret["result"]
  1963. assert ret["comment"] == "File {} updated".format(filename)
  1964. assert os.path.isfile(filename)
  1965. finally:
  1966. try:
  1967. os.remove(filename)
  1968. except OSError:
  1969. pass
  1970. @skipIf(
  1971. sys.platform.startswith("win"),
  1972. "Skipped until parallel states can be fixed on Windows",
  1973. )
  1974. @skipIf(
  1975. salt.utils.platform.is_darwin() and six.PY2, "This test hangs on OS X on Py2"
  1976. )
  1977. @slowTest
  1978. def test_parallel_state_with_long_tag(self):
  1979. """
  1980. This tests the case where the state being executed has a long ID dec or
  1981. name and states are being run in parallel. The filenames used for the
  1982. parallel state cache were previously based on the tag for each chunk,
  1983. and longer ID decs or name params can cause the cache file to be longer
  1984. than the operating system's max file name length. To counter this we
  1985. instead generate a SHA1 hash of the chunk's tag to use as the cache
  1986. filename. This test will ensure that long tags don't cause caching
  1987. failures.
  1988. See https://github.com/saltstack/salt/issues/49738 for more info.
  1989. """
  1990. short_command = "helloworld"
  1991. long_command = short_command * 25
  1992. ret = self.run_function(
  1993. "state.sls",
  1994. mods="issue-49738",
  1995. pillar={"short_command": short_command, "long_command": long_command},
  1996. )
  1997. comments = sorted([x["comment"] for x in ret.values()])
  1998. expected = sorted(
  1999. ['Command "{}" run'.format(x) for x in (short_command, long_command)]
  2000. )
  2001. assert comments == expected, "{} != {}".format(comments, expected)
  2002. def _add_runtime_pillar(self, pillar):
  2003. """
  2004. helper class to add pillar data at runtime
  2005. """
  2006. import salt.utils.yaml
  2007. with salt.utils.files.fopen(
  2008. os.path.join(RUNTIME_VARS.TMP_PILLAR_TREE, "pillar.sls"), "w"
  2009. ) as fp:
  2010. salt.utils.yaml.safe_dump(pillar, fp)
  2011. with salt.utils.files.fopen(
  2012. os.path.join(RUNTIME_VARS.TMP_PILLAR_TREE, "top.sls"), "w"
  2013. ) as fp:
  2014. fp.write(
  2015. textwrap.dedent(
  2016. """\
  2017. base:
  2018. '*':
  2019. - pillar
  2020. """
  2021. )
  2022. )
  2023. self.run_function("saltutil.refresh_pillar")
  2024. self.run_function("test.sleep", [5])
  2025. @slowTest
  2026. def test_state_sls_id_test(self):
  2027. """
  2028. test state.sls_id when test is set
  2029. to true in pillar data
  2030. """
  2031. self._add_runtime_pillar(pillar={"test": True})
  2032. testfile = os.path.join(RUNTIME_VARS.TMP, "testfile")
  2033. comment = "The file {} is set to be changed\nNote: No changes made, actual changes may\nbe different due to other states.".format(
  2034. testfile
  2035. )
  2036. ret = self.run_function("state.sls", ["core"])
  2037. for key, val in ret.items():
  2038. self.assertEqual(val["comment"], comment)
  2039. self.assertEqual(val["changes"], {"newfile": testfile})
  2040. @slowTest
  2041. def test_state_sls_id_test_state_test_post_run(self):
  2042. """
  2043. test state.sls_id when test is set to
  2044. true post the state already being run previously
  2045. """
  2046. file_name = os.path.join(RUNTIME_VARS.TMP, "testfile")
  2047. ret = self.run_function("state.sls", ["core"])
  2048. for key, val in ret.items():
  2049. self.assertEqual(val["comment"], "File {} updated".format(file_name))
  2050. self.assertEqual(val["changes"]["diff"], "New file")
  2051. self._add_runtime_pillar(pillar={"test": True})
  2052. ret = self.run_function("state.sls", ["core"])
  2053. for key, val in ret.items():
  2054. self.assertEqual(
  2055. val["comment"], "The file {} is in the correct state".format(file_name)
  2056. )
  2057. self.assertEqual(val["changes"], {})
  2058. @slowTest
  2059. def test_state_sls_id_test_true(self):
  2060. """
  2061. test state.sls_id when test=True is passed as arg
  2062. """
  2063. file_name = os.path.join(RUNTIME_VARS.TMP, "testfile")
  2064. ret = self.run_function("state.sls", ["core"], test=True)
  2065. for key, val in ret.items():
  2066. self.assertEqual(
  2067. val["comment"],
  2068. "The file {} is set to be changed\nNote: No changes made, actual changes may\nbe different due to other states.".format(
  2069. file_name
  2070. ),
  2071. )
  2072. self.assertEqual(val["changes"], {"newfile": file_name})
  2073. @slowTest
  2074. def test_state_sls_id_test_true_post_run(self):
  2075. """
  2076. test state.sls_id when test is set to true as an
  2077. arg post the state already being run previously
  2078. """
  2079. file_name = os.path.join(RUNTIME_VARS.TMP, "testfile")
  2080. ret = self.run_function("state.sls", ["core"])
  2081. for key, val in ret.items():
  2082. self.assertEqual(val["comment"], "File {} updated".format(file_name))
  2083. self.assertEqual(val["changes"]["diff"], "New file")
  2084. ret = self.run_function("state.sls", ["core"], test=True)
  2085. for key, val in ret.items():
  2086. self.assertEqual(
  2087. val["comment"], "The file {} is in the correct state".format(file_name)
  2088. )
  2089. self.assertEqual(val["changes"], {})
  2090. @slowTest
  2091. def test_state_sls_id_test_false_pillar_true(self):
  2092. """
  2093. test state.sls_id when test is set to false as an
  2094. arg and minion_state_test is set to True. Should
  2095. return test=False.
  2096. """
  2097. file_name = os.path.join(RUNTIME_VARS.TMP, "testfile")
  2098. self._add_runtime_pillar(pillar={"test": True})
  2099. ret = self.run_function("state.sls", ["core"], test=False)
  2100. for key, val in ret.items():
  2101. self.assertEqual(val["comment"], "File {} updated".format(file_name))
  2102. self.assertEqual(val["changes"]["diff"], "New file")
  2103. def test_state_test_pillar_false(self):
  2104. """
  2105. test state.test forces test kwarg to True even when pillar is set to False
  2106. """
  2107. self._add_runtime_pillar(pillar={"test": False})
  2108. testfile = os.path.join(RUNTIME_VARS.TMP, "testfile")
  2109. comment = "The file {} is set to be changed\nNote: No changes made, actual changes may\nbe different due to other states.".format(
  2110. testfile
  2111. )
  2112. ret = self.run_function("state.test", ["core"])
  2113. self.assertIsInstance(ret, dict)
  2114. for key, val in ret.items():
  2115. self.assertEqual(val["comment"], comment)
  2116. self.assertEqual(val["changes"], {"newfile": testfile})
  2117. def test_state_test_test_false_pillar_false(self):
  2118. """
  2119. test state.test forces test kwarg to True even when pillar and kwarg are set
  2120. to False
  2121. """
  2122. self._add_runtime_pillar(pillar={"test": False})
  2123. testfile = os.path.join(RUNTIME_VARS.TMP, "testfile")
  2124. comment = "The file {} is set to be changed\nNote: No changes made, actual changes may\nbe different due to other states.".format(
  2125. testfile
  2126. )
  2127. ret = self.run_function("state.test", ["core"], test=False)
  2128. for key, val in ret.items():
  2129. self.assertEqual(val["comment"], comment)
  2130. self.assertEqual(val["changes"], {"newfile": testfile})
  2131. @skipIf(
  2132. six.PY3 and salt.utils.platform.is_darwin(), "Test is broken on macosx and PY3"
  2133. )
  2134. @slowTest
  2135. def test_issue_30161_unless_and_onlyif_together(self):
  2136. """
  2137. test cmd.run using multiple unless options where the first cmd in the
  2138. list will pass, but the second will fail. This tests the fix for issue
  2139. #35384. (The fix is in PR #35545.)
  2140. """
  2141. sls = self.run_function("state.sls", mods="issue-30161")
  2142. self.assertSaltTrueReturn(sls)
  2143. # We must assert against the comment here to make sure the comment reads that the
  2144. # command "echo "hello"" was run. This ensures that we made it to the last unless
  2145. # command in the state. If the comment reads "unless condition is true", or similar,
  2146. # then the unless state run bailed out after the first unless command succeeded,
  2147. # which is the bug we're regression testing for.
  2148. _expected = {
  2149. "file_|-unless_false_onlyif_false_|-{}{}test.txt_|-managed".format(
  2150. RUNTIME_VARS.TMP, os.path.sep
  2151. ): {
  2152. "comment": "onlyif condition is false\nunless condition is false",
  2153. "name": "{}{}test.txt".format(RUNTIME_VARS.TMP, os.path.sep),
  2154. "skip_watch": True,
  2155. "changes": {},
  2156. "result": True,
  2157. },
  2158. "file_|-unless_false_onlyif_true_|-{}{}test.txt_|-managed".format(
  2159. RUNTIME_VARS.TMP, os.path.sep
  2160. ): {
  2161. "comment": "Empty file",
  2162. "name": "{}{}test.txt".format(RUNTIME_VARS.TMP, os.path.sep),
  2163. "start_time": "18:10:20.341753",
  2164. "result": True,
  2165. "changes": {
  2166. "new": "file {}{}test.txt created".format(
  2167. RUNTIME_VARS.TMP, os.path.sep
  2168. )
  2169. },
  2170. },
  2171. "file_|-unless_true_onlyif_false_|-{}{}test.txt_|-managed".format(
  2172. RUNTIME_VARS.TMP, os.path.sep
  2173. ): {
  2174. "comment": "onlyif condition is false\nunless condition is true",
  2175. "name": "{}{}test.txt".format(RUNTIME_VARS.TMP, os.path.sep),
  2176. "start_time": "18:10:22.936446",
  2177. "skip_watch": True,
  2178. "changes": {},
  2179. "result": True,
  2180. },
  2181. "file_|-unless_true_onlyif_true_|-{}{}test.txt_|-managed".format(
  2182. RUNTIME_VARS.TMP, os.path.sep
  2183. ): {
  2184. "comment": "onlyif condition is true\nunless condition is true",
  2185. "name": "{}{}test.txt".format(RUNTIME_VARS.TMP, os.path.sep),
  2186. "skip_watch": True,
  2187. "changes": {},
  2188. "result": True,
  2189. },
  2190. }
  2191. for id in _expected:
  2192. self.assertEqual(sls[id]["comment"], _expected[id]["comment"])
  2193. @skipIf(
  2194. six.PY3 and salt.utils.platform.is_darwin(), "Test is broken on macosx and PY3"
  2195. )
  2196. @slowTest
  2197. def test_state_sls_unicode_characters(self):
  2198. """
  2199. test state.sls when state file contains non-ascii characters
  2200. """
  2201. ret = self.run_function("state.sls", ["issue-46672"])
  2202. log.debug("== ret %s ==", type(ret))
  2203. _expected = "cmd_|-echo1_|-echo 'This is Æ test!'_|-run"
  2204. self.assertIn(_expected, ret)
  2205. def tearDown(self):
  2206. rm_files = [
  2207. os.path.join(RUNTIME_VARS.TMP, "nonbase_env"),
  2208. os.path.join(RUNTIME_VARS.TMP, "testfile"),
  2209. os.path.join(RUNTIME_VARS.TMP, "test.txt"),
  2210. os.path.join(RUNTIME_VARS.TMP_STATE_TREE, "top.sls"),
  2211. ]
  2212. for file_ in rm_files:
  2213. if os.path.isfile(file_):
  2214. os.remove(file_)
  2215. # remove old pillar data
  2216. for filename in os.listdir(RUNTIME_VARS.TMP_PILLAR_TREE):
  2217. os.remove(os.path.join(RUNTIME_VARS.TMP_PILLAR_TREE, filename))
  2218. self.run_function("saltutil.refresh_pillar")
  2219. self.run_function("test.sleep", [5])
  2220. @slowTest
  2221. def test_state_sls_integer_name(self):
  2222. """
  2223. This tests the case where the state file is named
  2224. only with integers
  2225. """
  2226. state_run = self.run_function("state.sls", mods="12345")
  2227. state_id = "test_|-always-passes_|-always-passes_|-succeed_without_changes"
  2228. self.assertIn(state_id, state_run)
  2229. self.assertEqual(state_run[state_id]["comment"], "Success!")
  2230. self.assertTrue(state_run[state_id]["result"])
  2231. @slowTest
  2232. def test_state_sls_lazyloader_allows_recursion(self):
  2233. """
  2234. This tests that referencing dunders like __salt__ work
  2235. context: https://github.com/saltstack/salt/pull/51499
  2236. """
  2237. state_run = self.run_function("state.sls", mods="issue-51499")
  2238. state_id = "test_|-always-passes_|-foo_|-succeed_without_changes"
  2239. self.assertIn(state_id, state_run)
  2240. self.assertEqual(state_run[state_id]["comment"], "Success!")
  2241. self.assertTrue(state_run[state_id]["result"])
  2242. @slowTest
  2243. def test_issue_56131(self):
  2244. module_path = os.path.join(RUNTIME_VARS.CODE_DIR, "pip.py")
  2245. modulec_path = os.path.join(RUNTIME_VARS.CODE_DIR, "__pycache__", "pip.pyc")
  2246. unzip_path = os.path.join(RUNTIME_VARS.TMP, "issue-56131.txt")
  2247. def clean_paths(paths):
  2248. for path in paths:
  2249. try:
  2250. os.remove(path)
  2251. except OSError:
  2252. log.warn("Path not found: %s", path)
  2253. with salt.utils.files.fopen(module_path, "w") as fp:
  2254. fp.write('raise ImportError("No module named pip")')
  2255. self.addCleanup(clean_paths, [unzip_path, module_path, modulec_path])
  2256. assert not os.path.exists(unzip_path)
  2257. state_run = self.run_function(
  2258. "state.sls",
  2259. mods="issue-56131",
  2260. pillar={"unzip_to": RUNTIME_VARS.TMP},
  2261. timeout=30,
  2262. )
  2263. assert state_run is not False
  2264. assert os.path.exists(unzip_path)
  2265. @slowTest
  2266. def test_jinja_renderer_argline(self):
  2267. """
  2268. This is a test case for https://github.com/saltstack/salt/issues/55124
  2269. Renderer for this is in tests/integration/files/file/base/_renderers/issue55124.py
  2270. """
  2271. result = self.run_function("state.sls", mods="issue-55124")
  2272. assert isinstance(result, dict), result
  2273. result = result[next(iter(result))]
  2274. assert result["result"], result
  2275. @slowTest
  2276. def test_parallel_state_with_requires(self):
  2277. """
  2278. This is a test case for https://github.com/saltstack/salt/issues/49273
  2279. Parallel state object has any requisites
  2280. """
  2281. state_file = """
  2282. barrier:
  2283. cmd.run:
  2284. - name: sleep 1
  2285. {%- for x in range(1, 10) %}
  2286. blah-{{x}}:
  2287. cmd.run:
  2288. - name: sleep 2
  2289. - require:
  2290. - barrier
  2291. - barrier2
  2292. - parallel: true
  2293. {% endfor %}
  2294. barrier2:
  2295. test.nop
  2296. """
  2297. with temp_state_file("parallel-with-requisites.sls", state_file):
  2298. start_time = time.time()
  2299. result = self.run_function("state.sls", mods="parallel-with-requisites")
  2300. end_time = time.time()
  2301. # We're running 3 states that sleep for 10 seconds each
  2302. # they'll run in parallel so we should be below 30 seconds
  2303. # confirm that the total runtime is below 30s
  2304. self.assertTrue((time.time() - start_time) < 30)