Add support to remote_id

The federation APIs for the identity providers introduce a new parameter
for every identity provider, named remote_ids, which contains a list of
entity ID associated with. This parameter can be provided during the creation
of the identity provider and can be updated at any time. For more information
look at the blueprint:

https://blueprints.launchpad.net/keystone/+spec/idp-id-registration

This patch add the support to this new parameter in the command line by
inserting the option "--remote-id" in the following commands:

- "identity provider create"
- "identity provider set"

Additionally, the values can be read from a file, specified by
"--remote-id-file", containing an entity id per line.

Change-Id: Ie93340ee57e54128daa70d8a7bd0a9975ff7eef4
Depends-On: I12a262c55b5f6b5cc7007865edf30f14269da537
Implements: blueprint idp-id-registration
This commit is contained in:
Marco Fargetta 2015-03-04 17:24:07 +01:00 committed by Steve Martinelli
parent 33313eac5a
commit 6a9d6af225
4 changed files with 314 additions and 14 deletions

View File

@ -15,10 +15,21 @@ Create new identity provider
.. code:: bash
os identity provider create
[--remote-id <remote-id> [...] | --remote-id-file <file-name>]
[--description <description>]
[--enable | --disable]
<name>
.. option:: --remote-id <remote-id>
Remote IDs to associate with the Identity Provider (repeat to provide
multiple values)
.. option:: --remote-id-file <file-name>
Name of a file that contains many remote IDs to associate with the identity
provider, one per line
.. option:: --description
New identity provider description
@ -69,9 +80,20 @@ Set identity provider properties
.. code:: bash
os identity provider set
[--remote-id <remote-id> [...] | --remote-id-file <file-name>]
[--enable | --disable]
<identity-provider>
.. option:: --remote-id <remote-id>
Remote IDs to associate with the Identity Provider (repeat to provide
multiple values)
.. option:: --remote-id-file <file-name>
Name of a file that contains many remote IDs to associate with the identity
provider, one per line
.. option:: --enable
Enable the identity provider

View File

@ -35,6 +35,20 @@ class CreateIdentityProvider(show.ShowOne):
metavar='<name>',
help='New identity provider name (must be unique)'
)
identity_remote_id_provider = parser.add_mutually_exclusive_group()
identity_remote_id_provider.add_argument(
'--remote-id',
metavar='<remote-id>',
action='append',
help='Remote IDs to associate with the Identity Provider '
'(repeat to provide multiple values)'
)
identity_remote_id_provider.add_argument(
'--remote-id-file',
metavar='<file-name>',
help='Name of a file that contains many remote IDs to associate '
'with the identity provider, one per line'
)
parser.add_argument(
'--description',
metavar='<description>',
@ -59,8 +73,17 @@ class CreateIdentityProvider(show.ShowOne):
def take_action(self, parsed_args):
self.log.debug('take_action(%s)', parsed_args)
identity_client = self.app.client_manager.identity
if parsed_args.remote_id_file:
file_content = utils.read_blob_file_contents(
parsed_args.remote_id_file)
remote_ids = file_content.splitlines()
remote_ids = list(map(str.strip, remote_ids))
else:
remote_ids = (parsed_args.remote_id
if parsed_args.remote_id else None)
idp = identity_client.federation.identity_providers.create(
id=parsed_args.identity_provider_id,
remote_ids=remote_ids,
description=parsed_args.description,
enabled=parsed_args.enabled)
@ -119,6 +142,20 @@ class SetIdentityProvider(command.Command):
metavar='<identity-provider>',
help='Identity provider to modify',
)
identity_remote_id_provider = parser.add_mutually_exclusive_group()
identity_remote_id_provider.add_argument(
'--remote-id',
metavar='<remote-id>',
action='append',
help='Remote IDs to associate with the Identity Provider '
'(repeat to provide multiple values)'
)
identity_remote_id_provider.add_argument(
'--remote-id-file',
metavar='<file-name>',
help='Name of a file that contains many remote IDs to associate '
'with the identity provider, one per line'
)
enable_identity_provider = parser.add_mutually_exclusive_group()
enable_identity_provider.add_argument(
'--enable',
@ -136,16 +173,33 @@ class SetIdentityProvider(command.Command):
self.log.debug('take_action(%s)', parsed_args)
federation_client = self.app.client_manager.identity.federation
if parsed_args.enable is True:
enabled = True
elif parsed_args.disable is True:
enabled = False
else:
self.log.error("No changes requested")
# Basic argument checking
if (not parsed_args.enable and not parsed_args.disable and not
parsed_args.remote_id and not parsed_args.remote_id_file):
self.log.error('No changes requested')
return (None, None)
# Always set remote_ids if either is passed in
if parsed_args.remote_id_file:
file_content = utils.read_blob_file_contents(
parsed_args.remote_id_file)
remote_ids = file_content.splitlines()
remote_ids = list(map(str.strip, remote_ids))
elif parsed_args.remote_id:
remote_ids = parsed_args.remote_id
# Setup keyword args for the client
kwargs = {}
if parsed_args.enable:
kwargs['enabled'] = True
if parsed_args.disable:
kwargs['enabled'] = False
if parsed_args.remote_id_file or parsed_args.remote_id:
kwargs['remote_ids'] = remote_ids
identity_provider = federation_client.identity_providers.update(
parsed_args.identity_provider, enabled=enabled)
parsed_args.identity_provider, **kwargs)
identity_provider._info.pop('links', None)
return zip(*sorted(six.iteritems(identity_provider._info)))

