From 953fc1bcf73a693d3eef6de2d2f5d2b1f6b26c47 Mon Sep 17 00:00:00 2001 From: Ladislav Smola Date: Wed, 19 Feb 2014 16:22:55 +0100 Subject: [PATCH] Showing configuration tab of deployed overcloud -showing configuration from heat -test for configuration tab -test for event logs was missing, so I've added it too -fixing test for mocking only needed values -all tabs set to preload=False -extracting deCamelCase into utils and changed 2 usages Change-Id: I312bbc6e47137e5184bcb60963472c55388b64e6 --- tuskar_ui/infrastructure/overcloud/tables.py | 18 +++++ tuskar_ui/infrastructure/overcloud/tabs.py | 16 +++-- .../overcloud/_detail_configuration.html | 5 -- tuskar_ui/infrastructure/overcloud/tests.py | 70 ++++++++++++++++++- .../workflows/undeployed_configuration.py | 14 +--- tuskar_ui/test/test_data/tuskar_data.py | 6 +- tuskar_ui/utils.py | 21 ++++++ 7 files changed, 126 insertions(+), 24 deletions(-) delete mode 100644 tuskar_ui/infrastructure/overcloud/templates/overcloud/_detail_configuration.html create mode 100644 tuskar_ui/utils.py diff --git a/tuskar_ui/infrastructure/overcloud/tables.py b/tuskar_ui/infrastructure/overcloud/tables.py index 786149c2e..a0c28a13c 100644 --- a/tuskar_ui/infrastructure/overcloud/tables.py +++ b/tuskar_ui/infrastructure/overcloud/tables.py @@ -28,6 +28,24 @@ class OvercloudRoleNodeTable(nodes_tables.DeployedNodesTable): row_actions = () +class ConfigurationTable(tables.DataTable): + + key = tables.Column(lambda parameter: parameter[0], + verbose_name=_("Attribute Name")) + value = tables.Column(lambda parameter: parameter[1], + verbose_name=_("Attribute Value")) + + class Meta: + name = "configuration" + verbose_name = _("Configuration") + multi_select = False + table_actions = () + row_actions = () + + def get_object_id(self, datum): + return datum[0] + + class LogTable(tables.DataTable): timestamp = tables.Column('event_time', diff --git a/tuskar_ui/infrastructure/overcloud/tabs.py b/tuskar_ui/infrastructure/overcloud/tabs.py index a9fa28883..925e9dd9a 100644 --- a/tuskar_ui/infrastructure/overcloud/tabs.py +++ b/tuskar_ui/infrastructure/overcloud/tabs.py @@ -13,7 +13,6 @@ # 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 django.utils.translation import ungettext_lazy @@ -22,6 +21,7 @@ from horizon import tabs from tuskar_ui import api from tuskar_ui.infrastructure.overcloud import tables +from tuskar_ui import utils def _get_role_data(overcloud, role): @@ -60,6 +60,7 @@ class OverviewTab(tabs.Tab): name = _("Overview") slug = "overview" template_name = ("infrastructure/overcloud/_detail_overview.html") + preload = False def get_context_data(self, request, **kwargs): overcloud = self.tab_group.kwargs['overcloud'] @@ -86,13 +87,18 @@ class OverviewTab(tabs.Tab): } -class ConfigurationTab(tabs.Tab): +class ConfigurationTab(tabs.TableTab): + table_classes = (tables.ConfigurationTable,) name = _("Configuration") slug = "configuration" - template_name = ("infrastructure/overcloud/_detail_configuration.html") + template_name = "horizon/common/_detail_table.html" + preload = False - def get_context_data(self, request): - return {} + def get_configuration_data(self): + overcloud = self.tab_group.kwargs['overcloud'] + + return [(utils.de_camel_case(key), value) for key, value in + overcloud.stack.parameters.items()] class LogTab(tabs.TableTab): diff --git a/tuskar_ui/infrastructure/overcloud/templates/overcloud/_detail_configuration.html b/tuskar_ui/infrastructure/overcloud/templates/overcloud/_detail_configuration.html deleted file mode 100644 index d5b3c89a1..000000000 --- a/tuskar_ui/infrastructure/overcloud/templates/overcloud/_detail_configuration.html +++ /dev/null @@ -1,5 +0,0 @@ -{% load i18n %} -{% load url from future%} - -
-
diff --git a/tuskar_ui/infrastructure/overcloud/tests.py b/tuskar_ui/infrastructure/overcloud/tests.py index 123245726..6ae9505e4 100644 --- a/tuskar_ui/infrastructure/overcloud/tests.py +++ b/tuskar_ui/infrastructure/overcloud/tests.py @@ -29,6 +29,9 @@ CREATE_URL = urlresolvers.reverse( 'horizon:infrastructure:overcloud:create') DETAIL_URL = urlresolvers.reverse( 'horizon:infrastructure:overcloud:detail', args=(1,)) +DETAIL_URL_CONFIGURATION_TAB = (DETAIL_URL + + "?tab=detail__configuration") +DETAIL_URL_LOG_TAB = (DETAIL_URL + "?tab=detail__log") DELETE_URL = urlresolvers.reverse( 'horizon:infrastructure:overcloud:undeploy_confirmation', args=(1,)) TEST_DATA = utils.TestDataContainer() @@ -199,10 +202,75 @@ class OvercloudTests(test.BaseAdminViewTests): self.assertTemplateUsed( res, 'infrastructure/overcloud/detail.html') + self.assertTemplateNotUsed( + res, 'horizon/common/_detail_table.html') self.assertTemplateUsed( res, 'infrastructure/overcloud/_detail_overview.html') + + def test_detail_get_configuration_tab(self): + oc = None + stack = TEST_DATA.heatclient_stacks.first() + with patch('tuskar_ui.api.Overcloud', **{ + 'spec_set': [ + 'get', + 'id', + 'is_deployed', + 'is_deploying', + 'is_failed', + 'resources', + 'dashboard_url', + 'stack', + ], + 'id': 1, + 'is_deployed': True, + 'is_deploying': False, + 'is_failed': False, + 'get.side_effect': lambda request, overcloud_id: oc, + 'resources.return_value': [], + 'dashboard_url': '', + 'stack': stack, + }) as Overcloud: + oc = Overcloud + res = self.client.get(DETAIL_URL_CONFIGURATION_TAB) + self.assertTemplateUsed( - res, 'infrastructure/overcloud/_detail_configuration.html') + res, 'infrastructure/overcloud/detail.html') + self.assertTemplateNotUsed( + res, 'infrastructure/overcloud/_detail_overview.html') + self.assertTemplateUsed( + res, 'horizon/common/_detail_table.html') + + def test_detail_get_log_tab(self): + oc = None + with patch('tuskar_ui.api.Overcloud', **{ + 'spec_set': [ + 'get', + 'id', + 'is_deployed', + 'is_deploying', + 'is_failed', + 'resources', + 'dashboard_url', + 'stack_events', + ], + 'id': 1, + 'is_deployed': True, + 'is_deploying': False, + 'is_failed': False, + 'get.side_effect': lambda request, overcloud_id: oc, + 'resources.return_value': [], + 'dashboard_url': '', + 'stack_events': [], + }) as Overcloud: + oc = Overcloud + res = self.client.get(DETAIL_URL_LOG_TAB) + + self.assertTemplateUsed( + res, 'infrastructure/overcloud/detail.html') + self.assertTemplateNotUsed( + res, 'infrastructure/overcloud/_detail_overview.html') + self.assertTemplateUsed( + res, 'horizon/common/_detail_table.html') def test_delete_get(self): res = self.client.get(DELETE_URL) diff --git a/tuskar_ui/infrastructure/overcloud/workflows/undeployed_configuration.py b/tuskar_ui/infrastructure/overcloud/workflows/undeployed_configuration.py index 90e3a0627..9b5a58c86 100644 --- a/tuskar_ui/infrastructure/overcloud/workflows/undeployed_configuration.py +++ b/tuskar_ui/infrastructure/overcloud/workflows/undeployed_configuration.py @@ -11,13 +11,11 @@ # 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 re - import django.forms from django.utils.translation import ugettext_lazy as _ import horizon.workflows +from tuskar_ui import utils # TODO(rdopieralski) Get this from the Heat template. TEMPLATE_DATA = { @@ -221,20 +219,12 @@ TEMPLATE_DATA = { }, } -CAMEL_RE = re.compile(r'([a-z]|SSL)([A-Z])') - - -def deCamelCase(text): - """Convert CamelCase names to human-readable format.""" - - return CAMEL_RE.sub(lambda m: m.group(1) + ' ' + m.group(2), text) - def make_field(name, Type, NoEcho, Default, Description, AllowedValues=None, **kwargs): """Create a form field using the parameters from a Heat template.""" - label = deCamelCase(name) + label = utils.de_camel_case(name) Widget = django.forms.TextInput attrs = {} widget_kwargs = {} diff --git a/tuskar_ui/test/test_data/tuskar_data.py b/tuskar_ui/test/test_data/tuskar_data.py index 7572193ec..207454b6b 100644 --- a/tuskar_ui/test/test_data/tuskar_data.py +++ b/tuskar_ui/test/test_data/tuskar_data.py @@ -32,7 +32,11 @@ def data(TEST): stacks.StackManager(None), {'id': 'stack-id-1', 'stack_name': 'overcloud', - 'stack_status': 'RUNNING'}) + 'stack_status': 'RUNNING', + 'parameters': { + 'one': 'one', + 'two': 'two' + }}) TEST.heatclient_stacks.add(stack_1) # Events diff --git a/tuskar_ui/utils.py b/tuskar_ui/utils.py new file mode 100644 index 000000000..bdfaf8cf4 --- /dev/null +++ b/tuskar_ui/utils.py @@ -0,0 +1,21 @@ +# -*- coding: utf8 -*- +# +# 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 re + +CAMEL_RE = re.compile(r'([a-z]|SSL)([A-Z])') + + +def de_camel_case(text): + """Convert CamelCase names to human-readable format.""" + return CAMEL_RE.sub(lambda m: m.group(1) + ' ' + m.group(2), text)