Пример #1
0
    class TestClean:
        @pytest.mark.parametrize(
            "req",
            [
                Request(system="foo", command="bar", status="bad"),
                Request(system="foo", command="bar", command_type="BAD"),
                Request(system="foo", command="bar", output_type="BAD"),
            ],
        )
        def test_bad_values(self, req):
            with pytest.raises(ModelValidationError):
                req.clean()

        @pytest.mark.parametrize(
            "parent, has_parent",
            [(None, False), ("something", True)],
        )
        def test_set_has_parent(self, parent, has_parent):
            req = Request(command="bar", parent=parent)
            req.clean()
            assert req.has_parent is has_parent

        @pytest.mark.parametrize(
            "parent, has_parent",
            [(None, True), (Request(command="say"), False)],
        )
        def test_parent_mismatch(self, parent, has_parent):
            req = Request(command="bar", parent=parent, has_parent=has_parent)
            with pytest.raises(ModelValidationError):
                req.clean()
Пример #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
class TestSendEventToParent(object):
    event = Event(
        payload_type="Request",
        payload=Request(
            system="system_test",
            command="command_test",
            namespace="test",
        ),
    )

    def config_get(self, config_name):
        return []

    @pytest.fixture()
    def command_blocklist(self):
        blocklist = CommandPublishingBlockList(
            namespace=self.event.payload.namespace,
            system=self.event.payload.system,
            command=self.event.payload.command,
        ).save()

        yield blocklist
        blocklist.delete()

    def test_command_exists_in_blocklist(self, command_blocklist, monkeypatch):
        monkeypatch.setattr(config, "get", self.config_get)

        assert event_blocklisted(self.event)

    def test_command_missing_in_blocklist(self, monkeypatch):
        monkeypatch.setattr(config, "get", self.config_get)

        assert not event_blocklisted(self.event)

    def test_event_not_request(self, monkeypatch):
        monkeypatch.setattr(config, "get", self.config_get)
        event = Event(name="ENTRY_STARTED")

        assert not event_blocklisted(event)

    def test_can_send_event_error(self, monkeypatch):
        monkeypatch.setattr(config, "get", self.config_get)
        event = Event(name="REQUEST_CREATE", error=True)

        assert event_blocklisted(event)

    def test_can_send_event_to_parent(self, monkeypatch):
        monkeypatch.setattr(config, "get", self.config_get)

        assert not event_blocklisted(self.event)

    def test_can_send_event_to_parent_blocklist(self, command_blocklist, monkeypatch):
        monkeypatch.setattr(config, "get", self.config_get)

        assert event_blocklisted(self.event)
Пример #4
0
 def request_model(self, raw_file, local_garden_name):
     req = Request(
         system="foo",
         command="bar",
         status="CREATED",
         system_version="1.0.0",
         instance_name="foobar",
         namespace=local_garden_name,
     )
     req.parameters = {
         "message": "hi",
         "file_param": {
             "type": "bytes",
             "id": str(raw_file.id)
         },
     }
     req.output = "bye"
     req.parameters_gridfs.put = Mock()
     req.output_gridfs.put = Mock()
     return req
 def setUp(self):
     brew_view.backend = Mock()
     brew_view.transport = Mock()
     self.default_request = Request(
         system="foo",
         command="bar",
         parameters={"baz": "bat"},
         output="output",
         status="CREATED",
     )
     self.default_request.validate_backend = Mock()
     self.app = brew_view.app.test_client()
Пример #6
0
    def setUp(self):
        self.app = brew_view.app.test_client()

        self.default_request = Request(
            system="foo",
            command="bar",
            parameters={"baz": "bat"},
            output="output",
            status="CREATED",
        )
        self.default_request.validate_backend = Mock()

        objects_patch = patch("bg_utils.mongo.models.Request.objects")
        self.addCleanup(objects_patch.stop)
        self.objects_mock = objects_patch.start()
        self.objects_mock.return_value = None
        self.objects_mock.get = Mock(return_value=self.default_request)
Пример #7
0
def test_request(test_request_template):
    request = Request(
        system=test_request_template.system,
        system_version=test_request_template.system_version,
        namespace=test_request_template.namespace,
        instance_name=test_request_template.instance_name,
        command=test_request_template.command,
        updated_at=datetime.datetime.utcnow,
    )
    request.save()

    yield request
    request.delete()
Пример #8
0
def request_not_permitted(local_system):
    request = Request(
        system=local_system.name,
        system_version=local_system.version,
        namespace=local_system.namespace,
        command="mycommand",
        instance_name="default",
        parameters={"this": "doesntmatter"},
    )
    request.save()

    yield request
    request.delete()
