Пример #1
0
    def test_no_spec(self):
        obj = {u'body': {'event': 'start_backup'}, 'ttl': 300}
        document = json.dumps(obj, ensure_ascii=False)
        doc_stream = io.StringIO(document)

        filtered = utils.filter_stream(doc_stream, len(document), spec=None)
        self.assertEqual(filtered[0], obj)

        # NOTE(kgriffs): Ensure default value for *spec* is None
        doc_stream.seek(0)
        filtered2 = utils.filter_stream(doc_stream, len(document))
        self.assertEqual(filtered2, filtered)
Пример #2
0
    def test_no_spec(self):
        obj = {u'body': {'event': 'start_backup'}, 'ttl': 300}
        document = json.dumps(obj, ensure_ascii=False)
        doc_stream = io.StringIO(document)

        filtered = utils.filter_stream(doc_stream, len(document), spec=None)
        self.assertEqual(filtered[0], obj)

        # NOTE(kgriffs): Ensure default value for *spec* is None
        doc_stream.seek(0)
        filtered2 = utils.filter_stream(doc_stream, len(document))
        self.assertEqual(filtered2, filtered)
Пример #3
0
    def on_patch(self, req, resp, project_id, queue_name, claim_id):
        LOG.debug(_("Claim Item PATCH - claim: %(claim_id)s, "
                    "queue: %(queue_name)s, project:%(project_id)s") %
                  {"queue_name": queue_name,
                   "project_id": project_id,
                   "claim_id": claim_id})

        # Place JSON size restriction before parsing
        if req.content_length > CFG.metadata_max_length:
            description = _('Claim metadata size is too large.')
            raise wsgi_exceptions.HTTPBadRequestBody(description)

        # Read claim metadata (e.g., TTL) and raise appropriate
        # HTTP errors as needed.
        metadata, = wsgi_utils.filter_stream(req.stream, req.content_length,
                                             CLAIM_PATCH_SPEC)

        try:
            self.claim_controller.update(queue_name,
                                         claim_id=claim_id,
                                         metadata=metadata,
                                         project=project_id)

            resp.status = falcon.HTTP_204

        except storage_exceptions.DoesNotExist:
            raise falcon.HTTPNotFound()
        except Exception as ex:
            LOG.exception(ex)
            description = _('Claim could not be updated.')
            raise wsgi_exceptions.HTTPServiceUnavailable(description)
Пример #4
0
    def on_put(self, req, resp, project_id, queue_name):
        LOG.debug(
            _(u"Queue metadata PUT - queue: %(queue)s, " u"project: %(project)s")
            % {"queue": queue_name, "project": project_id}
        )

        # Place JSON size restriction before parsing
        if req.content_length > CFG.metadata_max_length:
            description = _(u"Queue metadata size is too large.")
            raise wsgi_exceptions.HTTPBadRequestBody(description)

        # Deserialize queue metadata
        metadata, = wsgi_utils.filter_stream(req.stream, req.content_length, spec=None)

        try:
            validate.queue_content(metadata, check_size=(validate.CFG.metadata_size_uplimit < CFG.metadata_max_length))
            self.queue_ctrl.set_metadata(queue_name, metadata=metadata, project=project_id)

        except input_exceptions.ValidationFailed as ex:
            raise wsgi_exceptions.HTTPBadRequestBody(str(ex))

        except storage_exceptions.QueueDoesNotExist:
            raise falcon.HTTPNotFound()

        except Exception as ex:
            LOG.exception(ex)
            description = _(u"Metadata could not be updated.")
            raise wsgi_exceptions.HTTPServiceUnavailable(description)

        resp.status = falcon.HTTP_204
        resp.location = req.path
Пример #5
0
    def test_no_spec_array(self):
        things = [{u'body': {'event': 'start_backup'}, 'ttl': 300}]
        document = json.dumps(things, ensure_ascii=False)
        doc_stream = io.StringIO(document)

        filtered = utils.filter_stream(doc_stream, len(document),
                                       doctype=utils.JSONArray, spec=None)
        self.assertEqual(filtered, things)
