Add CRUD operations for Federated Protocols.

Add relevant methods for adding, updating, listing, getting, and deleting
Federated Protocol objects.

Change-Id: Ibd8488158619d1689fbdfe21df114433c41c91f8
Implements: blueprint federation-crud-operations
This commit is contained in:
Marek Denis
2014-03-28 18:14:07 +01:00
committed by Steve Martinelli
parent 90abb4cfb2
commit 9dbdb3a651
3 changed files with 345 additions and 0 deletions

View File

@@ -10,13 +10,16 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import copy
import uuid import uuid
import httpretty import httpretty
from keystoneclient import exceptions
from keystoneclient.tests.v3 import utils from keystoneclient.tests.v3 import utils
from keystoneclient.v3.contrib.federation import identity_providers from keystoneclient.v3.contrib.federation import identity_providers
from keystoneclient.v3.contrib.federation import mappings from keystoneclient.v3.contrib.federation import mappings
from keystoneclient.v3.contrib.federation import protocols
class IdentityProviderTests(utils.TestCase, utils.CrudTests): class IdentityProviderTests(utils.TestCase, utils.CrudTests):
@@ -125,3 +128,198 @@ class MappingTests(utils.TestCase, utils.CrudTests):
req_ref[attr], req_ref[attr],
'Expected different %s' % attr) 'Expected different %s' % attr)
self.assertEntityRequestBodyIs(manager_ref) self.assertEntityRequestBodyIs(manager_ref)
class ProtocolTests(utils.TestCase, utils.CrudTests):
def setUp(self):
super(ProtocolTests, self).setUp()
self.key = 'protocol'
self.collection_key = 'protocols'
self.model = protocols.Protocol
self.manager = self.client.federation.protocols
self.path_prefix = 'OS-FEDERATION/identity_providers'
def _transform_to_response(self, ref):
"""Rebuild dictionary so it can be used as a
reference response body.
"""
response = copy.deepcopy(ref)
response['id'] = response.pop('protocol_id')
del response['identity_provider']
return response
def new_ref(self, **kwargs):
kwargs.setdefault('mapping', uuid.uuid4().hex)
kwargs.setdefault('identity_provider', uuid.uuid4().hex)
kwargs.setdefault('protocol_id', uuid.uuid4().hex)
return kwargs
def build_parts(self, identity_provider, protocol_id=None):
"""Build array used to construct httpretty URL/
Construct and return array with URL parts later used
by methods like utils.TestCase.stub_entity().
Example of URL:
``OS-FEDERATION/identity_providers/{idp_id}/
protocols/{protocol_id}``
"""
parts = ['OS-FEDERATION', 'identity_providers',
identity_provider, 'protocols']
if protocol_id:
parts.append(protocol_id)
return parts
def test_build_url_provide_base_url(self):
base_url = uuid.uuid4().hex
parameters = {'base_url': base_url}
url = self.manager.build_url(dict_args_in_out=parameters)
self.assertEqual('/'.join([base_url, self.collection_key]), url)
def test_build_url_w_idp_id(self):
"""Test whether kwargs ``base_url`` discards object's base_url
This test shows, that when ``base_url`` is specified in the
dict_args_in_out dictionary, values like ``identity_provider_id``
are not taken into consideration while building the url.
"""
base_url, identity_provider_id = uuid.uuid4().hex, uuid.uuid4().hex
parameters = {
'base_url': base_url,
'identity_provider_id': identity_provider_id
}
url = self.manager.build_url(dict_args_in_out=parameters)
self.assertEqual('/'.join([base_url, self.collection_key]), url)
def test_build_url_default_base_url(self):
identity_provider_id = uuid.uuid4().hex
parameters = {
'identity_provider_id': identity_provider_id
}
url = self.manager.build_url(dict_args_in_out=parameters)
self.assertEqual(
'/'.join([self.manager.base_url, identity_provider_id,
self.manager.collection_key]), url)
@httpretty.activate
def test_create(self):
"""Test creating federation protocol tied to an Identity Provider.
URL to be tested: PUT /OS-FEDERATION/identity_providers/
$identity_provider/protocols/$protocol
"""
request_args = self.new_ref()
expected = self._transform_to_response(request_args)
parts = self.build_parts(request_args['identity_provider'],
request_args['protocol_id'])
self.stub_entity(httpretty.PUT, entity=expected,
parts=parts, status=201)
returned = self.manager.create(**request_args)
self.assertEqual(expected, returned.to_dict())
request_body = {'mapping_id': request_args['mapping']}
self.assertEntityRequestBodyIs(request_body)
@httpretty.activate
def test_get(self):
"""Fetch federation protocol object.
URL to be tested: GET /OS-FEDERATION/identity_providers/
$identity_provider/protocols/$protocol
"""
request_args = self.new_ref()
expected = self._transform_to_response(request_args)
parts = self.build_parts(request_args['identity_provider'],
request_args['protocol_id'])
self.stub_entity(httpretty.GET, entity=expected,
parts=parts, status=201)
returned = self.manager.get(request_args['identity_provider'],
request_args['protocol_id'])
self.assertIsInstance(returned, self.model)
self.assertEqual(expected, returned.to_dict())
@httpretty.activate
def test_delete(self):
"""Delete federation protocol object.
URL to be tested: DELETE /OS-FEDERATION/identity_providers/
$identity_provider/protocols/$protocol
"""
request_args = self.new_ref()
parts = self.build_parts(request_args['identity_provider'],
request_args['protocol_id'])
self.stub_entity(httpretty.DELETE, parts=parts, status=204)
self.manager.delete(request_args['identity_provider'],
request_args['protocol_id'])
@httpretty.activate
def test_list(self):
"""Test listing all federation protocols tied to the Identity Provider.
URL to be tested: GET /OS-FEDERATION/identity_providers/
$identity_provider/protocols
"""
def _ref_protocols():
return {
'id': uuid.uuid4().hex,
'mapping_id': uuid.uuid4().hex
}
request_args = self.new_ref()
expected = [_ref_protocols() for _ in range(3)]
parts = self.build_parts(request_args['identity_provider'])
self.stub_entity(httpretty.GET, parts=parts,
entity=expected, status=200)
returned = self.manager.list(request_args['identity_provider'])
for obj, ref_obj in zip(returned, expected):
self.assertEqual(obj.to_dict(), ref_obj)
@httpretty.activate
def test_list_params(self):
request_args = self.new_ref()
filter_kwargs = {uuid.uuid4().hex: uuid.uuid4().hex}
parts = self.build_parts(request_args['identity_provider'])
# Return HTTP 401 as we don't accept such requests.
self.stub_entity(httpretty.GET, parts=parts, status=401)
self.assertRaises(exceptions.Unauthorized,
self.manager.list,
request_args['identity_provider'],
**filter_kwargs)
self.assertQueryStringContains(**filter_kwargs)
@httpretty.activate
def test_update(self):
"""Test updating federation protocol
URL to be tested: PATCH /OS-FEDERATION/identity_providers/
$identity_provider/protocols/$protocol
"""
request_args = self.new_ref()
expected = self._transform_to_response(request_args)
parts = self.build_parts(request_args['identity_provider'],
request_args['protocol_id'])
self.stub_entity(httpretty.PATCH, parts=parts,
entity=expected, status=200)
returned = self.manager.update(request_args['identity_provider'],
request_args['protocol_id'],
mapping=request_args['mapping'])
self.assertIsInstance(returned, self.model)
self.assertEqual(expected, returned.to_dict())
request_body = {'mapping_id': request_args['mapping']}
self.assertEntityRequestBodyIs(request_body)

