示例#1
0
def test_job(test_request_template):
    job = Job(
        name="testjob",
        request_template=test_request_template,
        trigger_type="interval",
        trigger=IntervalTrigger(),
    ).save()

    yield job
    job.delete()
示例#2
0
def data_cleanup():
    """Cleanup all data between test modules to ensure each one is independent"""
    yield
    Event.drop_collection()
    File.drop_collection()
    Garden.drop_collection()
    Job.drop_collection()
    RawFile.drop_collection()
    Request.drop_collection()
    RemoteUser.drop_collection()
    Role.drop_collection()
    System.drop_collection()
    User.drop_collection()
    UserToken.drop_collection()
示例#3
0
def mongo_job(job_dict, ts_dt, mongo_request_template, mongo_date_trigger):
    """A job as a model."""
    dict_copy = copy.deepcopy(job_dict)
    dict_copy["next_run_time"] = ts_dt
    dict_copy["trigger"] = mongo_date_trigger
    dict_copy["request_template"] = mongo_request_template
    return Job(**dict_copy)
示例#4
0
 def setUp(self):
     self.ts_epoch = 1451606400000
     self.ts_dt = datetime(2016, 1, 1)
     self.job_dict = {
         "name": "job_name",
         "trigger_type": "date",
         "trigger": {
             "run_date": self.ts_epoch,
             "timezone": "utc"
         },
         "request_template": {
             "system": "system",
             "system_version": "1.0.0",
             "instance_name": "default",
             "command": "speak",
             "parameters": {
                 "message": "hey!"
             },
             "comment": "hi!",
             "metadata": {
                 "request": "stuff"
             },
         },
         "misfire_grace_time": 3,
         "coalesce": True,
         "next_run_time": self.ts_epoch,
         "success_count": 0,
         "error_count": 0,
         "status": "RUNNING",
         "max_instances": 3,
     }
     db_dict = copy.deepcopy(self.job_dict)
     db_dict["request_template"] = RequestTemplate(
         **db_dict["request_template"])
     db_dict["trigger"]["run_date"] = self.ts_dt
     db_dict["trigger"] = DateTrigger(**db_dict["trigger"])
     db_dict["next_run_time"] = self.ts_dt
     self.job = Job(**db_dict)
     super(JobListAPITest, self).setUp()
示例#5
0
class JobListAPITest(TestHandlerBase):
    def setUp(self):
        self.ts_epoch = 1451606400000
        self.ts_dt = datetime(2016, 1, 1)
        self.job_dict = {
            "name": "job_name",
            "trigger_type": "date",
            "trigger": {
                "run_date": self.ts_epoch,
                "timezone": "utc"
            },
            "request_template": {
                "system": "system",
                "system_version": "1.0.0",
                "instance_name": "default",
                "command": "speak",
                "parameters": {
                    "message": "hey!"
                },
                "comment": "hi!",
                "metadata": {
                    "request": "stuff"
                },
            },
            "misfire_grace_time": 3,
            "coalesce": True,
            "next_run_time": self.ts_epoch,
            "success_count": 0,
            "error_count": 0,
            "status": "RUNNING",
            "max_instances": 3,
        }
        db_dict = copy.deepcopy(self.job_dict)
        db_dict["request_template"] = RequestTemplate(
            **db_dict["request_template"])
        db_dict["trigger"]["run_date"] = self.ts_dt
        db_dict["trigger"] = DateTrigger(**db_dict["trigger"])
        db_dict["next_run_time"] = self.ts_dt
        self.job = Job(**db_dict)
        super(JobListAPITest, self).setUp()

    def tearDown(self):
        Job.objects.delete()

    def test_get(self):
        self.job.save()
        self.job_dict["id"] = str(self.job.id)
        response = self.fetch("/api/v1/jobs")
        self.assertEqual(200, response.code)
        self.assertEqual(json.loads(response.body.decode("utf-8")),
                         [self.job_dict])

    def test_get_with_filter_param(self):
        self.job.save()
        self.job_dict["id"] = str(self.job.id)

        response = self.fetch("/api/v1/jobs?name=DOES_NOT_EXIST")
        self.assertEqual(200, response.code)
        self.assertEqual(json.loads(response.body.decode("utf-8")), [])

        response = self.fetch("/api/v1/jobs?name=job_name")
        self.assertEqual(200, response.code)
        self.assertEqual(json.loads(response.body.decode("utf-8")),
                         [self.job_dict])

    @patch("brew_view.request_scheduler")
    def test_post(self, scheduler_mock):
        body = json.dumps(self.job_dict)
        self.job_dict["id"] = None
        response = self.fetch("/api/v1/jobs", method="POST", body=body)
        self.assertEqual(response.code, 201)
        data_without_id = json.loads(response.body.decode("utf-8"))
        data_without_id["id"] = None
        self.assertEqual(data_without_id, self.job_dict)
        self.assertEqual(scheduler_mock.add_job.call_count, 1)

    @patch("brew_view.request_scheduler")
    def test_post_error_delete(self, scheduler_mock):
        body = json.dumps(self.job_dict)
        self.job_dict["id"] = None
        scheduler_mock.add_job.side_effect = ValueError
        response = self.fetch("/api/v1/jobs", method="POST", body=body)
        self.assertGreaterEqual(response.code, 500)