Пример #6
0
    def on_post(self, req, resp, project_id, queue_name):
        LOG.debug(_(u'Claims collection POST - queue: %(queue)s, '
                    u'project: %(project)s') %
                  {'queue': queue_name, 'project': project_id})

        # Check for an explicit limit on the # of messages to claim
        limit = req.get_param_as_int('limit')
        claim_options = {} if limit is None else {'limit': limit}

        # Place JSON size restriction before parsing
        if req.content_length > CFG.metadata_max_length:
            description = _(u'Claim metadata size is too large.')
            raise wsgi_exceptions.HTTPBadRequestBody(description)

        # Read claim metadata (e.g., TTL) and raise appropriate
        # HTTP errors as needed.
        metadata, = wsgi_utils.filter_stream(req.stream, req.content_length,
                                             CLAIM_POST_SPEC)

        # Claim some messages
        try:
            validate.claim_creation(metadata, **claim_options)
            cid, msgs = self.claim_controller.create(
                queue_name,
                metadata=metadata,
                project=project_id,
                **claim_options)

            # Buffer claimed messages
            # TODO(kgriffs): optimize, along with serialization (below)
            resp_msgs = list(msgs)

        except input_exceptions.ValidationFailed as ex:
            raise wsgi_exceptions.HTTPBadRequestBody(str(ex))

        except storage_exceptions.DoesNotExist:
            raise falcon.HTTPNotFound()

        except Exception as ex:
            LOG.exception(ex)
            description = _(u'Claim could not be created.')
            raise wsgi_exceptions.HTTPServiceUnavailable(description)

        # Serialize claimed messages, if any. This logic assumes
        # the storage driver returned well-formed messages.
        if len(resp_msgs) != 0:
            for msg in resp_msgs:
                msg['href'] = _msg_uri_from_claim(
                    req.path.rpartition('/')[0], msg['id'], cid)

                del msg['id']

            resp.location = req.path + '/' + cid
            resp.body = utils.to_json(resp_msgs)
            resp.status = falcon.HTTP_201
        else:
            resp.status = falcon.HTTP_204
Пример #7
0
    def test_no_spec_array(self):
        things = [{u'body': {'event': 'start_backup'}, 'ttl': 300}]
        document = json.dumps(things, ensure_ascii=False)
        doc_stream = io.StringIO(document)

        filtered = utils.filter_stream(doc_stream,
                                       len(document),
                                       doctype=utils.JSONArray,
                                       spec=None)
        self.assertEqual(filtered, things)
Пример #8
0
    def test_filter_stream_expect_obj(self):
        obj = {u'body': {'event': 'start_backup'}, 'id': 'DEADBEEF'}

        document = json.dumps(obj, ensure_ascii=False)
        stream = io.StringIO(document)
        spec = [('body', dict), ('id', basestring)]
        filtered_object, = utils.filter_stream(stream, len(document), spec)

        self.assertEqual(filtered_object, obj)

        stream.seek(0)
        self.assertRaises(falcon.HTTPBadRequest,
                          utils.filter_stream, stream, len(document), spec,
                          doctype=utils.JSONArray)
Пример #9
0
    def test_filter_stream_expect_array(self):
        array = [{u'body': {u'x': 1}}, {u'body': {u'x': 2}}]

        document = json.dumps(array, ensure_ascii=False)
        stream = io.StringIO(document)
        spec = [('body', dict)]
        filtered_objects = list(utils.filter_stream(
            stream, len(document), spec, doctype=utils.JSONArray))

        self.assertEqual(filtered_objects, array)

        stream.seek(0)
        self.assertRaises(falcon.HTTPBadRequest,
                          utils.filter_stream, stream, len(document), spec,
                          doctype=utils.JSONObject)
Пример #10
0
    def test_filter_stream_expect_obj(self):
        obj = {u'body': {'event': 'start_backup'}, 'id': 'DEADBEEF'}

        document = json.dumps(obj, ensure_ascii=False)
        stream = io.StringIO(document)
        spec = [('body', dict), ('id', basestring)]
        filtered_object, = utils.filter_stream(stream, len(document), spec)

        self.assertEqual(filtered_object, obj)

        stream.seek(0)
        self.assertRaises(falcon.HTTPBadRequest,
                          utils.filter_stream,
                          stream,
                          len(document),
                          spec,
                          doctype=utils.JSONArray)
Пример #11
0
    def test_filter_stream_expect_array(self):
        array = [{u'body': {u'x': 1}}, {u'body': {u'x': 2}}]

        document = json.dumps(array, ensure_ascii=False)
        stream = io.StringIO(document)
        spec = [('body', dict)]
        filtered_objects = list(
            utils.filter_stream(stream,
                                len(document),
                                spec,
                                doctype=utils.JSONArray))

        self.assertEqual(filtered_objects, array)

        stream.seek(0)
        self.assertRaises(falcon.HTTPBadRequest,
                          utils.filter_stream,
                          stream,
                          len(document),
                          spec,
                          doctype=utils.JSONObject)
