Merge remote-tracking branch 'origin/feature/keystone-v3' into HEAD
Conflicts: tests/v2_0/test_tenants.py Change-Id: I37037e60210edd574da86b1dc07aa73e6761e338
This commit is contained in:
		| @@ -18,6 +18,8 @@ | ||||
| Base utilities to build API operation managers and objects on top of. | ||||
| """ | ||||
|  | ||||
| import urllib | ||||
|  | ||||
| from keystoneclient import exceptions | ||||
|  | ||||
|  | ||||
| @@ -76,20 +78,25 @@ class Manager(object): | ||||
|  | ||||
|     def _get(self, url, response_key): | ||||
|         resp, body = self.api.get(url) | ||||
|         return self.resource_class(self, body[response_key]) | ||||
|         return self.resource_class(self, body[response_key], loaded=True) | ||||
|  | ||||
|     def _head(self, url): | ||||
|         resp, body = self.api.head(url) | ||||
|         return resp.status == 204 | ||||
|  | ||||
|     def _create(self, url, body, response_key, return_raw=False): | ||||
|         resp, body = self.api.post(url, body=body) | ||||
|         if return_raw: | ||||
|             return body[response_key] | ||||
|         return self.resource_class(self, body[response_key]) | ||||
|         return self.resource_class(self, body[response_key], loaded=True) | ||||
|  | ||||
|     def _delete(self, url): | ||||
|         resp, body = self.api.delete(url) | ||||
|  | ||||
|     def _update(self, url, body, response_key=None, method="PUT"): | ||||
|     def _update(self, url, body=None, response_key=None, method="PUT"): | ||||
|         methods = {"PUT": self.api.put, | ||||
|                    "POST": self.api.post} | ||||
|                    "POST": self.api.post, | ||||
|                    "PATCH": self.api.patch} | ||||
|         try: | ||||
|             if body is not None: | ||||
|                 resp, body = methods[method](url, body=body) | ||||
| @@ -100,7 +107,7 @@ class Manager(object): | ||||
|                                              % method) | ||||
|         # PUT requests may not return a body | ||||
|         if body: | ||||
|             return self.resource_class(self, body[response_key]) | ||||
|             return self.resource_class(self, body[response_key], loaded=True) | ||||
|  | ||||
|  | ||||
| class ManagerWithFind(Manager): | ||||
| @@ -142,6 +149,115 @@ class ManagerWithFind(Manager): | ||||
|         return found | ||||
|  | ||||
|  | ||||
| class CrudManager(Manager): | ||||
|     """Base manager class for manipulating Keystone entities. | ||||
|  | ||||
|     Children of this class are expected to define a `collection_key` and `key`. | ||||
|  | ||||
|     - `collection_key`: Usually a plural noun by convention (e.g. `entities`); | ||||
|       used to refer collections in both URL's (e.g.  `/v3/entities`) and JSON | ||||
|       objects containing a list of member resources (e.g. `{'entities': [{}, | ||||
|       {}, {}]}`). | ||||
|     - `key`: Usually a singular noun by convention (e.g. `entity`); used to | ||||
|       refer to an individual member of the collection. | ||||
|  | ||||
|     """ | ||||
|     collection_key = None | ||||
|     key = None | ||||
|  | ||||
|     def build_url(self, base_url=None, **kwargs): | ||||
|         """Builds a resource URL for the given kwargs. | ||||
|  | ||||
|         Given an example collection where `collection_key = 'entities'` and | ||||
|         `key = 'entity'`, the following URL's could be generated. | ||||
|  | ||||
|         By default, the URL will represent a collection of entities, e.g.:: | ||||
|  | ||||
|             /entities | ||||
|  | ||||
|         If kwargs contains an `entity_id`, then the URL will represent a | ||||
|         specific member, e.g.:: | ||||
|  | ||||
|             /entities/{entity_id} | ||||
|  | ||||
|         If a `base_url` is provided, the generated URL will be appended to it. | ||||
|  | ||||
|         """ | ||||
|         url = base_url if base_url is not None else '' | ||||
|  | ||||
|         url += '/%s' % self.collection_key | ||||
|  | ||||
|         # do we have a specific entity? | ||||
|         entity_id = kwargs.get('%s_id' % self.key) | ||||
|         if entity_id is not None: | ||||
|             url += '/%s' % entity_id | ||||
|  | ||||
|         return url | ||||
|  | ||||
|     def _filter_kwargs(self, kwargs): | ||||
|         # drop null values | ||||
|         for key, ref in kwargs.copy().iteritems(): | ||||
|             if ref is None: | ||||
|                 kwargs.pop(key) | ||||
|             else: | ||||
|                 id_value = getid(ref) | ||||
|                 if id_value != ref: | ||||
|                     kwargs.pop(key) | ||||
|                     kwargs['%s_id' % key] = id_value | ||||
|         return kwargs | ||||
|  | ||||
|     def create(self, **kwargs): | ||||
|         kwargs = self._filter_kwargs(kwargs) | ||||
|         return self._create( | ||||
|             self.build_url(**kwargs), | ||||
|             {self.key: kwargs}, | ||||
|             self.key) | ||||
|  | ||||
|     def get(self, **kwargs): | ||||
|         kwargs = self._filter_kwargs(kwargs) | ||||
|         return self._get( | ||||
|             self.build_url(**kwargs), | ||||
|             self.key) | ||||
|  | ||||
|     def head(self, **kwargs): | ||||
|         kwargs = self._filter_kwargs(kwargs) | ||||
|         return self._head(self.build_url(**kwargs)) | ||||
|  | ||||
|     def list(self, base_url=None, **kwargs): | ||||
|         kwargs = self._filter_kwargs(kwargs) | ||||
|  | ||||
|         return self._list( | ||||
|             '%(base_url)s%(query)s' % { | ||||
|                 'base_url': self.build_url(base_url=base_url, **kwargs), | ||||
|                 'query': '?%s' % urllib.urlencode(kwargs) if kwargs else '', | ||||
|             }, | ||||
|             self.collection_key) | ||||
|  | ||||
|     def put(self, base_url=None, **kwargs): | ||||
|         kwargs = self._filter_kwargs(kwargs) | ||||
|  | ||||
|         return self._update( | ||||
|             self.build_url(base_url=base_url, **kwargs), | ||||
|             method='PUT') | ||||
|  | ||||
|     def update(self, **kwargs): | ||||
|         kwargs = self._filter_kwargs(kwargs) | ||||
|         params = kwargs.copy() | ||||
|         params.pop('%s_id' % self.key) | ||||
|  | ||||
|         return self._update( | ||||
|             self.build_url(**kwargs), | ||||
|             {self.key: params}, | ||||
|             self.key, | ||||
|             method='PATCH') | ||||
|  | ||||
|     def delete(self, **kwargs): | ||||
|         kwargs = self._filter_kwargs(kwargs) | ||||
|  | ||||
|         return self._delete( | ||||
|             self.build_url(**kwargs)) | ||||
|  | ||||
|  | ||||
| class Resource(object): | ||||
|     """ | ||||
|     A resource represents a particular instance of an object (tenant, user, | ||||
| @@ -188,6 +304,9 @@ class Resource(object): | ||||
|         if new: | ||||
|             self._add_details(new._info) | ||||
|  | ||||
|     def delete(self): | ||||
|         return self.manager.delete(self) | ||||
|  | ||||
|     def __eq__(self, other): | ||||
|         if not isinstance(other, self.__class__): | ||||
|             return False | ||||
|   | ||||
| @@ -108,6 +108,9 @@ class HTTPClient(httplib2.Http): | ||||
|         if self.debug_log: | ||||
|             _logger.debug("RESP: %s\nRESP BODY: %s\n", resp, body) | ||||
|  | ||||
|     def serialize(self, entity): | ||||
|         return json.dumps(entity) | ||||
|  | ||||
|     def request(self, url, method, **kwargs): | ||||
|         """ Send an http request with the specified characteristics. | ||||
|  | ||||
| @@ -123,7 +126,7 @@ class HTTPClient(httplib2.Http): | ||||
|                 self.original_ip, self.USER_AGENT) | ||||
|         if 'body' in kwargs: | ||||
|             request_kwargs['headers']['Content-Type'] = 'application/json' | ||||
|             request_kwargs['body'] = json.dumps(kwargs['body']) | ||||
|             request_kwargs['body'] = self.serialize(kwargs['body']) | ||||
|  | ||||
|         self.http_log_req((url, method,), request_kwargs) | ||||
|         resp, body = super(HTTPClient, self).request(url, | ||||
| @@ -180,11 +183,17 @@ class HTTPClient(httplib2.Http): | ||||
|     def get(self, url, **kwargs): | ||||
|         return self._cs_request(url, 'GET', **kwargs) | ||||
|  | ||||
|     def head(self, url, **kwargs): | ||||
|         return self._cs_request(url, 'HEAD', **kwargs) | ||||
|  | ||||
|     def post(self, url, **kwargs): | ||||
|         return self._cs_request(url, 'POST', **kwargs) | ||||
|  | ||||
|     def put(self, url, **kwargs): | ||||
|         return self._cs_request(url, 'PUT', **kwargs) | ||||
|  | ||||
|     def patch(self, url, **kwargs): | ||||
|         return self._cs_request(url, 'PATCH', **kwargs) | ||||
|  | ||||
|     def delete(self, url, **kwargs): | ||||
|         return self._cs_request(url, 'DELETE', **kwargs) | ||||
|   | ||||
| @@ -9,6 +9,10 @@ class CommandError(Exception): | ||||
|     pass | ||||
|  | ||||
|  | ||||
| class ValidationError(Exception): | ||||
|     pass | ||||
|  | ||||
|  | ||||
| class AuthorizationFailure(Exception): | ||||
|     pass | ||||
|  | ||||
|   | ||||
							
								
								
									
										1
									
								
								keystoneclient/v3/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								keystoneclient/v3/__init__.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| from keystoneclient.v3.client import Client | ||||
							
								
								
									
										85
									
								
								keystoneclient/v3/client.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								keystoneclient/v3/client.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,85 @@ | ||||
| # Copyright 2011 Nebula, Inc. | ||||
| # All Rights Reserved. | ||||
| # | ||||
| #    Licensed under the Apache License, Version 2.0 (the "License"); you may | ||||
| #    not use this file except in compliance with the License. You may obtain | ||||
| #    a copy of the License at | ||||
| # | ||||
| #         http://www.apache.org/licenses/LICENSE-2.0 | ||||
| # | ||||
| #    Unless required by applicable law or agreed to in writing, software | ||||
| #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||||
| #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||||
| #    License for the specific language governing permissions and limitations | ||||
| #    under the License. | ||||
| import json | ||||
| import logging | ||||
|  | ||||
| from keystoneclient.v2_0 import client | ||||
| from keystoneclient.v3 import credentials | ||||
| from keystoneclient.v3 import endpoints | ||||
| from keystoneclient.v3 import domains | ||||
| from keystoneclient.v3 import policies | ||||
| from keystoneclient.v3 import projects | ||||
| from keystoneclient.v3 import roles | ||||
| from keystoneclient.v3 import services | ||||
| from keystoneclient.v3 import users | ||||
|  | ||||
|  | ||||
| _logger = logging.getLogger(__name__) | ||||
|  | ||||
|  | ||||
| class Client(client.Client): | ||||
|     """Client for the OpenStack Identity API v3. | ||||
|  | ||||
|     :param string username: Username for authentication. (optional) | ||||
|     :param string password: Password for authentication. (optional) | ||||
|     :param string token: Token for authentication. (optional) | ||||
|     :param string tenant_name: Tenant id. (optional) | ||||
|     :param string tenant_id: Tenant name. (optional) | ||||
|     :param string auth_url: Keystone service endpoint for authorization. | ||||
|     :param string region_name: Name of a region to select when choosing an | ||||
|                                endpoint from the service catalog. | ||||
|     :param string endpoint: A user-supplied endpoint URL for the keystone | ||||
|                             service.  Lazy-authentication is possible for API | ||||
|                             service calls if endpoint is set at | ||||
|                             instantiation.(optional) | ||||
|     :param integer timeout: Allows customization of the timeout for client | ||||
|                             http requests. (optional) | ||||
|  | ||||
|     Example:: | ||||
|  | ||||
|         >>> from keystoneclient.v3 import client | ||||
|         >>> keystone = client.Client(username=USER, | ||||
|                                      password=PASS, | ||||
|                                      tenant_name=TENANT_NAME, | ||||
|                                      auth_url=KEYSTONE_URL) | ||||
|         >>> keystone.tenants.list() | ||||
|         ... | ||||
|         >>> user = keystone.users.get(USER_ID) | ||||
|         >>> user.delete() | ||||
|  | ||||
|     """ | ||||
|  | ||||
|     def __init__(self, endpoint=None, **kwargs): | ||||
|         """ Initialize a new client for the Keystone v2.0 API. """ | ||||
|         super(Client, self).__init__(endpoint=endpoint, **kwargs) | ||||
|  | ||||
|         self.credentials = credentials.CredentialManager(self) | ||||
|         self.endpoints = endpoints.EndpointManager(self) | ||||
|         self.domains = domains.DomainManager(self) | ||||
|         self.policies = policies.PolicyManager(self) | ||||
|         self.projects = projects.ProjectManager(self) | ||||
|         self.roles = roles.RoleManager(self) | ||||
|         self.services = services.ServiceManager(self) | ||||
|         self.users = users.UserManager(self) | ||||
|  | ||||
|         # NOTE(gabriel): If we have a pre-defined endpoint then we can | ||||
|         #                get away with lazy auth. Otherwise auth immediately. | ||||
|         if endpoint: | ||||
|             self.management_url = endpoint | ||||
|         else: | ||||
|             self.authenticate() | ||||
|  | ||||
|     def serialize(self, entity): | ||||
|         return json.dumps(entity, sort_keys=True) | ||||
							
								
								
									
										57
									
								
								keystoneclient/v3/credentials.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								keystoneclient/v3/credentials.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| # Copyright 2011 OpenStack LLC. | ||||
| # Copyright 2011 Nebula, Inc. | ||||
| # All Rights Reserved. | ||||
| # | ||||
| #    Licensed under the Apache License, Version 2.0 (the "License"); you may | ||||
| #    not use this file except in compliance with the License. You may obtain | ||||
| #    a copy of the License at | ||||
| # | ||||
| #         http://www.apache.org/licenses/LICENSE-2.0 | ||||
| # | ||||
| #    Unless required by applicable law or agreed to in writing, software | ||||
| #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||||
| #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||||
| #    License for the specific language governing permissions and limitations | ||||
| #    under the License. | ||||
|  | ||||
| from keystoneclient import base | ||||
|  | ||||
|  | ||||
| class Credential(base.Resource): | ||||
|     """Represents an Identity credential. | ||||
|  | ||||
|     Attributes: | ||||
|         * id: a uuid that identifies the credential | ||||
|  | ||||
|     """ | ||||
|     pass | ||||
|  | ||||
|  | ||||
| class CredentialManager(base.CrudManager): | ||||
|     """Manager class for manipulating Identity credentials.""" | ||||
|     resource_class = Credential | ||||
|     collection_key = 'credentials' | ||||
|     key = 'credential' | ||||
|  | ||||
|     def create(self, user, type, data, project=None): | ||||
|         return super(CredentialManager, self).create( | ||||
|             user_id=base.getid(user), | ||||
|             type=type, | ||||
|             data=data, | ||||
|             project_id=base.getid(project)) | ||||
|  | ||||
|     def get(self, credential): | ||||
|         return super(CredentialManager, self).get( | ||||
|             credential_id=base.getid(credential)) | ||||
|  | ||||
|     def update(self, credential, user, type=None, data=None, project=None): | ||||
|         return super(CredentialManager, self).update( | ||||
|             credential_id=base.getid(credential), | ||||
|             user_id=base.getid(user), | ||||
|             type=type, | ||||
|             data=data, | ||||
|             project_id=base.getid(project)) | ||||
|  | ||||
|     def delete(self, credential): | ||||
|         return super(CredentialManager, self).delete( | ||||
|             credential_id=base.getid(credential)) | ||||
							
								
								
									
										55
									
								
								keystoneclient/v3/domains.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								keystoneclient/v3/domains.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,55 @@ | ||||
| # Copyright 2011 OpenStack LLC. | ||||
| # Copyright 2011 Nebula, Inc. | ||||
| # All Rights Reserved. | ||||
| # | ||||
| #    Licensed under the Apache License, Version 2.0 (the "License"); you may | ||||
| #    not use this file except in compliance with the License. You may obtain | ||||
| #    a copy of the License at | ||||
| # | ||||
| #         http://www.apache.org/licenses/LICENSE-2.0 | ||||
| # | ||||
| #    Unless required by applicable law or agreed to in writing, software | ||||
| #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||||
| #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||||
| #    License for the specific language governing permissions and limitations | ||||
| #    under the License. | ||||
|  | ||||
| from keystoneclient import base | ||||
|  | ||||
|  | ||||
| class Domain(base.Resource): | ||||
|     """Represents an Identity domain. | ||||
|  | ||||
|     Attributes: | ||||
|         * id: a uuid that identifies the domain | ||||
|  | ||||
|     """ | ||||
|     pass | ||||
|  | ||||
|  | ||||
| class DomainManager(base.CrudManager): | ||||
|     """Manager class for manipulating Identity domains.""" | ||||
|     resource_class = Domain | ||||
|     collection_key = 'domains' | ||||
|     key = 'domain' | ||||
|  | ||||
|     def create(self, name, description=None, enabled=True): | ||||
|         return super(DomainManager, self).create( | ||||
|             name=name, | ||||
|             description=description, | ||||
|             enabled=enabled) | ||||
|  | ||||
|     def get(self, domain): | ||||
|         return super(DomainManager, self).get( | ||||
|             domain_id=base.getid(domain)) | ||||
|  | ||||
|     def update(self, domain, name=None, description=None, enabled=None): | ||||
|         return super(DomainManager, self).update( | ||||
|             domain_id=base.getid(domain), | ||||
|             name=name, | ||||
|             description=description, | ||||
|             enabled=enabled) | ||||
|  | ||||
|     def delete(self, domain): | ||||
|         return super(DomainManager, self).delete( | ||||
|             domain_id=base.getid(domain)) | ||||
							
								
								
									
										86
									
								
								keystoneclient/v3/endpoints.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								keystoneclient/v3/endpoints.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,86 @@ | ||||
| # Copyright 2011 OpenStack LLC. | ||||
| # Copyright 2011 Nebula, Inc. | ||||
| # All Rights Reserved. | ||||
| # | ||||
| #    Licensed under the Apache License, Version 2.0 (the "License"); you may | ||||
| #    not use this file except in compliance with the License. You may obtain | ||||
| #    a copy of the License at | ||||
| # | ||||
| #         http://www.apache.org/licenses/LICENSE-2.0 | ||||
| # | ||||
| #    Unless required by applicable law or agreed to in writing, software | ||||
| #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||||
| #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||||
| #    License for the specific language governing permissions and limitations | ||||
| #    under the License. | ||||
|  | ||||
| from keystoneclient import base | ||||
|  | ||||
|  | ||||
| VALID_INTERFACES = ['public', 'admin', 'internal'] | ||||
|  | ||||
|  | ||||
| class Endpoint(base.Resource): | ||||
|     """Represents an Identity endpoint. | ||||
|  | ||||
|     Attributes: | ||||
|         * id: a uuid that identifies the endpoint | ||||
|         * interface: 'public', 'admin' or 'internal' network interface | ||||
|         * region: geographic location of the endpoint | ||||
|         * service_id: service to which the endpoint belongs | ||||
|         * url: fully qualified service endpoint | ||||
|         * enabled: determines whether the endpoint appears in the catalog | ||||
|  | ||||
|     """ | ||||
|     pass | ||||
|  | ||||
|  | ||||
| class EndpointManager(base.CrudManager): | ||||
|     """Manager class for manipulating Identity endpoints.""" | ||||
|     resource_class = Endpoint | ||||
|     collection_key = 'endpoints' | ||||
|     key = 'endpoint' | ||||
|  | ||||
|     def _validate_interface(self, interface): | ||||
|         if interface is not None and interface not in VALID_INTERFACES: | ||||
|             msg = '"interface" must be one of: %s' | ||||
|             msg = msg % ', '.join(VALID_INTERFACES) | ||||
|             raise Exception(msg) | ||||
|  | ||||
|     def create(self, service, url, name=None, interface=None, region=None, | ||||
|                enabled=True): | ||||
|         self._validate_interface(interface) | ||||
|         return super(EndpointManager, self).create( | ||||
|             service_id=base.getid(service), | ||||
|             interface=interface, | ||||
|             url=url, | ||||
|             region=region, | ||||
|             enabled=enabled) | ||||
|  | ||||
|     def get(self, endpoint): | ||||
|         return super(EndpointManager, self).get( | ||||
|             endpoint_id=base.getid(endpoint)) | ||||
|  | ||||
|     def list(self, service=None, name=None, interface=None, region=None, | ||||
|              enabled=None): | ||||
|         self._validate_interface(interface) | ||||
|         return super(EndpointManager, self).list( | ||||
|             service_id=base.getid(service), | ||||
|             interface=interface, | ||||
|             region=region, | ||||
|             enabled=enabled) | ||||
|  | ||||
|     def update(self, endpoint, service=None, url=None, name=None, | ||||
|                interface=None, region=None, enabled=None): | ||||
|         self._validate_interface(interface) | ||||
|         return super(EndpointManager, self).update( | ||||
|             endpoint_id=base.getid(endpoint), | ||||
|             service_id=base.getid(service), | ||||
|             interface=interface, | ||||
|             url=url, | ||||
|             region=region, | ||||
|             enabled=enabled) | ||||
|  | ||||
|     def delete(self, endpoint): | ||||
|         return super(EndpointManager, self).delete( | ||||
|             endpoint_id=base.getid(endpoint)) | ||||
							
								
								
									
										77
									
								
								keystoneclient/v3/policies.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								keystoneclient/v3/policies.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,77 @@ | ||||
| # Copyright 2011 OpenStack LLC. | ||||
| # Copyright 2011 Nebula, Inc. | ||||
| # All Rights Reserved. | ||||
| # | ||||
| #    Licensed under the Apache License, Version 2.0 (the "License"); you may | ||||
| #    not use this file except in compliance with the License. You may obtain | ||||
| #    a copy of the License at | ||||
| # | ||||
| #         http://www.apache.org/licenses/LICENSE-2.0 | ||||
| # | ||||
| #    Unless required by applicable law or agreed to in writing, software | ||||
| #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||||
| #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||||
| #    License for the specific language governing permissions and limitations | ||||
| #    under the License. | ||||
|  | ||||
| from keystoneclient import base | ||||
|  | ||||
|  | ||||
| class Policy(base.Resource): | ||||
|     """Represents an Identity policy. | ||||
|  | ||||
|     Attributes: | ||||
|         * id: a uuid that identifies the policy | ||||
|         * endpoint_id: references the endpoint the policy applies to | ||||
|         * blob: a policy document (blob) | ||||
|         * type: the mime type of the policy blob | ||||
|  | ||||
|     """ | ||||
|     def update(self, endpoint=None, blob=None, type=None): | ||||
|         kwargs = { | ||||
|             'endpoint_id': (base.getid(endpoint) | ||||
|                             if endpoint is not None | ||||
|                             else self.endpoint_id), | ||||
|             'blob': blob if blob is not None else self.blob, | ||||
|             'type': type if type is not None else self.type, | ||||
|         } | ||||
|  | ||||
|         try: | ||||
|             retval = self.manager.update(self.id, **kwargs) | ||||
|             self = retval | ||||
|         except Exception: | ||||
|             retval = None | ||||
|  | ||||
|         return retval | ||||
|  | ||||
|  | ||||
| class PolicyManager(base.CrudManager): | ||||
|     """Manager class for manipulating Identity policies.""" | ||||
|     resource_class = Policy | ||||
|     collection_key = 'policies' | ||||
|     key = 'policy' | ||||
|  | ||||
|     def create(self, endpoint, blob, type='application/json'): | ||||
|         return super(PolicyManager, self).create( | ||||
|             endpoint_id=base.getid(endpoint), | ||||
|             blob=blob, | ||||
|             type=type) | ||||
|  | ||||
|     def get(self, policy): | ||||
|         return super(PolicyManager, self).get( | ||||
|             policy_id=base.getid(policy)) | ||||
|  | ||||
|     def list(self, endpoint=None): | ||||
|         return super(PolicyManager, self).list( | ||||
|             endpoint_id=base.getid(endpoint)) | ||||
|  | ||||
|     def update(self, entity, endpoint=None, blob=None, type=None): | ||||
|         return super(PolicyManager, self).update( | ||||
|             policy_id=base.getid(entity), | ||||
|             endpoint_id=base.getid(endpoint), | ||||
|             blob=blob, | ||||
|             type=type) | ||||
|  | ||||
|     def delete(self, policy): | ||||
|         return super(PolicyManager, self).delete( | ||||
|             policy_id=base.getid(policy)) | ||||
							
								
								
									
										82
									
								
								keystoneclient/v3/projects.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								keystoneclient/v3/projects.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,82 @@ | ||||
| # Copyright 2011 OpenStack LLC. | ||||
| # Copyright 2011 Nebula, Inc. | ||||
| # All Rights Reserved. | ||||
| # | ||||
| #    Licensed under the Apache License, Version 2.0 (the "License"); you may | ||||
| #    not use this file except in compliance with the License. You may obtain | ||||
| #    a copy of the License at | ||||
| # | ||||
| #         http://www.apache.org/licenses/LICENSE-2.0 | ||||
| # | ||||
| #    Unless required by applicable law or agreed to in writing, software | ||||
| #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||||
| #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||||
| #    License for the specific language governing permissions and limitations | ||||
| #    under the License. | ||||
|  | ||||
| from keystoneclient import base | ||||
|  | ||||
|  | ||||
| class Project(base.Resource): | ||||
|     """Represents an Identity project. | ||||
|  | ||||
|     Attributes: | ||||
|         * id: a uuid that identifies the project | ||||
|         * name: project name | ||||
|         * description: project description | ||||
|         * enabled: boolean to indicate if project is enabled | ||||
|  | ||||
|     """ | ||||
|     def update(self, name=None, description=None, enabled=None): | ||||
|         kwargs = { | ||||
|             'name': name if name is not None else self.name, | ||||
|             'description': (description | ||||
|                             if description is not None | ||||
|                             else self.description), | ||||
|             'enabled': enabled if enabled is not None else self.enabled, | ||||
|         } | ||||
|  | ||||
|         try: | ||||
|             retval = self.manager.update(self.id, **kwargs) | ||||
|             self = retval | ||||
|         except Exception: | ||||
|             retval = None | ||||
|  | ||||
|         return retval | ||||
|  | ||||
|  | ||||
| class ProjectManager(base.CrudManager): | ||||
|     """Manager class for manipulating Identity projects.""" | ||||
|     resource_class = Project | ||||
|     collection_key = 'projects' | ||||
|     key = 'project' | ||||
|  | ||||
|     def create(self, name, domain, description=None, enabled=True): | ||||
|         return super(ProjectManager, self).create( | ||||
|             domain_id=base.getid(domain), | ||||
|             name=name, | ||||
|             description=description, | ||||
|             enabled=enabled) | ||||
|  | ||||
|     def list(self, domain=None, user=None): | ||||
|         base_url = '/users/%s' % base.getid(user) if user else None | ||||
|         return super(ProjectManager, self).list( | ||||
|             base_url=base_url, | ||||
|             domain_id=base.getid(domain)) | ||||
|  | ||||
|     def get(self, project): | ||||
|         return super(ProjectManager, self).get( | ||||
|             project_id=base.getid(project)) | ||||
|  | ||||
|     def update(self, project, name=None, domain=None, description=None, | ||||
|                enabled=None): | ||||
|         return super(ProjectManager, self).update( | ||||
|             project_id=base.getid(project), | ||||
|             domain_id=base.getid(domain), | ||||
|             name=name, | ||||
|             description=description, | ||||
|             enabled=enabled) | ||||
|  | ||||
|     def delete(self, project): | ||||
|         return super(ProjectManager, self).delete( | ||||
|             project_id=base.getid(project)) | ||||
							
								
								
									
										110
									
								
								keystoneclient/v3/roles.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								keystoneclient/v3/roles.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,110 @@ | ||||
| # Copyright 2011 OpenStack LLC. | ||||
| # Copyright 2011 Nebula, Inc. | ||||
| # All Rights Reserved. | ||||
| # | ||||
| #    Licensed under the Apache License, Version 2.0 (the "License"); you may | ||||
| #    not use this file except in compliance with the License. You may obtain | ||||
| #    a copy of the License at | ||||
| # | ||||
| #         http://www.apache.org/licenses/LICENSE-2.0 | ||||
| # | ||||
| #    Unless required by applicable law or agreed to in writing, software | ||||
| #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||||
| #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||||
| #    License for the specific language governing permissions and limitations | ||||
| #    under the License. | ||||
|  | ||||
| from keystoneclient import base | ||||
| from keystoneclient import exceptions | ||||
|  | ||||
|  | ||||
| class Role(base.Resource): | ||||
|     """Represents an Identity role. | ||||
|  | ||||
|     Attributes: | ||||
|         * id: a uuid that identifies the role | ||||
|         * name: user-facing identifier | ||||
|  | ||||
|     """ | ||||
|     pass | ||||
|  | ||||
|  | ||||
| class RoleManager(base.CrudManager): | ||||
|     """Manager class for manipulating Identity roles.""" | ||||
|     resource_class = Role | ||||
|     collection_key = 'roles' | ||||
|     key = 'role' | ||||
|  | ||||
|     def _role_grants_base_url(self, user, domain, project): | ||||
|         params = {'user_id': base.getid(user)} | ||||
|  | ||||
|         if domain: | ||||
|             params['domain_id'] = base.getid(domain) | ||||
|             base_url = '/domains/%(domain_id)s/users/%(user_id)s' | ||||
|         elif project: | ||||
|             params['project_id'] = base.getid(project) | ||||
|             base_url = '/projects/%(project_id)s/users/%(user_id)s' | ||||
|  | ||||
|         return base_url % params | ||||
|  | ||||
|     def _require_domain_or_project(self, domain, project): | ||||
|         if (domain and project) or (not domain and not project): | ||||
|             msg = 'Specify either a domain or project, not both' | ||||
|             raise exceptions.ValidationError(msg) | ||||
|  | ||||
|     def create(self, name): | ||||
|         return super(RoleManager, self).create( | ||||
|             name=name) | ||||
|  | ||||
|     def get(self, role): | ||||
|         return super(RoleManager, self).get( | ||||
|             role_id=base.getid(role)) | ||||
|  | ||||
|     def list(self, user=None, domain=None, project=None): | ||||
|         """Lists roles and role grants. | ||||
|  | ||||
|         If no arguments are provided, all roles in the system will be listed. | ||||
|  | ||||
|         If a user is specified, you must also specify either a domain or | ||||
|         project to list role grants on that pair. | ||||
|         """ | ||||
|  | ||||
|         if user: | ||||
|             self._require_domain_or_project(domain, project) | ||||
|             return super(RoleManager, self).list( | ||||
|                 base_url=self._role_grants_base_url(user, domain, project)) | ||||
|  | ||||
|         return super(RoleManager, self).list() | ||||
|  | ||||
|     def update(self, role, name=None): | ||||
|         return super(RoleManager, self).update( | ||||
|             role_id=base.getid(role), | ||||
|             name=name) | ||||
|  | ||||
|     def delete(self, role): | ||||
|         return super(RoleManager, self).delete( | ||||
|             role_id=base.getid(role)) | ||||
|  | ||||
|     def grant(self, role, user, domain=None, project=None): | ||||
|         """Grants a role to a user on either a domain or project.""" | ||||
|         self._require_domain_or_project(domain, project) | ||||
|  | ||||
|         return super(RoleManager, self).put( | ||||
|             base_url=self._role_grants_base_url(user, domain, project), | ||||
|             role_id=base.getid(role)) | ||||
|  | ||||
|     def check(self, role, user, domain=None, project=None): | ||||
|         """Grants a role to a user on either a domain or project.""" | ||||
|         self._require_domain_or_project(domain, project) | ||||
|  | ||||
|         return super(RoleManager, self).head( | ||||
|             base_url=self._role_grants_base_url(user, domain, project), | ||||
|             role_id=base.getid(role)) | ||||
|  | ||||
|     def revoke(self, role, user, domain=None, project=None): | ||||
|         """Revokes a role from a user on either a domain or project.""" | ||||
|         self._require_domain_or_project(domain, project) | ||||
|  | ||||
|         return super(RoleManager, self).delete( | ||||
|             base_url=self._role_grants_base_url(user, domain, project), | ||||
|             role_id=base.getid(role)) | ||||
							
								
								
									
										60
									
								
								keystoneclient/v3/services.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								keystoneclient/v3/services.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | ||||
| # Copyright 2011 OpenStack LLC. | ||||
| # Copyright 2011 Nebula, Inc. | ||||
| # All Rights Reserved. | ||||
| # | ||||
| #    Licensed under the Apache License, Version 2.0 (the "License"); you may | ||||
| #    not use this file except in compliance with the License. You may obtain | ||||
| #    a copy of the License at | ||||
| # | ||||
| #         http://www.apache.org/licenses/LICENSE-2.0 | ||||
| # | ||||
| #    Unless required by applicable law or agreed to in writing, software | ||||
| #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||||
| #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||||
| #    License for the specific language governing permissions and limitations | ||||
| #    under the License. | ||||
|  | ||||
| from keystoneclient import base | ||||
|  | ||||
|  | ||||
| class Service(base.Resource): | ||||
|     """Represents an Identity service. | ||||
|  | ||||
|     Attributes: | ||||
|         * id: a uuid that identifies the service | ||||
|         * name: user-facing name of the service (e.g. Keystone) | ||||
|         * type: 'compute', 'identity', etc | ||||
|         * enabled: determines whether the service appears in the catalog | ||||
|  | ||||
|     """ | ||||
|     pass | ||||
|  | ||||
|  | ||||
| class ServiceManager(base.CrudManager): | ||||
|     """Manager class for manipulating Identity services.""" | ||||
|     resource_class = Service | ||||
|     collection_key = 'services' | ||||
|     key = 'service' | ||||
|  | ||||
|     def create(self, name, type, enabled=True, **kwargs): | ||||
|         return super(ServiceManager, self).create( | ||||
|             name=name, | ||||
|             type=type, | ||||
|             enabled=enabled, | ||||
|             **kwargs) | ||||
|  | ||||
|     def get(self, service): | ||||
|         return super(ServiceManager, self).get( | ||||
|             service_id=base.getid(service)) | ||||
|  | ||||
|     def update(self, service, name=None, type=None, enabled=None, **kwargs): | ||||
|         return super(ServiceManager, self).update( | ||||
|             service_id=base.getid(service), | ||||
|             name=name, | ||||
|             type=type, | ||||
|             enabled=enabled, | ||||
|             **kwargs) | ||||
|  | ||||
|     def delete(self, service): | ||||
|         return super(ServiceManager, self).delete( | ||||
|             service_id=base.getid(service)) | ||||
							
								
								
									
										70
									
								
								keystoneclient/v3/users.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								keystoneclient/v3/users.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | ||||
| # Copyright 2011 OpenStack LLC. | ||||
| # Copyright 2011 Nebula, Inc. | ||||
| # All Rights Reserved. | ||||
| # | ||||
| #    Licensed under the Apache License, Version 2.0 (the "License"); you may | ||||
| #    not use this file except in compliance with the License. You may obtain | ||||
| #    a copy of the License at | ||||
| # | ||||
| #         http://www.apache.org/licenses/LICENSE-2.0 | ||||
| # | ||||
| #    Unless required by applicable law or agreed to in writing, software | ||||
| #    distributed under the License is distributed on an "AS IS" BASIS, WITHOUT | ||||
| #    WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the | ||||
| #    License for the specific language governing permissions and limitations | ||||
| #    under the License. | ||||
|  | ||||
| from keystoneclient import base | ||||
|  | ||||
|  | ||||
| class User(base.Resource): | ||||
|     """Represents an Identity user. | ||||
|  | ||||
|     Attributes: | ||||
|         * id: a uuid that identifies the user | ||||
|  | ||||
|     """ | ||||
|     pass | ||||
|  | ||||
|  | ||||
| class UserManager(base.CrudManager): | ||||
|     """Manager class for manipulating Identity users.""" | ||||
|     resource_class = User | ||||
|     collection_key = 'users' | ||||
|     key = 'user' | ||||
|  | ||||
|     def create(self, name, domain=None, project=None, password=None, | ||||
|                email=None, description=None, enabled=True): | ||||
|         return super(UserManager, self).create( | ||||
|             name=name, | ||||
|             domain_id=base.getid(domain), | ||||
|             project_id=base.getid(project), | ||||
|             password=password, | ||||
|             email=email, | ||||
|             description=description, | ||||
|             enabled=enabled) | ||||
|  | ||||
|     def list(self, project=None, domain=None): | ||||
|         return super(UserManager, self).list( | ||||
|             domain_id=base.getid(domain), | ||||
|             project_id=base.getid(project)) | ||||
|  | ||||
|     def get(self, user): | ||||
|         return super(UserManager, self).get( | ||||
|             user_id=base.getid(user)) | ||||
|  | ||||
|     def update(self, user, name=None, domain=None, project=None, password=None, | ||||
|                email=None, description=None, enabled=None): | ||||
|         return super(UserManager, self).update( | ||||
|             user_id=base.getid(user), | ||||
|             name=name, | ||||
|             domain_id=base.getid(domain), | ||||
|             project_id=base.getid(project), | ||||
|             password=password, | ||||
|             email=email, | ||||
|             description=description, | ||||
|             enabled=enabled) | ||||
|  | ||||
|     def delete(self, user): | ||||
|         return super(UserManager, self).delete( | ||||
|             user_id=base.getid(user)) | ||||
							
								
								
									
										0
									
								
								tests/v3/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										0
									
								
								tests/v3/__init__.py
									
									
									
									
									
										Normal file
									
								
							
							
								
								
									
										22
									
								
								tests/v3/test_credentials.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								tests/v3/test_credentials.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| import uuid | ||||
|  | ||||
| from keystoneclient.v3 import credentials | ||||
| from tests.v3 import utils | ||||
|  | ||||
|  | ||||
| class CredentialTests(utils.TestCase, utils.CrudTests): | ||||
|     def setUp(self): | ||||
|         super(CredentialTests, self).setUp() | ||||
|         self.additionalSetUp() | ||||
|         self.key = 'credential' | ||||
|         self.collection_key = 'credentials' | ||||
|         self.model = credentials.Credential | ||||
|         self.manager = self.client.credentials | ||||
|  | ||||
|     def new_ref(self, **kwargs): | ||||
|         kwargs = super(CredentialTests, self).new_ref(**kwargs) | ||||
|         kwargs.setdefault('data', uuid.uuid4().hex) | ||||
|         kwargs.setdefault('project_id', uuid.uuid4().hex) | ||||
|         kwargs.setdefault('type', uuid.uuid4().hex) | ||||
|         kwargs.setdefault('user_id', uuid.uuid4().hex) | ||||
|         return kwargs | ||||
							
								
								
									
										20
									
								
								tests/v3/test_domains.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								tests/v3/test_domains.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| import uuid | ||||
|  | ||||
| from keystoneclient.v3 import domains | ||||
| from tests.v3 import utils | ||||
|  | ||||
|  | ||||
| class DomainTests(utils.TestCase, utils.CrudTests): | ||||
|     def setUp(self): | ||||
|         super(DomainTests, self).setUp() | ||||
|         self.additionalSetUp() | ||||
|         self.key = 'domain' | ||||
|         self.collection_key = 'domains' | ||||
|         self.model = domains.Domain | ||||
|         self.manager = self.client.domains | ||||
|  | ||||
|     def new_ref(self, **kwargs): | ||||
|         kwargs = super(DomainTests, self).new_ref(**kwargs) | ||||
|         kwargs.setdefault('enabled', True) | ||||
|         kwargs.setdefault('name', uuid.uuid4().hex) | ||||
|         return kwargs | ||||
							
								
								
									
										78
									
								
								tests/v3/test_endpoints.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								tests/v3/test_endpoints.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | ||||
| import uuid | ||||
|  | ||||
| from keystoneclient.v3 import endpoints | ||||
| from tests.v3 import utils | ||||
|  | ||||
|  | ||||
| class EndpointTests(utils.TestCase, utils.CrudTests): | ||||
|     def setUp(self): | ||||
|         super(EndpointTests, self).setUp() | ||||
|         self.additionalSetUp() | ||||
|         self.key = 'endpoint' | ||||
|         self.collection_key = 'endpoints' | ||||
|         self.model = endpoints.Endpoint | ||||
|         self.manager = self.client.endpoints | ||||
|  | ||||
|     def new_ref(self, **kwargs): | ||||
|         kwargs = super(EndpointTests, self).new_ref(**kwargs) | ||||
|         kwargs.setdefault('interface', 'public') | ||||
|         kwargs.setdefault('region', uuid.uuid4().hex) | ||||
|         kwargs.setdefault('service_id', uuid.uuid4().hex) | ||||
|         kwargs.setdefault('url', uuid.uuid4().hex) | ||||
|         kwargs.setdefault('enabled', True) | ||||
|         return kwargs | ||||
|  | ||||
|     def test_create_public_interface(self): | ||||
|         ref = self.new_ref(interface='public') | ||||
|         self.test_create(ref) | ||||
|  | ||||
|     def test_create_admin_interface(self): | ||||
|         ref = self.new_ref(interface='admin') | ||||
|         self.test_create(ref) | ||||
|  | ||||
|     def test_create_internal_interface(self): | ||||
|         ref = self.new_ref(interface='internal') | ||||
|         self.test_create(ref) | ||||
|  | ||||
|     def test_create_invalid_interface(self): | ||||
|         ref = self.new_ref(interface=uuid.uuid4().hex) | ||||
|         with self.assertRaises(Exception): | ||||
|             self.manager.create(**utils.parameterize(ref)) | ||||
|  | ||||
|     def test_update_public_interface(self): | ||||
|         ref = self.new_ref(interface='public') | ||||
|         self.test_update(ref) | ||||
|  | ||||
|     def test_update_admin_interface(self): | ||||
|         ref = self.new_ref(interface='admin') | ||||
|         self.test_update(ref) | ||||
|  | ||||
|     def test_update_internal_interface(self): | ||||
|         ref = self.new_ref(interface='internal') | ||||
|         self.test_update(ref) | ||||
|  | ||||
|     def test_update_invalid_interface(self): | ||||
|         ref = self.new_ref(interface=uuid.uuid4().hex) | ||||
|         with self.assertRaises(Exception): | ||||
|             self.manager.update(**utils.parameterize(ref)) | ||||
|  | ||||
|     def test_list_public_interface(self): | ||||
|         interface = 'public' | ||||
|         expected_path = 'v3/%s?interface=%s' % (self.collection_key, interface) | ||||
|         self.test_list(expected_path=expected_path, interface=interface) | ||||
|  | ||||
|     def test_list_admin_interface(self): | ||||
|         interface = 'admin' | ||||
|         expected_path = 'v3/%s?interface=%s' % (self.collection_key, interface) | ||||
|         self.test_list(expected_path=expected_path, interface=interface) | ||||
|  | ||||
|     def test_list_internal_interface(self): | ||||
|         interface = 'admin' | ||||
|         expected_path = 'v3/%s?interface=%s' % (self.collection_key, interface) | ||||
|         self.test_list(expected_path=expected_path, interface=interface) | ||||
|  | ||||
|     def test_list_invalid_interface(self): | ||||
|         interface = uuid.uuid4().hex | ||||
|         expected_path = 'v3/%s?interface=%s' % (self.collection_key, interface) | ||||
|         with self.assertRaises(Exception): | ||||
|             self.manager.list(expected_path=expected_path, interface=interface) | ||||
							
								
								
									
										21
									
								
								tests/v3/test_policies.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								tests/v3/test_policies.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| import uuid | ||||
|  | ||||
| from keystoneclient.v3 import policies | ||||
| from tests.v3 import utils | ||||
|  | ||||
|  | ||||
| class PolicyTests(utils.TestCase, utils.CrudTests): | ||||
|     def setUp(self): | ||||
|         super(PolicyTests, self).setUp() | ||||
|         self.additionalSetUp() | ||||
|         self.key = 'policy' | ||||
|         self.collection_key = 'policies' | ||||
|         self.model = policies.Policy | ||||
|         self.manager = self.client.policies | ||||
|  | ||||
|     def new_ref(self, **kwargs): | ||||
|         kwargs = super(PolicyTests, self).new_ref(**kwargs) | ||||
|         kwargs.setdefault('endpoint_id', uuid.uuid4().hex) | ||||
|         kwargs.setdefault('type', uuid.uuid4().hex) | ||||
|         kwargs.setdefault('blob', uuid.uuid4().hex) | ||||
|         return kwargs | ||||
							
								
								
									
										69
									
								
								tests/v3/test_projects.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										69
									
								
								tests/v3/test_projects.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,69 @@ | ||||
| import httplib2 | ||||
| import urlparse | ||||
| import uuid | ||||
|  | ||||
| from keystoneclient.v3 import projects | ||||
| from tests.v3 import utils | ||||
|  | ||||
|  | ||||
| class ProjectTests(utils.TestCase, utils.CrudTests): | ||||
|     def setUp(self): | ||||
|         super(ProjectTests, self).setUp() | ||||
|         self.additionalSetUp() | ||||
|         self.key = 'project' | ||||
|         self.collection_key = 'projects' | ||||
|         self.model = projects.Project | ||||
|         self.manager = self.client.projects | ||||
|  | ||||
|     def new_ref(self, **kwargs): | ||||
|         kwargs = super(ProjectTests, self).new_ref(**kwargs) | ||||
|         kwargs.setdefault('domain_id', uuid.uuid4().hex) | ||||
|         kwargs.setdefault('enabled', True) | ||||
|         kwargs.setdefault('name', uuid.uuid4().hex) | ||||
|         return kwargs | ||||
|  | ||||
|     def test_list_projects_for_user(self): | ||||
|         ref_list = [self.new_ref(), self.new_ref()] | ||||
|  | ||||
|         user_id = uuid.uuid4().hex | ||||
|         resp = httplib2.Response({ | ||||
|             'status': 200, | ||||
|             'body': self.serialize(ref_list), | ||||
|         }) | ||||
|  | ||||
|         method = 'GET' | ||||
|         httplib2.Http.request( | ||||
|             urlparse.urljoin( | ||||
|                 self.TEST_URL, | ||||
|                 'v3/users/%s/%s' % (user_id, self.collection_key)), | ||||
|             method, | ||||
|             headers=self.headers[method]) \ | ||||
|             .AndReturn((resp, resp['body'])) | ||||
|         self.mox.ReplayAll() | ||||
|  | ||||
|         returned_list = self.manager.list(user=user_id) | ||||
|         self.assertTrue(len(returned_list)) | ||||
|         [self.assertTrue(isinstance(r, self.model)) for r in returned_list] | ||||
|  | ||||
|     def test_list_projects_for_domain(self): | ||||
|         ref_list = [self.new_ref(), self.new_ref()] | ||||
|  | ||||
|         domain_id = uuid.uuid4().hex | ||||
|         resp = httplib2.Response({ | ||||
|             'status': 200, | ||||
|             'body': self.serialize(ref_list), | ||||
|         }) | ||||
|  | ||||
|         method = 'GET' | ||||
|         httplib2.Http.request( | ||||
|             urlparse.urljoin( | ||||
|                 self.TEST_URL, | ||||
|                 'v3/%s?domain_id=%s' % (self.collection_key, domain_id)), | ||||
|             method, | ||||
|             headers=self.headers[method]) \ | ||||
|             .AndReturn((resp, resp['body'])) | ||||
|         self.mox.ReplayAll() | ||||
|  | ||||
|         returned_list = self.manager.list(domain=domain_id) | ||||
|         self.assertTrue(len(returned_list)) | ||||
|         [self.assertTrue(isinstance(r, self.model)) for r in returned_list] | ||||
							
								
								
									
										252
									
								
								tests/v3/test_roles.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										252
									
								
								tests/v3/test_roles.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,252 @@ | ||||
| import httplib2 | ||||
| import urlparse | ||||
| import uuid | ||||
|  | ||||
| from keystoneclient import exceptions | ||||
| from keystoneclient.v3 import roles | ||||
| from tests.v3 import utils | ||||
|  | ||||
|  | ||||
| class RoleTests(utils.TestCase, utils.CrudTests): | ||||
|     def setUp(self): | ||||
|         super(RoleTests, self).setUp() | ||||
|         self.additionalSetUp() | ||||
|         self.key = 'role' | ||||
|         self.collection_key = 'roles' | ||||
|         self.model = roles.Role | ||||
|         self.manager = self.client.roles | ||||
|  | ||||
|     def new_ref(self, **kwargs): | ||||
|         kwargs = super(RoleTests, self).new_ref(**kwargs) | ||||
|         kwargs.setdefault('name', uuid.uuid4().hex) | ||||
|         return kwargs | ||||
|  | ||||
|     def test_domain_role_grant(self): | ||||
|         user_id = uuid.uuid4().hex | ||||
|         domain_id = uuid.uuid4().hex | ||||
|         ref = self.new_ref() | ||||
|         resp = httplib2.Response({ | ||||
|             'status': 201, | ||||
|             'body': '', | ||||
|         }) | ||||
|  | ||||
|         method = 'PUT' | ||||
|         httplib2.Http.request( | ||||
|             urlparse.urljoin( | ||||
|                 self.TEST_URL, | ||||
|                 'v3/domains/%s/users/%s/%s/%s' % ( | ||||
|                     domain_id, user_id, self.collection_key, ref['id'])), | ||||
|             method, | ||||
|             headers=self.headers[method]) \ | ||||
|             .AndReturn((resp, resp['body'])) | ||||
|         self.mox.ReplayAll() | ||||
|  | ||||
|         self.manager.grant(role=ref['id'], domain=domain_id, user=user_id) | ||||
|  | ||||
|     def test_domain_role_list(self): | ||||
|         user_id = uuid.uuid4().hex | ||||
|         domain_id = uuid.uuid4().hex | ||||
|         ref_list = [self.new_ref(), self.new_ref()] | ||||
|         resp = httplib2.Response({ | ||||
|             'status': 200, | ||||
|             'body': self.serialize(ref_list), | ||||
|         }) | ||||
|  | ||||
|         method = 'GET' | ||||
|         httplib2.Http.request( | ||||
|             urlparse.urljoin( | ||||
|                 self.TEST_URL, | ||||
|                 'v3/domains/%s/users/%s/%s' % ( | ||||
|                     domain_id, user_id, self.collection_key)), | ||||
|             method, | ||||
|             headers=self.headers[method]) \ | ||||
|             .AndReturn((resp, resp['body'])) | ||||
|         self.mox.ReplayAll() | ||||
|  | ||||
|         self.manager.list(domain=domain_id, user=user_id) | ||||
|  | ||||
|     def test_domain_role_check(self): | ||||
|         user_id = uuid.uuid4().hex | ||||
|         domain_id = uuid.uuid4().hex | ||||
|         ref = self.new_ref() | ||||
|         resp = httplib2.Response({ | ||||
|             'status': 200, | ||||
|             'body': '', | ||||
|         }) | ||||
|  | ||||
|         method = 'HEAD' | ||||
|         httplib2.Http.request( | ||||
|             urlparse.urljoin( | ||||
|                 self.TEST_URL, | ||||
|                 'v3/domains/%s/users/%s/%s/%s' % ( | ||||
|                     domain_id, user_id, self.collection_key, ref['id'])), | ||||
|             method, | ||||
|             headers=self.headers[method]) \ | ||||
|             .AndReturn((resp, resp['body'])) | ||||
|         self.mox.ReplayAll() | ||||
|  | ||||
|         self.manager.check(role=ref['id'], domain=domain_id, user=user_id) | ||||
|  | ||||
|     def test_domain_role_revoke(self): | ||||
|         user_id = uuid.uuid4().hex | ||||
|         domain_id = uuid.uuid4().hex | ||||
|         ref = self.new_ref() | ||||
|         resp = httplib2.Response({ | ||||
|             'status': 204, | ||||
|             'body': '', | ||||
|         }) | ||||
|  | ||||
|         method = 'DELETE' | ||||
|         httplib2.Http.request( | ||||
|             urlparse.urljoin( | ||||
|                 self.TEST_URL, | ||||
|                 'v3/domains/%s/users/%s/%s/%s' % ( | ||||
|                     domain_id, user_id, self.collection_key, ref['id'])), | ||||
|             method, | ||||
|             headers=self.headers[method]) \ | ||||
|             .AndReturn((resp, resp['body'])) | ||||
|         self.mox.ReplayAll() | ||||
|  | ||||
|         self.manager.revoke(role=ref['id'], domain=domain_id, user=user_id) | ||||
|  | ||||
|     def test_project_role_grant(self): | ||||
|         user_id = uuid.uuid4().hex | ||||
|         project_id = uuid.uuid4().hex | ||||
|         ref = self.new_ref() | ||||
|         resp = httplib2.Response({ | ||||
|             'status': 201, | ||||
|             'body': '', | ||||
|         }) | ||||
|  | ||||
|         method = 'PUT' | ||||
|         httplib2.Http.request( | ||||
|             urlparse.urljoin( | ||||
|                 self.TEST_URL, | ||||
|                 'v3/projects/%s/users/%s/%s/%s' % ( | ||||
|                     project_id, user_id, self.collection_key, ref['id'])), | ||||
|             method, | ||||
|             headers=self.headers[method]) \ | ||||
|             .AndReturn((resp, resp['body'])) | ||||
|         self.mox.ReplayAll() | ||||
|  | ||||
|         self.manager.grant(role=ref['id'], project=project_id, user=user_id) | ||||
|  | ||||
|     def test_project_role_list(self): | ||||
|         user_id = uuid.uuid4().hex | ||||
|         project_id = uuid.uuid4().hex | ||||
|         ref_list = [self.new_ref(), self.new_ref()] | ||||
|         resp = httplib2.Response({ | ||||
|             'status': 200, | ||||
|             'body': self.serialize(ref_list), | ||||
|         }) | ||||
|  | ||||
|         method = 'GET' | ||||
|         httplib2.Http.request( | ||||
|             urlparse.urljoin( | ||||
|                 self.TEST_URL, | ||||
|                 'v3/projects/%s/users/%s/%s' % ( | ||||
|                     project_id, user_id, self.collection_key)), | ||||
|             method, | ||||
|             headers=self.headers[method]) \ | ||||
|             .AndReturn((resp, resp['body'])) | ||||
|         self.mox.ReplayAll() | ||||
|  | ||||
|         self.manager.list(project=project_id, user=user_id) | ||||
|  | ||||
|     def test_project_role_check(self): | ||||
|         user_id = uuid.uuid4().hex | ||||
|         project_id = uuid.uuid4().hex | ||||
|         ref = self.new_ref() | ||||
|         resp = httplib2.Response({ | ||||
|             'status': 200, | ||||
|             'body': '', | ||||
|         }) | ||||
|  | ||||
|         method = 'HEAD' | ||||
|         httplib2.Http.request( | ||||
|             urlparse.urljoin( | ||||
|                 self.TEST_URL, | ||||
|                 'v3/projects/%s/users/%s/%s/%s' % ( | ||||
|                     project_id, user_id, self.collection_key, ref['id'])), | ||||
|             method, | ||||
|             headers=self.headers[method]) \ | ||||
|             .AndReturn((resp, resp['body'])) | ||||
|         self.mox.ReplayAll() | ||||
|  | ||||
|         self.manager.check(role=ref['id'], project=project_id, user=user_id) | ||||
|  | ||||
|     def test_project_role_revoke(self): | ||||
|         user_id = uuid.uuid4().hex | ||||
|         project_id = uuid.uuid4().hex | ||||
|         ref = self.new_ref() | ||||
|         resp = httplib2.Response({ | ||||
|             'status': 204, | ||||
|             'body': '', | ||||
|         }) | ||||
|  | ||||
|         method = 'DELETE' | ||||
|         httplib2.Http.request( | ||||
|             urlparse.urljoin( | ||||
|                 self.TEST_URL, | ||||
|                 'v3/projects/%s/users/%s/%s/%s' % ( | ||||
|                     project_id, user_id, self.collection_key, ref['id'])), | ||||
|             method, | ||||
|             headers=self.headers[method]) \ | ||||
|             .AndReturn((resp, resp['body'])) | ||||
|         self.mox.ReplayAll() | ||||
|  | ||||
|         self.manager.revoke(role=ref['id'], project=project_id, user=user_id) | ||||
|  | ||||
|     def test_domain_project_role_grant_fails(self): | ||||
|         user_id = uuid.uuid4().hex | ||||
|         project_id = uuid.uuid4().hex | ||||
|         domain_id = uuid.uuid4().hex | ||||
|         ref = self.new_ref() | ||||
|  | ||||
|         self.assertRaises( | ||||
|             exceptions.ValidationError, | ||||
|             self.manager.grant, | ||||
|             role=ref['id'], | ||||
|             domain=domain_id, | ||||
|             project=project_id, | ||||
|             user=user_id) | ||||
|  | ||||
|     def test_domain_project_role_list_fails(self): | ||||
|         user_id = uuid.uuid4().hex | ||||
|         project_id = uuid.uuid4().hex | ||||
|         domain_id = uuid.uuid4().hex | ||||
|  | ||||
|         self.assertRaises( | ||||
|             exceptions.ValidationError, | ||||
|             self.manager.list, | ||||
|             domain=domain_id, | ||||
|             project=project_id, | ||||
|             user=user_id) | ||||
|  | ||||
|     def test_domain_project_role_check_fails(self): | ||||
|         user_id = uuid.uuid4().hex | ||||
|         project_id = uuid.uuid4().hex | ||||
|         domain_id = uuid.uuid4().hex | ||||
|         ref = self.new_ref() | ||||
|  | ||||
|         self.assertRaises( | ||||
|             exceptions.ValidationError, | ||||
|             self.manager.check, | ||||
|             role=ref['id'], | ||||
|             domain=domain_id, | ||||
|             project=project_id, | ||||
|             user=user_id) | ||||
|  | ||||
|     def test_domain_project_role_revoke_fails(self): | ||||
|         user_id = uuid.uuid4().hex | ||||
|         project_id = uuid.uuid4().hex | ||||
|         domain_id = uuid.uuid4().hex | ||||
|         ref = self.new_ref() | ||||
|  | ||||
|         self.assertRaises( | ||||
|             exceptions.ValidationError, | ||||
|             self.manager.revoke, | ||||
|             role=ref['id'], | ||||
|             domain=domain_id, | ||||
|             project=project_id, | ||||
|             user=user_id) | ||||
							
								
								
									
										21
									
								
								tests/v3/test_services.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								tests/v3/test_services.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| import uuid | ||||
|  | ||||
| from keystoneclient.v3 import services | ||||
| from tests.v3 import utils | ||||
|  | ||||
|  | ||||
| class ServiceTests(utils.TestCase, utils.CrudTests): | ||||
|     def setUp(self): | ||||
|         super(ServiceTests, self).setUp() | ||||
|         self.additionalSetUp() | ||||
|         self.key = 'service' | ||||
|         self.collection_key = 'services' | ||||
|         self.model = services.Service | ||||
|         self.manager = self.client.services | ||||
|  | ||||
|     def new_ref(self, **kwargs): | ||||
|         kwargs = super(ServiceTests, self).new_ref(**kwargs) | ||||
|         kwargs.setdefault('name', uuid.uuid4().hex) | ||||
|         kwargs.setdefault('type', uuid.uuid4().hex) | ||||
|         kwargs.setdefault('enabled', True) | ||||
|         return kwargs | ||||
							
								
								
									
										23
									
								
								tests/v3/test_users.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								tests/v3/test_users.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| import uuid | ||||
|  | ||||
| from keystoneclient.v3 import users | ||||
| from tests.v3 import utils | ||||
|  | ||||
|  | ||||
| class UserTests(utils.TestCase, utils.CrudTests): | ||||
|     def setUp(self): | ||||
|         super(UserTests, self).setUp() | ||||
|         self.additionalSetUp() | ||||
|         self.key = 'user' | ||||
|         self.collection_key = 'users' | ||||
|         self.model = users.User | ||||
|         self.manager = self.client.users | ||||
|  | ||||
|     def new_ref(self, **kwargs): | ||||
|         kwargs = super(UserTests, self).new_ref(**kwargs) | ||||
|         kwargs.setdefault('description', uuid.uuid4().hex) | ||||
|         kwargs.setdefault('domain_id', uuid.uuid4().hex) | ||||
|         kwargs.setdefault('enabled', True) | ||||
|         kwargs.setdefault('name', uuid.uuid4().hex) | ||||
|         kwargs.setdefault('project_id', uuid.uuid4().hex) | ||||
|         return kwargs | ||||
							
								
								
									
										227
									
								
								tests/v3/utils.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										227
									
								
								tests/v3/utils.py
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,227 @@ | ||||
| import json | ||||
| import uuid | ||||
| import time | ||||
| import urlparse | ||||
|  | ||||
| import httplib2 | ||||
| import mox | ||||
| import unittest2 as unittest | ||||
|  | ||||
| from keystoneclient.v3 import client | ||||
|  | ||||
|  | ||||
| def parameterize(ref): | ||||
|     """Rewrites attributes to match the kwarg naming convention in client. | ||||
|  | ||||
|     >>> paramterize({'project_id': 0}) | ||||
|     {'project': 0} | ||||
|  | ||||
|     """ | ||||
|     params = ref.copy() | ||||
|     for key in ref: | ||||
|         if key[-3:] == '_id': | ||||
|             params.setdefault(key[:-3], params.pop(key)) | ||||
|     return params | ||||
|  | ||||
|  | ||||
| class TestCase(unittest.TestCase): | ||||
|     TEST_TENANT_NAME = 'aTenant' | ||||
|     TEST_TOKEN = 'aToken' | ||||
|     TEST_USER = 'test' | ||||
|     TEST_ROOT_URL = 'http://127.0.0.1:5000/' | ||||
|     TEST_URL = '%s%s' % (TEST_ROOT_URL, 'v3') | ||||
|     TEST_ROOT_ADMIN_URL = 'http://127.0.0.1:35357/' | ||||
|     TEST_ADMIN_URL = '%s%s' % (TEST_ROOT_ADMIN_URL, 'v3') | ||||
|  | ||||
|     def setUp(self): | ||||
|         super(TestCase, self).setUp() | ||||
|         self.mox = mox.Mox() | ||||
|         self._original_time = time.time | ||||
|         time.time = lambda: 1234 | ||||
|         httplib2.Http.request = self.mox.CreateMockAnything() | ||||
|         self.client = client.Client(username=self.TEST_USER, | ||||
|                                     token=self.TEST_TOKEN, | ||||
|                                     tenant_name=self.TEST_TENANT_NAME, | ||||
|                                     auth_url=self.TEST_URL, | ||||
|                                     endpoint=self.TEST_URL) | ||||
|  | ||||
|     def tearDown(self): | ||||
|         time.time = self._original_time | ||||
|         super(TestCase, self).tearDown() | ||||
|         self.mox.UnsetStubs() | ||||
|         self.mox.VerifyAll() | ||||
|  | ||||
|  | ||||
| class UnauthenticatedTestCase(unittest.TestCase): | ||||
|     """ Class used as base for unauthenticated calls """ | ||||
|     TEST_ROOT_URL = 'http://127.0.0.1:5000/' | ||||
|     TEST_URL = '%s%s' % (TEST_ROOT_URL, 'v3') | ||||
|     TEST_ROOT_ADMIN_URL = 'http://127.0.0.1:35357/' | ||||
|     TEST_ADMIN_URL = '%s%s' % (TEST_ROOT_ADMIN_URL, 'v3') | ||||
|  | ||||
|     def setUp(self): | ||||
|         super(UnauthenticatedTestCase, self).setUp() | ||||
|         self.mox = mox.Mox() | ||||
|         self._original_time = time.time | ||||
|         time.time = lambda: 1234 | ||||
|         httplib2.Http.request = self.mox.CreateMockAnything() | ||||
|  | ||||
|     def tearDown(self): | ||||
|         time.time = self._original_time | ||||
|         super(UnauthenticatedTestCase, self).tearDown() | ||||
|         self.mox.UnsetStubs() | ||||
|         self.mox.VerifyAll() | ||||
|  | ||||
|  | ||||
| class CrudTests(object): | ||||
|     key = None | ||||
|     collection_key = None | ||||
|     model = None | ||||
|     manager = None | ||||
|  | ||||
|     def new_ref(self, **kwargs): | ||||
|         kwargs.setdefault('id', uuid.uuid4().hex) | ||||
|         return kwargs | ||||
|  | ||||
|     def additionalSetUp(self): | ||||
|         self.headers = { | ||||
|             'GET': { | ||||
|                 'X-Auth-Token': 'aToken', | ||||
|                 'User-Agent': 'python-keystoneclient', | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         self.headers['HEAD'] = self.headers['GET'].copy() | ||||
|         self.headers['DELETE'] = self.headers['GET'].copy() | ||||
|         self.headers['PUT'] = self.headers['GET'].copy() | ||||
|         self.headers['POST'] = self.headers['GET'].copy() | ||||
|         self.headers['POST']['Content-Type'] = 'application/json' | ||||
|         self.headers['PATCH'] = self.headers['POST'].copy() | ||||
|  | ||||
|     def serialize(self, entity): | ||||
|         if isinstance(entity, dict): | ||||
|             return json.dumps({self.key: entity}, sort_keys=True) | ||||
|         if isinstance(entity, list): | ||||
|             return json.dumps({self.collection_key: entity}, sort_keys=True) | ||||
|         raise NotImplementedError('Are you sure you want to serialize that?') | ||||
|  | ||||
|     def test_create(self, ref=None): | ||||
|         ref = ref or self.new_ref() | ||||
|         resp = httplib2.Response({ | ||||
|             'status': 201, | ||||
|             'body': self.serialize(ref), | ||||
|         }) | ||||
|  | ||||
|         method = 'POST' | ||||
|         req_ref = ref.copy() | ||||
|         req_ref.pop('id') | ||||
|         httplib2.Http.request( | ||||
|             urlparse.urljoin( | ||||
|                 self.TEST_URL, | ||||
|                 'v3/%s' % self.collection_key), | ||||
|             method, | ||||
|             body=self.serialize(req_ref), | ||||
|             headers=self.headers[method]) \ | ||||
|             .AndReturn((resp, resp['body'])) | ||||
|         self.mox.ReplayAll() | ||||
|  | ||||
|         returned = self.manager.create(**parameterize(req_ref)) | ||||
|         self.assertTrue(isinstance(returned, self.model)) | ||||
|         for attr in ref: | ||||
|             self.assertEqual( | ||||
|                 getattr(returned, attr), | ||||
|                 ref[attr], | ||||
|                 'Expected different %s' % attr) | ||||
|  | ||||
|     def test_get(self, ref=None): | ||||
|         ref = ref or self.new_ref() | ||||
|         resp = httplib2.Response({ | ||||
|             'status': 200, | ||||
|             'body': self.serialize(ref), | ||||
|         }) | ||||
|         method = 'GET' | ||||
|         httplib2.Http.request( | ||||
|             urlparse.urljoin( | ||||
|                 self.TEST_URL, | ||||
|                 'v3/%s/%s' % (self.collection_key, ref['id'])), | ||||
|             method, | ||||
|             headers=self.headers[method]) \ | ||||
|             .AndReturn((resp, resp['body'])) | ||||
|         self.mox.ReplayAll() | ||||
|  | ||||
|         returned = self.manager.get(ref['id']) | ||||
|         self.assertTrue(isinstance(returned, self.model)) | ||||
|         for attr in ref: | ||||
|             self.assertEqual( | ||||
|                 getattr(returned, attr), | ||||
|                 ref[attr], | ||||
|                 'Expected different %s' % attr) | ||||
|  | ||||
|     def test_list(self, ref_list=None, expected_path=None, **filter_kwargs): | ||||
|         ref_list = ref_list or [self.new_ref(), self.new_ref()] | ||||
|  | ||||
|         resp = httplib2.Response({ | ||||
|             'status': 200, | ||||
|             'body': self.serialize(ref_list), | ||||
|         }) | ||||
|  | ||||
|         method = 'GET' | ||||
|         httplib2.Http.request( | ||||
|             urlparse.urljoin( | ||||
|                 self.TEST_URL, | ||||
|                 expected_path or 'v3/%s' % self.collection_key), | ||||
|             method, | ||||
|             headers=self.headers[method]) \ | ||||
|             .AndReturn((resp, resp['body'])) | ||||
|         self.mox.ReplayAll() | ||||
|  | ||||
|         returned_list = self.manager.list(**filter_kwargs) | ||||
|         self.assertTrue(len(returned_list)) | ||||
|         [self.assertTrue(isinstance(r, self.model)) for r in returned_list] | ||||
|  | ||||
|     def test_update(self, ref=None): | ||||
|         ref = ref or self.new_ref() | ||||
|         req_ref = ref.copy() | ||||
|         del req_ref['id'] | ||||
|  | ||||
|         resp = httplib2.Response({ | ||||
|             'status': 200, | ||||
|             'body': self.serialize(ref), | ||||
|         }) | ||||
|  | ||||
|         method = 'PATCH' | ||||
|         httplib2.Http.request( | ||||
|             urlparse.urljoin( | ||||
|                 self.TEST_URL, | ||||
|                 'v3/%s/%s' % (self.collection_key, ref['id'])), | ||||
|             method, | ||||
|             body=self.serialize(req_ref), | ||||
|             headers=self.headers[method]) \ | ||||
|             .AndReturn((resp, resp['body'])) | ||||
|         self.mox.ReplayAll() | ||||
|  | ||||
|         returned = self.manager.update(ref['id'], **parameterize(req_ref)) | ||||
|         self.assertTrue(isinstance(returned, self.model)) | ||||
|         for attr in ref: | ||||
|             self.assertEqual( | ||||
|                 getattr(returned, attr), | ||||
|                 ref[attr], | ||||
|                 'Expected different %s' % attr) | ||||
|  | ||||
|     def test_delete(self, ref=None): | ||||
|         ref = ref or self.new_ref() | ||||
|         method = 'DELETE' | ||||
|         resp = httplib2.Response({ | ||||
|             'status': 204, | ||||
|             'body': '', | ||||
|         }) | ||||
|         httplib2.Http.request( | ||||
|             urlparse.urljoin( | ||||
|                 self.TEST_URL, | ||||
|                 'v3/%s/%s' % (self.collection_key, ref['id'])), | ||||
|             method, | ||||
|             headers=self.headers[method]) \ | ||||
|             .AndReturn((resp, resp['body'])) | ||||
|         self.mox.ReplayAll() | ||||
|  | ||||
|         self.manager.delete(ref['id']) | ||||
		Reference in New Issue
	
	Block a user
	 Dolph Mathews
					Dolph Mathews