From 49f74fd84ddffcd6287ff645023d321bd7bf440a Mon Sep 17 00:00:00 2001 From: Marek Denis Date: Wed, 26 Mar 2014 17:44:08 +0100 Subject: [PATCH] Add CRUD operations for Identity Providers. Add relevant methods for adding, updating, listing, getting, and deleting Identity Provider objects. Change-Id: Ib77781b507d2c06c368a1877eb716ec7fe2d88e4 Implements: blueprint federation-crud-operations --- keystoneclient/tests/v3/test_federation.py | 86 +++++++++++++++ keystoneclient/v3/client.py | 2 + .../v3/contrib/federation/__init__.py | 13 +++ keystoneclient/v3/contrib/federation/core.py | 19 ++++ .../contrib/federation/identity_providers.py | 100 ++++++++++++++++++ 5 files changed, 220 insertions(+) create mode 100644 keystoneclient/tests/v3/test_federation.py create mode 100644 keystoneclient/v3/contrib/federation/__init__.py create mode 100644 keystoneclient/v3/contrib/federation/core.py create mode 100644 keystoneclient/v3/contrib/federation/identity_providers.py diff --git a/keystoneclient/tests/v3/test_federation.py b/keystoneclient/tests/v3/test_federation.py new file mode 100644 index 000000000..086104a37 --- /dev/null +++ b/keystoneclient/tests/v3/test_federation.py @@ -0,0 +1,86 @@ +# 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 uuid + +import httpretty + +from keystoneclient.tests.v3 import utils +from keystoneclient.v3.contrib.federation import identity_providers + + +class IdentityProviderTests(utils.TestCase, utils.CrudTests): + def setUp(self): + super(IdentityProviderTests, self).setUp() + self.key = 'identity_provider' + self.collection_key = 'identity_providers' + self.model = identity_providers.IdentityProvider + self.manager = self.client.federation.identity_providers + self.path_prefix = 'OS-FEDERATION' + + def new_ref(self, **kwargs): + kwargs.setdefault('id', uuid.uuid4().hex) + kwargs.setdefault('description', uuid.uuid4().hex) + kwargs.setdefault('enabled', True) + return kwargs + + def test_positional_parameters_expect_fail(self): + """Ensure CrudManager raises TypeError exceptions. + + After passing wrong number of positional arguments + an exception should be raised. + + Operations to be tested: + * create() + * get() + * list() + * delete() + * update() + + """ + POS_PARAM_1 = uuid.uuid4().hex + POS_PARAM_2 = uuid.uuid4().hex + POS_PARAM_3 = uuid.uuid4().hex + + PARAMETERS = { + 'create': (POS_PARAM_1, POS_PARAM_2), + 'get': (POS_PARAM_1, POS_PARAM_2), + 'list': (POS_PARAM_1, POS_PARAM_2), + 'update': (POS_PARAM_1, POS_PARAM_2, POS_PARAM_3), + 'delete': (POS_PARAM_1, POS_PARAM_2) + } + + for f_name, args in PARAMETERS.items(): + self.assertRaises(TypeError, getattr(self.manager, f_name), + *args) + + @httpretty.activate + def test_create(self, ref=None, req_ref=None): + ref = ref or self.new_ref() + + # req_ref argument allows you to specify a different + # signature for the request when the manager does some + # conversion before doing the request (e.g converting + # from datetime object to timestamp string) + req_ref = (req_ref or ref).copy() + req_ref.pop('id') + + self.stub_entity(httpretty.PUT, entity=ref, id=ref['id'], status=201) + + returned = self.manager.create(**ref) + self.assertIsInstance(returned, self.model) + for attr in req_ref: + self.assertEqual( + getattr(returned, attr), + req_ref[attr], + 'Expected different %s' % attr) + self.assertEntityRequestBodyIs(req_ref) diff --git a/keystoneclient/v3/client.py b/keystoneclient/v3/client.py index 0b0b17db2..65ba5d72d 100644 --- a/keystoneclient/v3/client.py +++ b/keystoneclient/v3/client.py @@ -19,6 +19,7 @@ from keystoneclient.auth.identity import v3 as v3_auth from keystoneclient import exceptions from keystoneclient import httpclient from keystoneclient.openstack.common import jsonutils +from keystoneclient.v3.contrib import federation from keystoneclient.v3.contrib import trusts from keystoneclient.v3 import credentials from keystoneclient.v3 import domains @@ -95,6 +96,7 @@ class Client(httpclient.HTTPClient): self.credentials = credentials.CredentialManager(self) self.endpoints = endpoints.EndpointManager(self) self.domains = domains.DomainManager(self) + self.federation = federation.FederationManager(self) self.groups = groups.GroupManager(self) self.policies = policies.PolicyManager(self) self.projects = projects.ProjectManager(self) diff --git a/keystoneclient/v3/contrib/federation/__init__.py b/keystoneclient/v3/contrib/federation/__init__.py new file mode 100644 index 000000000..8d31b75e3 --- /dev/null +++ b/keystoneclient/v3/contrib/federation/__init__.py @@ -0,0 +1,13 @@ +# 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.v3.contrib.federation.core import * # flake8: noqa diff --git a/keystoneclient/v3/contrib/federation/core.py b/keystoneclient/v3/contrib/federation/core.py new file mode 100644 index 000000000..880427823 --- /dev/null +++ b/keystoneclient/v3/contrib/federation/core.py @@ -0,0 +1,19 @@ +# 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.v3.contrib.federation import identity_providers + + +class FederationManager(object): + def __init__(self, api): + self.identity_providers = identity_providers.IdentityProviderManager( + api) diff --git a/keystoneclient/v3/contrib/federation/identity_providers.py b/keystoneclient/v3/contrib/federation/identity_providers.py new file mode 100644 index 000000000..242d5d962 --- /dev/null +++ b/keystoneclient/v3/contrib/federation/identity_providers.py @@ -0,0 +1,100 @@ +# 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 utils + + +class IdentityProvider(base.Resource): + """Object representing Identity Provider container + + Attributes: + * id: user-defined unique string identifying Identity Provider. + + """ + pass + + +class IdentityProviderManager(base.CrudManager): + """Manager class for manipulating Identity Providers.""" + + resource_class = IdentityProvider + collection_key = 'identity_providers' + key = 'identity_provider' + base_url = 'OS-FEDERATION' + + def _build_url_and_put(self, **kwargs): + url = self.build_url(dict_args_in_out=kwargs) + body = {self.key: kwargs} + return self._update(url, body=body, response_key=self.key, + method='PUT') + + @utils.positional.method(0) + def create(self, id, **kwargs): + """Create Identity Provider object. + + Utilize Keystone URI: + PUT /OS-FEDERATION/identity_providers/$identity_provider + + :param id: unique id of the identity provider. + + """ + return self._build_url_and_put(identity_provider_id=id, + **kwargs) + + def get(self, identity_provider): + """Fetch Identity Provider object + + Utilize Keystone URI: + GET /OS-FEDERATION/identity_providers/$identity_provider + + :param identity_provider: an object with identity_provider_id + stored inside. + + """ + return super(IdentityProviderManager, self).get( + identity_provider_id=base.getid(identity_provider)) + + def list(self, **kwargs): + """List all Identity Providers. + + Utilize Keystone URI: + GET /OS-FEDERATION/identity_providers + + """ + return super(IdentityProviderManager, self).list(**kwargs) + + def update(self, identity_provider, **kwargs): + """Update Identity Provider object. + + Utilize Keystone URI: + PATCH /OS-FEDERATION/identity_providers/$identity_provider + + :param identity_provider: an object with identity_provider_id + stored inside. + + """ + return super(IdentityProviderManager, self).update( + identity_provider_id=base.getid(identity_provider), **kwargs) + + def delete(self, identity_provider): + """Delete Identity Provider object. + + Utilize Keystone URI: + DELETE /OS-FEDERATION/identity_providers/$identity_provider + + :param identity_provider: an object with identity_provider_id + stored inside. + + """ + return super(IdentityProviderManager, self).delete( + identity_provider_id=base.getid(identity_provider))