Exemplo n.º 1
0
class Queue(resource2.Resource):
    # FIXME(anyone): The name string of `location` field of Zaqar API response
    # is lower case. That is inconsistent with the guide from API-WG. This is
    # a workaround for this issue.
    location = resource2.Header("location")

    resources_key = "queues"
    base_path = "/queues"
    service = message_service.MessageService()

    # capabilities
    allow_create = True
    allow_list = True
    allow_get = True
    allow_delete = True

    # Properties
    #: The default TTL of messages defined for a queue, which will effect for
    #: any messages posted to the queue.
    default_message_ttl = resource2.Body("_default_message_ttl")
    #: Description of the queue.
    description = resource2.Body("description")
    #: The max post size of messages defined for a queue, which will effect
    #: for any messages posted to the queue.
    max_messages_post_size = resource2.Body("_max_messages_post_size")
    #: Name of the queue. The name is the unique identity of a queue. It
    #: must not exceed 64 bytes in length, and it is limited to US-ASCII
    #: letters, digits, underscores, and hyphens.
    name = resource2.Body("name", alternate_id=True)
    #: The ID to identify the client accessing Zaqar API. Must be specified
    #: in header for each API request.
    client_id = resource2.Header("Client-ID")
    #: The ID to identify the project accessing Zaqar API. Must be specified
    #: in case keystone auth is not enabled in Zaqar service.
    project_id = resource2.Header("X-PROJECT-ID")

    def create(self, session, prepend_key=True):
        request = self._prepare_request(requires_id=True,
                                        prepend_key=prepend_key)
        headers = {
            "Client-ID": self.client_id or str(uuid.uuid4()),
            "X-PROJECT-ID": self.project_id or session.get_project_id()
        }
        request.headers.update(headers)
        response = session.put(request.url,
                               json=request.body,
                               headers=request.headers)

        self._translate_response(response, has_body=False)
        return self

    @classmethod
    def list(cls, session, paginated=False, **params):
        """This method is a generator which yields queue objects.

        This is almost the copy of list method of resource2.Resource class.
        The only difference is the request header now includes `Client-ID`
        and `X-PROJECT-ID` fields which are required by Zaqar v2 API.
        """
        more_data = True
        query_params = cls._query_mapping._transpose(params)
        uri = cls.base_path % params
        headers = {
            "Client-ID":
            params.get('client_id', None) or str(uuid.uuid4()),
            "X-PROJECT-ID":
            params.get('project_id', None) or session.get_project_id()
        }

        while more_data:
            resp = session.get(uri, headers=headers, params=query_params)
            resp = resp.json()
            resp = resp[cls.resources_key]

            if not resp:
                more_data = False

            yielded = 0
            new_marker = None
            for data in resp:
                value = cls.existing(**data)
                new_marker = value.id
                yielded += 1
                yield value

            if not paginated:
                return
            if "limit" in query_params and yielded < query_params["limit"]:
                return
            query_params["limit"] = yielded
            query_params["marker"] = new_marker

    def get(self, session, requires_id=True):
        request = self._prepare_request(requires_id=requires_id)
        headers = {
            "Client-ID": self.client_id or str(uuid.uuid4()),
            "X-PROJECT-ID": self.project_id or session.get_project_id()
        }
        request.headers.update(headers)
        response = session.get(request.url, headers=headers)
        self._translate_response(response)

        return self

    def delete(self, session):
        request = self._prepare_request()
        headers = {
            "Client-ID": self.client_id or str(uuid.uuid4()),
            "X-PROJECT-ID": self.project_id or session.get_project_id()
        }
        request.headers.update(headers)
        response = session.delete(request.url, headers=headers)

        self._translate_response(response, has_body=False)
        return self