示例#6
0
class JobAPITest(TestHandlerBase):
    def setUp(self):
        self.ts_epoch = 1451606400000
        self.ts_dt = datetime(2016, 1, 1)
        self.job_dict = {
            "name": "job_name",
            "trigger_type": "date",
            "trigger": {
                "run_date": self.ts_epoch,
                "timezone": "utc"
            },
            "request_template": {
                "system": "system",
                "system_version": "1.0.0",
                "instance_name": "default",
                "command": "speak",
                "parameters": {
                    "message": "hey!"
                },
                "comment": "hi!",
                "metadata": {
                    "request": "stuff"
                },
            },
            "misfire_grace_time": 3,
            "coalesce": True,
            "next_run_time": self.ts_epoch,
            "success_count": 0,
            "error_count": 0,
            "status": "RUNNING",
            "max_instances": 3,
        }
        db_dict = copy.deepcopy(self.job_dict)
        db_dict["request_template"] = RequestTemplate(
            **db_dict["request_template"])
        db_dict["trigger"]["run_date"] = self.ts_dt
        db_dict["trigger"] = DateTrigger(**db_dict["trigger"])
        db_dict["next_run_time"] = self.ts_dt
        self.job = Job(**db_dict)
        super(JobAPITest, self).setUp()

    def tearDown(self):
        Job.objects.delete()

    def test_get_404(self):
        self.job.save()
        bad_id = "".join(["1" for _ in range(24)])
        if bad_id == self.job.id:
            bad_id = "".join(["2" for _ in range(24)])
        response = self.fetch("/api/v1/jobs/" + bad_id)
        self.assertEqual(404, response.code)

    def test_get(self):
        self.job.save()
        self.job_dict["id"] = str(self.job.id)
        response = self.fetch("/api/v1/jobs/" + str(self.job.id))
        self.assertEqual(200, response.code)
        self.assertEqual(json.loads(response.body.decode("utf-8")),
                         self.job_dict)

    @patch("brew_view.request_scheduler")
    def test_delete(self, scheduler_mock):
        self.job.save()
        response = self.fetch("/api/v1/jobs/" + str(self.job.id),
                              method="DELETE")
        self.assertEqual(204, response.code)
        scheduler_mock.remove_job.assert_called_with(str(self.job.id),
                                                     jobstore="beer_garden")

    @patch("brew_view.request_scheduler")
    def test_pause(self, scheduler_mock):
        self.job.save()
        body = json.dumps({
            "operations": [{
                "operation": "update",
                "path": "/status",
                "value": "PAUSED"
            }]
        })
        response = self.fetch(
            "/api/v1/jobs/" + str(self.job.id),
            method="PATCH",
            body=body,
            headers={"content-type": "application/json"},
        )
        self.assertEqual(200, response.code)
        scheduler_mock.pause_job.assert_called_with(str(self.job.id),
                                                    jobstore="beer_garden")
        self.job.reload()
        self.assertEqual(self.job.status, "PAUSED")

    @patch("brew_view.request_scheduler")
    def test_resume(self, scheduler_mock):
        self.job.status = "PAUSED"
        self.job.save()
        body = json.dumps({
            "operations": [{
                "operation": "update",
                "path": "/status",
                "value": "RUNNING"
            }]
        })
        response = self.fetch(
            "/api/v1/jobs/" + str(self.job.id),
            method="PATCH",
            body=body,
            headers={"content-type": "application/json"},
        )
        self.assertEqual(200, response.code)
        scheduler_mock.resume_job.assert_called_with(str(self.job.id),
                                                     jobstore="beer_garden")
        self.job.reload()
        self.assertEqual(self.job.status, "RUNNING")

    def test_invalid_operation(self):
        self.job.save()
        body = json.dumps({
            "operations": [{
                "operation": "INVALID",
                "path": "/status",
                "value": "RUNNING"
            }]
        })
        response = self.fetch(
            "/api/v1/jobs/" + str(self.job.id),
            method="PATCH",
            body=body,
            headers={"content-type": "application/json"},
        )
        self.assertGreaterEqual(400, response.code)

    def test_invalid_path(self):
        self.job.save()
        body = json.dumps({
            "operations": [{
                "operation": "update",
                "path": "/INVALID",
                "value": "RUNNING"
            }]
        })
        response = self.fetch(
            "/api/v1/jobs/" + str(self.job.id),
            method="PATCH",
            body=body,
            headers={"content-type": "application/json"},
        )
        self.assertGreaterEqual(400, response.code)

    def test_invalid_value(self):
        self.job.save()
        body = json.dumps({
            "operations": [{
                "operation": "update",
                "path": "/status",
                "value": "INVALID"
            }]
        })
        response = self.fetch(
            "/api/v1/jobs/" + str(self.job.id),
            method="PATCH",
            body=body,
            headers={"content-type": "application/json"},
        )
        self.assertGreaterEqual(400, response.code)