Пример #12
0
    def on_patch(self, req, resp, project_id, queue_name, claim_id):
        LOG.debug(
            _(u'Claim Item PATCH - claim: %(claim_id)s, '
              u'queue: %(queue_name)s, project:%(project_id)s') % {
                  'queue_name': queue_name,
                  'project_id': project_id,
                  'claim_id': claim_id
              })

        # Place JSON size restriction before parsing
        if req.content_length > CFG.metadata_max_length:
            description = _(u'Claim metadata size is too large.')
            raise wsgi_exceptions.HTTPBadRequestBody(description)

        # Read claim metadata (e.g., TTL) and raise appropriate
        # HTTP errors as needed.
        metadata, = wsgi_utils.filter_stream(req.stream, req.content_length,
                                             CLAIM_PATCH_SPEC)

        try:
            validate.claim_updating(metadata)
            self.claim_controller.update(queue_name,
                                         claim_id=claim_id,
                                         metadata=metadata,
                                         project=project_id)

            resp.status = falcon.HTTP_204

        except input_exceptions.ValidationFailed as ex:
            raise wsgi_exceptions.HTTPBadRequestBody(str(ex))

        except storage_exceptions.DoesNotExist:
            raise falcon.HTTPNotFound()

        except Exception as ex:
            LOG.exception(ex)
            description = _(u'Claim could not be updated.')
            raise wsgi_exceptions.HTTPServiceUnavailable(description)
Пример #13
0
    def on_put(self, req, resp, project_id, queue_name):
        LOG.debug(_(u'Queue metadata PUT - queue: %(queue)s, '
                    u'project: %(project)s') %
                  {'queue': queue_name, 'project': project_id})

        # Place JSON size restriction before parsing
        if req.content_length > CFG.metadata_max_length:
            description = _(u'Queue metadata size is too large.')
            raise wsgi_exceptions.HTTPBadRequestBody(description)

        # Deserialize queue metadata
        metadata, = wsgi_utils.filter_stream(req.stream,
                                             req.content_length,
                                             spec=None)

        try:
            validate.queue_content(
                metadata, check_size=(
                    validate.CFG.metadata_size_uplimit <
                    CFG.metadata_max_length))
            self.queue_ctrl.set_metadata(queue_name,
                                         metadata=metadata,
                                         project=project_id)

        except input_exceptions.ValidationFailed as ex:
            raise wsgi_exceptions.HTTPBadRequestBody(str(ex))

        except storage_exceptions.QueueDoesNotExist:
            raise falcon.HTTPNotFound()

        except Exception as ex:
            LOG.exception(ex)
            description = _(u'Metadata could not be updated.')
            raise wsgi_exceptions.HTTPServiceUnavailable(description)

        resp.status = falcon.HTTP_204
        resp.location = req.path
Пример #14
0
    def on_post(self, req, resp, project_id, queue_name):
        LOG.debug(
            _(u'Messages collection POST - queue:  %(queue)s, '
              u'project: %(project)s') % {
                  'queue': queue_name,
                  'project': project_id
              })

        uuid = req.get_header('Client-ID', required=True)

        # Place JSON size restriction before parsing
        if req.content_length > CFG.content_max_length:
            description = _(u'Message collection size is too large.')
            raise wsgi_exceptions.HTTPBadRequestBody(description)

        # Pull out just the fields we care about
        messages = wsgi_utils.filter_stream(req.stream,
                                            req.content_length,
                                            MESSAGE_POST_SPEC,
                                            doctype=wsgi_utils.JSONArray)

        # Enqueue the messages
        partial = False

        try:
            # No need to check each message's size if it
            # can not exceed the request size limit
            validate.message_posting(
                messages,
                check_size=(validate.CFG.message_size_uplimit <
                            CFG.content_max_length))
            message_ids = self.message_controller.post(queue_name,
                                                       messages=messages,
                                                       project=project_id,
                                                       client_uuid=uuid)

        except input_exceptions.ValidationFailed as ex:
            raise wsgi_exceptions.HTTPBadRequestBody(str(ex))

        except storage_exceptions.DoesNotExist:
            raise falcon.HTTPNotFound()

        except storage_exceptions.MessageConflict as ex:
            LOG.exception(ex)
            partial = True
            message_ids = ex.succeeded_ids

            if not message_ids:
                # TODO(kgriffs): Include error code that is different
                # from the code used in the generic case, below.
                description = _(u'No messages could be enqueued.')
                raise wsgi_exceptions.HTTPServiceUnavailable(description)

        except Exception as ex:
            LOG.exception(ex)
            description = _(u'Messages could not be enqueued.')
            raise wsgi_exceptions.HTTPServiceUnavailable(description)

        # Prepare the response
        ids_value = ','.join(message_ids)
        resp.location = req.path + '?ids=' + ids_value

        hrefs = [req.path + '/' + id for id in message_ids]
        body = {'resources': hrefs, 'partial': partial}
        resp.body = utils.to_json(body)
        resp.status = falcon.HTTP_201
