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
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
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
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
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")
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')