示例#7
0
 def drop_systems(self, mongo_conn):
     Job.drop_collection()
示例#8
0
 def test_invalid_trigger_type(self):
     with pytest.raises(ModelValidationError):
         Job(trigger_type="INVALID_TRIGGER_TYPE").clean()
示例#9
0
 def test_trigger_mismatch(self):
     date_trigger = DateTrigger()
     with pytest.raises(ModelValidationError):
         Job(trigger_type="cron", trigger=date_trigger).clean()
示例#10
0
 def drop(self, mongo_conn):
     Job.drop_collection()
示例#11
0
 def drop(self):
     yield
     Job.drop_collection()
示例#12
0
    def setUp(self):
        self.request_mock = Mock()

        self.ts_epoch = 1451606400000
        self.ts_dt = datetime.datetime(2016, 1, 1)
        self.request_dict = {
            "children": [],
            "parent": None,
            "system": "system_name",
            "system_version": "0.0.1",
            "instance_name": "default",
            "command": "say",
            "id": "58542eb571afd47ead90d25f",
            "parameters": {},
            "comment": "bye!",
            "output": "nested output",
            "output_type": "STRING",
            "status": "IN_PROGRESS",
            "command_type": "ACTION",
            "created_at": self.ts_epoch,
            "updated_at": self.ts_epoch,
            "error_class": None,
            "metadata": {},
            "has_parent": True,
            "requester": None,
        }
        self.job_dict = {
            "name": "job_name",
            "trigger_type": "date",
            "trigger": {
                "run_date": self.ts_epoch,
                "timezone": "utc"
            },
            "request_template": {
                "system": "system",
                "system_version": "1.0.0",
                "instance_name": "default",
                "command": "speak",
                "parameters": {
                    "message": "hey!"
                },
                "comment": "hi!",
                "metadata": {
                    "request": "stuff"
                },
            },
            "misfire_grace_time": 3,
            "coalesce": True,
            "next_run_time": self.ts_epoch,
            "success_count": 0,
            "error_count": 0,
        }
        db_dict = copy.deepcopy(self.job_dict)
        db_dict["request_template"] = RequestTemplate(
            **db_dict["request_template"])
        db_dict["trigger"]["run_date"] = self.ts_dt
        db_dict["trigger"] = DateTrigger(**db_dict["trigger"])
        db_dict["next_run_time"] = self.ts_dt
        self.job = Job(**db_dict)

        db_dict = copy.deepcopy(self.request_dict)
        db_dict["created_at"] = self.ts_dt
        db_dict["updated_at"] = self.ts_dt
        self.request = Request(**db_dict)

        super(RequestAPITest, self).setUp()