View File

@ -231,9 +231,11 @@ TOKEN_WITH_DOMAIN_ID = {
idp_id = 'test_idp'
idp_description = 'super exciting IdP description'
idp_remote_ids = ['entity1', 'entity2']
IDENTITY_PROVIDER = {
'id': idp_id,
'remote_ids': idp_remote_ids,
'enabled': True,
'description': idp_description
}

View File

@ -14,6 +14,8 @@
import copy
import mock
from openstackclient.identity.v3 import identity_provider
from openstackclient.tests import fakes
from openstackclient.tests.identity.v3 import fakes as identity_fakes
@ -51,6 +53,7 @@ class TestIdentityProviderCreate(TestIdentityProvider):
# Set expected values
kwargs = {
'remote_ids': None,
'enabled': True,
'description': None,
}
@ -60,12 +63,13 @@ class TestIdentityProviderCreate(TestIdentityProvider):
**kwargs
)
collist = ('description', 'enabled', 'id')
collist = ('description', 'enabled', 'id', 'remote_ids')
self.assertEqual(collist, columns)
datalist = (
identity_fakes.idp_description,
True,
identity_fakes.idp_id,
identity_fakes.idp_remote_ids
)
self.assertEqual(datalist, data)
@ -83,6 +87,7 @@ class TestIdentityProviderCreate(TestIdentityProvider):
# Set expected values
kwargs = {
'remote_ids': None,
'description': identity_fakes.idp_description,
'enabled': True,
}
@ -92,12 +97,121 @@ class TestIdentityProviderCreate(TestIdentityProvider):
**kwargs
)
collist = ('description', 'enabled', 'id')
collist = ('description', 'enabled', 'id', 'remote_ids')
self.assertEqual(collist, columns)
datalist = (
identity_fakes.idp_description,
True,
identity_fakes.idp_id,
identity_fakes.idp_remote_ids
)
self.assertEqual(datalist, data)
def test_create_identity_provider_remote_id(self):
arglist = [
identity_fakes.idp_id,
'--remote-id', identity_fakes.idp_remote_ids[0]
]
verifylist = [
('identity_provider_id', identity_fakes.idp_id),
('remote_id', identity_fakes.idp_remote_ids[:1]),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
# Set expected values
kwargs = {
'remote_ids': identity_fakes.idp_remote_ids[:1],
'description': None,
'enabled': True,
}
self.identity_providers_mock.create.assert_called_with(
id=identity_fakes.idp_id,
**kwargs
)
collist = ('description', 'enabled', 'id', 'remote_ids')
self.assertEqual(collist, columns)
datalist = (
identity_fakes.idp_description,
True,
identity_fakes.idp_id,
identity_fakes.idp_remote_ids
)
self.assertEqual(datalist, data)
def test_create_identity_provider_remote_ids_multiple(self):
arglist = [
'--remote-id', identity_fakes.idp_remote_ids[0],
'--remote-id', identity_fakes.idp_remote_ids[1],
identity_fakes.idp_id
]
verifylist = [
('identity_provider_id', identity_fakes.idp_id),
('remote_id', identity_fakes.idp_remote_ids),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
# Set expected values
kwargs = {
'remote_ids': identity_fakes.idp_remote_ids,
'description': None,
'enabled': True,
}
self.identity_providers_mock.create.assert_called_with(
id=identity_fakes.idp_id,
**kwargs
)
collist = ('description', 'enabled', 'id', 'remote_ids')
self.assertEqual(collist, columns)
datalist = (
identity_fakes.idp_description,
True,
identity_fakes.idp_id,
identity_fakes.idp_remote_ids
)
self.assertEqual(datalist, data)
def test_create_identity_provider_remote_ids_file(self):
arglist = [
'--remote-id-file', '/tmp/file_name',
identity_fakes.idp_id,
]
verifylist = [
('identity_provider_id', identity_fakes.idp_id),
('remote_id_file', '/tmp/file_name'),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
mocker = mock.Mock()
mocker.return_value = "\n".join(identity_fakes.idp_remote_ids)
with mock.patch("openstackclient.identity.v3.identity_provider."
"utils.read_blob_file_contents", mocker):
columns, data = self.cmd.take_action(parsed_args)
# Set expected values
kwargs = {
'remote_ids': identity_fakes.idp_remote_ids,
'description': None,
'enabled': True,
}
self.identity_providers_mock.create.assert_called_with(
id=identity_fakes.idp_id,
**kwargs
)
collist = ('description', 'enabled', 'id', 'remote_ids')
self.assertEqual(collist, columns)
datalist = (
identity_fakes.idp_description,
True,
identity_fakes.idp_id,
identity_fakes.idp_remote_ids
)
self.assertEqual(datalist, data)
@ -123,6 +237,7 @@ class TestIdentityProviderCreate(TestIdentityProvider):
# Set expected values
kwargs = {
'remote_ids': None,
'enabled': False,
'description': None,
}
@ -132,12 +247,13 @@ class TestIdentityProviderCreate(TestIdentityProvider):
**kwargs
)
collist = ('description', 'enabled', 'id')
collist = ('description', 'enabled', 'id', 'remote_ids')
self.assertEqual(collist, columns)
datalist = (
None,
False,
identity_fakes.idp_id,
identity_fakes.idp_remote_ids
)
self.assertEqual(datalist, data)
@ -241,12 +357,13 @@ class TestIdentityProviderShow(TestIdentityProvider):
identity_fakes.idp_id,
)
collist = ('description', 'enabled', 'id')
collist = ('description', 'enabled', 'id', 'remote_ids')
self.assertEqual(collist, columns)
datalist = (
identity_fakes.idp_description,
True,
identity_fakes.idp_id,
identity_fakes.idp_remote_ids
)
self.assertEqual(datalist, data)
@ -276,11 +393,14 @@ class TestIdentityProviderSet(TestIdentityProvider):
prepare(self)
arglist = [
'--disable', identity_fakes.idp_id,
'--remote-id', identity_fakes.idp_remote_ids[0],
'--remote-id', identity_fakes.idp_remote_ids[1]
]
verifylist = [
('identity_provider', identity_fakes.idp_id),
('enable', False),
('disable', True),
('remote_id', identity_fakes.idp_remote_ids)
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
@ -288,14 +408,16 @@ class TestIdentityProviderSet(TestIdentityProvider):
self.identity_providers_mock.update.assert_called_with(
identity_fakes.idp_id,
enabled=False,
remote_ids=identity_fakes.idp_remote_ids
)
collist = ('description', 'enabled', 'id')
collist = ('description', 'enabled', 'id', 'remote_ids')
self.assertEqual(collist, columns)
datalist = (
identity_fakes.idp_description,
False,
identity_fakes.idp_id,
identity_fakes.idp_remote_ids
)
self.assertEqual(datalist, data)
@ -316,23 +438,122 @@ class TestIdentityProviderSet(TestIdentityProvider):
prepare(self)
arglist = [
'--enable', identity_fakes.idp_id,
'--remote-id', identity_fakes.idp_remote_ids[0],
'--remote-id', identity_fakes.idp_remote_ids[1]
]
verifylist = [
('identity_provider', identity_fakes.idp_id),
('enable', True),
('disable', False),
('remote_id', identity_fakes.idp_remote_ids)
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
self.identity_providers_mock.update.assert_called_with(
identity_fakes.idp_id, enabled=True)
collist = ('description', 'enabled', 'id')
identity_fakes.idp_id, enabled=True,
remote_ids=identity_fakes.idp_remote_ids)
collist = ('description', 'enabled', 'id', 'remote_ids')
self.assertEqual(collist, columns)
datalist = (
identity_fakes.idp_description,
True,
identity_fakes.idp_id,
identity_fakes.idp_remote_ids
)
self.assertEqual(datalist, data)
def test_identity_provider_replace_remote_ids(self):
"""Enable Identity Provider.
Set Identity Provider's ``enabled`` attribute to True.
"""
def prepare(self):
"""Prepare fake return objects before the test is executed"""
self.new_remote_id = 'new_entity'
updated_idp = copy.deepcopy(identity_fakes.IDENTITY_PROVIDER)
updated_idp['remote_ids'] = [self.new_remote_id]
resources = fakes.FakeResource(
None,
updated_idp,
loaded=True
)
self.identity_providers_mock.update.return_value = resources
prepare(self)
arglist = [
'--enable', identity_fakes.idp_id,
'--remote-id', self.new_remote_id
]
verifylist = [
('identity_provider', identity_fakes.idp_id),
('enable', True),
('disable', False),
('remote_id', [self.new_remote_id])
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
columns, data = self.cmd.take_action(parsed_args)
self.identity_providers_mock.update.assert_called_with(
identity_fakes.idp_id, enabled=True,
remote_ids=[self.new_remote_id])
collist = ('description', 'enabled', 'id', 'remote_ids')
self.assertEqual(collist, columns)
datalist = (
identity_fakes.idp_description,
True,
identity_fakes.idp_id,
[self.new_remote_id]
)
self.assertEqual(datalist, data)
def test_identity_provider_replace_remote_ids_file(self):
"""Enable Identity Provider.
Set Identity Provider's ``enabled`` attribute to True.
"""
def prepare(self):
"""Prepare fake return objects before the test is executed"""
self.new_remote_id = 'new_entity'
updated_idp = copy.deepcopy(identity_fakes.IDENTITY_PROVIDER)
updated_idp['remote_ids'] = [self.new_remote_id]
resources = fakes.FakeResource(
None,
updated_idp,
loaded=True
)
self.identity_providers_mock.update.return_value = resources
prepare(self)
arglist = [
'--enable', identity_fakes.idp_id,
'--remote-id-file', self.new_remote_id,
]
verifylist = [
('identity_provider', identity_fakes.idp_id),
('enable', True),
('disable', False),
('remote_id_file', self.new_remote_id),
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
mocker = mock.Mock()
mocker.return_value = self.new_remote_id
with mock.patch("openstackclient.identity.v3.identity_provider."
"utils.read_blob_file_contents", mocker):
columns, data = self.cmd.take_action(parsed_args)
self.identity_providers_mock.update.assert_called_with(
identity_fakes.idp_id, enabled=True,
remote_ids=[self.new_remote_id])
collist = ('description', 'enabled', 'id', 'remote_ids')
self.assertEqual(collist, columns)
datalist = (
identity_fakes.idp_description,
True,
identity_fakes.idp_id,
[self.new_remote_id]
)
self.assertEqual(datalist, data)
@ -361,6 +582,7 @@ class TestIdentityProviderSet(TestIdentityProvider):
('identity_provider', identity_fakes.idp_id),
('enable', False),
('disable', False),
('remote_id', None)
]
parsed_args = self.check_parser(self.cmd, arglist, verifylist)