def set_periodic_task(name=None, interval=None, nodes=None, taskmodule=None, ordering=0, options=None, active=True, id=None, retry_if_failed=True): """ Set a periodic task configuration. If ``id`` is None, this creates a new database entry. Otherwise, an existing entry is overwritten. We actually ensure that such an entry exists and throw a ``ParameterError`` otherwise. This also checks if ``interval`` is a valid cron expression, and throws a ``ParameterError`` if it is not. :param name: Unique name of the periodic task :type name: unicode :param interval: Periodicity as a string in crontab format :type interval: unicode :param nodes: List of nodes on which this task should be run :type nodes: list of unicode :param taskmodule: Name of the task module :type taskmodule: unicode :param ordering: Ordering of the periodic task (>= 0). Lower numbers are executed first. :type ordering: int :param options: Additional options for the task module :type options: Dictionary mapping unicodes to values that can be converted to unicode or None :param active: Flag determining whether the periodic task is active :type active: bool :param retry_if_failed: true if privacyidea should retry to execute this periodic task if it fails false if privacyidea should just try onetime regardless the failing of the task :type retry_if_failed: bool :param id: ID of the existing entry, or None :type id: int or None :return: ID of the entry """ try: croniter(interval) except ValueError as e: raise ParameterError("Invalid interval: {!s}".format(e)) if ordering < 0: raise ParameterError("Invalid ordering: {!s}".format(ordering)) if id is not None: # This will throw a ParameterError if there is no such entry get_periodic_task_by_id(id) periodic_task = PeriodicTask(name, active, interval, nodes, taskmodule, ordering, options, id, retry_if_failed) return periodic_task.id
def test_26_periodictask(self): current_utc_time = datetime(2018, 3, 4, 5, 6, 8) with mock.patch('privacyidea.models.datetime') as mock_dt: mock_dt.utcnow.return_value = current_utc_time task1 = PeriodicTask("task1", False, "0 5 * * *", ["localhost"], "some.module", 2, { "key1": "value2", "KEY2": True, "key3": u"öfføff", }) task2 = PeriodicTask("some other task", True, "0 6 * * *", ["localhost"], "some.other.module", 1, { "foo": "bar" }) self.assertEqual(PeriodicTask.query.filter_by(name="task1").one(), task1) self.assertEqual(PeriodicTask.query.filter_by(name="some other task").one(), task2) self.assertEqual(PeriodicTaskOption.query.filter_by(periodictask_id=task1.id, key="KEY2").one().value, "True") # Values are converted to strings self.assertEqual(task1.get(), { "id": task1.id, "name": "task1", "active": False, "interval": "0 5 * * *", # we get a timezone-aware datetime here "last_update": current_utc_time.replace(tzinfo=tzutc()), "nodes": ["localhost"], "taskmodule": "some.module", "ordering": 2, "options": { "key1": "value2", "KEY2": "True", "key3": u"öfføff", }, "last_runs": {}}) # register a run task1.set_last_run("localhost", datetime(2018, 3, 4, 5, 6, 7)) # assert we can update the task later_utc_time = current_utc_time + timedelta(seconds=1) with mock.patch('privacyidea.models.datetime') as mock_dt: mock_dt.utcnow.return_value = later_utc_time PeriodicTask("task one", True, "0 8 * * *", ["localhost", "otherhost"], "some.module", 3, { "KEY2": "value number 2", "key 4": 1234 }, id=task1.id) # the first run for otherhost task1.set_last_run("otherhost", datetime(2018, 8, 9, 10, 11, 12)) result = PeriodicTask.query.filter_by(name="task one").one().get() self.assertEqual(result, { "id": task1.id, "active": True, "name": "task one", "interval": "0 8 * * *", "last_update": later_utc_time.replace(tzinfo=tzutc()), "nodes": ["localhost", "otherhost"], "taskmodule": "some.module", "ordering": 3, "options": {"KEY2": "value number 2", "key 4": "1234"}, "last_runs": { "localhost": datetime(2018, 3, 4, 5, 6, 7, tzinfo=tzutc()), "otherhost": datetime(2018, 8, 9, 10, 11, 12, tzinfo=tzutc()), } }) # assert all old options are removed self.assertEqual(PeriodicTaskOption.query.filter_by(periodictask_id=task1.id, key="key3").count(), 0) # the second run for localhost task1.set_last_run("localhost", datetime(2018, 3, 4, 5, 6, 8)) result = PeriodicTask.query.filter_by(name="task one").one().get() self.assertEqual(result, { "id": task1.id, "active": True, "name": "task one", "interval": "0 8 * * *", "last_update": later_utc_time.replace(tzinfo=tzutc()), "nodes": ["localhost", "otherhost"], "taskmodule": "some.module", "ordering": 3, "options": {"KEY2": "value number 2", "key 4": "1234"}, "last_runs": { "localhost": datetime(2018, 3, 4, 5, 6, 8, tzinfo=tzutc()), "otherhost": datetime(2018, 8, 9, 10, 11, 12, tzinfo=tzutc()), } }) # remove "localhost", assert the last run is removed PeriodicTask("task one", True, "0 8 * * *", ["otherhost"], "some.module", 4, {"foo": "bar"}, id=task1.id) self.assertEqual(PeriodicTaskOption.query.filter_by(periodictask_id=task1.id).count(), 1) self.assertEqual(PeriodicTaskLastRun.query.filter_by(periodictask_id=task1.id).one().node, "otherhost") # naive timestamp in the database self.assertEqual(PeriodicTaskLastRun.query.filter_by(periodictask_id=task1.id).one().timestamp, datetime(2018, 8, 9, 10, 11, 12, tzinfo=None)) self.assertEqual(PeriodicTaskLastRun.query.filter_by(periodictask_id=task1.id).one().aware_timestamp, datetime(2018, 8, 9, 10, 11, 12, tzinfo=tzutc())) # remove the tasks, everything is removed task1.delete() self.assertEqual(PeriodicTaskOption.query.count(), 1) # from task2 self.assertEqual(PeriodicTaskLastRun.query.count(), 0) task2.delete() self.assertEqual(PeriodicTaskOption.query.count(), 0)
def test_26_periodictask(self): current_utc_time = datetime(2018, 3, 4, 5, 6, 8) with mock.patch('privacyidea.models.datetime') as mock_dt: mock_dt.utcnow.return_value = current_utc_time task1 = PeriodicTask("task1", False, "0 5 * * *", ["localhost"], "some.module", 2, { "key1": "value2", "KEY2": True, "key3": u"öfføff", }) task2 = PeriodicTask("some other task", True, "0 6 * * *", ["localhost"], "some.other.module", 1, {"foo": "bar"}) self.assertEqual( PeriodicTask.query.filter_by(name="task1").one(), task1) self.assertEqual( PeriodicTask.query.filter_by(name="some other task").one(), task2) self.assertEqual( PeriodicTaskOption.query.filter_by(periodictask_id=task1.id, key="KEY2").one().value, "True") # Values are converted to strings self.assertEqual( task1.get(), { "id": task1.id, "name": "task1", "active": False, "interval": "0 5 * * *", # we get a timezone-aware datetime here "last_update": current_utc_time.replace(tzinfo=tzutc()), "nodes": ["localhost"], "taskmodule": "some.module", "ordering": 2, "options": { "key1": "value2", "KEY2": "True", "key3": u"öfføff", }, "last_runs": {} }) # register a run task1.set_last_run("localhost", datetime(2018, 3, 4, 5, 6, 7)) # assert we can update the task later_utc_time = current_utc_time + timedelta(seconds=1) with mock.patch('privacyidea.models.datetime') as mock_dt: mock_dt.utcnow.return_value = later_utc_time PeriodicTask("task one", True, "0 8 * * *", ["localhost", "otherhost"], "some.module", 3, { "KEY2": "value number 2", "key 4": 1234 }, id=task1.id) # the first run for otherhost task1.set_last_run("otherhost", datetime(2018, 8, 9, 10, 11, 12)) result = PeriodicTask.query.filter_by(name="task one").one().get() self.assertEqual( result, { "id": task1.id, "active": True, "name": "task one", "interval": "0 8 * * *", "last_update": later_utc_time.replace(tzinfo=tzutc()), "nodes": ["localhost", "otherhost"], "taskmodule": "some.module", "ordering": 3, "options": { "KEY2": "value number 2", "key 4": "1234" }, "last_runs": { "localhost": datetime(2018, 3, 4, 5, 6, 7, tzinfo=tzutc()), "otherhost": datetime( 2018, 8, 9, 10, 11, 12, tzinfo=tzutc()), } }) # assert all old options are removed self.assertEqual( PeriodicTaskOption.query.filter_by(periodictask_id=task1.id, key="key3").count(), 0) # the second run for localhost task1.set_last_run("localhost", datetime(2018, 3, 4, 5, 6, 8)) result = PeriodicTask.query.filter_by(name="task one").one().get() self.assertEqual( result, { "id": task1.id, "active": True, "name": "task one", "interval": "0 8 * * *", "last_update": later_utc_time.replace(tzinfo=tzutc()), "nodes": ["localhost", "otherhost"], "taskmodule": "some.module", "ordering": 3, "options": { "KEY2": "value number 2", "key 4": "1234" }, "last_runs": { "localhost": datetime(2018, 3, 4, 5, 6, 8, tzinfo=tzutc()), "otherhost": datetime( 2018, 8, 9, 10, 11, 12, tzinfo=tzutc()), } }) # remove "localhost", assert the last run is removed PeriodicTask("task one", True, "0 8 * * *", ["otherhost"], "some.module", 4, {"foo": "bar"}, id=task1.id) self.assertEqual( PeriodicTaskOption.query.filter_by( periodictask_id=task1.id).count(), 1) self.assertEqual( PeriodicTaskLastRun.query.filter_by( periodictask_id=task1.id).one().node, "otherhost") # naive timestamp in the database self.assertEqual( PeriodicTaskLastRun.query.filter_by( periodictask_id=task1.id).one().timestamp, datetime(2018, 8, 9, 10, 11, 12, tzinfo=None)) self.assertEqual( PeriodicTaskLastRun.query.filter_by( periodictask_id=task1.id).one().aware_timestamp, datetime(2018, 8, 9, 10, 11, 12, tzinfo=tzutc())) # remove the tasks, everything is removed task1.delete() self.assertEqual(PeriodicTaskOption.query.count(), 1) # from task2 self.assertEqual(PeriodicTaskLastRun.query.count(), 0) task2.delete() self.assertEqual(PeriodicTaskOption.query.count(), 0)
def test_26_periodictask(self): task1 = PeriodicTask("task1", False, "0 5 * * *", ["localhost"], "some.module", { "key1": "value2", "KEY2": True, "key3": u"öfføff", }) task2 = PeriodicTask("some other task", True, "0 6 * * *", ["localhost"], "some.other.module", {"foo": "bar"}) self.assertEqual( PeriodicTask.query.filter_by(name="task1").one(), task1) self.assertEqual( PeriodicTask.query.filter_by(name="some other task").one(), task2) self.assertEqual( PeriodicTaskOption.query.filter_by(periodictask_id=task1.id, key="KEY2").one().value, "True") # Values are converted to strings self.assertEqual( task1.get(), { "id": task1.id, "name": "task1", "active": False, "interval": "0 5 * * *", "nodes": ["localhost"], "taskmodule": "some.module", "options": { "key1": "value2", "KEY2": "True", "key3": u"öfføff", }, "last_runs": {} }) # register a run task1.set_last_run("localhost", datetime(2018, 3, 4, 5, 6, 7)) # assert we can update the task PeriodicTask("task one", True, "0 8 * * *", ["localhost", "otherhost"], "some.module", { "KEY2": "value number 2", "key 4": 1234 }, id=task1.id) # the first run for otherhost task1.set_last_run("otherhost", datetime(2018, 8, 9, 10, 11, 12)) result = PeriodicTask.query.filter_by(name="task one").one().get() self.assertEqual( result, { "id": task1.id, "active": True, "name": "task one", "interval": "0 8 * * *", "nodes": ["localhost", "otherhost"], "taskmodule": "some.module", "options": { "KEY2": "value number 2", "key 4": "1234" }, "last_runs": { "localhost": datetime(2018, 3, 4, 5, 6, 7), "otherhost": datetime(2018, 8, 9, 10, 11, 12), } }) # assert all old options are removed self.assertEqual( PeriodicTaskOption.query.filter_by(periodictask_id=task1.id, key="key3").count(), 0) # the second run for localhost task1.set_last_run("localhost", datetime(2018, 3, 4, 5, 6, 8)) result = PeriodicTask.query.filter_by(name="task one").one().get() self.assertEqual( result, { "id": task1.id, "active": True, "name": "task one", "interval": "0 8 * * *", "nodes": ["localhost", "otherhost"], "taskmodule": "some.module", "options": { "KEY2": "value number 2", "key 4": "1234" }, "last_runs": { "localhost": datetime(2018, 3, 4, 5, 6, 8), "otherhost": datetime(2018, 8, 9, 10, 11, 12), } }) # remove "localhost", assert the last run is removed PeriodicTask("task one", True, "0 8 * * *", ["otherhost"], "some.module", {"foo": "bar"}, id=task1.id) self.assertEqual( PeriodicTaskOption.query.filter_by( periodictask_id=task1.id).count(), 1) self.assertEqual( PeriodicTaskLastRun.query.filter_by( periodictask_id=task1.id).one().node, "otherhost") # remove the tasks, everything is removed task1.delete() self.assertEqual(PeriodicTaskOption.query.count(), 1) # from task2 self.assertEqual(PeriodicTaskLastRun.query.count(), 0) task2.delete() self.assertEqual(PeriodicTaskOption.query.count(), 0)