示例#13
0
class RequestAPITest(TestHandlerBase):
    def setUp(self):
        self.request_mock = Mock()

        self.ts_epoch = 1451606400000
        self.ts_dt = datetime.datetime(2016, 1, 1)
        self.request_dict = {
            "children": [],
            "parent": None,
            "system": "system_name",
            "system_version": "0.0.1",
            "instance_name": "default",
            "command": "say",
            "id": "58542eb571afd47ead90d25f",
            "parameters": {},
            "comment": "bye!",
            "output": "nested output",
            "output_type": "STRING",
            "status": "IN_PROGRESS",
            "command_type": "ACTION",
            "created_at": self.ts_epoch,
            "updated_at": self.ts_epoch,
            "error_class": None,
            "metadata": {},
            "has_parent": True,
            "requester": None,
        }
        self.job_dict = {
            "name": "job_name",
            "trigger_type": "date",
            "trigger": {
                "run_date": self.ts_epoch,
                "timezone": "utc"
            },
            "request_template": {
                "system": "system",
                "system_version": "1.0.0",
                "instance_name": "default",
                "command": "speak",
                "parameters": {
                    "message": "hey!"
                },
                "comment": "hi!",
                "metadata": {
                    "request": "stuff"
                },
            },
            "misfire_grace_time": 3,
            "coalesce": True,
            "next_run_time": self.ts_epoch,
            "success_count": 0,
            "error_count": 0,
        }
        db_dict = copy.deepcopy(self.job_dict)
        db_dict["request_template"] = RequestTemplate(
            **db_dict["request_template"])
        db_dict["trigger"]["run_date"] = self.ts_dt
        db_dict["trigger"] = DateTrigger(**db_dict["trigger"])
        db_dict["next_run_time"] = self.ts_dt
        self.job = Job(**db_dict)

        db_dict = copy.deepcopy(self.request_dict)
        db_dict["created_at"] = self.ts_dt
        db_dict["updated_at"] = self.ts_dt
        self.request = Request(**db_dict)

        super(RequestAPITest, self).setUp()

    def tearDown(self):
        Request.objects.delete()
        Job.objects.delete()

    def test_get(self):
        self.request.save()
        response = self.fetch("/api/v1/requests/" + str(self.request.id))
        self.assertEqual(200, response.code)
        data = json.loads(response.body.decode("utf-8"))
        data.pop("updated_at")
        self.request_dict.pop("updated_at")
        self.assertEqual(self.request_dict, data)

    def test_patch_replace_duplicate(self):
        self.request.status = "SUCCESS"
        self.request.output = "output"
        self.request.save()
        body = json.dumps({
            "operations": [
                {
                    "operation": "replace",
                    "path": "/output",
                    "value": "output"
                },
                {
                    "operation": "replace",
                    "path": "/status",
                    "value": "SUCCESS"
                },
            ]
        })

        response = self.fetch(
            "/api/v1/requests/" + str(self.request.id),
            method="PATCH",
            body=body,
            headers={"content-type": "application/json"},
        )
        self.assertEqual(200, response.code)

        self.request.reload()
        self.assertEqual("SUCCESS", self.request.status)
        self.assertEqual("output", self.request.output)

    def test_patch_replace_status(self):
        self.request.save()
        body = json.dumps({
            "operations": [{
                "operation": "replace",
                "path": "/status",
                "value": "SUCCESS"
            }]
        })

        response = self.fetch(
            "/api/v1/requests/" + str(self.request.id),
            method="PATCH",
            body=body,
            headers={"content-type": "application/json"},
        )
        self.assertEqual(200, response.code)
        self.request.reload()
        self.assertEqual("SUCCESS", self.request.status)

    def test_patch_replace_output(self):
        self.request.output = "old_output_but_not_done_with_progress"
        self.request.save()
        body = json.dumps({
            "operations": [{
                "operation": "replace",
                "path": "/output",
                "value": "output"
            }]
        })

        response = self.fetch(
            "/api/v1/requests/" + str(self.request.id),
            method="PATCH",
            body=body,
            headers={"content-type": "application/json"},
        )
        self.assertEqual(200, response.code)
        self.request.reload()
        self.assertEqual("output", self.request.output)

    def test_patch_replace_error_class(self):
        self.request.error_class = "Klazz1"
        body = json.dumps({
            "operations": [{
                "operation": "replace",
                "path": "/error_class",
                "value": "error"
            }]
        })
        self.request.save()

        response = self.fetch(
            "/api/v1/requests/" + str(self.request.id),
            method="PATCH",
            body=body,
            headers={"content-type": "application/json"},
        )
        self.request.reload()
        self.assertEqual(200, response.code)
        self.assertEqual("error", self.request.error_class)

    def test_patch_replace_bad_status(self):
        self.request.save()
        body = json.dumps({
            "operations": [{
                "operation": "replace",
                "path": "/status",
                "value": "bad"
            }]
        })
        response = self.fetch(
            "/api/v1/requests/" + str(self.request.id),
            method="PATCH",
            body=body,
            headers={"content-type": "application/json"},
        )
        self.assertGreaterEqual(response.code, 400)

    def test_patch_update_output_for_complete_request(self):
        self.request.status = "SUCCESS"
        self.request.output = "old_value"
        self.request.save()
        body = json.dumps({
            "operations": [{
                "operation": "replace",
                "path": "/output",
                "value": "shouldnt work",
            }]
        })
        response = self.fetch(
            "/api/v1/requests/" + str(self.request.id),
            method="PATCH",
            body=body,
            headers={"content-type": "application/json"},
        )
        self.request.reload()
        self.assertGreaterEqual(response.code, 400)
        self.assertEqual(self.request.output, "old_value")

    def test_patch_no_system(self):
        good_id_does_not_exist = "".join("1" for _ in range(24))
        response = self.fetch(
            "/api/v1/requests/" + good_id_does_not_exist,
            method="PATCH",
            body='{"operations": [{"operation": "fake"}]}',
            headers={"content-type": "application/json"},
        )
        self.assertEqual(response.code, 404)

    def test_patch_replace_bad_path(self):
        self.request.save()
        body = json.dumps({
            "operations": [{
                "operation": "replace",
                "path": "/bad",
                "value": "error"
            }]
        })
        response = self.fetch(
            "/api/v1/requests/" + str(self.request.id),
            method="PATCH",
            body=body,
            headers={"content-type": "application/json"},
        )
        self.assertGreaterEqual(response.code, 400)

    def test_patch_bad_operation(self):
        self.request.save()
        response = self.fetch(
            "/api/v1/requests/" + str(self.request.id),
            method="PATCH",
            body='{"operations": [{"operation": "fake"}]}',
            headers={"content-type": "application/json"},
        )
        self.assertGreaterEqual(response.code, 400)

    def test_prometheus_endpoint(self):
        handler = self.app.find_handler(request=Mock(path="/api/v1/requests"))
        c = handler.handler_class(
            self.app, Mock(path="/api/v1/requests/111111111111111111111111"))
        assert c.prometheus_endpoint == "/api/v1/requests/<ID>"

    def test_update_job_numbers(self):
        self.job.save()
        self.request.metadata["_bg_job_id"] = str(self.job.id)
        self.request.save()
        body = json.dumps({
            "operations": [{
                "operation": "replace",
                "path": "/status",
                "value": "SUCCESS"
            }]
        })
        response = self.fetch(
            "/api/v1/requests/" + str(self.request.id),
            method="PATCH",
            body=body,
            headers={"content-type": "application/json"},
        )
        self.assertEqual(response.code, 200)
        self.job.reload()
        self.assertEqual(self.job.success_count, 1)
        self.assertEqual(self.job.error_count, 0)

    def test_update_job_numbers_error(self):
        self.job.save()
        self.request.metadata["_bg_job_id"] = str(self.job.id)
        self.request.save()
        body = json.dumps({
            "operations": [{
                "operation": "replace",
                "path": "/status",
                "value": "ERROR"
            }]
        })
        response = self.fetch(
            "/api/v1/requests/" + str(self.request.id),
            method="PATCH",
            body=body,
            headers={"content-type": "application/json"},
        )
        self.assertEqual(response.code, 200)
        self.job.reload()
        self.assertEqual(self.job.success_count, 0)
        self.assertEqual(self.job.error_count, 1)

    def test_update_job_invalid_id(self):
        self.request.metadata["_bg_job_id"] = "".join(["1" for _ in range(24)])
        self.request.save()
        body = json.dumps({
            "operations": [{
                "operation": "replace",
                "path": "/status",
                "value": "ERROR"
            }]
        })
        response = self.fetch(
            "/api/v1/requests/" + str(self.request.id),
            method="PATCH",
            body=body,
            headers={"content-type": "application/json"},
        )
        self.assertEqual(response.code, 200)
示例#14
0
def drop_jobs():
    yield
    Job.drop_collection()