Merge "Enables retrieval of project's parents and subtree"
This commit is contained in:
commit
ec31a2a12e
@ -171,6 +171,18 @@ Display project details
|
|||||||
|
|
||||||
.. versionadded:: 3
|
.. versionadded:: 3
|
||||||
|
|
||||||
|
.. option:: --parents
|
||||||
|
|
||||||
|
Show the project\'s parents as a list
|
||||||
|
|
||||||
|
.. versionadded:: 3
|
||||||
|
|
||||||
|
.. option:: --children
|
||||||
|
|
||||||
|
Show project\'s subtree (children) as a list
|
||||||
|
|
||||||
|
.. versionadded:: 3
|
||||||
|
|
||||||
.. _project_show-project:
|
.. _project_show-project:
|
||||||
.. describe:: <project>
|
.. describe:: <project>
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ def find_resource(manager, name_or_id, **kwargs):
|
|||||||
# Try to get entity as integer id
|
# Try to get entity as integer id
|
||||||
try:
|
try:
|
||||||
if isinstance(name_or_id, int) or name_or_id.isdigit():
|
if isinstance(name_or_id, int) or name_or_id.isdigit():
|
||||||
return manager.get(int(name_or_id))
|
return manager.get(int(name_or_id), **kwargs)
|
||||||
# FIXME(dtroyer): The exception to catch here is dependent on which
|
# FIXME(dtroyer): The exception to catch here is dependent on which
|
||||||
# client library the manager passed in belongs to.
|
# client library the manager passed in belongs to.
|
||||||
# Eventually this should be pulled from a common set
|
# Eventually this should be pulled from a common set
|
||||||
@ -64,7 +64,7 @@ def find_resource(manager, name_or_id, **kwargs):
|
|||||||
|
|
||||||
# Try directly using the passed value
|
# Try directly using the passed value
|
||||||
try:
|
try:
|
||||||
return manager.get(name_or_id)
|
return manager.get(name_or_id, **kwargs)
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -323,6 +323,18 @@ class ShowProject(show.ShowOne):
|
|||||||
metavar='<domain>',
|
metavar='<domain>',
|
||||||
help='Domain owning <project> (name or ID)',
|
help='Domain owning <project> (name or ID)',
|
||||||
)
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--parents',
|
||||||
|
action='store_true',
|
||||||
|
default=False,
|
||||||
|
help='Show the project\'s parents as a list',
|
||||||
|
)
|
||||||
|
parser.add_argument(
|
||||||
|
'--children',
|
||||||
|
action='store_true',
|
||||||
|
default=False,
|
||||||
|
help='Show project\'s subtree (children) as a list',
|
||||||
|
)
|
||||||
return parser
|
return parser
|
||||||
|
|
||||||
def take_action(self, parsed_args):
|
def take_action(self, parsed_args):
|
||||||
@ -331,14 +343,25 @@ class ShowProject(show.ShowOne):
|
|||||||
|
|
||||||
if parsed_args.domain:
|
if parsed_args.domain:
|
||||||
domain = common.find_domain(identity_client, parsed_args.domain)
|
domain = common.find_domain(identity_client, parsed_args.domain)
|
||||||
project = utils.find_resource(identity_client.projects,
|
project = utils.find_resource(
|
||||||
parsed_args.project,
|
identity_client.projects,
|
||||||
domain_id=domain.id)
|
parsed_args.project,
|
||||||
|
domain_id=domain.id,
|
||||||
|
parents_as_list=parsed_args.parents,
|
||||||
|
subtree_as_list=parsed_args.children)
|
||||||
else:
|
else:
|
||||||
project = utils.find_resource(identity_client.projects,
|
project = utils.find_resource(
|
||||||
parsed_args.project)
|
identity_client.projects,
|
||||||
|
parsed_args.project,
|
||||||
|
parents_as_list=parsed_args.parents,
|
||||||
|
subtree_as_list=parsed_args.children)
|
||||||
|
|
||||||
|
if project._info.get('parents'):
|
||||||
|
project._info['parents'] = [str(p['project']['id'])
|
||||||
|
for p in project._info['parents']]
|
||||||
|
if project._info.get('subtree'):
|
||||||
|
project._info['subtree'] = [str(p['project']['id'])
|
||||||
|
for p in project._info['subtree']]
|
||||||
|
|
||||||
project._info.pop('links')
|
project._info.pop('links')
|
||||||
# TODO(stevemar): Remove the line below when we support multitenancy
|
|
||||||
project._info.pop('parent_id', None)
|
|
||||||
return zip(*sorted(six.iteritems(project._info)))
|
return zip(*sorted(six.iteritems(project._info)))
|
||||||
|
@ -145,6 +145,25 @@ PROJECT_WITH_PARENT = {
|
|||||||
'links': base_url + 'projects/' + (project_id + '-with-parent'),
|
'links': base_url + 'projects/' + (project_id + '-with-parent'),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PROJECT_WITH_GRANDPARENT = {
|
||||||
|
'id': project_id + '-with-grandparent',
|
||||||
|
'name': project_name + ', granny and grandpa',
|
||||||
|
'description': project_description + ' plus another eight?',
|
||||||
|
'enabled': True,
|
||||||
|
'domain_id': domain_id,
|
||||||
|
'parent_id': PROJECT_WITH_PARENT['id'],
|
||||||
|
'links': base_url + 'projects/' + (project_id + '-with-grandparent'),
|
||||||
|
}
|
||||||
|
|
||||||
|
parents = [{'project': PROJECT}]
|
||||||
|
grandparents = [{'project': PROJECT}, {'project': PROJECT_WITH_PARENT}]
|
||||||
|
ids_for_parents = [PROJECT['id']]
|
||||||
|
ids_for_parents_and_grandparents = [PROJECT['id'], PROJECT_WITH_PARENT['id']]
|
||||||
|
|
||||||
|
children = [{'project': PROJECT_WITH_GRANDPARENT}]
|
||||||
|
ids_for_children = [PROJECT_WITH_GRANDPARENT['id']]
|
||||||
|
|
||||||
|
|
||||||
role_id = 'r1'
|
role_id = 'r1'
|
||||||
role_name = 'roller'
|
role_name = 'roller'
|
||||||
|
|
||||||
|
@ -783,6 +783,8 @@ class TestProjectShow(TestProject):
|
|||||||
columns, data = self.cmd.take_action(parsed_args)
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
self.projects_mock.get.assert_called_with(
|
self.projects_mock.get.assert_called_with(
|
||||||
identity_fakes.project_id,
|
identity_fakes.project_id,
|
||||||
|
parents_as_list=False,
|
||||||
|
subtree_as_list=False,
|
||||||
)
|
)
|
||||||
|
|
||||||
collist = ('description', 'domain_id', 'enabled', 'id', 'name')
|
collist = ('description', 'domain_id', 'enabled', 'id', 'name')
|
||||||
@ -795,3 +797,151 @@ class TestProjectShow(TestProject):
|
|||||||
identity_fakes.project_name,
|
identity_fakes.project_name,
|
||||||
)
|
)
|
||||||
self.assertEqual(datalist, data)
|
self.assertEqual(datalist, data)
|
||||||
|
|
||||||
|
def test_project_show_parents(self):
|
||||||
|
project = copy.deepcopy(identity_fakes.PROJECT_WITH_GRANDPARENT)
|
||||||
|
project['parents'] = identity_fakes.grandparents
|
||||||
|
self.projects_mock.get.return_value = fakes.FakeResource(
|
||||||
|
None,
|
||||||
|
project,
|
||||||
|
loaded=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
arglist = [
|
||||||
|
identity_fakes.PROJECT_WITH_GRANDPARENT['id'],
|
||||||
|
'--parents',
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('project', identity_fakes.PROJECT_WITH_GRANDPARENT['id']),
|
||||||
|
('parents', True),
|
||||||
|
('children', False),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
self.projects_mock.get.assert_called_with(
|
||||||
|
identity_fakes.PROJECT_WITH_GRANDPARENT['id'],
|
||||||
|
parents_as_list=True,
|
||||||
|
subtree_as_list=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
collist = (
|
||||||
|
'description',
|
||||||
|
'domain_id',
|
||||||
|
'enabled',
|
||||||
|
'id',
|
||||||
|
'name',
|
||||||
|
'parent_id',
|
||||||
|
'parents',
|
||||||
|
)
|
||||||
|
self.assertEqual(columns, collist)
|
||||||
|
datalist = (
|
||||||
|
identity_fakes.PROJECT_WITH_GRANDPARENT['description'],
|
||||||
|
identity_fakes.PROJECT_WITH_GRANDPARENT['domain_id'],
|
||||||
|
identity_fakes.PROJECT_WITH_GRANDPARENT['enabled'],
|
||||||
|
identity_fakes.PROJECT_WITH_GRANDPARENT['id'],
|
||||||
|
identity_fakes.PROJECT_WITH_GRANDPARENT['name'],
|
||||||
|
identity_fakes.PROJECT_WITH_GRANDPARENT['parent_id'],
|
||||||
|
identity_fakes.ids_for_parents_and_grandparents,
|
||||||
|
)
|
||||||
|
self.assertEqual(data, datalist)
|
||||||
|
|
||||||
|
def test_project_show_subtree(self):
|
||||||
|
project = copy.deepcopy(identity_fakes.PROJECT_WITH_PARENT)
|
||||||
|
project['subtree'] = identity_fakes.children
|
||||||
|
self.projects_mock.get.return_value = fakes.FakeResource(
|
||||||
|
None,
|
||||||
|
project,
|
||||||
|
loaded=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
arglist = [
|
||||||
|
identity_fakes.PROJECT_WITH_PARENT['id'],
|
||||||
|
'--children',
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('project', identity_fakes.PROJECT_WITH_PARENT['id']),
|
||||||
|
('parents', False),
|
||||||
|
('children', True),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
self.projects_mock.get.assert_called_with(
|
||||||
|
identity_fakes.PROJECT_WITH_PARENT['id'],
|
||||||
|
parents_as_list=False,
|
||||||
|
subtree_as_list=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
collist = (
|
||||||
|
'description',
|
||||||
|
'domain_id',
|
||||||
|
'enabled',
|
||||||
|
'id',
|
||||||
|
'name',
|
||||||
|
'parent_id',
|
||||||
|
'subtree',
|
||||||
|
)
|
||||||
|
self.assertEqual(columns, collist)
|
||||||
|
datalist = (
|
||||||
|
identity_fakes.PROJECT_WITH_PARENT['description'],
|
||||||
|
identity_fakes.PROJECT_WITH_PARENT['domain_id'],
|
||||||
|
identity_fakes.PROJECT_WITH_PARENT['enabled'],
|
||||||
|
identity_fakes.PROJECT_WITH_PARENT['id'],
|
||||||
|
identity_fakes.PROJECT_WITH_PARENT['name'],
|
||||||
|
identity_fakes.PROJECT_WITH_PARENT['parent_id'],
|
||||||
|
identity_fakes.ids_for_children,
|
||||||
|
)
|
||||||
|
self.assertEqual(data, datalist)
|
||||||
|
|
||||||
|
def test_project_show_parents_and_children(self):
|
||||||
|
project = copy.deepcopy(identity_fakes.PROJECT_WITH_PARENT)
|
||||||
|
project['subtree'] = identity_fakes.children
|
||||||
|
project['parents'] = identity_fakes.parents
|
||||||
|
self.projects_mock.get.return_value = fakes.FakeResource(
|
||||||
|
None,
|
||||||
|
project,
|
||||||
|
loaded=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
arglist = [
|
||||||
|
identity_fakes.PROJECT_WITH_PARENT['id'],
|
||||||
|
'--parents',
|
||||||
|
'--children',
|
||||||
|
]
|
||||||
|
verifylist = [
|
||||||
|
('project', identity_fakes.PROJECT_WITH_PARENT['id']),
|
||||||
|
('parents', True),
|
||||||
|
('children', True),
|
||||||
|
]
|
||||||
|
parsed_args = self.check_parser(self.cmd, arglist, verifylist)
|
||||||
|
|
||||||
|
columns, data = self.cmd.take_action(parsed_args)
|
||||||
|
self.projects_mock.get.assert_called_with(
|
||||||
|
identity_fakes.PROJECT_WITH_PARENT['id'],
|
||||||
|
parents_as_list=True,
|
||||||
|
subtree_as_list=True,
|
||||||
|
)
|
||||||
|
|
||||||
|
collist = (
|
||||||
|
'description',
|
||||||
|
'domain_id',
|
||||||
|
'enabled',
|
||||||
|
'id',
|
||||||
|
'name',
|
||||||
|
'parent_id',
|
||||||
|
'parents',
|
||||||
|
'subtree',
|
||||||
|
)
|
||||||
|
self.assertEqual(columns, collist)
|
||||||
|
datalist = (
|
||||||
|
identity_fakes.PROJECT_WITH_PARENT['description'],
|
||||||
|
identity_fakes.PROJECT_WITH_PARENT['domain_id'],
|
||||||
|
identity_fakes.PROJECT_WITH_PARENT['enabled'],
|
||||||
|
identity_fakes.PROJECT_WITH_PARENT['id'],
|
||||||
|
identity_fakes.PROJECT_WITH_PARENT['name'],
|
||||||
|
identity_fakes.PROJECT_WITH_PARENT['parent_id'],
|
||||||
|
identity_fakes.ids_for_parents,
|
||||||
|
identity_fakes.ids_for_children,
|
||||||
|
)
|
||||||
|
self.assertEqual(data, datalist)
|
||||||
|
Loading…
Reference in New Issue
Block a user