summaryrefslogtreecommitdiff
path: root/openstackclient
diff options
context:
space:
mode:
authorRodrigo Duarte Sousa <rodrigods@lsd.ufcg.edu.br>2015-03-20 17:51:02 -0300
committerRodrigo Duarte Sousa <rodrigods@lsd.ufcg.edu.br>2015-06-09 13:10:22 -0300
commit4fab60634983f9327295cc68edf89824557728f9 (patch)
tree78d4f07a598b721bbc51de123ead5a888815e6ca /openstackclient
parent7cf779004e5e9eab9abee8d8a5bc2db3dfa8bd5d (diff)
downloadpython-openstackclient-4fab60634983f9327295cc68edf89824557728f9.tar.gz
Enables retrieval of project's parents and subtree
Adds the possibility to retrieve a project and list its parents and subtree in the hierarchy. Co-Authored-By: Rodrigo Duarte <rodrigods@lsd.ufcg.edu.br> Co-Authored-By: Samuel de Medeiros Queiroz <samuel@lsd.ufcg.edu.br> Implements: bp hierarchical-multitenancy Change-Id: I874f6faffc8a2db9d99f12cbe0a69c0a30c0d9df
Diffstat (limited to 'openstackclient')
-rw-r--r--openstackclient/common/utils.py4
-rw-r--r--openstackclient/identity/v3/project.py37
-rw-r--r--openstackclient/tests/identity/v3/fakes.py19
-rw-r--r--openstackclient/tests/identity/v3/test_project.py150
4 files changed, 201 insertions, 9 deletions
diff --git a/openstackclient/common/utils.py b/openstackclient/common/utils.py
index aad0519c..c824678e 100644
--- a/openstackclient/common/utils.py
+++ b/openstackclient/common/utils.py
@@ -51,7 +51,7 @@ def find_resource(manager, name_or_id, **kwargs):
# Try to get entity as integer id
try:
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
# client library the manager passed in belongs to.
# 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:
- return manager.get(name_or_id)
+ return manager.get(name_or_id, **kwargs)
except Exception:
pass
diff --git a/openstackclient/identity/v3/project.py b/openstackclient/identity/v3/project.py
index 48f547f3..8185d65a 100644
--- a/openstackclient/identity/v3/project.py
+++ b/openstackclient/identity/v3/project.py
@@ -323,6 +323,18 @@ class ShowProject(show.ShowOne):
metavar='<domain>',
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
def take_action(self, parsed_args):
@@ -331,14 +343,25 @@ class ShowProject(show.ShowOne):
if parsed_args.domain:
domain = common.find_domain(identity_client, parsed_args.domain)
- project = utils.find_resource(identity_client.projects,
- parsed_args.project,
- domain_id=domain.id)
+ project = utils.find_resource(
+ identity_client.projects,
+ parsed_args.project,
+ domain_id=domain.id,
+ parents_as_list=parsed_args.parents,
+ subtree_as_list=parsed_args.children)
else:
- project = utils.find_resource(identity_client.projects,
- parsed_args.project)
+ project = utils.find_resource(
+ 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')
- # TODO(stevemar): Remove the line below when we support multitenancy
- project._info.pop('parent_id', None)
return zip(*sorted(six.iteritems(project._info)))
diff --git a/openstackclient/tests/identity/v3/fakes.py b/openstackclient/tests/identity/v3/fakes.py
index dfbcf44f..ae7a684c 100644
--- a/openstackclient/tests/identity/v3/fakes.py
+++ b/openstackclient/tests/identity/v3/fakes.py
@@ -145,6 +145,25 @@ PROJECT_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_name = 'roller'
diff --git a/openstackclient/tests/identity/v3/test_project.py b/openstackclient/tests/identity/v3/test_project.py
index ebf612cc..946bbdcd 100644
--- a/openstackclient/tests/identity/v3/test_project.py
+++ b/openstackclient/tests/identity/v3/test_project.py
@@ -783,6 +783,8 @@ class TestProjectShow(TestProject):
columns, data = self.cmd.take_action(parsed_args)
self.projects_mock.get.assert_called_with(
identity_fakes.project_id,
+ parents_as_list=False,
+ subtree_as_list=False,
)
collist = ('description', 'domain_id', 'enabled', 'id', 'name')
@@ -795,3 +797,151 @@ class TestProjectShow(TestProject):
identity_fakes.project_name,
)
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)