Пример #15
0
    def on_post(self, req, resp, project_id, queue_name):
        LOG.debug(_(u'Messages collection POST - queue:  %(queue)s, '
                    u'project: %(project)s') %
                  {'queue': queue_name, 'project': project_id})

        uuid = req.get_header('Client-ID', required=True)

        # Place JSON size restriction before parsing
        if req.content_length > CFG.content_max_length:
            description = _(u'Message collection size is too large.')
            raise wsgi_exceptions.HTTPBadRequestBody(description)

        # Pull out just the fields we care about
        messages = wsgi_utils.filter_stream(
            req.stream,
            req.content_length,
            MESSAGE_POST_SPEC,
            doctype=wsgi_utils.JSONArray)

        # Enqueue the messages
        partial = False

        try:
            # No need to check each message's size if it
            # can not exceed the request size limit
            validate.message_posting(
                messages, check_size=(
                    validate.CFG.message_size_uplimit <
                    CFG.content_max_length))
            message_ids = self.message_controller.post(
                queue_name,
                messages=messages,
                project=project_id,
                client_uuid=uuid)

        except input_exceptions.ValidationFailed as ex:
            raise wsgi_exceptions.HTTPBadRequestBody(str(ex))

        except storage_exceptions.DoesNotExist:
            raise falcon.HTTPNotFound()

        except storage_exceptions.MessageConflict as ex:
            LOG.exception(ex)
            partial = True
            message_ids = ex.succeeded_ids

            if not message_ids:
                # TODO(kgriffs): Include error code that is different
                # from the code used in the generic case, below.
                description = _(u'No messages could be enqueued.')
                raise wsgi_exceptions.HTTPServiceUnavailable(description)

        except Exception as ex:
            LOG.exception(ex)
            description = _(u'Messages could not be enqueued.')
            raise wsgi_exceptions.HTTPServiceUnavailable(description)

        # Prepare the response
        ids_value = ','.join(message_ids)
        resp.location = req.path + '?ids=' + ids_value

        hrefs = [req.path + '/' + id for id in message_ids]
        body = {'resources': hrefs, 'partial': partial}
        resp.body = utils.to_json(body)
        resp.status = falcon.HTTP_201
Пример #16
0
    def on_post(self, req, resp, project_id, queue_name):
        LOG.debug(_("Messages collection POST - queue:  %(queue)s, "
                    "project: %(project)s") %
                  {"queue": queue_name, "project": project_id})

        uuid = req.get_header('Client-ID', required=True)

        # Place JSON size restriction before parsing
        if req.content_length > CFG.content_max_length:
            description = _('Message collection size is too large.')
            raise wsgi_exceptions.HTTPBadRequestBody(description)

        # Pull out just the fields we care about
        messages = wsgi_utils.filter_stream(
            req.stream,
            req.content_length,
            MESSAGE_POST_SPEC,
            doctype=wsgi_utils.JSONArray)

        # Verify that at least one message was provided.
        # NOTE(kgriffs): This check assumes messages is a
        # collection (not a generator).
        if not messages:
            description = _('No messages were provided.')
            raise wsgi_exceptions.HTTPBadRequestBody(description)

        # Enqueue the messages
        partial = False

        try:
            message_ids = self.message_controller.post(
                queue_name,
                messages=messages,
                project=project_id,
                client_uuid=uuid)

        except storage_exceptions.DoesNotExist:
            raise falcon.HTTPNotFound()
        except storage_exceptions.MessageConflict as ex:
            LOG.exception(ex)
            partial = True
            message_ids = ex.succeeded_ids

            if not message_ids:
                # TODO(kgriffs): Include error code that is different
                # from the code used in the generic case, below.
                description = _('No messages could be enqueued.')
                raise wsgi_exceptions.HTTPServiceUnavailable(description)

        except Exception as ex:
            LOG.exception(ex)
            description = _('Messages could not be enqueued.')
            raise wsgi_exceptions.HTTPServiceUnavailable(description)

        # Prepare the response
        resp.status = falcon.HTTP_201

        ids_value = ','.join(message_ids)
        resp.location = req.path + '?ids=' + ids_value

        hrefs = [req.path + '/' + id for id in message_ids]
        body = {'resources': hrefs, 'partial': partial}
        resp.body = utils.to_json(body)