test_skip.py 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. # -*- coding: utf-8 -*-
  2. # Import Python libs
  3. from __future__ import absolute_import
  4. import copy
  5. import logging
  6. import os
  7. import dateutil.parser as dateutil_parser
  8. # Import Salt Testing libs
  9. from tests.support.case import ModuleCase
  10. from tests.support.mixins import SaltReturnAssertsMixin
  11. # Import Salt Testing Libs
  12. from tests.support.mock import MagicMock, patch
  13. import tests.integration as integration
  14. # Import Salt libs
  15. import salt.utils.schedule
  16. from salt.modules.test import ping as ping
  17. log = logging.getLogger(__name__)
  18. ROOT_DIR = os.path.join(integration.TMP, 'schedule-unit-tests')
  19. SOCK_DIR = os.path.join(ROOT_DIR, 'test-socks')
  20. DEFAULT_CONFIG = salt.config.minion_config(None)
  21. DEFAULT_CONFIG['conf_dir'] = ROOT_DIR
  22. DEFAULT_CONFIG['root_dir'] = ROOT_DIR
  23. DEFAULT_CONFIG['sock_dir'] = SOCK_DIR
  24. DEFAULT_CONFIG['pki_dir'] = os.path.join(ROOT_DIR, 'pki')
  25. DEFAULT_CONFIG['cachedir'] = os.path.join(ROOT_DIR, 'cache')
  26. class SchedulerSkipTest(ModuleCase, SaltReturnAssertsMixin):
  27. '''
  28. Validate the pkg module
  29. '''
  30. def setUp(self):
  31. with patch('salt.utils.schedule.clean_proc_dir', MagicMock(return_value=None)):
  32. functions = {'test.ping': ping}
  33. self.schedule = salt.utils.schedule.Schedule(copy.deepcopy(DEFAULT_CONFIG), functions, returners={})
  34. self.schedule.opts['loop_interval'] = 1
  35. def tearDown(self):
  36. self.schedule.reset()
  37. def test_skip(self):
  38. '''
  39. verify that scheduled job is skipped at the specified time
  40. '''
  41. job_name = 'test_skip'
  42. job = {
  43. 'schedule': {
  44. job_name: {
  45. 'function': 'test.ping',
  46. 'when': ['11/29/2017 4pm', '11/29/2017 5pm'],
  47. }
  48. }
  49. }
  50. # Add job to schedule
  51. self.schedule.opts.update(job)
  52. run_time = dateutil_parser.parse('11/29/2017 4:00pm')
  53. self.schedule.skip_job(job_name, {'time': run_time.strftime('%Y-%m-%dT%H:%M:%S'),
  54. 'time_fmt': '%Y-%m-%dT%H:%M:%S'})
  55. # Run 11/29/2017 at 4pm
  56. self.schedule.eval(now=run_time)
  57. ret = self.schedule.job_status(job_name)
  58. self.assertNotIn('_last_run', ret)
  59. self.assertEqual(ret['_skip_reason'], 'skip_explicit')
  60. self.assertEqual(ret['_skipped_time'], run_time)
  61. # Run 11/29/2017 at 5pm
  62. run_time = dateutil_parser.parse('11/29/2017 5:00pm')
  63. self.schedule.eval(now=run_time)
  64. ret = self.schedule.job_status(job_name)
  65. self.assertEqual(ret['_last_run'], run_time)
  66. def test_skip_during_range(self):
  67. '''
  68. verify that scheduled job is skipped during the specified range
  69. '''
  70. job_name = 'test_skip_during_range'
  71. job = {
  72. 'schedule': {
  73. job_name: {
  74. 'function': 'test.ping',
  75. 'hours': '1',
  76. 'skip_during_range': {
  77. 'start': '11/29/2017 2pm',
  78. 'end': '11/29/2017 3pm'
  79. }
  80. }
  81. }
  82. }
  83. # Add job to schedule
  84. self.schedule.opts.update(job)
  85. # eval at 1:30pm to prime.
  86. run_time = dateutil_parser.parse('11/29/2017 1:30pm')
  87. self.schedule.eval(now=run_time)
  88. ret = self.schedule.job_status(job_name)
  89. # eval at 2:30pm, will not run during range.
  90. run_time = dateutil_parser.parse('11/29/2017 2:30pm')
  91. self.schedule.eval(now=run_time)
  92. ret = self.schedule.job_status(job_name)
  93. self.assertNotIn('_last_run', ret)
  94. self.assertEqual(ret['_skip_reason'], 'in_skip_range')
  95. self.assertEqual(ret['_skipped_time'], run_time)
  96. # eval at 3:30pm, will run.
  97. run_time = dateutil_parser.parse('11/29/2017 3:30pm')
  98. self.schedule.eval(now=run_time)
  99. ret = self.schedule.job_status(job_name)
  100. self.assertEqual(ret['_last_run'], run_time)
  101. def test_skip_during_range_global(self):
  102. '''
  103. verify that scheduled job is skipped during the specified range
  104. '''
  105. job_name = 'skip_during_range_global'
  106. job = {
  107. 'schedule': {
  108. 'skip_during_range': {
  109. 'start': '11/29/2017 2pm',
  110. 'end': '11/29/2017 3pm'
  111. },
  112. job_name: {
  113. 'function': 'test.ping',
  114. 'hours': '1',
  115. }
  116. }
  117. }
  118. # Add job to schedule
  119. self.schedule.opts.update(job)
  120. # eval at 1:30pm to prime.
  121. run_time = dateutil_parser.parse('11/29/2017 1:30pm')
  122. self.schedule.eval(now=run_time)
  123. ret = self.schedule.job_status(job_name)
  124. # eval at 2:30pm, will not run during range.
  125. run_time = dateutil_parser.parse('11/29/2017 2:30pm')
  126. self.schedule.eval(now=run_time)
  127. ret = self.schedule.job_status(job_name)
  128. self.assertNotIn('_last_run', ret)
  129. self.assertEqual(ret['_skip_reason'], 'in_skip_range')
  130. self.assertEqual(ret['_skipped_time'], run_time)
  131. # eval at 3:30pm, will run.
  132. run_time = dateutil_parser.parse('11/29/2017 3:30pm')
  133. self.schedule.eval(now=run_time)
  134. ret = self.schedule.job_status(job_name)
  135. self.assertEqual(ret['_last_run'], run_time)
  136. def test_run_after_skip_range(self):
  137. '''
  138. verify that scheduled job is skipped during the specified range
  139. '''
  140. job_name = 'skip_run_after_skip_range'
  141. job = {
  142. 'schedule': {
  143. job_name: {
  144. 'function': 'test.ping',
  145. 'when': '11/29/2017 2:30pm',
  146. 'run_after_skip_range': True,
  147. 'skip_during_range': {
  148. 'start': '11/29/2017 2pm',
  149. 'end': '11/29/2017 3pm'
  150. }
  151. }
  152. }
  153. }
  154. # Add job to schedule
  155. self.schedule.opts.update(job)
  156. # eval at 2:30pm, will not run during range.
  157. run_time = dateutil_parser.parse('11/29/2017 2:30pm')
  158. self.schedule.eval(now=run_time)
  159. ret = self.schedule.job_status(job_name)
  160. self.assertNotIn('_last_run', ret)
  161. self.assertEqual(ret['_skip_reason'], 'in_skip_range')
  162. self.assertEqual(ret['_skipped_time'], run_time)
  163. # eval at 3:00:01pm, will run.
  164. run_time = dateutil_parser.parse('11/29/2017 3:00:01pm')
  165. self.schedule.eval(now=run_time)
  166. ret = self.schedule.job_status(job_name)
  167. self.assertEqual(ret['_last_run'], run_time)
  168. def test_run_seconds_skip(self):
  169. '''
  170. verify that scheduled job is skipped during the specified range
  171. '''
  172. job_name = 'run_seconds_skip'
  173. job = {
  174. 'schedule': {
  175. job_name: {
  176. 'function': 'test.ping',
  177. 'seconds': '10',
  178. }
  179. }
  180. }
  181. # Add job to schedule
  182. self.schedule.opts.update(job)
  183. # eval at 2:00pm, to prime the scheduler
  184. run_time = dateutil_parser.parse('11/29/2017 2:00pm')
  185. self.schedule.eval(now=run_time)
  186. ret = self.schedule.job_status(job_name)
  187. # eval at 2:00:10pm
  188. run_time = dateutil_parser.parse('11/29/2017 2:00:10pm')
  189. self.schedule.eval(now=run_time)
  190. ret = self.schedule.job_status(job_name)
  191. # Skip at 2:00:20pm
  192. run_time = dateutil_parser.parse('11/29/2017 2:00:20pm')
  193. self.schedule.skip_job(job_name, {'time': run_time.strftime('%Y-%m-%dT%H:%M:%S'),
  194. 'time_fmt': '%Y-%m-%dT%H:%M:%S'})
  195. self.schedule.eval(now=run_time)
  196. ret = self.schedule.job_status(job_name)
  197. self.assertIn('_next_fire_time', ret)
  198. self.assertEqual(ret['_skip_reason'], 'skip_explicit')
  199. self.assertEqual(ret['_skipped_time'], run_time)
  200. # Run at 2:00:30pm
  201. run_time = dateutil_parser.parse('11/29/2017 2:00:30pm')
  202. self.schedule.eval(now=run_time)
  203. ret = self.schedule.job_status(job_name)
  204. self.assertIn('_last_run', ret)