diff --git a/keystoneclient/base.py b/keystoneclient/base.py index 839b8a1ff..f5e38ebc9 100644 --- a/keystoneclient/base.py +++ b/keystoneclient/base.py @@ -214,6 +214,10 @@ class Manager(object): else: return self._prepare_return_value( resp, self.resource_class(self, body)) + # In some cases (e.g. 'add_endpoint_to_project' from endpoint_filters + # resource), PUT request may not return a body so return None as + # response along with request_id if include_metadata is True. + return self._prepare_return_value(resp, body) def _patch(self, url, body=None, response_key=None, **kwargs): """Update an object with PATCH method. diff --git a/keystoneclient/tests/unit/v3/test_roles.py b/keystoneclient/tests/unit/v3/test_roles.py index 51d9fc73f..0e531e736 100644 --- a/keystoneclient/tests/unit/v3/test_roles.py +++ b/keystoneclient/tests/unit/v3/test_roles.py @@ -656,7 +656,7 @@ class ImpliedRoleTests(utils.ClientTestCase, utils.CrudTests): implied_role_id = uuid.uuid4().hex self.stub_url('HEAD', ['roles', prior_role_id, 'implies', implied_role_id], - status_code=200) + status_code=204) result = self.manager.check(prior_role_id, implied_role_id) self.assertTrue(result) diff --git a/keystoneclient/v3/contrib/federation/saml.py b/keystoneclient/v3/contrib/federation/saml.py index 9be657a57..435e45dc6 100644 --- a/keystoneclient/v3/contrib/federation/saml.py +++ b/keystoneclient/v3/contrib/federation/saml.py @@ -37,7 +37,7 @@ class SamlManager(base.Manager): headers, body = self._create_common_request(service_provider, token_id) resp, body = self.client.post(SAML2_ENDPOINT, json=body, headers=headers) - return resp.text + return self._prepare_return_value(resp, resp.text) def create_ecp_assertion(self, service_provider, token_id): """Create an ECP wrapped SAML assertion from a token. @@ -56,7 +56,7 @@ class SamlManager(base.Manager): headers, body = self._create_common_request(service_provider, token_id) resp, body = self.client.post(ECP_ENDPOINT, json=body, headers=headers) - return resp.text + return self._prepare_return_value(resp, resp.text) def _create_common_request(self, service_provider, token_id): headers = {'Content-Type': 'application/json'} diff --git a/keystoneclient/v3/limits.py b/keystoneclient/v3/limits.py index 5d298a4a3..52b1b886c 100644 --- a/keystoneclient/v3/limits.py +++ b/keystoneclient/v3/limits.py @@ -70,7 +70,9 @@ class LimitManager(base.CrudManager): body = {self.collection_key: [limit_data]} resp, body = self.client.post('/limits', body=body) limit = body[self.collection_key].pop() - return self.resource_class(self, limit) + return self._prepare_return_value(resp, + self.resource_class( + self, limit)) def update(self, limit, project=None, service=None, resource_name=None, resource_limit=None, description=None, **kwargs): diff --git a/keystoneclient/v3/projects.py b/keystoneclient/v3/projects.py index aa94293d3..5975bdac2 100644 --- a/keystoneclient/v3/projects.py +++ b/keystoneclient/v3/projects.py @@ -278,7 +278,7 @@ class ProjectManager(base.CrudManager): """ url = "/projects/%s/tags/%s" % (base.getid(project), urllib.parse.quote(tag)) - self.client.put(url) + return self._put(url) def update_tags(self, project, tags): """Update tag list of a project. @@ -295,7 +295,7 @@ class ProjectManager(base.CrudManager): for tag in tags: tag = urllib.parse.quote(tag) resp, body = self.client.put(url, body={"tags": tags}) - return body['tags'] + return self._prepare_return_value(resp, body['tags']) def delete_tag(self, project, tag): """Remove tag from project. @@ -304,7 +304,7 @@ class ProjectManager(base.CrudManager): :param tag: str name of tag to remove from project """ - self._delete( + return self._delete( "/projects/%s/tags/%s" % (base.getid(project), urllib.parse.quote(tag))) @@ -318,7 +318,8 @@ class ProjectManager(base.CrudManager): """ url = "/projects/%s/tags" % base.getid(project) resp, body = self.client.get(url) - return self._encode_tags(body['tags']) + body['tags'] = self._encode_tags(body['tags']) + return self._prepare_return_value(resp, body['tags']) def check_tag(self, project, tag): """Check if tag is associated with project. @@ -332,9 +333,9 @@ class ProjectManager(base.CrudManager): url = "/projects/%s/tags/%s" % (base.getid(project), urllib.parse.quote(tag)) try: - self.client.head(url) + resp, body = self.client.head(url) # no errors means found the tag - return True - except exceptions.NotFound: - # 404 means tag not in project - return False + return self._prepare_return_value(resp, True) + except exceptions.HttpError as ex: + # return false with request_id if include_metadata=True + return self._prepare_return_value(ex.response, False) diff --git a/keystoneclient/v3/registered_limits.py b/keystoneclient/v3/registered_limits.py index 6593845d3..088aadc9e 100644 --- a/keystoneclient/v3/registered_limits.py +++ b/keystoneclient/v3/registered_limits.py @@ -69,7 +69,9 @@ class RegisteredLimitManager(base.CrudManager): body = {self.collection_key: [limit_data]} resp, body = self.client.post('/registered_limits', body=body) registered_limit = body[self.collection_key].pop() - return self.resource_class(self, registered_limit) + return self._prepare_return_value(resp, + self.resource_class( + self, registered_limit)) def update(self, registered_limit, service=None, resource_name=None, default_limit=None, description=None, region=None, **kwargs): diff --git a/keystoneclient/v3/roles.py b/keystoneclient/v3/roles.py index a84ab39a3..3364bd88b 100644 --- a/keystoneclient/v3/roles.py +++ b/keystoneclient/v3/roles.py @@ -455,7 +455,8 @@ class InferenceRuleManager(base.CrudManager): """ url_tail = self._implied_role_url_tail(prior_role, implied_role) _resp, body = self.client.put("/roles" + url_tail) - return self.resource_class(self, body['role_inference']) + return self._prepare_return_value( + _resp, self.resource_class(self, body['role_inference'])) def delete(self, prior_role, implied_role): """Delete an inference rule. @@ -478,7 +479,7 @@ class InferenceRuleManager(base.CrudManager): """ url_tail = self._implied_role_url_tail(prior_role, implied_role) - return self.client.delete("/roles" + url_tail) + return self._delete("/roles" + url_tail) def get(self, prior_role, implied_role): """Retrieve an inference rule. @@ -499,7 +500,8 @@ class InferenceRuleManager(base.CrudManager): """ url_tail = self._implied_role_url_tail(prior_role, implied_role) _resp, body = self.client.get("/roles" + url_tail) - return self.resource_class(self, body['role_inference']) + return self._prepare_return_value( + _resp, self.resource_class(self, body['role_inference'])) def list(self, prior_role): """List all roles that a role may imply. @@ -518,7 +520,8 @@ class InferenceRuleManager(base.CrudManager): """ url_tail = ('/%s/implies' % base.getid(prior_role)) _resp, body = self.client.get("/roles" + url_tail) - return self.resource_class(self, body['role_inference']) + return self._prepare_return_value( + _resp, self.resource_class(self, body['role_inference'])) def check(self, prior_role, implied_role): """Check if an inference rule exists. @@ -538,7 +541,7 @@ class InferenceRuleManager(base.CrudManager): """ url_tail = self._implied_role_url_tail(prior_role, implied_role) - return self.client.head("/roles" + url_tail) + return self._head("/roles" + url_tail) def list_inference_roles(self): """List all rule inferences. diff --git a/releasenotes/notes/return-request-id-to-caller-97fa269ad626f8c1.yaml b/releasenotes/notes/return-request-id-to-caller-97fa269ad626f8c1.yaml index f1d4dbf72..8ef4701db 100644 --- a/releasenotes/notes/return-request-id-to-caller-97fa269ad626f8c1.yaml +++ b/releasenotes/notes/return-request-id-to-caller-97fa269ad626f8c1.yaml @@ -3,5 +3,11 @@ features: - > [`blueprint return-request-id-to-caller `_] - Added support to return "x-openstack-request-id" header in request_ids attribute - for better tracing. + Instantiating client with ``include_metadata=True`` will cause manager response to return data + along with request_ids for better tracing. Refer [`using-api-v3 + `_] + + + Added support to return "x-openstack-request-id" header in request_ids attribute if + ``include_metadata=True``. Also, for APIs which return response as None, client will return request_ids + as well if ``include_metadata`` is True. \ No newline at end of file