Merge "Add groups tab in project details view."

This commit is contained in:
Zuul 2018-09-13 03:16:01 +00:00 committed by Gerrit Code Review
commit 0202d17c88
4 changed files with 162 additions and 1 deletions

View File

@ -0,0 +1,33 @@
# 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.
from django.utils.translation import ugettext_lazy as _
from horizon import forms
from horizon import tables
from openstack_dashboard.dashboards.identity.groups \
import tables as groups_tables
class GroupsTable(groups_tables.GroupsTable):
"""Display groups of the project."""
roles = tables.Column(
lambda obj: ", ".join(getattr(obj, 'roles', [])),
verbose_name=_('Roles'),
form_field=forms.CharField(
widget=forms.Textarea(attrs={'rows': 4}),
required=False))
class Meta(object):
name = "groupstable"
verbose_name = _("Groups")

View File

@ -18,6 +18,8 @@ from horizon import tabs
from openstack_dashboard import api
from openstack_dashboard.dashboards.identity.projects.groups \
import tables as groups_tables
from openstack_dashboard.dashboards.identity.projects.users \
import tables as users_tables
@ -169,6 +171,44 @@ class UsersTab(tabs.TableTab):
return project_users.values()
class GroupsTab(tabs.TableTab):
"""Display groups member of the project. """
table_classes = (groups_tables.GroupsTable,)
name = _("Groups")
slug = "groups"
template_name = "horizon/common/_detail_table.html"
preload = False
def get_groupstable_data(self):
groups_in_project = []
project = self.tab_group.kwargs['project']
try:
# Get project_groups_roles: {group_id: [role_id_1, role_id_2]}
project_groups_roles = api.keystone.get_project_groups_roles(
self.request,
project=project.id)
# Get global roles and groups
roles = api.keystone.role_list(self.request)
# For keystone.group_list, we do not give the project_id because it
# is ignored when called with admin creds.
groups = api.keystone.group_list(self.request)
groups = {group.id: group for group in groups}
except Exception:
exceptions.handle(self.request,
_("Unable to display the groups of this"
" project."))
else:
# Construct Groups list, adding the role attribute
for group_id in project_groups_roles:
group = groups[group_id]
group.roles = [role.name for role in roles
if role.id in project_groups_roles[group_id]]
groups_in_project.append(group)
return groups_in_project
class ProjectDetailTabs(tabs.DetailTabsGroup):
slug = "project_details"
tabs = (OverviewTab, UsersTab,)
tabs = (OverviewTab, UsersTab, GroupsTab,)

View File

@ -1486,6 +1486,94 @@ class DetailProjectViewTests(test.BaseAdminViewTests):
self.mock_enabled_quotas.assert_called_once_with(test.IsHttpRequest())
self.mock_role_list.assert_called_once_with(test.IsHttpRequest())
@test.create_mocks({api.keystone: ("tenant_get",
"get_project_groups_roles",
"role_list",
"group_list"),
quotas: ('enabled_quotas',)})
def test_detail_view_groups_tab(self):
project = self.tenants.first()
groups = self.groups.filter(domain_id=project.domain_id)
role_assignments = self.role_assignments.filter(
scope={'project': {'id': project.id}})
# {group_id: [role_id1, role_id2]} as returned by the api
project_groups_roles = self._project_group_roles(role_assignments)
# Prepare mocks
self.mock_tenant_get.return_value = project
self.mock_enabled_quotas.return_value = ('instances',)
self.mock_get_project_groups_roles.return_value = project_groups_roles
self.mock_group_list.return_value = groups
self.mock_role_list.return_value = self.roles.list()
# Get project details view on group tab
url = reverse('horizon:identity:projects:detail', args=[project.id])
detail_view = tabs.ProjectDetailTabs(self.request, group=project)
groups_tab_link = "?%s=%s" % (
detail_view.param_name,
detail_view.get_tab("groups").get_id()
)
url += groups_tab_link
res = self.client.get(url)
# Check the template expected has been used
self.assertTemplateUsed(res,
"horizon/common/_detail_table.html")
# Check the table content
groups_expected = {'1': ["_member_"], }
groups_id_observed = [group.id for group in
res.context["groupstable_table"].data]
# Check the group is displayed
self.assertItemsEqual(groups_id_observed, groups_expected.keys())
# Check the groups roles
for group in res.context["groupstable_table"].data:
self.assertEqual(groups_expected[group.id], group.roles)
self.mock_tenant_get.assert_called_once_with(test.IsHttpRequest(),
self.tenant.id)
self.mock_enabled_quotas.assert_called_once_with(test.IsHttpRequest())
self.mock_role_list.assert_called_once_with(test.IsHttpRequest())
self.mock_group_list.assert_called_once_with(test.IsHttpRequest())
self.mock_get_project_groups_roles.assert_called_once_with(
test.IsHttpRequest(), project=project.id)
@test.create_mocks({api.keystone: ("tenant_get",
"get_project_groups_roles"),
quotas: ('enabled_quotas',)})
def test_detail_view_groups_tab_exception(self):
project = self.tenants.first()
# Prepare mocks
self.mock_tenant_get.return_value = project
self.mock_enabled_quotas.return_value = ('instances',)
self.mock_get_project_groups_roles.side_effect = \
self.exceptions.keystone
# Get project details view on group tab
url = reverse('horizon:identity:projects:detail', args=[project.id])
detail_view = tabs.ProjectDetailTabs(self.request, group=project)
groups_tab_link = "?%s=%s" % (
detail_view.param_name,
detail_view.get_tab("groups").get_id()
)
url += groups_tab_link
res = self.client.get(url)
# Check the projects table is empty
self.assertFalse(res.context["groupstable_table"].data)
# Check one error message is displayed
self.assertMessageCount(res, error=1)
self.mock_tenant_get.assert_called_once_with(test.IsHttpRequest(),
self.tenant.id)
self.mock_enabled_quotas.assert_called_once_with(test.IsHttpRequest())
self.mock_get_project_groups_roles.assert_called_once_with(
test.IsHttpRequest(), project=project.id)
@tag('selenium')
class SeleniumTests(test.SeleniumAdminTestCase, test.TestCase):