From 91914c79be27cf15b7b99ed96c4581c4fc2d7611 Mon Sep 17 00:00:00 2001 From: Marek Denis Date: Fri, 28 Mar 2014 14:23:55 +0100 Subject: [PATCH] Add CRUD operations for Federation Mapping Rules. Add relevant methods for adding, updating, listing, getting, and deleting Mapping objects. Change-Id: I26a3822d9e341b9ddec10ecb8590432554837dce Implements: blueprint federation-crud-operations --- keystoneclient/tests/v3/test_federation.py | 41 +++++ keystoneclient/v3/contrib/federation/core.py | 2 + .../v3/contrib/federation/mappings.py | 160 ++++++++++++++++++ 3 files changed, 203 insertions(+) create mode 100644 keystoneclient/v3/contrib/federation/mappings.py diff --git a/keystoneclient/tests/v3/test_federation.py b/keystoneclient/tests/v3/test_federation.py index 086104a37..77ff4b9f3 100644 --- a/keystoneclient/tests/v3/test_federation.py +++ b/keystoneclient/tests/v3/test_federation.py @@ -16,6 +16,7 @@ import httpretty from keystoneclient.tests.v3 import utils from keystoneclient.v3.contrib.federation import identity_providers +from keystoneclient.v3.contrib.federation import mappings class IdentityProviderTests(utils.TestCase, utils.CrudTests): @@ -84,3 +85,43 @@ class IdentityProviderTests(utils.TestCase, utils.CrudTests): req_ref[attr], 'Expected different %s' % attr) self.assertEntityRequestBodyIs(req_ref) + + +class MappingTests(utils.TestCase, utils.CrudTests): + def setUp(self): + super(MappingTests, self).setUp() + self.key = 'mapping' + self.collection_key = 'mappings' + self.model = mappings.Mapping + self.manager = self.client.federation.mappings + self.path_prefix = 'OS-FEDERATION' + + def new_ref(self, **kwargs): + kwargs.setdefault('id', uuid.uuid4().hex) + kwargs.setdefault('rules', [uuid.uuid4().hex, + uuid.uuid4().hex]) + return kwargs + + @httpretty.activate + def test_create(self, ref=None, req_ref=None): + ref = ref or self.new_ref() + manager_ref = ref.copy() + mapping_id = manager_ref.pop('id') + + # 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() + + self.stub_entity(httpretty.PUT, entity=req_ref, id=mapping_id, + status=201) + + returned = self.manager.create(mapping_id=mapping_id, **manager_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(manager_ref) diff --git a/keystoneclient/v3/contrib/federation/core.py b/keystoneclient/v3/contrib/federation/core.py index 880427823..3cb1061f9 100644 --- a/keystoneclient/v3/contrib/federation/core.py +++ b/keystoneclient/v3/contrib/federation/core.py @@ -11,9 +11,11 @@ # under the License. from keystoneclient.v3.contrib.federation import identity_providers +from keystoneclient.v3.contrib.federation import mappings class FederationManager(object): def __init__(self, api): self.identity_providers = identity_providers.IdentityProviderManager( api) + self.mappings = mappings.MappingManager(api) diff --git a/keystoneclient/v3/contrib/federation/mappings.py b/keystoneclient/v3/contrib/federation/mappings.py new file mode 100644 index 000000000..d0c033f13 --- /dev/null +++ b/keystoneclient/v3/contrib/federation/mappings.py @@ -0,0 +1,160 @@ +# 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 Mapping(base.Resource): + """An object representing mapping container + + Attributes: + * id: user defined unique string identifying mapping. + + """ + pass + + +class MappingManager(base.CrudManager): + """Manager class for manipulating federation mappings.""" + + resource_class = Mapping + collection_key = 'mappings' + key = 'mapping' + 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, mapping_id, **kwargs): + """Create federation mapping. + + Utilize Identity API operation: + PUT /OS-FEDERATION/mappings/$mapping_id + + :param mapping_id: user defined string identifier of the federation + mapping. + :param rules: a JSON dictionary with list a list + of mapping rules. + + Example of the ``rules``:: + + { + "mapping": { + "rules": [ + { + "local": [ + { + "group": { + "id": "0cd5e9" + } + } + ], + "remote": [ + { + "type": "orgPersonType", + "not_any_of": [ + "Contractor", + "Guest" + ] + } + ] + } + ] + } + } + + """ + return self._build_url_and_put( + mapping_id=mapping_id, **kwargs) + + def get(self, mapping): + """Fetch federation mapping identified by mapping id. + + Utilize Identity API operation: + GET /OS-FEDERATION/mappings/$mapping_id + + :param mapping: a Mapping type object with mapping id + stored inside. + + """ + return super(MappingManager, self).get( + mapping_id=base.getid(mapping)) + + def list(self, **kwargs): + """List all federation mappings. + + Utilize Identity API operation: + GET /OS-FEDERATION/mappings/$mapping_id + + """ + return super(MappingManager, self).list(**kwargs) + + def update(self, mapping, **kwargs): + """Update federation mapping identified by mapping id. + + Utilize Identity API operation: + PATCH /OS-FEDERATION/mappings/$mapping_id + + :param mapping: a Mapping type object with mapping id + stored inside. + :param rules: a JSON dictionary with list a list + of mapping rules. + + Example of the ``rules``:: + + { + "mapping": { + "rules": [ + { + "local": [ + { + "group": { + "id": "0cd5e9" + } + } + ], + "remote": [ + { + "type": "orgPersonType", + "not_any_of": [ + "Contractor", + "Guest" + ] + } + ] + } + ] + } + } + + """ + return super(MappingManager, self).update( + mapping_id=base.getid(mapping), **kwargs) + + def delete(self, mapping): + """Delete federation mapping identified by mapping id. + + Utilize Identity API operation: + DELETE /OS-FEDERATION/mappings/$mapping_id + + :param mapping: a Mapping type object with mapping id + stored inside. + + """ + return super(MappingManager, self).delete( + mapping_id=base.getid(mapping))