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
This commit is contained in:
parent
1fc6db3187
commit
953fc1bcf7
@ -28,6 +28,24 @@ class OvercloudRoleNodeTable(nodes_tables.DeployedNodesTable):
|
|||||||
row_actions = ()
|
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):
|
class LogTable(tables.DataTable):
|
||||||
|
|
||||||
timestamp = tables.Column('event_time',
|
timestamp = tables.Column('event_time',
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from django.utils.translation import ungettext_lazy
|
from django.utils.translation import ungettext_lazy
|
||||||
|
|
||||||
@ -22,6 +21,7 @@ from horizon import tabs
|
|||||||
|
|
||||||
from tuskar_ui import api
|
from tuskar_ui import api
|
||||||
from tuskar_ui.infrastructure.overcloud import tables
|
from tuskar_ui.infrastructure.overcloud import tables
|
||||||
|
from tuskar_ui import utils
|
||||||
|
|
||||||
|
|
||||||
def _get_role_data(overcloud, role):
|
def _get_role_data(overcloud, role):
|
||||||
@ -60,6 +60,7 @@ class OverviewTab(tabs.Tab):
|
|||||||
name = _("Overview")
|
name = _("Overview")
|
||||||
slug = "overview"
|
slug = "overview"
|
||||||
template_name = ("infrastructure/overcloud/_detail_overview.html")
|
template_name = ("infrastructure/overcloud/_detail_overview.html")
|
||||||
|
preload = False
|
||||||
|
|
||||||
def get_context_data(self, request, **kwargs):
|
def get_context_data(self, request, **kwargs):
|
||||||
overcloud = self.tab_group.kwargs['overcloud']
|
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")
|
name = _("Configuration")
|
||||||
slug = "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):
|
def get_configuration_data(self):
|
||||||
return {}
|
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):
|
class LogTab(tabs.TableTab):
|
||||||
|
@ -1,5 +0,0 @@
|
|||||||
{% load i18n %}
|
|
||||||
{% load url from future%}
|
|
||||||
|
|
||||||
<div class="row-fluid"><div class="span12">
|
|
||||||
</div></div>
|
|
@ -29,6 +29,9 @@ CREATE_URL = urlresolvers.reverse(
|
|||||||
'horizon:infrastructure:overcloud:create')
|
'horizon:infrastructure:overcloud:create')
|
||||||
DETAIL_URL = urlresolvers.reverse(
|
DETAIL_URL = urlresolvers.reverse(
|
||||||
'horizon:infrastructure:overcloud:detail', args=(1,))
|
'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(
|
DELETE_URL = urlresolvers.reverse(
|
||||||
'horizon:infrastructure:overcloud:undeploy_confirmation', args=(1,))
|
'horizon:infrastructure:overcloud:undeploy_confirmation', args=(1,))
|
||||||
TEST_DATA = utils.TestDataContainer()
|
TEST_DATA = utils.TestDataContainer()
|
||||||
@ -199,10 +202,75 @@ class OvercloudTests(test.BaseAdminViewTests):
|
|||||||
|
|
||||||
self.assertTemplateUsed(
|
self.assertTemplateUsed(
|
||||||
res, 'infrastructure/overcloud/detail.html')
|
res, 'infrastructure/overcloud/detail.html')
|
||||||
|
self.assertTemplateNotUsed(
|
||||||
|
res, 'horizon/common/_detail_table.html')
|
||||||
self.assertTemplateUsed(
|
self.assertTemplateUsed(
|
||||||
res, 'infrastructure/overcloud/_detail_overview.html')
|
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(
|
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):
|
def test_delete_get(self):
|
||||||
res = self.client.get(DELETE_URL)
|
res = self.client.get(DELETE_URL)
|
||||||
|
@ -11,13 +11,11 @@
|
|||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import re
|
|
||||||
|
|
||||||
import django.forms
|
import django.forms
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
import horizon.workflows
|
import horizon.workflows
|
||||||
|
|
||||||
|
from tuskar_ui import utils
|
||||||
|
|
||||||
# TODO(rdopieralski) Get this from the Heat template.
|
# TODO(rdopieralski) Get this from the Heat template.
|
||||||
TEMPLATE_DATA = {
|
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,
|
def make_field(name, Type, NoEcho, Default, Description, AllowedValues=None,
|
||||||
**kwargs):
|
**kwargs):
|
||||||
"""Create a form field using the parameters from a Heat template."""
|
"""Create a form field using the parameters from a Heat template."""
|
||||||
|
|
||||||
label = deCamelCase(name)
|
label = utils.de_camel_case(name)
|
||||||
Widget = django.forms.TextInput
|
Widget = django.forms.TextInput
|
||||||
attrs = {}
|
attrs = {}
|
||||||
widget_kwargs = {}
|
widget_kwargs = {}
|
||||||
|
@ -32,7 +32,11 @@ def data(TEST):
|
|||||||
stacks.StackManager(None),
|
stacks.StackManager(None),
|
||||||
{'id': 'stack-id-1',
|
{'id': 'stack-id-1',
|
||||||
'stack_name': 'overcloud',
|
'stack_name': 'overcloud',
|
||||||
'stack_status': 'RUNNING'})
|
'stack_status': 'RUNNING',
|
||||||
|
'parameters': {
|
||||||
|
'one': 'one',
|
||||||
|
'two': 'two'
|
||||||
|
}})
|
||||||
TEST.heatclient_stacks.add(stack_1)
|
TEST.heatclient_stacks.add(stack_1)
|
||||||
|
|
||||||
# Events
|
# Events
|
||||||
|
21
tuskar_ui/utils.py
Normal file
21
tuskar_ui/utils.py
Normal file
@ -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)
|
Loading…
x
Reference in New Issue
Block a user