diff --git a/openstackclient/identity/common.py b/openstackclient/identity/common.py index 1f645b7d9..3dc5adbbd 100644 --- a/openstackclient/identity/common.py +++ b/openstackclient/identity/common.py @@ -58,7 +58,7 @@ def find_service(identity_client, name_type_or_id): raise exceptions.CommandError(msg % name_type_or_id) -def _get_token_resource(client, resource, parsed_name): +def _get_token_resource(client, resource, parsed_name, parsed_domain=None): """Peek into the user's auth token to get resource IDs Look into a user's token to try and find the ID of a domain, project or @@ -71,6 +71,8 @@ def _get_token_resource(client, resource, parsed_name): `project_domain`, `user_domain`, `project`, or `user`. :param parsed_name: This is input from parsed_args that the user is hoping to find in the token. + :param parsed_domain: This is domain filter from parsed_args that used to + filter the results. :returns: The ID of the resource from the token, or the original value from parsed_args if it does not match. @@ -85,6 +87,10 @@ def _get_token_resource(client, resource, parsed_name): if resource == 'domain': token_dict = token_dict['project'] obj = token_dict[resource] + + # user/project under different domain may has a same name + if parsed_domain and parsed_domain not in obj['domain'].values(): + return parsed_name return obj['id'] if obj['name'] == parsed_name else parsed_name # diaper defense in case parsing the token fails except Exception: # noqa diff --git a/openstackclient/identity/v3/project.py b/openstackclient/identity/v3/project.py index 873ee9c73..c7806ee17 100644 --- a/openstackclient/identity/v3/project.py +++ b/openstackclient/identity/v3/project.py @@ -360,7 +360,8 @@ class ShowProject(command.ShowOne): identity_client = self.app.client_manager.identity project_str = common._get_token_resource(identity_client, 'project', - parsed_args.project) + parsed_args.project, + parsed_args.domain) if parsed_args.domain: domain = common.find_domain(identity_client, parsed_args.domain) diff --git a/openstackclient/identity/v3/user.py b/openstackclient/identity/v3/user.py index 9c289a6d8..5f4fb544f 100644 --- a/openstackclient/identity/v3/user.py +++ b/openstackclient/identity/v3/user.py @@ -358,7 +358,8 @@ class SetUser(command.Command): "when a user does not have a password.")) user_str = common._get_token_resource(identity_client, 'user', - parsed_args.user) + parsed_args.user, + parsed_args.domain) if parsed_args.domain: domain = common.find_domain(identity_client, parsed_args.domain) user = utils.find_resource(identity_client.users, @@ -473,7 +474,8 @@ class ShowUser(command.ShowOne): identity_client = self.app.client_manager.identity user_str = common._get_token_resource(identity_client, 'user', - parsed_args.user) + parsed_args.user, + parsed_args.domain) if parsed_args.domain: domain = common.find_domain(identity_client, parsed_args.domain) user = utils.find_resource(identity_client.users, diff --git a/openstackclient/tests/unit/identity/v3/test_project.py b/openstackclient/tests/unit/identity/v3/test_project.py index 7be81153c..2ce26c641 100644 --- a/openstackclient/tests/unit/identity/v3/test_project.py +++ b/openstackclient/tests/unit/identity/v3/test_project.py @@ -19,6 +19,7 @@ from mock import call from osc_lib import exceptions from osc_lib import utils +from openstackclient.identity import common from openstackclient.identity.v3 import project from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes @@ -1060,3 +1061,48 @@ class TestProjectShow(TestProject): ['children-id'], ) self.assertEqual(data, datalist) + + def test_project_show_with_domain(self): + project = identity_fakes.FakeProject.create_one_project( + {"name": self.project.name}) + + self.app.client_manager.identity.tokens.get_token_data.return_value = \ + {'token': + {'project': + {'domain': {"id": self.project.domain_id}, + 'name': self.project.name, + 'id': self.project.id + } + } + } + + identity_client = self.app.client_manager.identity + arglist = [ + "--domain", self.domain.id, + project.name, + ] + verifylist = [ + ('domain', self.domain.id), + ('project', project.name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + project_str = common._get_token_resource(identity_client, 'project', + parsed_args.project, + parsed_args.domain) + self.assertEqual(self.project.id, project_str) + + arglist = [ + "--domain", project.domain_id, + project.name, + ] + verifylist = [ + ('domain', project.domain_id), + ('project', project.name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + project_str = common._get_token_resource(identity_client, 'project', + parsed_args.project, + parsed_args.domain) + self.assertEqual(project.name, project_str) diff --git a/openstackclient/tests/unit/identity/v3/test_user.py b/openstackclient/tests/unit/identity/v3/test_user.py index 2ce66e94a..96f507665 100644 --- a/openstackclient/tests/unit/identity/v3/test_user.py +++ b/openstackclient/tests/unit/identity/v3/test_user.py @@ -19,6 +19,7 @@ import mock from osc_lib import exceptions from osc_lib import utils +from openstackclient.identity import common from openstackclient.identity.v3 import user from openstackclient.tests.unit.identity.v3 import fakes as identity_fakes @@ -1091,7 +1092,7 @@ class TestUserShow(TestUser): self.app.client_manager.identity.tokens.get_token_data.return_value = \ {'token': {'user': - {'domain': {}, + {'domain': {'id': self.user.domain_id}, 'id': self.user.id, 'name': self.user.name, } @@ -1126,3 +1127,38 @@ class TestUserShow(TestUser): self.user.name, ) self.assertEqual(datalist, data) + + def test_user_show_with_domain(self): + user = identity_fakes.FakeUser.create_one_user( + {"name": self.user.name}) + identity_client = self.app.client_manager.identity + + arglist = [ + "--domain", self.user.domain_id, + user.name, + ] + verifylist = [ + ('domain', self.user.domain_id), + ('user', user.name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + user_str = common._get_token_resource(identity_client, 'user', + parsed_args.user, + parsed_args.domain) + self.assertEqual(self.user.id, user_str) + + arglist = [ + "--domain", user.domain_id, + user.name, + ] + verifylist = [ + ('domain', user.domain_id), + ('user', user.name), + ] + parsed_args = self.check_parser(self.cmd, arglist, verifylist) + + user_str = common._get_token_resource(identity_client, 'user', + parsed_args.user, + parsed_args.domain) + self.assertEqual(user.name, user_str) diff --git a/releasenotes/notes/bug-1704097-8ff1ce1444b81b04.yaml b/releasenotes/notes/bug-1704097-8ff1ce1444b81b04.yaml new file mode 100644 index 000000000..c20d0c999 --- /dev/null +++ b/releasenotes/notes/bug-1704097-8ff1ce1444b81b04.yaml @@ -0,0 +1,9 @@ +--- +fixes: + - | + Fix an issue when run commands `project show`, `user show` and `user set` + with `--domain` specific, the domain filter won't work if the login user's + project name or user name is same with the resource name user hoping to + get. + + [Bug `1704097 `_]