View File

@@ -12,6 +12,7 @@
from keystoneclient.v3.contrib.federation import identity_providers from keystoneclient.v3.contrib.federation import identity_providers
from keystoneclient.v3.contrib.federation import mappings from keystoneclient.v3.contrib.federation import mappings
from keystoneclient.v3.contrib.federation import protocols
class FederationManager(object): class FederationManager(object):
@@ -19,3 +20,4 @@ class FederationManager(object):
self.identity_providers = identity_providers.IdentityProviderManager( self.identity_providers = identity_providers.IdentityProviderManager(
api) api)
self.mappings = mappings.MappingManager(api) self.mappings = mappings.MappingManager(api)
self.protocols = protocols.ProtocolManager(api)

View File

@@ -0,0 +1,145 @@
# 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 Protocol(base.Resource):
"""An object representing federation protocol container.
Attributes:
* id: user-defined unique per Identity Provider string identifying
federation protocol.
"""
pass
class ProtocolManager(base.CrudManager):
"""Manager class for manipulating federation protocols."""
resource_class = Protocol
collection_key = 'protocols'
key = 'protocol'
base_url = 'OS-FEDERATION/identity_providers'
def build_url(self, dict_args_in_out=None):
"""Build URL for federation protocols."""
if dict_args_in_out is None:
dict_args_in_out = {}
identity_provider_id = dict_args_in_out.pop('identity_provider_id',
None)
if identity_provider_id:
base_url = '/'.join([self.base_url, identity_provider_id])
else:
base_url = self.base_url
dict_args_in_out.setdefault('base_url', base_url)
return super(ProtocolManager, self).build_url(dict_args_in_out)
def _build_url_and_put(self, request_body=None, **kwargs):
url = self.build_url(dict_args_in_out=kwargs)
body = {self.key: request_body}
return self._update(url, body=body,
response_key=self.key,
method='PUT')
@utils.positional.method(3)
def create(self, protocol_id, identity_provider, mapping, **kwargs):
"""Create federation protocol object and tie to the Identity Provider.
Utilize Identity API operation:
PUT /OS-FEDERATION/identity_providers/
$identity_provider/protocols/$protocol
:param protocol_id: a string type parameter identifying a federation
protocol
:param identity_provider: a string type parameter identifying an
Identity Provider
:param mapping: a base.Resource object with federation mapping id
"""
return self._build_url_and_put(
request_body={'mapping_id': base.getid(mapping)},
identity_provider_id=base.getid(identity_provider),
protocol_id=protocol_id, **kwargs)
def get(self, identity_provider, protocol, **kwargs):
"""Fetch federation protocol object tied to the Identity Provider.
Utilize Identity API operation:
GET /OS-FEDERATION/identity_providers/
$identity_provider/protocols/$protocol
:param identity_provider: a base.Resource type object with Identity
Provider id stored inside
:param protocol: a base.Resource type object with federation protocol
id stored inside
"""
return super(ProtocolManager, self).get(
identity_provider_id=base.getid(identity_provider),
protocol_id=base.getid(protocol), **kwargs)
def list(self, identity_provider, **kwargs):
"""List all federation protocol objects tied to the Identity Provider.
Utilize Identity API operation:
GET /OS-FEDERATION/identity_providers/
$identity_provider/protocols
:param identity_provider: a base.Resource type object with Identity
Provider id stored inside
"""
return super(ProtocolManager, self).list(
identity_provider_id=base.getid(identity_provider), **kwargs)
def update(self, identity_provider, protocol, mapping, **kwargs):
"""Update Protocol object tied to the Identity Provider.
Utilize Identity API operation:
PATCH /OS-FEDERATION/identity_providers/
$identity_provider/protocols/$protocol
:param identity_provider: a base.Resource type object with Identity
Provider id stored inside
:param protocol: a base.Resource type object with federation protocol
id stored inside
:param mapping: a base.Resource object with federation mapping id
"""
return super(ProtocolManager, self).update(
identity_provider_id=base.getid(identity_provider),
protocol_id=base.getid(protocol), mapping_id=base.getid(mapping),
**kwargs)
def delete(self, identity_provider, protocol):
"""Delete Protocol object tied to the Identity Provider.
Utilize Identity API operation:
DELETE /OS-FEDERATION/identity_providers/
$identity_provider/protocols/$protocol
:param identity_provider: a base.Resource type object with
Identity Provider id stored inside
:param protocol: a base.Resource type object with federation
protocol id stored inside
"""
return super(ProtocolManager, self).delete(
identity_provider_id=base.getid(identity_provider),
protocol_id=base.getid(protocol))