From 8f068f6f9b67000aea4522303d288b28ee27cfee Mon Sep 17 00:00:00 2001 From: "Gareth J. Greenaway" Date: Fri, 14 Feb 2020 06:38:28 -0800 Subject: [PATCH] Fix for when using a combination of when and splay. Previously comparing the wrong value when determining if the job should be run and next_fire_time updated. This resulted in multiple job runs when `when` and `splay` were used together. Code updated and test updated to ensure only one run at the specific time. Skip eval tests is dateutil.parser is unavailable. --- salt/utils/schedule.py | 2 +- tests/integration/scheduler/test_eval.py | 16 +++++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/salt/utils/schedule.py b/salt/utils/schedule.py index 7dca34879ecc..474af442a1c0 100644 --- a/salt/utils/schedule.py +++ b/salt/utils/schedule.py @@ -1019,7 +1019,7 @@ def _handle_when(data, loop_interval): if when < now - loop_interval and \ not data.get('_run', False) and \ - not data.get('run', False) and \ + not run and \ not data['_splay']: data['_next_fire_time'] = None data['_continue'] = True diff --git a/tests/integration/scheduler/test_eval.py b/tests/integration/scheduler/test_eval.py index 8005525ab049..e4b41906a443 100644 --- a/tests/integration/scheduler/test_eval.py +++ b/tests/integration/scheduler/test_eval.py @@ -9,7 +9,12 @@ import random import time -import dateutil.parser as dateutil_parser +try: + import dateutil.parser as dateutil_parser + HAS_DATEUTIL_PARSER = True +except ImportError: + HAS_DATEUTIL_PARSER = False + import datetime # Import Salt Testing libs @@ -43,6 +48,7 @@ DEFAULT_CONFIG['cachedir'] = os.path.join(ROOT_DIR, 'cache') +@skipIf(HAS_DATEUTIL_PARSER is False, 'The \'dateutil.parser\' library is not available') class SchedulerEvalTest(ModuleCase, SaltReturnAssertsMixin): ''' Validate the pkg module @@ -920,6 +926,7 @@ def test_eval_when_splay(self): } run_time1 = dateutil_parser.parse('11/29/2017 4:00pm') run_time2 = run_time1 + datetime.timedelta(seconds=splay) + run_time3 = run_time2 + datetime.timedelta(seconds=1) # Add the job to the scheduler self.schedule.opts.update(job) @@ -940,6 +947,13 @@ def test_eval_when_splay(self): ret = self.schedule.job_status(job_name) self.assertEqual(ret['_last_run'], run_time2) + # Evaluate at expected runtime3, should not run + # _next_fire_time should be None + self.schedule.eval(now=run_time3) + ret = self.schedule.job_status(job_name) + self.assertEqual(ret['_last_run'], run_time2) + self.assertEqual(ret['_next_fire_time'], None) + def test_eval_when_splay_in_past(self): ''' verify that scheduled job runs