Exemplo n.º 2
0
class Authtoken(resource.Resource):
    resource_key = 'token'
    base_path = '/auth/tokens'
    service = identity_service.IdentityService()

    # capabilities
    allow_create = True
    allow_get = True

    x_subject_token = resource.Header("X-Subject-Token")

    _query_mapping = resource.QueryParameters("nocatalog")

    # Properties
    #: The identity of this token. *Type: dict*
    identity = resource.Body("identity", type=dict)
    #: The scope of this token. *Type: dict*
    scope = resource.Body("scope", type=dict)
    #: The catalog of this token. *Type: list*
    catalog = resource.Body("catalog", type=list)
    #: The domain of this token. *Type: dict*
    domain = resource.Body("domain", type=dict)
    #: The expires_at of this token. *Type: string*
    expires_at = resource.Body("expires_at")
    #: The issued_at of this token. *Type: string*
    issued_at = resource.Body("issued_at")
    #: The methods of this methods. *Type: list*
    methods = resource.Body("methods", type=list)
    #: The project of this token. *Type: dict*
    project = resource.Body("project", type=dict)
    #: The roles of this token. *Type: list*
    roles = resource.Body("roles", type=list)
    #: The user of this token. *Type: dict*
    user = resource.Body("user", type=dict)
    #: The assumed_by of this agency token. *Type: dict*
    assumed_by = resource.Body("assumed_by", type=dict)

    def create_authtoken(self, session, attr, nocatalog):
        endpoint_override = self.service.get_endpoint_override()
        if nocatalog is None:
            uri = self.base_path
        else:
            uri = self.base_path + "?nocatalog=" + nocatalog
        response = session.post(uri,
                                endpoint_filter=self.service,
                                endpoint_override=endpoint_override,
                                json=attr)
        self._translate_response(response)
        return self

    def validate_authtoken(self, session, x_subject_token, nocatalog):
        if not self.allow_get:
            raise exceptions.MethodNotSupported(self, "get")

        endpoint_override = self.service.get_endpoint_override()
        service = self.get_service_filter(self, session)
        if nocatalog is None:
            uri = self.base_path
        else:
            uri = self.base_path + "?nocatalog=" + nocatalog
        response = session.get(uri,
                               endpoint_filter=self.service,
                               microversion=service.microversion,
                               headers={"X-Subject-Token": x_subject_token},
                               endpoint_override=endpoint_override)
        self._translate_response(response)
        return self
Exemplo n.º 3
0
class Claim(resource2.Resource):
    resources_key = 'claims'
    base_path = '/queues/%(queue_name)s/claims'
    service = message_service.MessageService()

    # capabilities
    allow_create = True
    allow_get = True
    allow_update = True
    allow_delete = True
    patch_update = True

    # Properties
    #: The value in seconds indicating how long the claim has existed.
    age = resource2.Body("age")
    #: In case worker stops responding for a long time, the server will
    #: extend the lifetime of claimed messages to be at least as long as
    #: the lifetime of the claim itself, plus the specified grace period.
    #: Must between 60 and 43200 seconds(12 hours).
    grace = resource2.Body("grace")
    #: The number of messages to claim. Default 10, up to 20.
    limit = resource2.Body("limit")
    #: Messages have been successfully claimed.
    messages = resource2.Body("messages")
    #: Number of seconds the server wait before releasing the claim. Must
    #: between 60 and 43200 seconds(12 hours).
    ttl = resource2.Body("ttl")
    #: The name of queue to claim message from.
    queue_name = resource2.URI("queue_name")
    #: The ID to identify the client accessing Zaqar API. Must be specified
    #: in header for each API request.
    client_id = resource2.Header("Client-ID")
    #: The ID to identify the project. Must be provided when keystone
    #: authentication is not enabled in Zaqar service.
    project_id = resource2.Header("X-PROJECT-ID")

    def _translate_response(self, response, has_body=True):
        super(Claim, self)._translate_response(response, has_body=has_body)
        if has_body and self.location:
            # Extract claim ID from location
            self.id = self.location.split("claims/")[1]

    def create(self, session, prepend_key=False):
        request = self._prepare_request(requires_id=False,
                                        prepend_key=prepend_key)
        headers = {
            "Client-ID": self.client_id or str(uuid.uuid4()),
            "X-PROJECT-ID": self.project_id or session.get_project_id()
        }
        request.headers.update(headers)
        response = session.post(request.uri,
                                endpoint_filter=self.service,
                                json=request.body,
                                headers=request.headers)

        # For case no message was claimed successfully, 204 No Content
        # message will be returned. In other cases, we translate response
        # body which has `messages` field(list) included.
        if response.status_code != 204:
            self._translate_response(response)

        return self

    def get(self, session, requires_id=True):
        request = self._prepare_request(requires_id=requires_id)
        headers = {
            "Client-ID": self.client_id or str(uuid.uuid4()),
            "X-PROJECT-ID": self.project_id or session.get_project_id()
        }

        request.headers.update(headers)
        response = session.get(request.uri,
                               endpoint_filter=self.service,
                               headers=request.headers)
        self._translate_response(response)

        return self

    def update(self, session, prepend_key=False, has_body=False):
        request = self._prepare_request(prepend_key=prepend_key)
        headers = {
            "Client-ID": self.client_id or str(uuid.uuid4()),
            "X-PROJECT-ID": self.project_id or session.get_project_id()
        }

        request.headers.update(headers)
        session.patch(request.uri,
                      endpoint_filter=self.service,
                      json=request.body,
                      headers=request.headers)

        return self

    def delete(self, session):
        request = self._prepare_request()
        headers = {
            "Client-ID": self.client_id or str(uuid.uuid4()),
            "X-PROJECT-ID": self.project_id or session.get_project_id()
        }

        request.headers.update(headers)
        response = session.delete(request.uri,
                                  endpoint_filter=self.service,
                                  headers=request.headers)

        self._translate_response(response, has_body=False)
        return self
