summaryrefslogtreecommitdiff
path: root/openstackclient
diff options
context:
space:
mode:
authorJenkins <jenkins@review.openstack.org>2016-07-23 00:04:39 +0000
committerGerrit Code Review <review@openstack.org>2016-07-23 00:04:39 +0000
commita8880e8b34c1a0609a7b1c8f54de1f0199969a1c (patch)
tree8472911032bc30975f8fc8b151bf8eeae4e3c480 /openstackclient
parent02e95dc8ff62d978af802f525bd07915ff423e23 (diff)
parent713d92df4e53f74698a1ff2dfcb7514ff22f023b (diff)
downloadpython-openstackclient-a8880e8b34c1a0609a7b1c8f54de1f0199969a1c.tar.gz
Merge "Add assignment list to v2 identity and deprecate alternate listing"
Diffstat (limited to 'openstackclient')
-rw-r--r--openstackclient/identity/v2_0/role.py16
-rw-r--r--openstackclient/identity/v2_0/role_assignment.py113
-rw-r--r--openstackclient/identity/v3/role.py20
-rw-r--r--openstackclient/identity/v3/role_assignment.py26
-rw-r--r--openstackclient/tests/identity/v2_0/fakes.py5
-rw-r--r--openstackclient/tests/identity/v2_0/test_role_assignment.py270
-rw-r--r--openstackclient/tests/identity/v3/test_role_assignment.py60
7 files changed, 510 insertions, 0 deletions
diff --git a/openstackclient/identity/v2_0/role.py b/openstackclient/identity/v2_0/role.py
index 191cdaa3..b4b67bad 100644
--- a/openstackclient/identity/v2_0/role.py
+++ b/openstackclient/identity/v2_0/role.py
@@ -150,6 +150,15 @@ class ListRole(command.Lister):
return parser
def take_action(self, parsed_args):
+
+ def _deprecated():
+ # NOTE(henry-nash): Deprecated as of Newton, so we should remove
+ # this in the 'P' release.
+ self.log.warning(_('Listing assignments using role list is '
+ 'deprecated as of the Newton release. Use role '
+ 'assignment list --user <user-name> --project '
+ '<project-name> --names instead.'))
+
identity_client = self.app.client_manager.identity
auth_ref = self.app.client_manager.auth_ref
@@ -166,6 +175,7 @@ class ListRole(command.Lister):
identity_client.projects,
parsed_args.project,
)
+ _deprecated()
data = identity_client.roles.roles_for_user(user.id, project.id)
elif parsed_args.user:
@@ -181,6 +191,7 @@ class ListRole(command.Lister):
else:
msg = _("Project must be specified")
raise exceptions.CommandError(msg)
+ _deprecated()
data = identity_client.roles.roles_for_user(user.id, project.id)
elif parsed_args.project:
project = utils.find_resource(
@@ -195,6 +206,7 @@ class ListRole(command.Lister):
else:
msg = _("User must be specified")
raise exceptions.CommandError(msg)
+ _deprecated()
data = identity_client.roles.roles_for_user(user.id, project.id)
if parsed_args.user or parsed_args.project:
@@ -249,6 +261,10 @@ class ListUserRole(command.Lister):
msg = _("User must be specified")
raise exceptions.CommandError(msg)
+ self.log.warning(_('Listing assignments using user role list is '
+ 'deprecated as of the Newton release. Use role '
+ 'assignment list --user <user-name> --project '
+ '<project-name> --names instead.'))
project = utils.find_resource(
identity_client.tenants,
parsed_args.project,
diff --git a/openstackclient/identity/v2_0/role_assignment.py b/openstackclient/identity/v2_0/role_assignment.py
new file mode 100644
index 00000000..406508ac
--- /dev/null
+++ b/openstackclient/identity/v2_0/role_assignment.py
@@ -0,0 +1,113 @@
+# 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.
+#
+
+"""Identity v2 Assignment action implementations """
+
+from openstackclient.common import command
+from openstackclient.common import exceptions
+from openstackclient.common import utils
+from openstackclient.i18n import _ # noqa
+
+
+class ListRoleAssignment(command.Lister):
+ """List role assignments"""
+
+ def get_parser(self, prog_name):
+ parser = super(ListRoleAssignment, self).get_parser(prog_name)
+ parser.add_argument(
+ '--user',
+ metavar='<user>',
+ help='User to filter (name or ID)',
+ )
+ parser.add_argument(
+ '--project',
+ metavar='<project>',
+ help='Project to filter (name or ID)',
+ )
+ parser.add_argument(
+ '--names',
+ action="store_true",
+ help='Display names instead of IDs',
+ )
+ parser.add_argument(
+ '--auth-user',
+ action="store_true",
+ dest='authuser',
+ help='Only list assignments for the authenticated user',
+ )
+ parser.add_argument(
+ '--auth-project',
+ action="store_true",
+ dest='authproject',
+ help='Only list assignments for the project to which the '
+ 'authenticated user\'s token is scoped',
+ )
+ return parser
+
+ def take_action(self, parsed_args):
+ identity_client = self.app.client_manager.identity
+ auth_ref = self.app.client_manager.auth_ref
+
+ include_names = True if parsed_args.names else False
+
+ user = None
+ if parsed_args.user:
+ user = utils.find_resource(
+ identity_client.users,
+ parsed_args.user,
+ )
+ elif parsed_args.authuser:
+ if auth_ref:
+ user = utils.find_resource(
+ identity_client.users,
+ auth_ref.user_id
+ )
+
+ project = None
+ if parsed_args.project:
+ project = utils.find_resource(
+ identity_client.projects,
+ parsed_args.project,
+ )
+ elif parsed_args.authproject:
+ if auth_ref:
+ project = utils.find_resource(
+ identity_client.projects,
+ auth_ref.project_id
+ )
+
+ # If user or project is not specified, we would ideally list all
+ # relevant assignments in the system (to be compatible with v3).
+ # However, there is no easy way of doing that in v2.
+ if not user or not project:
+ msg = _("Project and User must be specified")
+ raise exceptions.CommandError(msg)
+ else:
+ data = identity_client.roles.roles_for_user(user.id, project.id)
+
+ columns = ('Role', 'User', 'Project')
+ for user_role in data:
+ if include_names:
+ setattr(user_role, 'role', user_role.name)
+ user_role.user = user.name
+ user_role.project = project.name
+ else:
+ setattr(user_role, 'role', user_role.id)
+ user_role.user = user.id
+ user_role.project = project.id
+
+ return (columns,
+ (utils.get_item_properties(
+ s, columns,
+ formatters={},
+ ) for s in data))
diff --git a/openstackclient/identity/v3/role.py b/openstackclient/identity/v3/role.py
index 27380179..e8a03ff3 100644
--- a/openstackclient/identity/v3/role.py
+++ b/openstackclient/identity/v3/role.py
@@ -251,6 +251,10 @@ class ListRole(command.Lister):
for user_role in data:
user_role.user = user.name
user_role.domain = domain.name
+ self.log.warning(_('Listing assignments using role list is '
+ 'deprecated. Use role assignment list --user '
+ '<user-name> --domain <domain-name> --names '
+ 'instead.'))
elif parsed_args.user and parsed_args.project:
columns = ('ID', 'Name', 'Project', 'User')
data = identity_client.roles.list(
@@ -261,6 +265,10 @@ class ListRole(command.Lister):
for user_role in data:
user_role.user = user.name
user_role.project = project.name
+ self.log.warning(_('Listing assignments using role list is '
+ 'deprecated. Use role assignment list --user '
+ '<user-name> --project <project-name> --names '
+ 'instead.'))
elif parsed_args.user:
columns = ('ID', 'Name')
data = identity_client.roles.list(
@@ -268,6 +276,10 @@ class ListRole(command.Lister):
domain='default',
os_inherit_extension_inherited=parsed_args.inherited
)
+ self.log.warning(_('Listing assignments using role list is '
+ 'deprecated. Use role assignment list --user '
+ '<user-name> --domain default --names '
+ 'instead.'))
elif parsed_args.group and parsed_args.domain:
columns = ('ID', 'Name', 'Domain', 'Group')
data = identity_client.roles.list(
@@ -278,6 +290,10 @@ class ListRole(command.Lister):
for group_role in data:
group_role.group = group.name
group_role.domain = domain.name
+ self.log.warning(_('Listing assignments using role list is '
+ 'deprecated. Use role assignment list --group '
+ '<group-name> --domain <domain-name> --names '
+ 'instead.'))
elif parsed_args.group and parsed_args.project:
columns = ('ID', 'Name', 'Project', 'Group')
data = identity_client.roles.list(
@@ -288,6 +304,10 @@ class ListRole(command.Lister):
for group_role in data:
group_role.group = group.name
group_role.project = project.name
+ self.log.warning(_('Listing assignments using role list is '
+ 'deprecated. Use role assignment list --group '
+ '<group-name> --project <project-name> --names '
+ 'instead.'))
else:
sys.stderr.write(_("Error: If a user or group is specified, "
"either --domain or --project must also be "
diff --git a/openstackclient/identity/v3/role_assignment.py b/openstackclient/identity/v3/role_assignment.py
index 39e2336d..6177d1a5 100644
--- a/openstackclient/identity/v3/role_assignment.py
+++ b/openstackclient/identity/v3/role_assignment.py
@@ -67,6 +67,19 @@ class ListRoleAssignment(command.Lister):
)
common.add_project_domain_option_to_parser(parser)
common.add_inherited_option_to_parser(parser)
+ parser.add_argument(
+ '--auth-user',
+ action="store_true",
+ dest='authuser',
+ help='Only list assignments for the authenticated user',
+ )
+ parser.add_argument(
+ '--auth-project',
+ action="store_true",
+ dest='authproject',
+ help='Only list assignments for the project to which the '
+ 'authenticated user\'s token is scoped',
+ )
return parser
def _as_tuple(self, assignment):
@@ -75,6 +88,7 @@ class ListRoleAssignment(command.Lister):
def take_action(self, parsed_args):
identity_client = self.app.client_manager.identity
+ auth_ref = self.app.client_manager.auth_ref
role = None
if parsed_args.role:
@@ -90,6 +104,12 @@ class ListRoleAssignment(command.Lister):
parsed_args.user,
parsed_args.user_domain,
)
+ elif parsed_args.authuser:
+ if auth_ref:
+ user = common.find_user(
+ identity_client,
+ auth_ref.user_id
+ )
domain = None
if parsed_args.domain:
@@ -105,6 +125,12 @@ class ListRoleAssignment(command.Lister):
parsed_args.project,
parsed_args.project_domain,
)
+ elif parsed_args.authproject:
+ if auth_ref:
+ project = common.find_project(
+ identity_client,
+ auth_ref.project_id
+ )
group = None
if parsed_args.group:
diff --git a/openstackclient/tests/identity/v2_0/fakes.py b/openstackclient/tests/identity/v2_0/fakes.py
index 662d56b6..a715427c 100644
--- a/openstackclient/tests/identity/v2_0/fakes.py
+++ b/openstackclient/tests/identity/v2_0/fakes.py
@@ -50,6 +50,11 @@ ROLE = {
'name': role_name,
}
+ROLE_2 = {
+ 'id': '2',
+ 'name': 'bigboss',
+}
+
service_id = '1925-10-11'
service_name = 'elmore'
service_description = 'Leonard, Elmore, rip'
diff --git a/openstackclient/tests/identity/v2_0/test_role_assignment.py b/openstackclient/tests/identity/v2_0/test_role_assignment.py
new file mode 100644
index 00000000..ab48c2f4
--- /dev/null
+++ b/openstackclient/tests/identity/v2_0/test_role_assignment.py
@@ -0,0 +1,270 @@
+# 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 copy
+import mock
+
+from openstackclient.common import exceptions
+from openstackclient.identity.v2_0 import role_assignment
+from openstackclient.tests import fakes
+from openstackclient.tests.identity.v2_0 import fakes as identity_fakes
+
+
+class TestRoleAssignment(identity_fakes.TestIdentityv2):
+
+ def setUp(self):
+ super(TestRoleAssignment, self).setUp()
+
+
+class TestRoleAssignmentList(TestRoleAssignment):
+
+ columns = (
+ 'Role',
+ 'User',
+ 'Project',
+ )
+
+ def setUp(self):
+ super(TestRoleAssignment, self).setUp()
+
+ # Get a shortcut to the UserManager Mock
+ self.users_mock = self.app.client_manager.identity.users
+ self.users_mock.reset_mock()
+
+ # Get a shortcut to the ProjectManager Mock
+ self.projects_mock = self.app.client_manager.identity.projects
+ self.projects_mock.reset_mock()
+
+ # Get a shortcut to the RoleManager Mock
+ self.roles_mock = self.app.client_manager.identity.roles
+ self.roles_mock.reset_mock()
+
+ self.projects_mock.get.return_value = fakes.FakeResource(
+ None,
+ copy.deepcopy(identity_fakes.PROJECT),
+ loaded=True,
+ )
+
+ self.users_mock.get.return_value = fakes.FakeResource(
+ None,
+ copy.deepcopy(identity_fakes.USER),
+ loaded=True,
+ )
+
+ self.roles_mock.roles_for_user.return_value = [
+ fakes.FakeResource(
+ None,
+ copy.deepcopy(identity_fakes.ROLE),
+ loaded=True,
+ ),
+ ]
+
+ # Get the command object to test
+ self.cmd = role_assignment.ListRoleAssignment(self.app, None)
+
+ def test_role_assignment_list_no_filters(self):
+
+ arglist = []
+ verifylist = []
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ # This argument combination should raise a CommandError
+ self.assertRaises(
+ exceptions.CommandError,
+ self.cmd.take_action,
+ parsed_args,
+ )
+
+ def test_role_assignment_list_only_project_filter(self):
+
+ arglist = [
+ '--project', identity_fakes.project_name,
+ ]
+ verifylist = [
+ ('project', identity_fakes.project_name),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ # This argument combination should raise a CommandError
+ self.assertRaises(
+ exceptions.CommandError,
+ self.cmd.take_action,
+ parsed_args,
+ )
+
+ def test_role_assignment_list_only_user_filter(self):
+
+ arglist = [
+ '--user', identity_fakes.user_name,
+ ]
+ verifylist = [
+ ('user', identity_fakes.user_name),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ # This argument combination should raise a CommandError
+ self.assertRaises(
+ exceptions.CommandError,
+ self.cmd.take_action,
+ parsed_args,
+ )
+
+ def test_role_assignment_list_project_and_user(self):
+
+ self.roles_mock.roles_for_user.return_value = [
+ fakes.FakeResource(
+ None,
+ copy.deepcopy(
+ identity_fakes.ROLE),
+ loaded=True,
+ ),
+ fakes.FakeResource(
+ None,
+ copy.deepcopy(
+ identity_fakes.ROLE_2),
+ loaded=True,
+ ),
+ ]
+
+ arglist = [
+ '--project', identity_fakes.project_name,
+ '--user', identity_fakes.user_name,
+ ]
+ verifylist = [
+ ('user', identity_fakes.user_name),
+ ('project', identity_fakes.project_name),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ # In base command class Lister in cliff, abstract method take_action()
+ # returns a tuple containing the column names and an iterable
+ # containing the data to be listed.
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.roles_mock.roles_for_user.assert_called_with(
+ identity_fakes.user_id,
+ identity_fakes.project_id,
+ )
+
+ self.assertEqual(self.columns, columns)
+ datalist = ((
+ identity_fakes.role_id,
+ identity_fakes.user_id,
+ identity_fakes.project_id,
+ ), (identity_fakes.ROLE_2['id'],
+ identity_fakes.user_id,
+ identity_fakes.project_id,
+ ),)
+ self.assertEqual(datalist, tuple(data))
+
+ def test_role_assignment_list_def_creds(self):
+
+ auth_ref = self.app.client_manager.auth_ref = mock.MagicMock()
+ auth_ref.project_id.return_value = identity_fakes.project_id
+ auth_ref.user_id.return_value = identity_fakes.user_id
+
+ self.roles_mock.roles_for_user.return_value = [
+ fakes.FakeResource(
+ None,
+ copy.deepcopy(
+ identity_fakes.ROLE),
+ loaded=True,
+ ),
+ fakes.FakeResource(
+ None,
+ copy.deepcopy(
+ identity_fakes.ROLE_2),
+ loaded=True,
+ ),
+ ]
+
+ arglist = [
+ '--auth-user',
+ '--auth-project',
+ ]
+ verifylist = [
+ ('authuser', True),
+ ('authproject', True),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ # In base command class Lister in cliff, abstract method take_action()
+ # returns a tuple containing the column names and an iterable
+ # containing the data to be listed.
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.roles_mock.roles_for_user.assert_called_with(
+ identity_fakes.user_id,
+ identity_fakes.project_id,
+ )
+
+ self.assertEqual(self.columns, columns)
+ datalist = ((
+ identity_fakes.role_id,
+ identity_fakes.user_id,
+ identity_fakes.project_id,
+ ), (identity_fakes.ROLE_2['id'],
+ identity_fakes.user_id,
+ identity_fakes.project_id,
+ ),)
+ self.assertEqual(datalist, tuple(data))
+
+ def test_role_assignment_list_by_name_project_and_user(self):
+
+ self.roles_mock.roles_for_user.return_value = [
+ fakes.FakeResource(
+ None,
+ copy.deepcopy(
+ identity_fakes.ROLE),
+ loaded=True,
+ ),
+ fakes.FakeResource(
+ None,
+ copy.deepcopy(
+ identity_fakes.ROLE_2),
+ loaded=True,
+ ),
+ ]
+
+ arglist = [
+ '--project', identity_fakes.project_name,
+ '--user', identity_fakes.user_name,
+ '--names'
+ ]
+ verifylist = [
+ ('user', identity_fakes.user_name),
+ ('project', identity_fakes.project_name),
+ ('names', True),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ # In base command class Lister in cliff, abstract method take_action()
+ # returns a tuple containing the column names and an iterable
+ # containing the data to be listed.
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.roles_mock.roles_for_user.assert_called_with(
+ identity_fakes.user_id,
+ identity_fakes.project_id,
+ )
+
+ self.assertEqual(self.columns, columns)
+ datalist = ((
+ identity_fakes.role_name,
+ identity_fakes.user_name,
+ identity_fakes.project_name,
+ ), (identity_fakes.ROLE_2['name'],
+ identity_fakes.user_name,
+ identity_fakes.project_name,
+ ),)
+ self.assertEqual(datalist, tuple(data))
diff --git a/openstackclient/tests/identity/v3/test_role_assignment.py b/openstackclient/tests/identity/v3/test_role_assignment.py
index 8956b74f..0ae67c72 100644
--- a/openstackclient/tests/identity/v3/test_role_assignment.py
+++ b/openstackclient/tests/identity/v3/test_role_assignment.py
@@ -12,6 +12,7 @@
#
import copy
+import mock
from openstackclient.identity.v3 import role_assignment
from openstackclient.tests import fakes
@@ -374,6 +375,65 @@ class TestRoleAssignmentList(TestRoleAssignment):
),)
self.assertEqual(datalist, tuple(data))
+ def test_role_assignment_list_def_creds(self):
+
+ auth_ref = self.app.client_manager.auth_ref = mock.MagicMock()
+ auth_ref.project_id.return_value = identity_fakes.project_id
+ auth_ref.user_id.return_value = identity_fakes.user_id
+
+ self.role_assignments_mock.list.return_value = [
+ fakes.FakeResource(
+ None,
+ copy.deepcopy(
+ identity_fakes.ASSIGNMENT_WITH_PROJECT_ID_AND_USER_ID),
+ loaded=True,
+ ),
+ ]
+
+ arglist = [
+ '--auth-user',
+ '--auth-project',
+ ]
+ verifylist = [
+ ('user', None),
+ ('group', None),
+ ('domain', None),
+ ('project', None),
+ ('role', None),
+ ('effective', False),
+ ('inherited', False),
+ ('names', False),
+ ('authuser', True),
+ ('authproject', True),
+ ]
+ parsed_args = self.check_parser(self.cmd, arglist, verifylist)
+
+ # In base command class Lister in cliff, abstract method take_action()
+ # returns a tuple containing the column names and an iterable
+ # containing the data to be listed.
+ columns, data = self.cmd.take_action(parsed_args)
+
+ self.role_assignments_mock.list.assert_called_with(
+ domain=None,
+ user=self.users_mock.get(),
+ group=None,
+ project=self.projects_mock.get(),
+ role=None,
+ effective=False,
+ os_inherit_extension_inherited_to=None,
+ include_names=False)
+
+ self.assertEqual(self.columns, columns)
+ datalist = ((
+ identity_fakes.role_id,
+ identity_fakes.user_id,
+ '',
+ identity_fakes.project_id,
+ '',
+ False
+ ),)
+ self.assertEqual(datalist, tuple(data))
+
def test_role_assignment_list_effective(self):
self.role_assignments_mock.list.return_value = [