def get_periodic_task_api(ptaskid): """ Return the dictionary describing a periodic task. :param ptaskid: ID of the periodic task """ ptask = get_periodic_task_by_id(int(ptaskid)) g.audit_object.log({"success": True}) return send_result(convert_datetimes_to_string(ptask))
def test_05_scheduling(self): # this unit test operates in russian time tzinfo = gettz("Europe/Moscow") # at midnight on each 1st task1 = set_periodic_task("task one", "0 0 1 * *", ["pinode1"], "some.task.module", 3, { "key1": 1, "key2": False }) # at 08:00 on wednesdays current_utc_time = parse_timestamp("2018-05-31 05:08:00") with mock.patch('privacyidea.models.datetime') as mock_dt: mock_dt.utcnow.return_value = current_utc_time task2 = set_periodic_task("task two", "0 8 * * WED", ["pinode2", "pinode3"], "some.task.module", 1, { "key1": "value", "key2": "foo" }, active=False) self.assertEqual(get_periodic_task_by_id(task2)["last_update"], parse_timestamp("2018-05-31 08:08:00+03:00")) self.assertEqual(get_periodic_task_by_id(task2)["last_runs"], {}) # every 30 minutes, on Tuesdays task3 = set_periodic_task("task three", "*/30 * * * 2", ["pinode1", "pinode2"], "some.task.module", 2, { "key1": 1234, "key2": 5678, }) # on each 1st of august at midnight task4 = set_periodic_task("task four", "0 0 1 8 *", ["pinode2"], "some.task.module", 0) # we need some last runs set_periodic_task_last_run(task1, "pinode1", parse_timestamp("2018-06-01 00:00:05+03:00")) # no last run for pinode3 here! set_periodic_task_last_run(task2, "pinode2", parse_timestamp("2018-06-20 08:00:05+03:00")) set_periodic_task_last_run(task3, "pinode1", parse_timestamp("2018-06-26 11:36:37+03:00")) set_periodic_task_last_run(task3, "pinode2", parse_timestamp("2018-06-26 11:30:33+03:00")) set_periodic_task_last_run(task4, "pinode2", parse_timestamp("2017-08-01 00:00:43+03:00")) self.assertEqual([task["name"] for task in get_periodic_tasks()], ["task four", "task two", "task three", "task one"]) # Invalid timestamp with self.assertRaises(ParameterError): get_scheduled_periodic_tasks("pinode1", parse_timestamp("2017-08-01 00:00:00"), tzinfo) # On pinode1: # task1 at midnight on each 1st # task3 every 30 minutes on tuesdays # On pinode2: # task2 on 08:00 on wednesdays, but it is inactive # task3 every 30 minutes on tuesdays # task4 on each 1st August at midnight # 26th June (Tuesday), 11:59 # No tasks on both nodes current_timestamp = parse_timestamp("2018-06-26 11:59+03:00") scheduled = get_scheduled_periodic_tasks("pinode1", current_timestamp, tzinfo) self.assertEqual(scheduled, []) scheduled = get_scheduled_periodic_tasks("pinode2", current_timestamp, tzinfo) self.assertEqual(scheduled, []) # 26th June (Tuesday), 12:00 # Run task3 on both nodes current_timestamp = parse_timestamp("2018-06-26 12:00+03:00") scheduled = get_scheduled_periodic_tasks("pinode1", current_timestamp, tzinfo) self.assertEqual([task["name"] for task in scheduled], ["task three"]) scheduled = get_scheduled_periodic_tasks("pinode2", current_timestamp, tzinfo) self.assertEqual([task["name"] for task in scheduled], ["task three"]) # 1th August (Wednesday), 13:57 # Assume task3 has been run successfully on 30th July (Tuesday) set_periodic_task_last_run(task3, "pinode1", parse_timestamp("2018-08-01 00:00+03:00")) set_periodic_task_last_run(task3, "pinode2", parse_timestamp("2018-08-01 00:00+03:00")) # On pinode1, run task1 # On pinode2, run task4 current_timestamp = parse_timestamp("2018-08-01 11:59+03:00") scheduled = get_scheduled_periodic_tasks("pinode1", current_timestamp, tzinfo) self.assertEqual([task["name"] for task in scheduled], ["task one"]) scheduled = get_scheduled_periodic_tasks("pinode2", current_timestamp, tzinfo) self.assertEqual([task["name"] for task in scheduled], ["task four"]) # Enable task2, now we also have to run it on pinode2 and pinode3 with mock.patch('privacyidea.models.datetime') as mock_dt: mock_dt.utcnow.return_value = current_utc_time enable_periodic_task(task2) scheduled = get_scheduled_periodic_tasks("pinode1", current_timestamp, tzinfo) self.assertEqual([task["name"] for task in scheduled], ["task one"]) scheduled = get_scheduled_periodic_tasks("pinode2", current_timestamp, tzinfo) self.assertEqual([task["name"] for task in scheduled], ["task four", "task two"]) scheduled = get_scheduled_periodic_tasks("pinode3", current_timestamp, tzinfo) self.assertEqual([task["name"] for task in scheduled], ["task two"]) # Simulate runs set_periodic_task_last_run(task1, "pinode1", current_timestamp) set_periodic_task_last_run(task2, "pinode2", current_timestamp) set_periodic_task_last_run(task2, "pinode3", current_timestamp) set_periodic_task_last_run(task4, "pinode2", current_timestamp) # Now, we don't have to run anything current_timestamp += timedelta(seconds=1) self.assertEqual(get_scheduled_periodic_tasks("pinode1", current_timestamp, tzinfo), []) self.assertEqual(get_scheduled_periodic_tasks("pinode2", current_timestamp, tzinfo), []) delete_periodic_task(task1) delete_periodic_task(task2) delete_periodic_task(task3) delete_periodic_task(task4)
def test_03_crud(self): task1 = set_periodic_task("task one", "0 0 1 * *", ["pinode1"], "some.task.module", 3, { "key1": 1, "key2": False }) task2 = set_periodic_task("task two", "0 0 * * WED", ["pinode2"], "some.task.module", 1, { "key1": "value", "key2": "foo" }, active=False) task3 = set_periodic_task("task three", "30 * * * *", ["pinode1", "pinode2"], "some.task.module", 2, { "key1": 1234, "key2": 5678, }) with self.assertRaises(ParameterError): set_periodic_task("task four", "61 * * * *", ["pinode1", "pinode2"], "some.task.module", 1, { "key1": 1234, "key2": 5678, }) with self.assertRaises(ParameterError): set_periodic_task("task four", "1 * * * *", ["pinode1", "pinode2"], "some.task.module", -3, { "key1": 1234, "key2": 5678, }) task1_last_update = get_periodic_task_by_id(task1)["last_update"] self.assertEqual(get_periodic_task_by_name("task three")["id"], task3) with self.assertRaises(ResourceNotFoundError): get_periodic_task_by_name("task does not exist") self.assertEqual(get_periodic_task_by_id(task3)["name"], "task three") with self.assertRaises(ResourceNotFoundError): get_periodic_task_by_id(1337) self.assertEqual(len(PeriodicTask.query.all()), 3) # Updating an nonexistent task fails with self.assertRaises(ResourceNotFoundError): set_periodic_task("some task", "0 0 1 * *", ["pinode1"], "some.task.module", 5, {}, id=123456) task1_modified = set_periodic_task("every month", "0 0 1 * *", ["pinode1"], "some.task.module", 3, { "key1": 123, "key3": True, }, id=task1) self.assertEqual(len(PeriodicTask.query.all()), 3) self.assertEqual(task1, task1_modified) # we have updated the task definition self.assertGreater(get_periodic_task_by_id(task1)["last_update"], task1_last_update) self.assertEqual(get_periodic_tasks(name="every month")[0]["options"], {"key1": "123", "key3": "True"}) all_tasks = get_periodic_tasks() self.assertEqual(len(all_tasks), 3) # ordered by ordering self.assertEqual([task["name"] for task in all_tasks], ["task two", "task three", "every month"]) active_tasks = get_periodic_tasks(active=True) self.assertEqual(len(active_tasks), 2) self.assertEqual([task["name"] for task in active_tasks], ["task three", "every month"]) active_tasks_on_pinode2 = get_periodic_tasks(active=True, node="pinode2") self.assertEqual(len(active_tasks_on_pinode2), 1) self.assertEqual(active_tasks_on_pinode2[0]["name"], "task three") enable_periodic_task(task2) active_tasks_on_pinode2 = get_periodic_tasks(active=True, node="pinode2") self.assertEqual(len(active_tasks_on_pinode2), 2) self.assertEqual([task["name"] for task in active_tasks_on_pinode2], ["task two", "task three"]) active_tasks_on_pinode1 = get_periodic_tasks(active=True, node="pinode1") self.assertEqual(len(active_tasks_on_pinode1), 2) self.assertEqual([task["name"] for task in active_tasks_on_pinode1], ["task three", "every month"]) active_tasks_on_pinode3 = get_periodic_tasks(active=True, node="pinode3") self.assertEqual(active_tasks_on_pinode3, []) enable_periodic_task(task1, False) delete_periodic_task(task3) with self.assertRaises(ResourceNotFoundError): enable_periodic_task(task3) active_tasks_on_pinode1 = get_periodic_tasks(active=True, node="pinode1") self.assertEqual(active_tasks_on_pinode1, []) tasks_on_pinode1 = get_periodic_tasks(node="pinode1") self.assertEqual(len(tasks_on_pinode1), 1) self.assertEqual(tasks_on_pinode1[0]["name"], "every month") delete_periodic_task(task1) delete_periodic_task(task2) with self.assertRaises(ResourceNotFoundError): delete_periodic_task(task2) self.assertEqual(get_periodic_tasks(), [])
def test_05_scheduling(self): # this unit test operates in russian time tzinfo = gettz("Europe/Moscow") # at midnight on each 1st task1 = set_periodic_task("task one", "0 0 1 * *", ["pinode1"], "some.task.module", 3, { "key1": 1, "key2": False }) # at 08:00 on wednesdays current_utc_time = parse_timestamp("2018-05-31 05:08:00") with mock.patch('privacyidea.models.datetime') as mock_dt: mock_dt.utcnow.return_value = current_utc_time task2 = set_periodic_task("task two", "0 8 * * WED", ["pinode2", "pinode3"], "some.task.module", 1, { "key1": "value", "key2": "foo" }, active=False) self.assertEqual( get_periodic_task_by_id(task2)["last_update"], parse_timestamp("2018-05-31 08:08:00+03:00")) self.assertEqual(get_periodic_task_by_id(task2)["last_runs"], {}) # every 30 minutes, on Tuesdays task3 = set_periodic_task("task three", "*/30 * * * 2", ["pinode1", "pinode2"], "some.task.module", 2, { "key1": 1234, "key2": 5678, }) # on each 1st of august at midnight task4 = set_periodic_task("task four", "0 0 1 8 *", ["pinode2"], "some.task.module", 0) # we need some last runs set_periodic_task_last_run( task1, "pinode1", parse_timestamp("2018-06-01 00:00:05+03:00")) # no last run for pinode3 here! set_periodic_task_last_run( task2, "pinode2", parse_timestamp("2018-06-20 08:00:05+03:00")) set_periodic_task_last_run( task3, "pinode1", parse_timestamp("2018-06-26 11:36:37+03:00")) set_periodic_task_last_run( task3, "pinode2", parse_timestamp("2018-06-26 11:30:33+03:00")) set_periodic_task_last_run( task4, "pinode2", parse_timestamp("2017-08-01 00:00:43+03:00")) self.assertEqual([task["name"] for task in get_periodic_tasks()], ["task four", "task two", "task three", "task one"]) # Invalid timestamp with self.assertRaises(ParameterError): get_scheduled_periodic_tasks( "pinode1", parse_timestamp("2017-08-01 00:00:00"), tzinfo) # On pinode1: # task1 at midnight on each 1st # task3 every 30 minutes on tuesdays # On pinode2: # task2 on 08:00 on wednesdays, but it is inactive # task3 every 30 minutes on tuesdays # task4 on each 1st August at midnight # 26th June (Tuesday), 11:59 # No tasks on both nodes current_timestamp = parse_timestamp("2018-06-26 11:59+03:00") scheduled = get_scheduled_periodic_tasks("pinode1", current_timestamp, tzinfo) self.assertEqual(scheduled, []) scheduled = get_scheduled_periodic_tasks("pinode2", current_timestamp, tzinfo) self.assertEqual(scheduled, []) # 26th June (Tuesday), 12:00 # Run task3 on both nodes current_timestamp = parse_timestamp("2018-06-26 12:00+03:00") scheduled = get_scheduled_periodic_tasks("pinode1", current_timestamp, tzinfo) self.assertEqual([task["name"] for task in scheduled], ["task three"]) scheduled = get_scheduled_periodic_tasks("pinode2", current_timestamp, tzinfo) self.assertEqual([task["name"] for task in scheduled], ["task three"]) # 1th August (Wednesday), 13:57 # Assume task3 has been run successfully on 30th July (Tuesday) set_periodic_task_last_run(task3, "pinode1", parse_timestamp("2018-08-01 00:00+03:00")) set_periodic_task_last_run(task3, "pinode2", parse_timestamp("2018-08-01 00:00+03:00")) # On pinode1, run task1 # On pinode2, run task4 current_timestamp = parse_timestamp("2018-08-01 11:59+03:00") scheduled = get_scheduled_periodic_tasks("pinode1", current_timestamp, tzinfo) self.assertEqual([task["name"] for task in scheduled], ["task one"]) scheduled = get_scheduled_periodic_tasks("pinode2", current_timestamp, tzinfo) self.assertEqual([task["name"] for task in scheduled], ["task four"]) # Enable task2, now we also have to run it on pinode2 and pinode3 with mock.patch('privacyidea.models.datetime') as mock_dt: mock_dt.utcnow.return_value = current_utc_time enable_periodic_task(task2) scheduled = get_scheduled_periodic_tasks("pinode1", current_timestamp, tzinfo) self.assertEqual([task["name"] for task in scheduled], ["task one"]) scheduled = get_scheduled_periodic_tasks("pinode2", current_timestamp, tzinfo) self.assertEqual([task["name"] for task in scheduled], ["task four", "task two"]) scheduled = get_scheduled_periodic_tasks("pinode3", current_timestamp, tzinfo) self.assertEqual([task["name"] for task in scheduled], ["task two"]) # Simulate runs set_periodic_task_last_run(task1, "pinode1", current_timestamp) set_periodic_task_last_run(task2, "pinode2", current_timestamp) set_periodic_task_last_run(task2, "pinode3", current_timestamp) set_periodic_task_last_run(task4, "pinode2", current_timestamp) # Now, we don't have to run anything current_timestamp += timedelta(seconds=1) self.assertEqual( get_scheduled_periodic_tasks("pinode1", current_timestamp, tzinfo), []) self.assertEqual( get_scheduled_periodic_tasks("pinode2", current_timestamp, tzinfo), []) delete_periodic_task(task1) delete_periodic_task(task2) delete_periodic_task(task3) delete_periodic_task(task4)
def test_03_crud(self): task1 = set_periodic_task("task one", "0 0 1 * *", ["pinode1"], "some.task.module", 3, { "key1": 1, "key2": False }, retry_if_failed=False) task2 = set_periodic_task("task two", "0 0 * * WED", ["pinode2"], "some.task.module", 1, { "key1": "value", "key2": "foo" }, active=False, retry_if_failed=True) task3 = set_periodic_task("task three", "30 * * * *", ["pinode1", "pinode2"], "some.task.module", 2, { "key1": 1234, "key2": 5678, }) with self.assertRaises(ParameterError): set_periodic_task("task four", "61 * * * *", ["pinode1", "pinode2"], "some.task.module", 1, { "key1": 1234, "key2": 5678, }) with self.assertRaises(ParameterError): set_periodic_task("task four", "1 * * * *", ["pinode1", "pinode2"], "some.task.module", -3, { "key1": 1234, "key2": 5678, }) task1_last_update = get_periodic_task_by_id(task1)["last_update"] self.assertEqual(get_periodic_task_by_name("task three")["id"], task3) with self.assertRaises(ResourceNotFoundError): get_periodic_task_by_name("task does not exist") self.assertEqual(get_periodic_task_by_id(task3)["name"], "task three") with self.assertRaises(ResourceNotFoundError): get_periodic_task_by_id(1337) self.assertEqual(len(PeriodicTask.query.all()), 3) # Updating an nonexistent task fails with self.assertRaises(ResourceNotFoundError): set_periodic_task("some task", "0 0 1 * *", ["pinode1"], "some.task.module", 5, {}, id=123456) task1_modified = set_periodic_task("every month", "0 0 1 * *", ["pinode1"], "some.task.module", 3, { "key1": 123, "key3": True, }, id=task1) self.assertEqual(len(PeriodicTask.query.all()), 3) self.assertEqual(task1, task1_modified) # we have updated the task definition self.assertGreater( get_periodic_task_by_id(task1)["last_update"], task1_last_update) self.assertEqual( get_periodic_tasks(name="every month")[0]["options"], { "key1": "123", "key3": "True" }) all_tasks = get_periodic_tasks() self.assertEqual(len(all_tasks), 3) # ordered by ordering self.assertEqual([task["name"] for task in all_tasks], ["task two", "task three", "every month"]) active_tasks = get_periodic_tasks(active=True) self.assertEqual(len(active_tasks), 2) self.assertEqual([task["name"] for task in active_tasks], ["task three", "every month"]) active_tasks_on_pinode2 = get_periodic_tasks(active=True, node="pinode2") self.assertEqual(len(active_tasks_on_pinode2), 1) self.assertEqual(active_tasks_on_pinode2[0]["name"], "task three") enable_periodic_task(task2) active_tasks_on_pinode2 = get_periodic_tasks(active=True, node="pinode2") self.assertEqual(len(active_tasks_on_pinode2), 2) self.assertEqual([task["name"] for task in active_tasks_on_pinode2], ["task two", "task three"]) active_tasks_on_pinode1 = get_periodic_tasks(active=True, node="pinode1") self.assertEqual(len(active_tasks_on_pinode1), 2) self.assertEqual([task["name"] for task in active_tasks_on_pinode1], ["task three", "every month"]) active_tasks_on_pinode3 = get_periodic_tasks(active=True, node="pinode3") self.assertEqual(active_tasks_on_pinode3, []) enable_periodic_task(task1, False) delete_periodic_task(task3) with self.assertRaises(ResourceNotFoundError): enable_periodic_task(task3) active_tasks_on_pinode1 = get_periodic_tasks(active=True, node="pinode1") self.assertEqual(active_tasks_on_pinode1, []) tasks_on_pinode1 = get_periodic_tasks(node="pinode1") self.assertEqual(len(tasks_on_pinode1), 1) self.assertEqual(tasks_on_pinode1[0]["name"], "every month") delete_periodic_task(task1) delete_periodic_task(task2) with self.assertRaises(ResourceNotFoundError): delete_periodic_task(task2) self.assertEqual(get_periodic_tasks(), [])