Exemplo n.º 4
0
class Message(resource2.Resource):
    # FIXME(anyone): The name string of `location` field of Zaqar API response
    # is lower case. That is inconsistent with the guide from API-WG. This is
    # a workaround for this issue.
    location = resource2.Header("location")

    resources_key = 'messages'
    base_path = '/queues/%(queue_name)s/messages'
    service = message_service.MessageService()

    # capabilities
    allow_create = True
    allow_list = True
    allow_get = True
    allow_delete = True

    _query_mapping = resource2.QueryParameters("echo", "include_claimed")

    # Properties
    #: The value in second to specify how long the message has been
    #: posted to the queue.
    age = resource2.Body("age")
    #: A dictionary specifies an arbitrary document that constitutes the
    #: body of the message being sent.
    body = resource2.Body("body")
    #: An uri string describe the location of the message resource.
    href = resource2.Body("href")
    #: The value in seconds to specify how long the server waits before
    #: marking the message as expired and removing it from the queue.
    ttl = resource2.Body("ttl")
    #: The name of target queue message is post to or got from.
    queue_name = resource2.URI("queue_name")
    #: The ID to identify the client accessing Zaqar API. Must be specified
    #: in header for each API request.
    client_id = resource2.Header("Client-ID")
    #: The ID to identify the project accessing Zaqar API. Must be specified
    #: in case keystone auth is not enabled in Zaqar service.
    project_id = resource2.Header("X-PROJECT-ID")

    def post(self, session, messages):
        request = self._prepare_request(requires_id=False, prepend_key=True)
        headers = {
            "Client-ID": self.client_id or str(uuid.uuid4()),
            "X-PROJECT-ID": self.project_id or session.get_project_id()
        }
        request.headers.update(headers)
        request.body = {'messages': messages}
        response = session.post(request.url,
                                json=request.body,
                                headers=request.headers)

        return response.json()['resources']

    @classmethod
    def list(cls, session, paginated=True, **params):
        """This method is a generator which yields message objects.

        This is almost the copy of list method of resource2.Resource class.
        The only difference is the request header now includes `Client-ID`
        and `X-PROJECT-ID` fields which are required by Zaqar v2 API.
        """
        more_data = True
        uri = cls.base_path % params
        headers = {
            "Client-ID":
            params.get('client_id', None) or str(uuid.uuid4()),
            "X-PROJECT-ID":
            params.get('project_id', None) or session.get_project_id()
        }

        query_params = cls._query_mapping._transpose(params)
        while more_data:
            resp = session.get(uri, headers=headers, params=query_params)
            resp = resp.json()
            resp = resp[cls.resources_key]

            if not resp:
                more_data = False

            yielded = 0
            new_marker = None
            for data in resp:
                value = cls.existing(**data)
                new_marker = value.id
                yielded += 1
                yield value

            if not paginated:
                return
            if "limit" in query_params and yielded < query_params["limit"]:
                return
            query_params["limit"] = yielded
            query_params["marker"] = new_marker

    def get(self, session, requires_id=True):
        request = self._prepare_request(requires_id=requires_id)
        headers = {
            "Client-ID": self.client_id or str(uuid.uuid4()),
            "X-PROJECT-ID": self.project_id or session.get_project_id()
        }

        request.headers.update(headers)
        response = session.get(request.url, headers=headers)
        self._translate_response(response)

        return self

    def delete(self, session):
        request = self._prepare_request()
        headers = {
            "Client-ID": self.client_id or str(uuid.uuid4()),
            "X-PROJECT-ID": self.project_id or session.get_project_id()
        }

        request.headers.update(headers)
        # For Zaqar v2 API requires client to specify claim_id as query
        # parameter when deleting a message that has been claimed, we
        # rebuild the request URI if claim_id is not None.
        if self.claim_id:
            request.url += '?claim_id=%s' % self.claim_id
        response = session.delete(request.url, headers=headers)

        self._translate_response(response, has_body=False)
        return self
