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:

committed by
Steve Martinelli

parent
90abb4cfb2
commit
9dbdb3a651
@@ -10,13 +10,16 @@
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
|
||||
import copy
|
||||
import uuid
|
||||
|
||||
import httpretty
|
||||
|
||||
from keystoneclient import exceptions
|
||||
from keystoneclient.tests.v3 import utils
|
||||
from keystoneclient.v3.contrib.federation import identity_providers
|
||||
from keystoneclient.v3.contrib.federation import mappings
|
||||
from keystoneclient.v3.contrib.federation import protocols
|
||||
|
||||
|
||||
class IdentityProviderTests(utils.TestCase, utils.CrudTests):
|
||||
@@ -125,3 +128,198 @@ class MappingTests(utils.TestCase, utils.CrudTests):
|
||||
req_ref[attr],
|
||||
'Expected different %s' % attr)
|
||||
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)
|
||||
|
@@ -12,6 +12,7 @@
|
||||
|
||||
from keystoneclient.v3.contrib.federation import identity_providers
|
||||
from keystoneclient.v3.contrib.federation import mappings
|
||||
from keystoneclient.v3.contrib.federation import protocols
|
||||
|
||||
|
||||
class FederationManager(object):
|
||||
@@ -19,3 +20,4 @@ class FederationManager(object):
|
||||
self.identity_providers = identity_providers.IdentityProviderManager(
|
||||
api)
|
||||
self.mappings = mappings.MappingManager(api)
|
||||
self.protocols = protocols.ProtocolManager(api)
|
||||
|
145
keystoneclient/v3/contrib/federation/protocols.py
Normal file
145
keystoneclient/v3/contrib/federation/protocols.py
Normal 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))
|
Reference in New Issue
Block a user