test_batch.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. # -*- coding: utf-8 -*-
  2. """
  3. :codeauthor: Nicole Thomas <nicole@saltstack.com>
  4. """
  5. from __future__ import absolute_import, print_function, unicode_literals
  6. import pytest
  7. import salt.utils.platform
  8. from tests.support.case import ShellCase
  9. from tests.support.helpers import slowTest
  10. @pytest.mark.windows_whitelisted
  11. @pytest.mark.usefixtures("salt_sub_minion")
  12. class BatchTest(ShellCase):
  13. """
  14. Integration tests for the salt.cli.batch module
  15. """
  16. if salt.utils.platform.is_windows():
  17. run_timeout = 180
  18. else:
  19. run_timeout = 30
  20. @slowTest
  21. def test_batch_run(self):
  22. """
  23. Tests executing a simple batch command to help catch regressions
  24. """
  25. ret = "Executing run on [{0}]".format(repr("sub_minion"))
  26. cmd = self.run_salt(
  27. '"*minion" test.echo "batch testing" -b 50%', timeout=self.run_timeout,
  28. )
  29. self.assertIn(ret, cmd)
  30. @slowTest
  31. def test_batch_run_number(self):
  32. """
  33. Tests executing a simple batch command using a number division instead of
  34. a percentage with full batch CLI call.
  35. """
  36. ret = "Executing run on [{0}, {1}]".format(repr("minion"), repr("sub_minion"))
  37. cmd = self.run_salt(
  38. '"*minion" test.ping --batch-size 2', timeout=self.run_timeout,
  39. )
  40. self.assertIn(ret, cmd)
  41. @slowTest
  42. def test_batch_run_grains_targeting(self):
  43. """
  44. Tests executing a batch command using a percentage divisor as well as grains
  45. targeting.
  46. """
  47. os_grain = ""
  48. sub_min_ret = "Executing run on [{0}]".format(repr("sub_minion"))
  49. min_ret = "Executing run on [{0}]".format(repr("minion"))
  50. for item in self.run_salt("minion grains.get os"):
  51. if item != "minion:":
  52. os_grain = item
  53. os_grain = os_grain.strip()
  54. cmd = self.run_salt(
  55. '-C "G@os:{0} and not localhost" -b 25% test.ping'.format(os_grain),
  56. timeout=self.run_timeout,
  57. )
  58. self.assertIn(sub_min_ret, cmd)
  59. self.assertIn(min_ret, cmd)
  60. @slowTest
  61. def test_batch_exit_code(self):
  62. """
  63. Test that a failed state returns a non-zero exit code in batch mode
  64. """
  65. cmd = self.run_salt(
  66. ' "*" state.single test.fail_without_changes name=test_me -b 25%',
  67. with_retcode=True,
  68. timeout=self.run_timeout,
  69. )
  70. self.assertEqual(cmd[-1], 2)
  71. # Test for failhard + batch. The best possible solution here was to do something like that:
  72. # assertRaises(StopIteration)
  73. # But it's impossible due to nature of the tests execution via fork()
  74. @slowTest
  75. def test_batch_module_stopping_after_error(self):
  76. """
  77. Test that a failed command stops the batch run
  78. """
  79. minions_list = []
  80. retcode = None
  81. # Executing salt with batch: 1 and with failhard. It should stop after the first error.
  82. cmd = self.run_salt(
  83. '"*minion" test.retcode 42 -b 1 --out=yaml --failhard',
  84. timeout=self.run_timeout,
  85. )
  86. # Parsing the output. Idea is to fetch number on minions and retcode of the execution.
  87. # retcode var could be overwritten in case of broken failhard but number of minions check should still fail.
  88. for line in cmd:
  89. if line.startswith("Executing run on"):
  90. minions_list.append(line)
  91. if line.startswith("retcode"):
  92. retcode = line[-1]
  93. # We expect to have only one minion to be run
  94. self.assertEqual(1, len(minions_list))
  95. # We expect to find a retcode in the output
  96. self.assertIsNot(None, retcode)
  97. # We expect retcode to be non-zero
  98. self.assertNotEqual(0, retcode)
  99. @slowTest
  100. def test_batch_state_stopping_after_error(self):
  101. """
  102. Test that a failed state stops the batch run
  103. """
  104. minions_list = []
  105. retcode = None
  106. # Executing salt with batch: 1 and with failhard. It should stop after the first error.
  107. cmd = self.run_salt(
  108. '"*minion" state.single test.fail_without_changes name=test_me -b 1 --out=yaml --failhard',
  109. timeout=self.run_timeout,
  110. )
  111. # Parsing the output. Idea is to fetch number on minions and retcode of the execution.
  112. # retcode var could be overwritten in case of broken failhard but number of minions check should still fail.
  113. for line in cmd:
  114. if line.startswith("Executing run on"):
  115. minions_list.append(line)
  116. if line.startswith("retcode"):
  117. retcode = line[-1]
  118. # We expect to have only one minion to be run
  119. self.assertEqual(1, len(minions_list))
  120. # We expect to find a retcode in the output
  121. self.assertIsNot(None, retcode)
  122. # We expect retcode to be non-zero
  123. self.assertNotEqual(0, retcode)