Exemplo n.º 5
0
class Subscription(resource2.Resource):
    # FIXME(anyone): The name string of `location` field of Zaqar API response
    # is lower case. That is inconsistent with the guide from API-WG. This is
    # a workaround for this issue.
    location = resource2.Header("location")

    resources_key = 'subscriptions'
    base_path = '/queues/%(queue_name)s/subscriptions'
    service = message_service.MessageService()

    # capabilities
    allow_create = True
    allow_list = True
    allow_get = True
    allow_delete = True

    # Properties
    #: The value in seconds indicating how long the subscription has existed.
    age = resource2.Body("age")
    #: Alternate id of the subscription. This key is used in response of
    #: subscription create API to return id of subscription created.
    subscription_id = resource2.Body("subscription_id", alternate_id=True)
    #: The extra metadata for the subscription. The value must be a dict.
    #: If the subscriber is `mailto`. The options can contain `from` and
    #: `subject` to indicate the email's author and title.
    options = resource2.Body("options", type=dict)
    #: The queue name which the subscription is registered on.
    source = resource2.Body("source")
    #: The destination of the message. Two kinds of subscribers are supported:
    #: http/https and email. The http/https subscriber should start with
    #: `http/https`. The email subscriber should start with `mailto`.
    subscriber = resource2.Body("subscriber")
    #: Number of seconds the subscription remains alive? The ttl value must
    #: be great than 60 seconds. The default value is 3600 seconds.
    ttl = resource2.Body("ttl")
    #: The queue name which the subscription is registered on.
    queue_name = resource2.URI("queue_name")
    #: The ID to identify the client accessing Zaqar API. Must be specified
    #: in header for each API request.
    client_id = resource2.Header("Client-ID")
    #: The ID to identify the project. Must be provided when keystone
    #: authentication is not enabled in Zaqar service.
    project_id = resource2.Header("X-PROJECT-ID")

    def create(self, session, prepend_key=True):
        request = self._prepare_request(requires_id=False,
                                        prepend_key=prepend_key)
        headers = {
            "Client-ID": self.client_id or str(uuid.uuid4()),
            "X-PROJECT-ID": self.project_id or session.get_project_id()
        }
        request.headers.update(headers)
        response = session.post(request.uri, endpoint_filter=self.service,
                                json=request.body, headers=request.headers)

        self._translate_response(response)
        return self

    @classmethod
    def list(cls, session, paginated=True, **params):
        """This method is a generator which yields subscription objects.

        This is almost the copy of list method of resource2.Resource class.
        The only difference is the request header now includes `Client-ID`
        and `X-PROJECT-ID` fields which are required by Zaqar v2 API.
        """
        more_data = True
        uri = cls.base_path % params
        headers = {
            "Client-ID": params.get('client_id', None) or str(uuid.uuid4()),
            "X-PROJECT-ID": params.get('project_id', None
                                       ) or session.get_project_id()
        }

        query_params = cls._query_mapping._transpose(params)
        while more_data:
            resp = session.get(uri, endpoint_filter=cls.service,
                               headers=headers, params=query_params)
            resp = resp.json()
            resp = resp[cls.resources_key]

            if not resp:
                more_data = False

            yielded = 0
            new_marker = None
            for data in resp:
                value = cls.existing(**data)
                new_marker = value.id
                yielded += 1
                yield value

            if not paginated:
                return
            if "limit" in query_params and yielded < query_params["limit"]:
                return
            query_params["limit"] = yielded
            query_params["marker"] = new_marker

    def get(self, session, requires_id=True):
        request = self._prepare_request(requires_id=requires_id)
        headers = {
            "Client-ID": self.client_id or str(uuid.uuid4()),
            "X-PROJECT-ID": self.project_id or session.get_project_id()
        }

        request.headers.update(headers)
        response = session.get(request.uri, endpoint_filter=self.service,
                               headers=request.headers)
        self._translate_response(response)

        return self

    def delete(self, session):
        request = self._prepare_request()
        headers = {
            "Client-ID": self.client_id or str(uuid.uuid4()),
            "X-PROJECT-ID": self.project_id or session.get_project_id()
        }

        request.headers.update(headers)
        response = session.delete(request.uri, endpoint_filter=self.service,
                                  headers=request.headers)

        self._translate_response(response, has_body=False)
        return self
 class Test(resource2.Resource):
     base_path = "/something"
     resource_key = key
     body_attr = resource2.Body("x")
     header_attr = resource2.Header("y")
 class Test(resource2.Resource):
     attr = resource2.Header("attr")
 class Example(resource2.Resource):
     x = resource2.Body("x")
     y = resource2.Header("y")
     z = resource2.URI("z")
 class Test(resource2.Resource):
     x = resource2.Header("x")
     y = resource2.Header("y")
     z = resource2.Header("z")
Exemplo n.º 10
0
 class Test(cdn_resource.Resource):
     attr = resource2.Header("attr")
 class Child(Parent):
     # The following two properties are not supposed to be overridden
     # by the parent class property values.
     header = resource2.Header('ANOTHER_HEADER')
     body = resource2.Body('ANOTHER_BODY')
 class Parent(resource2.Resource):
     header = resource2.Header('HEADER')
     body = resource2.Body('BODY')
 class Test(resource2.Resource):
     foo = resource2.Header('foo')
     bar = resource2.Body('bar')
 class Child(Parent):
     foo_new = resource2.Header('foo_baz_server')
     bar_new = resource2.Body('bar_baz_server')