Пример #9
0
def child_garden_request():
    request = Request(
        namespace="child_garden",
        system="testsystem",
        system_version="1.0.0",
        instance_name="instance1",
        command="somecommand",
        parameters={},
    )
    request.save()

    yield request
    request.delete()
Пример #10
0
def request_permitted_child(remote_system, request_permitted):
    request = Request(
        system=remote_system.name,
        system_version=remote_system.version,
        namespace=remote_system.namespace,
        command="mycommand",
        instance_name="default",
        parameters={"im": "thechild"},
        parent=request_permitted,
    )
    request.save()

    yield request
    request.delete()
Пример #11
0
def request_with_gridfs_output(monkeypatch, local_system):
    monkeypatch.setattr(beer_garden.db.mongo.models, "REQUEST_MAX_PARAM_SIZE",
                        0)

    request = Request(
        system=local_system.name,
        system_version=local_system.version,
        namespace=local_system.namespace,
        command="mycommand",
        instance_name="default",
        parameters={"this": "doesntmatter"},
        status="SUCCESS",
        output=_gridfs_output(),
    )
    request.save()

    yield request
    request.delete()
Пример #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
 def test_parent_mismatch(self, parent, has_parent):
     req = Request(command="bar", parent=parent, has_parent=has_parent)
     with pytest.raises(ModelValidationError):
         req.clean()
Пример #14
0
class TestRequest(object):
    @pytest.fixture(autouse=True)
    def drop(self, mongo_conn):
        Request.drop_collection()

    def test_str(self):
        assert str(Request(command="command")) == "command"

    def test_repr(self):
        request = Request(command="command", status="CREATED")
        assert "name" in repr(request)
        assert "CREATED" in repr(request)

    @pytest.mark.parametrize(
        "req",
        [
            Request(system="foo", command="bar", status="bad"),
            Request(system="foo", command="bar", command_type="BAD"),
            Request(system="foo", command="bar", output_type="BAD"),
        ],
    )
    def test_clean_fail(self, req):
        with pytest.raises(ModelValidationError):
            req.clean()

    @pytest.mark.parametrize(
        "start,end",
        [("SUCCESS", "IN_PROGRESS"), ("SUCCESS", "ERROR"),
         ("IN_PROGRESS", "CREATED")],
    )
    def test_invalid_status_transitions(self, bg_request, start, end):
        bg_request.status = start
        bg_request.output = None

        db.create(bg_request)

        with pytest.raises(RequestStatusTransitionError):
            bg_request.status = end
            db.update(bg_request)

    # TODO - Make these integration tests
    # @patch("bg_utils.mongo.models.Request.objects")
    # def test_find_one_or_none_found(self, objects_mock):
    #     self.assertEqual(objects_mock.get.return_value, Request.find_or_none("id"))
    #
    # @patch("bg_utils.mongo.models.Request.objects")
    # def test_find_one_or_none_none_found(self, objects_mock):
    #     objects_mock.get = Mock(side_effect=mongoengine.DoesNotExist)
    #     self.assertIsNone(Request.find_or_none("id"))
    #
    # @patch("mongoengine.Document.save", Mock())
    # def test_save_update_updated_at(self):
    #     request = Request(
    #         system="foo",
    #         command="bar",
    #         status="CREATED",
    #         updated_at="this_will_be_updated",
    #     )
    #     request.save()
    #     self.assertNotEqual(request.updated_at, "this_will_be_updated")

    # Namespace was removed from the TEMPLATE_FIELDS list, so reduce by one
    def test_template_check(self):
        assert len(Request.TEMPLATE_FIELDS) == len(
            RequestTemplateSchema.get_attribute_names())
Пример #15
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)
Пример #16
0
def db_cleanup():
    yield
    RawFile.drop_collection()
    Request.drop_collection()
Пример #17
0
 def test_repr(self):
     request = Request(command="command", status="CREATED")
     assert "name" in repr(request)
     assert "CREATED" in repr(request)
Пример #18
0
 def test_str(self):
     assert str(Request(command="command")) == "command"
Пример #19
0
 def drop(self, mongo_conn):
     Request.drop_collection()
Пример #20
0
 def test_set_has_parent(self, parent, has_parent):
     req = Request(command="bar", parent=parent)
     req.clean()
     assert req.has_parent is has_parent
Пример #21
0
def clear_requests(app):
    Request.drop_collection()