This is an automated email from the ASF dual-hosted git repository.
atkach pushed a commit to branch trunk
in repository https://gitbox.apache.org/repos/asf/ambari.git
The following commit(s) were added to refs/heads/trunk by this push:
new 26f178c AMBARI-22851 Host Details page style fixes
26f178c is described below
commit 26f178ca2b50ccd80e8d97808578e39b4be0e0f2
Author: Andrii Tkach <[email protected]>
AuthorDate: Fri Jan 26 13:47:55 2018 +0200
AMBARI-22851 Host Details page style fixes
---
ambari-web/app/messages.js | 3 +
ambari-web/app/models/host_component.js | 3 +
ambari-web/app/styles/application.less | 9 +-
ambari-web/app/styles/config_versions_control.less | 5 -
ambari-web/app/styles/hosts.less | 34 +-
.../templates/common/configs/service_config.hbs | 2 +-
.../common/configs/service_config_wizard.hbs | 2 +-
ambari-web/app/templates/main/host/details.hbs | 10 +-
.../templates/main/host/details/host_component.hbs | 289 +++++++++------
ambari-web/app/templates/main/host/summary.hbs | 121 ++-----
.../views/main/host/details/host_component_view.js | 92 +++--
ambari-web/app/views/main/host/summary.js | 170 ++-------
.../main/host/details/host_component_view_test.js | 136 +++----
ambari-web/test/views/main/host/summary_test.js | 396 +--------------------
14 files changed, 381 insertions(+), 891 deletions(-)
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index 1f87f60..391ac89 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -117,6 +117,8 @@ Em.I18n.translations = {
'common.description':'Description',
'common.default':'Default',
'common.client':'Client',
+ 'common.master':'Master',
+ 'common.slave':'Slave',
'common.zookeeper':'ZooKeeper',
'common.hbase':'HBase',
'common.regionServer':'RegionServer',
@@ -2722,6 +2724,7 @@ Em.I18n.translations = {
'hosts.host.summary.addComponent':'Add Component',
'hosts.host.summary.currentVersion':'Current Version',
+ 'hosts.host.details.upgradeFailed':'Component upgrade failed',
'hosts.host.details.hostActions':'Host Actions',
'hosts.host.details.needToRestart':'Host needs {0} {1} restarted',
'hosts.host.details.needToRestart.button':'Restart',
diff --git a/ambari-web/app/models/host_component.js
b/ambari-web/app/models/host_component.js
index 19eb085..8157b75 100644
--- a/ambari-web/app/models/host_component.js
+++ b/ambari-web/app/models/host_component.js
@@ -158,6 +158,9 @@ App.HostComponent = DS.Model.extend({
},
componentTextStatus: function () {
+ if (this.get('isClient') && this.get("workStatus") === 'INSTALLED') {
+ return Em.I18n.t('common.installed');
+ }
return App.HostComponentStatus.getTextStatus(this.get("workStatus"));
}.property('workStatus', 'isDecommissioning')
});
diff --git a/ambari-web/app/styles/application.less
b/ambari-web/app/styles/application.less
index e89e3fa..20ff5b1 100644
--- a/ambari-web/app/styles/application.less
+++ b/ambari-web/app/styles/application.less
@@ -317,6 +317,10 @@ footer {
display: inline-block;
}
+.display-inline {
+ display: inline;
+}
+
::-webkit-scrollbar {
-webkit-appearance: none;
}
@@ -1330,8 +1334,9 @@ ul.filter {
padding: 10px;
}
-.button-caret-margin {
- margin-top: 8px;
+.pull-caret-right {
+ float: right;
+ margin-top: 5px;
}
/*start charts rack*/
diff --git a/ambari-web/app/styles/config_versions_control.less
b/ambari-web/app/styles/config_versions_control.less
index 0b7f131..86584ad 100644
--- a/ambari-web/app/styles/config_versions_control.less
+++ b/ambari-web/app/styles/config_versions_control.less
@@ -111,11 +111,6 @@
text-align: left;
padding: 10px;
}
- .caret {
- position: absolute;
- top: 15px;
- right: 10px;
- }
}
.filter-combobox {
display: inline-block;
diff --git a/ambari-web/app/styles/hosts.less b/ambari-web/app/styles/hosts.less
index 29e4333..0909a3d 100644
--- a/ambari-web/app/styles/hosts.less
+++ b/ambari-web/app/styles/hosts.less
@@ -395,18 +395,11 @@
.host-components {
padding: 10px;
- border-radius: 4px;
- background: #FFF;
- .component-name-block-wrapper {
- display: table;
- height: 34px;
- .component-name-block {
- white-space: normal;
- word-wrap: break-word;
- display: table-cell;
- vertical-align: middle;
- }
-
+ .component-name-block {
+ white-space: normal;
+ word-wrap: break-word;
+ display: table-cell;
+ vertical-align: middle;
}
.dropdown-menu {
.disabled {
@@ -418,14 +411,15 @@
pointer-events: auto;
}
}
- .status-icons {
- line-height: 34px;
- }
- .client-list {
- ul {
- list-style: none;
- }
- }
+ }
+
+ .status-icons span {
+ padding-right: 2px;
+ }
+
+ .action-icon {
+ padding: 2px 5px 0 5px;
+ font-size: 16px;
}
.logs-tab-content {
diff --git a/ambari-web/app/templates/common/configs/service_config.hbs
b/ambari-web/app/templates/common/configs/service_config.hbs
index fe97062..e6a15ea 100644
--- a/ambari-web/app/templates/common/configs/service_config.hbs
+++ b/ambari-web/app/templates/common/configs/service_config.hbs
@@ -70,8 +70,8 @@
<button {{bindAttr disabled="controller.isHostsConfigsPage"}}
class="btn btn-default dropdown-toggle"
data-toggle="dropdown">
+ <span class="caret pull-caret-right"></span>
{{selectedConfigGroup.displayNameHosts}}
- <span class="caret"></span>
</button>
<ul class="dropdown-menu config-groups-dropdown-menu">
{{#isAuthorized "SERVICE.MANAGE_CONFIG_GROUPS"}}
diff --git a/ambari-web/app/templates/common/configs/service_config_wizard.hbs
b/ambari-web/app/templates/common/configs/service_config_wizard.hbs
index 3abd5eb..fdf0059 100644
--- a/ambari-web/app/templates/common/configs/service_config_wizard.hbs
+++ b/ambari-web/app/templates/common/configs/service_config_wizard.hbs
@@ -21,8 +21,8 @@
{{t common.group}}
<div class="btn-group config-groups-dropdown">
<button {{bindAttr disabled="controller.isHostsConfigsPage"}}
class="btn btn-default dropdown-toggle first" data-toggle="dropdown">
+ <span class="caret pull-caret-right"></span>
{{selectedConfigGroup.displayNameHosts}}
- <span class="caret"></span>
</button>
<ul class="dropdown-menu config-groups-dropdown-menu">
<!-- available config group menu links -->
diff --git a/ambari-web/app/templates/main/host/details.hbs
b/ambari-web/app/templates/main/host/details.hbs
index 15b0f4a..6616f6d 100644
--- a/ambari-web/app/templates/main/host/details.hbs
+++ b/ambari-web/app/templates/main/host/details.hbs
@@ -19,15 +19,15 @@
{{#if view.isLoaded}}
<div id="host-details">
<div class="host-details-header">
- <div class="status-info">
- <span rel="HealthTooltip" {{bindAttr class="view.content.healthClass
view.content.healthIconClass"}} data-placement="bottom" {{bindAttr
data-original-title="view.content.healthToolTip" }}></span><span
- class='host-title'>{{unbound view.content.hostName}}</span>
+ <div class="status-info mbm">
+ <h2 class='table-title display-inline'>
+ <a class="disabled">{{t common.host}}</a><span>: {{unbound
view.content.hostName}}</span>
+ </h2>
+ <span rel="HealthTooltip" {{bindAttr class="view.content.healthClass
view.content.healthIconClass"}} data-placement="bottom" {{bindAttr
data-original-title="view.content.healthToolTip" }}></span>
{{#unless view.isActive}}
<span class="host-maintenance-notice pull-right"><span
class="icon-medkit"></span> {{t hosts.host.passive.mode}}</span>
{{/unless}}
</div>
- <div><a href="javascript:void(null)" id="host-details-back-btn"
data-toggle="modal" {{action back}}><i
- class="glyphicon glyphicon-arrow-left"></i> {{t
common.back}}</a></div>
</div>
<div class="content">
{{view App.MainHostMenuView hostBinding="view.content"}}
diff --git a/ambari-web/app/templates/main/host/details/host_component.hbs
b/ambari-web/app/templates/main/host/details/host_component.hbs
index 28d2acf..e14ae6e 100644
--- a/ambari-web/app/templates/main/host/details/host_component.hbs
+++ b/ambari-web/app/templates/main/host/details/host_component.hbs
@@ -16,152 +16,205 @@
* limitations under the License.
}}
- <div class="col-md-1 col-lg-1 align-left status-icons component-label
host-component-block">
- <span class="health-icon-block">
- {{#if view.isUpgradeFailed}}
- {{#isAuthorized "HOST.ADD_DELETE_COMPONENTS"}}
- <a href="#" {{action "upgradeComponent" view.content
target="controller"}} >
- <i title="Component upgrade failed" class="components-health
glyphicon glyphicon-arrow-up"></i>
- </a>
- {{/isAuthorized}}
- {{else}}
- <span rel='componentHealthTooltip' {{bindAttr
class="view.statusClass view.statusIconClass :components-health"
data-original-title="view.componentTextStatus"}}></span>
- {{/if}}
- </span>
- </div>
- <div class="col-md-4 col-lg-5 component-name-block-wrapper">
- <span class="component-name-block">
- {{#if component.displayNameAdvanced}}
- <span {{bindAttr
title="component.displayNameAdvanced"}}>{{component.getDisplayNameAdvanced}} /</span>
- {{else}}
- <span {{bindAttr
title="component.displayName"}}>{{component.getDisplayName}} /</span>
- {{/if}}
- <span class="hidden-lg"><br /></span> <a href="#" {{action
routeToService component.service}} {{bindAttr
title="component.service.displayName"}}>{{component.serviceDisplayName}}</a>
- </span>
- </div>
-<div class="col-md-1 col-lg-1 align-center status-icons">
+<td class="status-icons">
+ <span class="health-icon-block">
+ {{#if view.isUpgradeFailed}}
+ {{#isAuthorized "HOST.ADD_DELETE_COMPONENTS"}}
+ <a href="#" rel='componentHealthTooltip'
+ {{bindAttr data-original-title="view.upgradeFailedMessage"}}
+ {{action "upgradeComponent" view.content target="controller"}}>
+ <i class="glyphicon glyphicon-arrow-up"></i>
+ </a>
+ {{/isAuthorized}}
+ {{else}}
+ <i rel='componentHealthTooltip'
+ {{bindAttr class="view.statusClass view.statusIconClass
:components-health"
+ data-original-title="view.componentTextStatus"}}></i>
+ {{/if}}
+ </span>
<span class="refresh-icon-block">
{{#if component.staleConfigs}}
- <span class="text-warning glyphicon glyphicon-refresh"></span>
+ <i class="text-warning glyphicon glyphicon-refresh"></i>
{{/if}}
</span>
-</div>
-<div class="col-md-1 col-lg-1 align-center status-icons">
<span class="medkit-icon-block">
{{#unless component.isActive}}
- <span class="icon-medkit"></span>
+ <i class="icon-medkit"></i>
{{/unless}}
</span>
-</div>
-<div class="col-md-5 col-lg-4">
+</td>
+
+<td class="component-name-block">
+ <span>
+ {{#if component.displayNameAdvanced}}
+ <span {{bindAttr
title="component.displayNameAdvanced"}}>{{component.getDisplayNameAdvanced}} /</span>
+ {{else}}
+ <span {{bindAttr
title="component.displayName"}}>{{component.getDisplayName}} /</span>
+ {{/if}}
+ <span class="hidden-lg"><br/></span> <a href="#" {{action routeToService
component.service}} {{bindAttr
+
title="component.service.displayName"}}>{{component.serviceDisplayName}}</a>
+ </span>
+</td>
+
+<td class="component-type-block">
+ <span>{{view.typeDisplay}}</span>
+</td>
+
+<td class="align-center">
{{#havePermissions "SERVICE.DECOMMISSION_RECOMMISSION"}}
<div class="dropdown">
- <button {{ bindAttr class="view.disabled :btn :btn-default :btn-block
:dropdown-toggle"
disabled="App.router.wizardWatcherController.isNonWizardUser"}}
data-toggle="dropdown">
- {{view.componentTextStatus}}
- <span class="caret pull-right button-caret-margin"></span>
- </button>
- {{#unless App.router.wizardWatcherController.isNonWizardUser}}
- <ul class="dropdown-menu">
- {{#if view.isComponentDecommissionAvailable}}
- {{view view.decommissionView}}
- {{/if}}
- {{#if view.isComponentRecommissionAvailable}}
- {{view view.decommissionView}}
- {{/if}}
- {{#if view.isRestartableComponent}}
- <li {{bindAttr class="view.isRestartComponentDisabled:hidden"}}>
- <a href="javascript:void(null)" data-toggle="modal" {{action
"restartComponent" view.content target="controller"}}>
- {{t common.restart}}
+ <a {{bindAttr class=":dropdown-toggle view.isDisabled:disabled"}}
data-toggle="dropdown" href="javascript:void(null)">
+ <i class="glyphicon glyphicon-option-horizontal action-icon"></i>
+ </a>
+ {{#unless isDisabled}}
+
+ {{!-- Actions of Clients --}}
+ {{#if view.content.isClient}}
+ <ul class="dropdown-menu">
+ <li>
+ <a href="javascript:void(null)" data-toggle="modal"
+ {{action "refreshComponentConfigs" view.content
target="controller"}}>
+ {{t hosts.host.details.refreshConfigs}}
+ </a>
+ </li>
+ <li>
+ <a href="javascript:void(null)" {{bindAttr
class="view.isInit::disabled" }}
+ data-toggle="modal" {{action installClient target="view"}}>
+ {{t common.install}}
</a>
</li>
- {{/if}}
- {{#unless view.isInstalling}}
- {{#isAuthorized "SERVICE.START_STOP"}}
- {{#if view.isStart}}
- <li {{bindAttr class="view.isComponentDecommissioning:hidden
view.noActionAvailable"}}>
- <a href="javascript:void(null)" data-toggle="modal" {{action
"stopComponent" view.content target="controller"}}>
- {{t common.stop}}
+ {{#if view.isInstallFailed}}
+ <li>
+ <a href="javascript:void(null)" {{action installClient
target="view"}}>
+ {{t common.reinstall}}
+ </a>
+ </li>
+ {{/if}}
+ {{#each command in view.clientCustomCommands}}
+ <li>
+ <a href="javascript:void(null)"
+ {{action "executeCustomCommand" command target="controller"
href=true}}>
+ {{command.label}}
+ </a>
+ </li>
+ {{/each}}
+ </ul>
+ {{else}}
+
+ {{!-- Actions of Masters and Slaves --}}
+ <ul class="dropdown-menu">
+ {{#if view.isComponentDecommissionAvailable}}
+ {{view view.decommissionView}}
+ {{/if}}
+ {{#if view.isComponentRecommissionAvailable}}
+ {{view view.decommissionView}}
+ {{/if}}
+ {{#if view.isRestartableComponent}}
+ <li {{bindAttr class="view.isRestartComponentDisabled:hidden"}}>
+ <a href="javascript:void(null)" data-toggle="modal" {{action
"restartComponent" view.content
+
target="controller"}}>
+ {{t common.restart}}
+ </a>
+ </li>
+ {{/if}}
+ {{#unless view.isInstalling}}
+ {{#isAuthorized "SERVICE.START_STOP"}}
+ {{#if view.isStart}}
+ <li {{bindAttr class="view.isComponentDecommissioning:hidden
view.noActionAvailable"}}>
+ <a href="javascript:void(null)" data-toggle="modal"
{{action "stopComponent" view.content
+
target="controller"}}>
+ {{t common.stop}}
+ </a>
+ </li>
+ {{/if}}
+ {{#unless view.isStart}}
+ {{#unless view.isInit}}
+ <li {{bindAttr
+ class="view.isUpgradeFailed:hidden
view.isInstallFailed:hidden view.isDecommissioning:hidden
view.noActionAvailable"}}>
+ <a href="javascript:void(null)" data-toggle="modal"
{{action "startComponent" view.content
+
target="controller"}}>
+ {{t common.start}}
+ </a>
+ </li>
+ {{/unless}}
+ {{/unless}}
+ {{/isAuthorized}}
+ {{#if view.isUpgradeFailed}}
+ <li {{bindAttr class="view.noActionAvailable"}}>
+ <a href="javascript:void(null)" data-toggle="modal" {{action
"upgradeComponent" view.content
+
target="controller"}}>
+ {{t common.reUpgrade}}
</a>
</li>
{{/if}}
- {{#unless view.isStart}}
- {{#unless view.isInit}}
- <li {{bindAttr class="view.isUpgradeFailed:hidden
view.isInstallFailed:hidden view.isDecommissioning:hidden
view.noActionAvailable"}}>
- <a href="javascript:void(null)" data-toggle="modal"
{{action "startComponent" view.content target="controller"}}>
- {{t common.start}}
+ {{#if view.isInstallFailed}}
+ <li {{bindAttr class="view.noActionAvailable"}}>
+ <a href="javascript:void(null)" data-toggle="modal" {{action
"installComponent" view.content
+
target="controller"}}>
+ {{t common.reinstall}}
+ </a>
+ </li>
+ {{/if}}
+ {{#if view.isReassignable}}
+ {{#isAuthorized "SERVICE.MOVE"}}
+ <li {{bindAttr class="view.noActionAvailable
view.isMoveComponentDisabled:disabled"}}>
+ <a href="javascript:void(null)" data-toggle="modal"
{{action "moveComponent" view.content
+
target="controller"}}>
+ {{t common.move}}
</a>
</li>
- {{/unless}}
- {{/unless}}
- {{/isAuthorized}}
- {{#if view.isUpgradeFailed}}
- <li {{bindAttr class="view.noActionAvailable"}}>
- <a href="javascript:void(null)" data-toggle="modal" {{action
"upgradeComponent" view.content target="controller"}}>
- {{t common.reUpgrade}}
- </a>
- </li>
- {{/if}}
- {{#if view.isInstallFailed}}
- <li {{bindAttr class="view.noActionAvailable"}}>
- <a href="javascript:void(null)" data-toggle="modal" {{action
"installComponent" view.content target="controller"}}>
+ {{/isAuthorized}}
+ {{/if}}
+ {{#isAuthorized "HOST.TOGGLE_MAINTENANCE"}}
+ <li {{bindAttr class="view.noActionAvailable
view.content.isImpliedState:disabled :allow-tooltip"}}
+ {{bindAttr data-original-title="view.maintenanceTooltip"}}
rel="passiveTooltip">
+ <a href="javascript:void(null)"
+ data-toggle="modal" {{action "toggleMaintenanceMode"
view.content target="controller"}}>
+ {{#if view.isActive}}
+ {{t passiveState.turnOn}}
+ {{else}}
+ {{t passiveState.turnOff}}
+ {{/if}}
+ </a>
+ </li>
+ {{/isAuthorized}}
+ {{/unless}}
+ {{#if view.isInit}}
+ <li>
+ <a href="javascript:void(null)" data-toggle="modal" {{action
"installComponent" view.content
+
target="controller"}}>
{{t common.reinstall}}
</a>
</li>
{{/if}}
- {{#if view.isReassignable}}
- {{#isAuthorized "SERVICE.MOVE"}}
- <li {{bindAttr class="view.noActionAvailable
view.isMoveComponentDisabled:disabled"}}>
- <a href="javascript:void(null)" data-toggle="modal" {{action
"moveComponent" view.content target="controller"}}>
- {{t common.move}}
+ {{#if view.isDeletableComponent}}
+ {{#isAuthorized "HOST.ADD_DELETE_COMPONENTS"}}
+ <li {{bindAttr
class="view.isDeleteComponentDisabled:disabled"}}>
+ <a href="javascript:void(null)" data-toggle="modal" {{action
"deleteComponent" view.content
+
target="controller"}}>
+ {{t common.delete}}
</a>
</li>
{{/isAuthorized}}
{{/if}}
- {{#isAuthorized "HOST.TOGGLE_MAINTENANCE"}}
- <li {{bindAttr class="view.noActionAvailable
view.content.isImpliedState:disabled :allow-tooltip"}}
- {{bindAttr data-original-title="view.maintenanceTooltip"}}
rel="passiveTooltip" >
- <a href="javascript:void(null)"
- data-toggle="modal" {{action "toggleMaintenanceMode"
view.content target="controller"}}>
- {{#if view.isActive}}
- {{t passiveState.turnOn}}
- {{else}}
- {{t passiveState.turnOff}}
- {{/if}}
- </a>
- </li>
- {{/isAuthorized}}
- {{/unless}}
- {{#if view.isInit}}
- <li>
- <a href="javascript:void(null)" data-toggle="modal" {{action
"installComponent" view.content target="controller"}}>
- {{t common.reinstall}}
- </a>
- </li>
- {{/if}}
- {{#if view.isDeletableComponent}}
- {{#isAuthorized "HOST.ADD_DELETE_COMPONENTS"}}
- <li {{bindAttr class="view.isDeleteComponentDisabled:disabled"}}>
- <a href="javascript:void(null)" data-toggle="modal" {{action
"deleteComponent" view.content target="controller"}}>
- {{t common.delete}}
- </a>
- </li>
- {{/isAuthorized}}
- {{/if}}
- {{#if view.isRefreshConfigsAllowed}}
+ {{#if view.isRefreshConfigsAllowed}}
<li>
- <a href="javascript:void(null)" data-toggle="modal" {{action
"refreshComponentConfigs" view.content target="controller"}}>
- {{t hosts.host.details.refreshConfigs}}
- </a>
+ <a href="javascript:void(null)" data-toggle="modal" {{action
"refreshComponentConfigs" view.content
+
target="controller"}}>
+ {{t hosts.host.details.refreshConfigs}}
+ </a>
</li>
- {{/if}}
+ {{/if}}
- {{#each command in view.customCommands}}
- <li {{bindAttr class="command.disabled:disabled"}}>
- <a href="javascript:void(null)" {{action "executeCustomCommand"
command target="controller" href=true}}>{{command.label}}</a>
- </li>
- {{/each}}
- </ul>
+ {{#each command in view.customCommands}}
+ <li {{bindAttr class="command.disabled:disabled"}}>
+ <a href="javascript:void(null)" {{action
"executeCustomCommand" command target="controller"
+
href=true}}>{{command.label}}</a>
+ </li>
+ {{/each}}
+ </ul>
+ {{/if}}
{{/unless}}
</div>
{{/havePermissions}}
-</div>
+</td>
diff --git a/ambari-web/app/templates/main/host/summary.hbs
b/ambari-web/app/templates/main/host/summary.hbs
index 3ceb92f..f04f134 100644
--- a/ambari-web/app/templates/main/host/summary.hbs
+++ b/ambari-web/app/templates/main/host/summary.hbs
@@ -16,6 +16,17 @@
* limitations under the License.
}}
+{{#havePermissions "SERVICE.MODIFY_CONFIGS, SERVICE.START_STOP,
HOST.ADD_DELETE_COMPONENTS, HOST.TOGGLE_MAINTENANCE"}}
+ {{#if view.content.componentsWithStaleConfigsCount}}
+ <div class="alert alert-warning clearfix restart-required">
+ <i class="glyphicon glyphicon-refresh"></i> {{view.needToRestartMessage}}
+ <button {{bindAttr class=":btn :restart-components :pull-right
:btn-warning" disabled="App.router.wizardWatcherController.isNonWizardUser"}}
{{action restartAllStaleConfigComponents target="controller"}}>
+ {{t hosts.host.details.needToRestart.button}}
+ </button>
+ </div>
+ {{/if}}
+{{/havePermissions}}
+
<div class="row host-block">
<div class="col-md-6">
{{!components}}
@@ -48,105 +59,21 @@
</div>
</div>
<div class="host-components panel-body">
+ <table class="table">
+ <thead>
+ <th>{{t common.status}}</th>
+ <th>{{t common.name}}</th>
+ <th>{{t common.type}}</th>
+ <th class="align-center">{{t common.action}}</th>
+ </thead>
+ <tbody>
{{#if view.sortedComponents.length}}
-
- {{#havePermissions "SERVICE.MODIFY_CONFIGS, SERVICE.START_STOP,
HOST.ADD_DELETE_COMPONENTS, HOST.TOGGLE_MAINTENANCE"}}
- {{#if view.content.componentsWithStaleConfigsCount}}
- <div class="alert alert-warning clearfix restart-required">
- <i class="glyphicon glyphicon-refresh"></i>
{{view.needToRestartMessage}}
- <button {{bindAttr class=":btn :restart-components
:pull-right :btn-warning"
disabled="App.router.wizardWatcherController.isNonWizardUser"}} {{action
restartAllStaleConfigComponents target="controller"}}>
- {{t hosts.host.details.needToRestart.button}}
- </button>
- </div>
- {{/if}}
- {{/havePermissions}}
-
- {{#each component in view.sortedComponents}}
- {{view component.viewClass classNames="row row-no-pad"
contentBinding="component"}}
- {{/each}}
+ {{#each component in view.sortedComponents}}
+ {{view component.viewClass contentBinding="component"}}
+ {{/each}}
{{/if}}
- {{!clients and add component button}}
- <div class="clients row row-no-pad">
- <div class="col-md-7 col-lg-8 row client-list
component-name-block-wrapper">
- {{#if view.clients.length}}
- <div class="col-md-3 align-right">{{t
common.clients}} /</div>
- <div class="col-md-9 component-name-block-wrapper">
- <ul>
- {{#each component in view.clients}}
- <li>
- <span {{bindAttr
class="component.staleConfigs:component-restart-required-name"}}>{{component.displayName}}</span>
- {{#if component.isInstallFailed}}
- <span class="health-status-installed
icon-warning-sign"></span>
- {{/if}}
- {{#if component.staleConfigs}}
- <span class="text-warning glyphicon
glyphicon-refresh"></span>
- {{/if}}
- {{#if component.service.isInPassive}}
- <span class="icon-medkit"></span>
- {{/if}}
- </li>
- {{/each}}
- </ul>
- </div>
- {{/if}}
- </div>
- <div class="col-md-5 col-lg-4 pull-right">
- {{#havePermissions "SERVICE.MODIFY_CONFIGS, SERVICE.START_STOP,
HOST.ADD_DELETE_COMPONENTS, HOST.TOGGLE_MAINTENANCE"}}
- {{#if view.clients.length}}
- <div class="dropdown">
- <button id="add_component"
- data-toggle="dropdown" {{bindAttr
disabled="App.router.wizardWatcherController.isNonWizardUser" class=":btn
:btn-default :btn-block :dropdown-toggle
controller.content.isNotHeartBeating:disabled"}}>
- {{t common.installed}}
- <span class="caret pull-right
button-caret-margin"></span>
- </button>
- {{#unless
App.router.wizardWatcherController.isNonWizardUser}}
- <ul class="dropdown-menu">
- <li>
- <a href="javascript:void(null)"
- data-toggle="modal" {{action refreshConfigs
view.clients target="controller"}}>
- {{t hosts.host.details.refreshConfigs}}
- </a>
- </li>
- <li>
- <a href="javascript:void(null)" {{bindAttr
class="view.areClientsNotInstalled::disabled" }}
- data-toggle="modal" {{action installClients
target="view"}}>
- {{t host.host.details.installClients}}
- </a>
- </li>
- {{#if view.anyClientFailedToInstall}}
- <li>
- <a href="javascript:void(null)" {{action
reinstallClients target="view"}}>
- {{t host.host.details.reinstallClients}}
- </a>
- </li>
- {{/if}}
- {{#each option in view.clientsWithCustomCommands}}
- <li class="dropdown-submenu submenu-left">
- <a href="javascript:void(null)">
- <i class="glyphicon
glyphicon-play-circle"></i>
- {{option.label}}
- </a>
-
- <div class="dropdown-menu-wrap">
- <ul class="dropdown-menu">
- {{#each command in option.commands}}
- <li>
- <a href="javascript:void(null)"
{{action "executeCustomCommand" command target="controller" href=true}}>
- {{command.label}}
- </a>
- </li>
- {{/each}}
- </ul>
- </div>
- </li>
- {{/each}}
- </ul>
- {{/unless}}
- </div>
- {{/if}}
- {{/havePermissions}}
- </div>
- </div>
+ </tbody>
+ </table>
</div>
</div>
<div class="host-configuration">
diff --git a/ambari-web/app/views/main/host/details/host_component_view.js
b/ambari-web/app/views/main/host/details/host_component_view.js
index 92cf0c6..45b2b0a 100644
--- a/ambari-web/app/views/main/host/details/host_component_view.js
+++ b/ambari-web/app/views/main/host/details/host_component_view.js
@@ -22,34 +22,48 @@ var uiEffects = require('utils/ui_effects');
App.HostComponentView = Em.View.extend({
templateName: require('templates/main/host/details/host_component'),
+ tagName: 'tr',
/**
* @type {App.HostComponent}
*/
content: null,
+
+ /**
+ * @type {Array}
+ * @const
+ */
excludedMasterCommands: ['DECOMMISSION', 'RECOMMISSION'],
+
/**
- * @type {App.HostComponent}
+ * @type {string}
+ * @const
*/
- hostComponent: function () {
- var hostComponent = null;
- var serviceComponent = this.get('content');
- var host = App.router.get('mainHostDetailsController.content');
- if (host) {
- hostComponent = host.get('hostComponents').findProperty('componentName',
serviceComponent.get('componentName'));
- }
- return hostComponent;
- }.property('content', 'App.router.mainHostDetailsController.content'),
+ upgradeFailedMessage: Em.I18n.t('hosts.host.details.upgradeFailed'),
+
/**
* @type {String}
*/
- workStatus: Em.computed.firstNotBlank('hostComponent.workStatus',
'content.workStatus'),
+ workStatus: Em.computed.alias('content.workStatus'),
/**
* Return host component text status
* @type {String}
*/
- componentTextStatus:
Em.computed.firstNotBlank('hostComponent.componentTextStatus',
'content.componentTextStatus'),
+ componentTextStatus: Em.computed.alias('content.componentTextStatus'),
+
+ /**
+ * @type {string}
+ */
+ typeDisplay: function() {
+ if (this.get('content.isMaster')) {
+ return Em.I18n.t('common.master')
+ } else if (this.get('content.isSlave')) {
+ return Em.I18n.t('common.slave')
+ } else if (this.get('content.isClient')) {
+ return Em.I18n.t('common.client')
+ }
+ }.property('content'),
/**
* CSS-class for host component status
@@ -66,9 +80,13 @@ App.HostComponentView = Em.View.extend({
return 'health-status-color-blue glyphicon glyphicon-cog';
}
+ // Client can't be started, it has only INSTALLED as a working state, so
show working/green icon
+ if (this.get('workStatus') === App.HostComponentStatus.stopped &&
this.get('content.isClient')) {
+ return 'health-status-started';
+ }
+
//For all other cases
return 'health-status-' +
App.HostComponentStatus.getKeyName(this.get('workStatus'));
-
}.property('workStatus'),
/**
@@ -90,11 +108,17 @@ App.HostComponentView = Em.View.extend({
* CSS-class for disabling drop-down menu with list of host component actions
* Disabled if host's <code>healthClass</code> is health-status-DEAD-YELLOW
(lost heartbeat)
* Disabled if component's action list is empty
- * @type {String}
+ * @type {boolean}
*/
- disabled: function () {
- return ( (this.get('parentView.content.healthClass') ===
"health-status-DEAD-YELLOW") || (this.get('noActionAvailable') === 'hidden' &&
this.get('isRestartComponentDisabled'))) ? 'disabled' : '';
- }.property('parentView.content.healthClass', 'noActionAvailable',
'isRestartComponentDisabled'),
+ isDisabled: function () {
+ return (this.get('parentView.content.healthClass') ===
"health-status-DEAD-YELLOW") ||
+ (this.get('noActionAvailable') === 'hidden' &&
this.get('isRestartComponentDisabled')) ||
+ App.router.get('wizardWatcherController.isNonWizardUser');
+ }.property(
+ 'parentView.content.healthClass',
+ 'noActionAvailable',
+ 'isRestartComponentDisabled',
+ 'App.router.wizardWatcherController.isNonWizardUser'),
/**
* For Upgrade failed state
@@ -154,7 +178,7 @@ App.HostComponentView = Em.View.extend({
/**
* Tooltip message for switch maintenance mode option
- * @type {Strting}
+ * @type {String}
*/
maintenanceTooltip: function () {
switch (this.get('content.passiveState')) {
@@ -188,9 +212,9 @@ App.HostComponentView = Em.View.extend({
* @type {bool}
*/
isDeleteComponentDisabled: function () {
- var stackComponentCount =
App.StackServiceComponent.find(this.get('hostComponent.componentName')).get('minToInstall');
- var installedCount =
App.HostComponent.getCount(this.get('hostComponent.componentName'),
'totalCount');
- if(this.get('hostComponent.componentName') == 'MYSQL_SERVER' &&
this.get('hostComponent.serviceDisplayName') == 'Hive') {
+ var stackComponentCount =
App.StackServiceComponent.find(this.get('content.componentName')).get('minToInstall');
+ var installedCount =
App.HostComponent.getCount(this.get('content.componentName'), 'totalCount');
+ if(this.get('content.componentName') === 'MYSQL_SERVER' &&
this.get('content.serviceDisplayName') === 'Hive') {
var
db_type=App.db.getConfigs().findProperty('type','hive-env').properties['hive_database'];
var status=[App.HostComponentStatus.stopped,
App.HostComponentStatus.unknown, App.HostComponentStatus.install_failed,
App.HostComponentStatus.upgrade_failed,
App.HostComponentStatus.init].contains(this.get('workStatus'));
if(db_type.indexOf('Existing') > -1 && status)
@@ -198,7 +222,7 @@ App.HostComponentView = Em.View.extend({
else
return true;
}
- if (this.get('hostComponent.componentName') == 'JOURNALNODE') {
+ if (this.get('content.componentName') === 'JOURNALNODE') {
var count_JN = App.HostComponent.find().filterProperty('componentName',
'JOURNALNODE').get('length');
return count_JN <= 3; // TODO get 3 from stack
}
@@ -365,7 +389,7 @@ App.HostComponentView = Em.View.extend({
if (component.get('cardinality') !== '1') {
if (!this.get('isStart')) {
- if
(App.HostComponent.getCount(this.get('hostComponent.componentName'),
'totalCount') > 1) {
+ if (App.HostComponent.getCount(this.get('content.componentName'),
'totalCount') > 1) {
if (this.runningComponentCounter()) {
return false;
}
@@ -376,6 +400,28 @@ App.HostComponentView = Em.View.extend({
}
return true;
+ },
+
+ /**
+ * @type {Array}
+ */
+ clientCustomCommands: function() {
+ const componentName = this.get('content.componentName');
+
+ if (componentName === 'KERBEROS_CLIENT') {
+ return [];
+ }
+
+ return
App.StackServiceComponent.find(componentName).get('customCommands').map(function
(command) {
+ return {
+ label:
Em.I18n.t('services.service.actions.run.executeCustomCommand.menu').format(command),
+ command: command
+ }
+ });
+ }.property('controller'),
+
+ installClient: function() {
+ this.get('controller').installClients([this.get('content')]);
}
});
diff --git a/ambari-web/app/views/main/host/summary.js
b/ambari-web/app/views/main/host/summary.js
index 89332de..82f42da 100644
--- a/ambari-web/app/views/main/host/summary.js
+++ b/ambari-web/app/views/main/host/summary.js
@@ -120,96 +120,43 @@ App.MainHostSummaryView =
Em.View.extend(App.TimeRangeMixin, {
/**
* Update <code>sortedComponents</code>
- * Master components first, then slaves
+ * Master components first, then slaves and clients
*/
sortedComponentsFormatter: function() {
- var updatebleProperties = Em.A(['workStatus', 'passiveState',
'staleConfigs', 'haStatus']);
- var self = this;
- var hostComponentViewMap = this.get('hostComponentViewMap');
+ const updatebleProperties = Em.A(['workStatus', 'passiveState',
'staleConfigs', 'haStatus']);
+ const hostComponentViewMap = this.get('hostComponentViewMap');
+ const masters = [], slaves = [], clients = [];
// Remove deleted components
- this.get('sortedComponents').forEach(function(sortedComponent, index) {
- if (!self.get('content.hostComponents').findProperty('id',
sortedComponent.get('id'))) {
- self.get('sortedComponents').removeAt(index, 1);
+ this.get('sortedComponents').forEach((sortedComponent, index) => {
+ if (!this.get('content.hostComponents').findProperty('id',
sortedComponent.get('id'))) {
+ this.get('sortedComponents').removeAt(index, 1);
}
});
this.get('content.hostComponents').forEach(function (component) {
- if (component.get('isMaster') || component.get('isSlave')) {
- var obj = this.get('sortedComponents').findProperty('id',
component.get('id'));
- if (obj) {
- // Update existing component
- updatebleProperties.forEach(function(property) {
- obj.set(property, component.get(property));
- });
- }
- else {
- // Add new component
- component.set('viewClass',
hostComponentViewMap[component.get('componentName')] ?
hostComponentViewMap[component.get('componentName')] : App.HostComponentView);
- if (component.get('isMaster')) {
- // Masters should be before slaves
- var lastMasterIndex = 0, atLeastOneMasterExists = false;
- this.get('sortedComponents').forEach(function(sortedComponent,
index) {
- if (sortedComponent.get('isMaster')) {
- lastMasterIndex = index;
- atLeastOneMasterExists = true;
- }
- });
- this.get('sortedComponents').insertAt(atLeastOneMasterExists ?
lastMasterIndex + 1 : 0, component);
- }
- else {
- // it is slave 100%
- this.get('sortedComponents').pushObject(component);
- }
+ const obj = this.get('sortedComponents').findProperty('id',
component.get('id'));
+ if (obj) {
+ // Update existing component
+ updatebleProperties.forEach(function (property) {
+ obj.set(property, component.get(property));
+ });
+ } else {
+ component.set('viewClass',
hostComponentViewMap[component.get('componentName')] ?
hostComponentViewMap[component.get('componentName')] : App.HostComponentView);
+ if (component.get('isMaster')) {
+ masters.push(component);
+ } else if (component.get('isSlave')) {
+ slaves.push(component);
+ } else if (component.get('isClient')) {
+ component.set('isLast', true);
+ component.set('isInstallFailed', ['INSTALL_FAILED',
'INIT'].contains(component.get('workStatus')));
+ clients.pushObject(component);
}
}
}, this);
+ this.set('sortedComponents', masters.concat(slaves, clients));
},
/**
- * List of installed clients
- * @type {App.HostComponent[]}
- */
- clients: function () {
- var clients = [];
- this.get('content.hostComponents').forEach(function (component) {
- if (!component.get('componentName')) {
- //temporary fix because of different data in hostComponents and
serviceComponents
- return;
- }
- if (!component.get('isSlave') && !component.get('isMaster')) {
- if (clients.length) {
- clients[clients.length - 1].set('isLast', false);
- }
- component.set('isLast', true);
- component.set('isInstallFailed', ['INSTALL_FAILED',
'INIT'].contains(component.get('workStatus')));
- clients.push(component);
- }
- }, this);
- return clients;
- }.property('content.hostComponents.length',
'[email protected]'),
-
- anyClientFailedToInstall: Em.computed.someBy('clients', 'isInstallFailed',
true),
-
- /**
- * Check if some clients not installed or started
- *
- * @type {bool}
- **/
- areClientsNotInstalled: Em.computed.or('anyClientFailedToInstall',
'installableClientComponents.length'),
-
- /**
- * Check if some clients have stale configs
- * @type {bool}
- */
- areClientWithStaleConfigs: Em.computed.someBy('clients', 'staleConfigs',
true),
-
- /**
- * List of install failed clients
- * @type {App.HostComponent[]}
- */
- installFailedClients: Em.computed.filterBy('clients', 'workStatus',
'INSTALL_FAILED'),
-
- /**
* Template for addable component
* @type {Em.Object}
*/
@@ -233,26 +180,6 @@ App.MainHostSummaryView =
Em.View.extend(App.TimeRangeMixin, {
addComponentDisabled: Em.computed.or('!isAddComponent',
'!addableComponents.length'),
/**
- * List of client's that may be installed to the current host
- * @type {String[]}
- */
- installableClientComponents: function() {
- var clientComponents =
App.StackServiceComponent.find().filterProperty('isClient');
- var installedServices = this.get('installedServices');
- var installedClients = this.get('clients').mapProperty('componentName');
- return clientComponents.filter(function(component) {
- // service for current client is installed but client isn't installed on
current host
- return installedServices.contains(component.get('serviceName')) &&
!installedClients.contains(component.get('componentName'));
- });
- }.property('content.hostComponents.length', 'installedServices.length'),
-
- notInstalledClientComponents: function () {
- return this.get('clients').filter(function(component) {
- return ['INIT', 'INSTALL_FAILED'].contains(component.get('workStatus'));
- }).concat(this.get('installableClientComponents'));
- }.property('installableClientComponents.length', 'clients.length'),
-
- /**
* List of components that may be added to the current host
* @type {Em.Object[]}
*/
@@ -299,52 +226,5 @@ App.MainHostSummaryView =
Em.View.extend(App.TimeRangeMixin, {
timeSinceHeartBeat: function () {
var d = this.get('content.rawLastHeartBeatTime');
return d ? $.timeago(d) : '';
- }.property('content.rawLastHeartBeatTime'),
-
- /**
- * Get clients with custom commands
- */
- clientsWithCustomCommands: function() {
- var clients = this.get('clients').rejectProperty('componentName',
'KERBEROS_CLIENT');
- var options = [];
- var clientWithCommands;
- clients.forEach(function(client) {
- var componentName = client.get('componentName');
- var customCommands =
App.StackServiceComponent.find(componentName).get('customCommands');
-
- if (customCommands.length) {
- clientWithCommands = {
- label: client.get('displayName'),
- commands: []
- };
- customCommands.forEach(function(command) {
- clientWithCommands.commands.push({
- label:
Em.I18n.t('services.service.actions.run.executeCustomCommand.menu').format(command),
- service: client.get('service.serviceName'),
- hosts: client.get('hostName'),
- component: componentName,
- command: command
- });
- });
-
- options.push(clientWithCommands);
- }
- });
-
- return options;
- }.property('controller'),
-
- /**
- * Call installClients method from controller for not installed client
components
- */
- installClients: function () {
-
this.get('controller').installClients(this.get('notInstalledClientComponents'));
- },
-
- /**
- * Call installClients method from controller for not install failed client
components
- */
- reinstallClients: function () {
- this.get('controller').installClients(this.get('installFailedClients'));
- }
+ }.property('content.rawLastHeartBeatTime')
});
diff --git
a/ambari-web/test/views/main/host/details/host_component_view_test.js
b/ambari-web/test/views/main/host/details/host_component_view_test.js
index f78c71e..1ac6fe0 100644
--- a/ambari-web/test/views/main/host/details/host_component_view_test.js
+++ b/ambari-web/test/views/main/host/details/host_component_view_test.js
@@ -30,7 +30,9 @@ function getView() {
content: Em.Object.create({
componentName: 'component'
}),
- hostComponent: Em.Object.create()
+ controller: Em.Object.create({
+ installClients: sinon.spy()
+ })
});
}
@@ -42,32 +44,32 @@ describe('App.HostComponentView', function() {
App.TestAliases.testAsComputedNotEqual(getView(),
'isRestartComponentDisabled', 'workStatus', App.HostComponentStatus.started);
- describe('#disabled', function() {
+ describe('#isDisabled', function() {
var tests = Em.A([
{
parentView: {content: {healthClass: 'health-status-DEAD-YELLOW'}},
noActionAvailable: '',
isRestartComponentDisabled: true,
- e: 'disabled'
+ e: true
},
{
parentView: {content: {healthClass: 'another-class'}},
noActionAvailable: '',
isRestartComponentDisabled: true,
- e: ''
+ e: false
},
{
parentView: {content: {healthClass: 'another-class'}},
noActionAvailable: 'hidden',
isRestartComponentDisabled: true,
- e: 'disabled'
+ e: true
},
{
parentView: {content: {healthClass: 'another-class'}},
noActionAvailable: 'hidden',
isRestartComponentDisabled: false,
- e: ''
+ e: false
}
]);
@@ -80,7 +82,7 @@ describe('App.HostComponentView', function() {
noActionAvailable: test.noActionAvailable,
isRestartComponentDisabled: test.isRestartComponentDisabled
});
- expect(hostComponentView.get('disabled')).to.equal(test.e);
+ expect(hostComponentView.get('isDisabled')).to.equal(test.e);
});
});
@@ -127,21 +129,21 @@ describe('App.HostComponentView', function() {
it('delete is disabled because min cardinality 1', function() {
this.mock.returns(Em.Object.create({minToInstall: 1}));
- hostComponentView.get('hostComponent').set('componentName', 'C1');
+ hostComponentView.get('content').set('componentName', 'C1');
hostComponentView.propertyDidChange('isDeleteComponentDisabled');
expect(hostComponentView.get('isDeleteComponentDisabled')).to.be.true;
});
it('delete is disabled because min cardinality 0 and status INSTALLED',
function() {
this.mock.returns(Em.Object.create({minToInstall: 0}));
- hostComponentView.get('hostComponent').set('workStatus', 'INIT');
+ hostComponentView.get('content').set('workStatus', 'INIT');
hostComponentView.propertyDidChange('isDeleteComponentDisabled');
expect(hostComponentView.get('isDeleteComponentDisabled')).to.be.false;
});
it('delete is enabled because min cardinality 0 and status STARTED',
function() {
this.mock.returns(Em.Object.create({minToInstall: 0}));
- hostComponentView.get('hostComponent').set('workStatus', 'STARTED');
+ hostComponentView.get('content').set('workStatus', 'STARTED');
hostComponentView.propertyDidChange('isDeleteComponentDisabled');
expect(hostComponentView.get('isDeleteComponentDisabled')).to.be.true;
});
@@ -149,79 +151,13 @@ describe('App.HostComponentView', function() {
it('delete is enabled because mysql server is stopped and hive is using
external database', function() {
App.db.setConfigs(configs);
this.mock.returns(Em.Object.create({minToInstall: 0}));
- hostComponentView.get('hostComponent').set('componentName',
'MYSQL_SERVER');
- hostComponentView.get('hostComponent').set('workStatus', 'STOPPED');
+ hostComponentView.get('content').set('componentName', 'MYSQL_SERVER');
+ hostComponentView.get('content').set('workStatus', 'STOPPED');
hostComponentView.propertyDidChange('isDeleteComponentDisabled');
expect(hostComponentView.get('isDeleteComponentDisabled')).to.be.true;
});
});
- describe('#componentTextStatus', function() {
-
- var tests = Em.A([
- {
- componentTextStatus: 'status',
- hostComponent: null,
- e: 'status',
- m: 'get content status'
- },
- {
- componentTextStatus: 'status',
- hostComponent: Em.Object.create({componentTextStatus: 'new_status'}),
- e: 'new_status',
- m: 'get hostComponent status'
- }
- ]);
-
- tests.forEach(function(test) {
- it(test.m, function() {
- hostComponentView = App.HostComponentView.create({
- startBlinking: function(){},
- doBlinking: function(){},
- getDesiredAdminState: function(){return $.ajax({});},
- hostComponent: test.hostComponent,
- content: Em.Object.create()
- });
- hostComponentView.get('content').set('componentTextStatus',
test.componentTextStatus);
- expect(hostComponentView.get('componentTextStatus')).to.equal(test.e);
- });
- });
-
- });
-
- describe('#workStatus', function() {
-
- var tests = Em.A([
- {
- workStatus: 'status',
- hostComponent: null,
- e: 'status',
- m: 'get content workStatus'
- },
- {
- workStatus: 'status',
- hostComponent: Em.Object.create({workStatus: 'new_status'}),
- e: 'new_status',
- m: 'get hostComponent workStatus'
- }
- ]);
-
- tests.forEach(function(test) {
- it(test.m, function() {
- hostComponentView = App.HostComponentView.create({
- startBlinking: function(){},
- doBlinking: function(){},
- getDesiredAdminState: function(){return $.ajax({});},
- hostComponent: test.hostComponent,
- content: Em.Object.create()
- });
- hostComponentView.get('content').set('workStatus', test.workStatus);
- expect(hostComponentView.get('workStatus')).to.equal(test.e);
- });
- });
-
- });
-
describe('#statusClass', function() {
var tests = Em.A([
@@ -249,19 +185,25 @@ describe('App.HostComponentView', function() {
workStatus: 'STARTED',
passiveState: 'OFF',
e: 'health-status-started'
+ },
+ {
+ workStatus: App.HostComponentStatus.stopped,
+ passiveState: 'OFF',
+ isClient: true,
+ e: 'health-status-started'
}
]);
tests.forEach(function(test) {
it(test.workStatus + ' ' + test.passiveState, function() {
hostComponentView = App.HostComponentView.create({
- startBlinking: function(){},
- doBlinking: function(){},
+ startBlinking: Em.K,
+ doBlinking: Em.K,
getDesiredAdminState: function(){return $.ajax({});},
- content: Em.Object.create(),
- hostComponent: Em.Object.create()
+ content: Em.Object.create()
});
-
hostComponentView.get('hostComponent').set('workStatus',test.workStatus);
+ hostComponentView.get('content').set('isClient', test.isClient);
+ hostComponentView.get('content').set('workStatus', test.workStatus);
hostComponentView.get('content').set('passiveState',
test.passiveState);
expect(hostComponentView.get('statusClass')).to.equal(test.e);
});
@@ -482,4 +424,32 @@ describe('App.HostComponentView', function() {
});
});
+ describe('#clientCustomCommands', function() {
+ beforeEach(function() {
+ sinon.stub(App.StackServiceComponent, 'find').returns(Em.Object.create({
+ customCommands: ['COMMAND1']
+ }));
+ });
+ afterEach(function() {
+ App.StackServiceComponent.find.restore();
+ });
+
+ it('should return list of commands', function() {
+ hostComponentView.set('content');
+ hostComponentView.propertyDidChange('clientCustomCommands');
+ expect(hostComponentView.get('clientCustomCommands')).to.be.eql([{
+ command: 'COMMAND1',
+ label:
Em.I18n.t('services.service.actions.run.executeCustomCommand.menu').format('COMMAND1')
+ }]);
+ });
+ });
+
+ describe('#installClient', function() {
+
+ it('installClients should be called', function() {
+ hostComponentView.installClient();
+
expect(hostComponentView.get('controller').installClients.calledOnce).to.be.true;
+ });
+ });
+
});
diff --git a/ambari-web/test/views/main/host/summary_test.js
b/ambari-web/test/views/main/host/summary_test.js
index f1c9d06..07d3ee8 100644
--- a/ambari-web/test/views/main/host/summary_test.js
+++ b/ambari-web/test/views/main/host/summary_test.js
@@ -112,14 +112,14 @@ describe('App.MainHostSummaryView', function() {
{
content: Em.Object.create({
hostComponents: Em.A([
- Em.Object.create({isMaster: false, isSlave: false, componentName:
'B'}),
- Em.Object.create({isMaster: false, isSlave: false, componentName:
'A'}),
- Em.Object.create({isMaster: false, isSlave: false, componentName:
'C'}),
- Em.Object.create({isMaster: false, isSlave: false, componentName:
'D'})
+ Em.Object.create({isClient: true, componentName: 'B'}),
+ Em.Object.create({isMaster: true, componentName: 'A'}),
+ Em.Object.create({isSlave: true, componentName: 'C'}),
+ Em.Object.create({isClient: true, componentName: 'D'})
])
}),
m: 'List of clients',
- e: []
+ e: ['A', 'C', 'B', 'D']
}
]);
@@ -137,151 +137,6 @@ describe('App.MainHostSummaryView', function() {
});
- describe('#clients', function() {
-
- var tests = Em.A([
- {
- content: Em.Object.create({
- hostComponents: Em.A([
- Em.Object.create({isMaster: false, isSlave: true, componentName:
'B'}),
- Em.Object.create({isMaster: true, isSlave: false, componentName:
'A'}),
- Em.Object.create({isMaster: true, isSlave: false, componentName:
'C'}),
- Em.Object.create({isMaster: false, isSlave: false, componentName:
'D'})
- ])
- }),
- m: 'List of masters, slaves and clients',
- e: ['D']
- },
- {
- content: Em.Object.create({
- hostComponents: Em.A([
- Em.Object.create({isMaster: false, isSlave: true, componentName:
'B'}),
- Em.Object.create({isMaster: true, isSlave: false, componentName:
'A'}),
- Em.Object.create({isMaster: true, isSlave: false, componentName:
'C'}),
- Em.Object.create({isMaster: true, isSlave: false, componentName:
'D'})
- ])
- }),
- m: 'List of masters and slaves',
- e: []
- },
- {
- content: Em.Object.create({
- hostComponents: Em.A([
- Em.Object.create({isMaster: true, isSlave: false, componentName:
'B'}),
- Em.Object.create({isMaster: true, isSlave: false, componentName:
'A'}),
- Em.Object.create({isMaster: true, isSlave: false, componentName:
'C'}),
- Em.Object.create({isMaster: true, isSlave: false, componentName:
'D'})
- ])
- }),
- m: 'List of masters',
- e: []
- },
- {
- content: Em.Object.create({
- hostComponents: Em.A([
- Em.Object.create({isMaster: false, isSlave: true, componentName:
'B'}),
- Em.Object.create({isMaster: false, isSlave: true, componentName:
'A'}),
- Em.Object.create({isMaster: false, isSlave: true, componentName:
'C'}),
- Em.Object.create({isMaster: false, isSlave: true, componentName:
'D'})
- ])
- }),
- m: 'List of slaves',
- e: []
- },
- {
- content: Em.Object.create({
- hostComponents: Em.A([])
- }),
- m: 'Empty list',
- e: []
- },
- {
- content: Em.Object.create({
- hostComponents: Em.A([
- Em.Object.create({isMaster: false, isSlave: false, componentName:
'B'}),
- Em.Object.create({isMaster: false, isSlave: false, componentName:
'A'}),
- Em.Object.create({isMaster: false, isSlave: false, componentName:
'C'}),
- Em.Object.create({isMaster: false, isSlave: false, componentName:
'D'})
- ])
- }),
- m: 'List of clients',
- e: ['B', 'A', 'C', 'D']
- }
- ]);
-
- tests.forEach(function(test) {
- it(test.m, function() {
- mainHostSummaryView.set('content', test.content);
-
expect(mainHostSummaryView.get('clients').mapProperty('componentName')).to.eql(test.e);
- });
- });
-
- it('should set isInstallFailed for clients with INIT and INSTALL_FAILED
workStatus', function() {
- mainHostSummaryView.set('content', Em.Object.create({
- hostComponents: [
- Em.Object.create({isMaster: false, isSlave: false, componentName:
'B', workStatus: 'INIT'}),
- Em.Object.create({isMaster: false, isSlave: false, componentName:
'A', workStatus: 'INSTALLED'}),
- Em.Object.create({isMaster: false, isSlave: false, componentName:
'C', workStatus: 'INSTALL_FAILED'}),
- Em.Object.create({isMaster: false, isSlave: false, componentName:
'D', workStatus: 'INSTALLING'})
- ]
- }));
-
expect(mainHostSummaryView.get('clients').filterProperty('isInstallFailed',
true).mapProperty('componentName')).to.eql(['B', 'C']);
-
expect(mainHostSummaryView.get('clients').filterProperty('isInstallFailed',
false).mapProperty('componentName')).to.eql(['A', 'D']);
- });
-
- });
-
- describe('#areClientWithStaleConfigs', function() {
-
- var tests = Em.A([
- {
- content: Em.Object.create({
- hostComponents: Em.A([
- Em.Object.create({isMaster: false, isSlave: false, componentName:
'D', staleConfigs: true}),
- Em.Object.create({isMaster: false, isSlave: false, componentName:
'C', staleConfigs: false})
- ])
- }),
- m: 'Some clients with stale configs',
- e: true
- },
- {
- content: Em.Object.create({
- hostComponents: Em.A([
- Em.Object.create({isMaster: false, isSlave: false, componentName:
'D', staleConfigs: false}),
- Em.Object.create({isMaster: false, isSlave: false, componentName:
'C', staleConfigs: false})
- ])
- }),
- m: 'No clients with stale configs',
- e: false
- },
- {
- content: Em.Object.create({
- hostComponents: Em.A([
- Em.Object.create({isMaster: false, isSlave: false, componentName:
'D', staleConfigs: true}),
- Em.Object.create({isMaster: false, isSlave: false, componentName:
'C', staleConfigs: true})
- ])
- }),
- m: 'All clients with stale configs',
- e: true
- },
- {
- content: Em.Object.create({
- hostComponents: Em.A([])
- }),
- m: 'Empty list',
- e: false
- }
- ]);
-
- tests.forEach(function(test) {
- it(test.m, function() {
- mainHostSummaryView.set('content', test.content);
-
expect(mainHostSummaryView.get('areClientWithStaleConfigs')).to.equal(test.e);
- });
- });
-
- });
-
describe('#isAddComponent', function() {
var tests = Em.A([
@@ -368,104 +223,6 @@ describe('App.MainHostSummaryView', function() {
});
});
- describe('#areClientsNotInstalled', function () {
-
- var cases = [
- {
- clients: [
- {
- isInstallFailed: true
- }
- ],
- installableClientComponents: [],
- areClientsNotInstalled: true,
- title: 'some clients failed to install, no clients to add'
- },
- {
- clients: [
- {
- isInstallFailed: false
- }
- ],
- installableClientComponents: [{}],
- areClientsNotInstalled: true,
- title: 'no clients failed to install, some clients to add'
- },
- {
- clients: [
- {
- isInstallFailed: true
- }
- ],
- installableClientComponents: [{}],
- areClientsNotInstalled: true,
- title: 'some clients failed to install, some clients to add'
- },
- {
- clients: [
- {
- isInstallFailed: false
- }
- ],
- installableClientComponents: [],
- areClientsNotInstalled: false,
- title: 'no clients failed to install, no clients to add'
- }
- ];
-
- cases.forEach(function (item) {
- it(item.title, function () {
- mainHostSummaryView.reopen({
- clients: item.clients,
- installableClientComponents: item.installableClientComponents
- });
-
expect(mainHostSummaryView.get('areClientsNotInstalled')).to.equal(item.areClientsNotInstalled);
- });
- });
-
- });
-
- describe('#notInstalledClientComponents', function () {
-
- it('should concat not added clients and the ones that failed to install',
function () {
- mainHostSummaryView.reopen({
- clients: [
- Em.Object.create({
- componentName: 'c0',
- workStatus: 'INIT'
- }),
- Em.Object.create({
- componentName: 'c1',
- workStatus: 'INSTALL_FAILED'
- }),
- Em.Object.create({
- componentName: 'c2',
- workStatus: 'INSTALLED'
- })
- ],
- installableClientComponents: [
- Em.Object.create({
- componentName: 'c3'
- })
- ]
- });
- expect(mainHostSummaryView.get('notInstalledClientComponents')).to.eql([
- Em.Object.create({
- componentName: 'c0',
- workStatus: 'INIT'
- }),
- Em.Object.create({
- componentName: 'c1',
- workStatus: 'INSTALL_FAILED'
- }),
- Em.Object.create({
- componentName: 'c3'
- })
- ]);
- });
-
- });
-
describe("#needToRestartMessage", function() {
it("one component", function() {
@@ -577,43 +334,6 @@ describe('App.MainHostSummaryView', function() {
});
- describe("#installableClientComponents", function() {
-
- beforeEach(function() {
- sinon.stub(App.StackServiceComponent, 'find').returns([
- Em.Object.create({
- isClient: true,
- serviceName: 'S1',
- componentName: 'C1'
- }),
- Em.Object.create({
- isClient: true,
- serviceName: 'S1',
- componentName: 'C2'
- }),
- Em.Object.create({
- isClient: true,
- serviceName: 'S2',
- componentName: 'C1'
- })
- ]);
- });
- afterEach(function() {
- App.StackServiceComponent.find.restore();
- });
-
- it("should return installable client components", function() {
- mainHostSummaryView.reopen({
- installedServices: ['S1'],
- clients: [
- Em.Object.create({componentName: 'C2'})
- ]
- });
- mainHostSummaryView.propertyDidChange('installableClientComponents');
-
expect(mainHostSummaryView.get('installableClientComponents').mapProperty('componentName')).to.eql(['C1']);
- });
- });
-
describe("#hasCardinalityConflict()", function () {
beforeEach(function() {
@@ -657,44 +377,6 @@ describe('App.MainHostSummaryView', function() {
});
});
- describe("#installClients()", function () {
-
- beforeEach(function () {
- var controller = {installClients: Em.K};
- sinon.spy(controller, 'installClients');
- mainHostSummaryView.set('controller', controller);
- mainHostSummaryView.reopen({'notInstalledClientComponents': [1,2,3]});
- });
-
- afterEach(function () {
- mainHostSummaryView.get('controller.installClients').restore();
- });
-
- it("should call installClients method from controller", function () {
- mainHostSummaryView.installClients();
-
expect(mainHostSummaryView.get('controller.installClients').calledWith([1,2,3])).to.be.true;
- });
- });
-
- describe("#reinstallClients()", function () {
-
- beforeEach(function () {
- var controller = {installClients: Em.K};
- sinon.spy(controller, 'installClients');
- mainHostSummaryView.set('controller', controller);
- mainHostSummaryView.reopen({'installFailedClients': [1,2,3]});
- });
-
- afterEach(function () {
- mainHostSummaryView.get('controller.installClients').restore();
- });
-
- it("should call installClients method from controller", function () {
- mainHostSummaryView.reinstallClients();
-
expect(mainHostSummaryView.get('controller.installClients').calledWith([1,2,3])).to.be.true;
- });
- });
-
describe("#timeSinceHeartBeat", function () {
beforeEach(function() {
@@ -717,72 +399,4 @@ describe('App.MainHostSummaryView', function() {
expect(mainHostSummaryView.get('timeSinceHeartBeat')).to.be.equal('1');
});
});
-
- describe("#clientsWithCustomCommands", function () {
-
- beforeEach(function() {
- this.mockComponents = sinon.stub(App.StackServiceComponent, 'find');
- });
-
- afterEach(function() {
- this.mockComponents.restore();
- });
-
- var testCases = [
- {
- component: Em.Object.create(),
- clients: [],
- expected: []
- },
- {
- component: Em.Object.create(),
- clients: [
- Em.Object.create({componentName: 'KERBEROS_CLIENT'})
- ],
- expected: []
- },
- {
- component: Em.Object.create({customCommands: []}),
- clients: [
- Em.Object.create({componentName: 'C1'})
- ],
- expected: []
- },
- {
- component: Em.Object.create({customCommands: ['cmd1']}),
- clients: [
- Em.Object.create({
- hostName: 'host1',
- displayName: 'dn1',
- componentName: 'C1',
- service: Em.Object.create({serviceName: 'S1'})
- })
- ],
- expected: [{
- label: 'dn1',
- commands: [
- {
- label:
Em.I18n.t('services.service.actions.run.executeCustomCommand.menu').format('cmd1'),
- service: "S1",
- hosts: 'host1',
- component: 'C1',
- command: 'cmd1'
- }
- ]
- }]
- }
- ];
-
- testCases.forEach(function(test) {
- it("component = " + JSON.stringify(test.component) +
- " clients = " + JSON.stringify(test.clients), function() {
- this.mockComponents.returns(test.component);
- mainHostSummaryView.reopen({
- clients: test.clients
- });
- mainHostSummaryView.propertyDidChange('clientsWithCustomCommands');
-
expect(mainHostSummaryView.get('clientsWithCustomCommands')).to.be.eql(test.expected);
- });
- });
- });
});
--
To stop receiving notification emails like this one, please contact
[email protected].