def test_04_last_run(self):
        task1_id = set_periodic_task("task one", "*/5 * * * *", ["pinode1", "pinode2"], "some.task.module", 3, {
            "key1": 1,
            "key2": False
        })
        self.assertEqual(len(PeriodicTask.query.all()), 1)
        task1_entry = PeriodicTask.query.filter_by(id=task1_id).one()

        # We have no initial last runs
        self.assertEqual(len(list(task1_entry.last_runs)), 0)

        set_periodic_task_last_run(task1_id, "pinode1", parse_timestamp("2018-06-26 08:00+02:00"))
        set_periodic_task_last_run(task1_id, "pinode1", parse_timestamp("2018-06-26 08:05+02:00"))

        task1 = get_periodic_tasks("task one")[0]
        self.assertEqual(len(list(task1_entry.last_runs)), 1)
        self.assertEqual(task1_entry.last_runs[0].timestamp,
                         parse_timestamp("2018-06-26 06:05"))
        self.assertEqual(task1["last_runs"]["pinode1"],
                         parse_timestamp("2018-06-26 06:05 UTC"))

        set_periodic_task_last_run(task1_id, "pinode2", parse_timestamp("2018-06-26 08:10+01:00"))
        set_periodic_task_last_run(task1_id, "pinode3", parse_timestamp("2018-06-26 08:10-08:00"))
        task1 = get_periodic_tasks("task one")[0]
        self.assertEqual(task1["last_runs"]["pinode1"],
                         parse_timestamp("2018-06-26 06:05 UTC"))
        self.assertEqual(task1["last_runs"]["pinode2"],
                         parse_timestamp("2018-06-26 07:10 UTC"))
        self.assertEqual(task1["last_runs"]["pinode3"],
                         parse_timestamp("2018-06-26 16:10 UTC"))

        delete_periodic_task(task1_id)
예제 #2
0
def delete_periodic_task_api(ptaskid):
    """
    Delete a certain periodic task.

    :param ptaskid: ID of the periodic task
    :return: ID of the periodic task
    """
    result = delete_periodic_task(int(ptaskid))
    g.audit_object.log({"success": True, "info": result})
    return send_result(result)
예제 #3
0
def delete_periodic_task_api(ptaskid):
    """
    Delete a certain periodic task.

    :param ptaskid: ID of the periodic task
    :return: ID of the periodic task
    """
    result = delete_periodic_task(int(ptaskid))
    g.audit_object.log({"success": True, "info": result})
    return send_result(result)
    def test_04_last_run(self):
        task1_id = set_periodic_task("task one", "*/5 * * * *",
                                     ["pinode1", "pinode2"],
                                     "some.task.module", 3, {
                                         "key1": 1,
                                         "key2": False
                                     })
        self.assertEqual(len(PeriodicTask.query.all()), 1)
        task1_entry = PeriodicTask.query.filter_by(id=task1_id).one()

        # We have no initial last runs
        self.assertEqual(len(list(task1_entry.last_runs)), 0)

        set_periodic_task_last_run(task1_id, "pinode1",
                                   parse_timestamp("2018-06-26 08:00+02:00"))
        set_periodic_task_last_run(task1_id, "pinode1",
                                   parse_timestamp("2018-06-26 08:05+02:00"))

        task1 = get_periodic_tasks("task one")[0]
        self.assertEqual(len(list(task1_entry.last_runs)), 1)
        self.assertEqual(task1_entry.last_runs[0].timestamp,
                         parse_timestamp("2018-06-26 06:05"))
        self.assertEqual(task1["last_runs"]["pinode1"],
                         parse_timestamp("2018-06-26 06:05 UTC"))

        set_periodic_task_last_run(task1_id, "pinode2",
                                   parse_timestamp("2018-06-26 08:10+01:00"))
        set_periodic_task_last_run(task1_id, "pinode3",
                                   parse_timestamp("2018-06-26 08:10-08:00"))
        task1 = get_periodic_tasks("task one")[0]
        self.assertEqual(task1["last_runs"]["pinode1"],
                         parse_timestamp("2018-06-26 06:05 UTC"))
        self.assertEqual(task1["last_runs"]["pinode2"],
                         parse_timestamp("2018-06-26 07:10 UTC"))
        self.assertEqual(task1["last_runs"]["pinode3"],
                         parse_timestamp("2018-06-26 16:10 UTC"))

        delete_periodic_task(task1_id)
    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(), [])