You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by on...@apache.org on 2014/04/25 18:31:22 UTC
[1/2] AMBARI-5575. Unit tests for steps 9 (with refactor).
(onechiporenko)
Repository: ambari
Updated Branches:
refs/heads/trunk 739d35e38 -> b96edcf90
http://git-wip-us.apache.org/repos/asf/ambari/blob/b96edcf9/ambari-web/test/installer/step9_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/installer/step9_test.js b/ambari-web/test/installer/step9_test.js
index f96ee00..2469828 100644
--- a/ambari-web/test/installer/step9_test.js
+++ b/ambari-web/test/installer/step9_test.js
@@ -24,12 +24,14 @@ require('models/hosts');
require('controllers/wizard/step9_controller');
require('utils/helper');
var modelSetup = require('test/init_model_test');
-
+var c, obj;
describe('App.InstallerStep9Controller', function () {
- beforeEach(function(){
+ beforeEach(function () {
modelSetup.setupStackServiceComponent();
+ c = App.WizardStep9Controller.create();
+ obj = App.InstallerController.create();
});
- afterEach(function(){
+ afterEach(function () {
modelSetup.cleanStackServiceComponent();
});
@@ -739,6 +741,22 @@ describe('App.InstallerStep9Controller', function () {
var result = controller.finishState();
expect(result).to.equal(false);
});
+ it('for INSTALLED status should call isServicesStarted', function () {
+ c.set('content', {cluster: {status: 'INSTALLED'}});
+ var polledData = {'{}': {}};
+ sinon.stub(c, 'isServicesStarted', Em.K);
+ c.finishState(polledData);
+ expect(c.isServicesStarted.calledWith(polledData)).to.equal(true);
+ c.isServicesStarted.restore();
+ });
+ it('for PENDING status should call isServicesInstalled', function () {
+ c.set('content', {cluster: {status: 'PENDING'}});
+ var polledData = {'{}': {}};
+ sinon.stub(c, 'isServicesInstalled', Em.K);
+ c.finishState(polledData);
+ expect(c.isServicesInstalled.calledWith(polledData)).to.equal(true);
+ c.isServicesInstalled.restore();
+ });
});
describe('#setLogTasksStatePerHost', function () {
@@ -937,11 +955,19 @@ describe('App.InstallerStep9Controller', function () {
expect(controller.get('progress')).to.equal(test.e.progress);
});
});
+ it('shouldn\'t do nothing if polledData.Requests.id != requestId', function () {
+ c.set('content', {cluster: {requestId: 1}});
+ var polledData = {Requests: {id: 2}, tasks: []};
+ sinon.spy(c, 'finishState');
+ expect(c.parseHostInfo(polledData)).to.equal(false);
+ expect(c.finishState.called).to.equal(false);
+ c.finishState.restore();
+ });
});
describe('#isAllComponentsInstalledSuccessCallback', function () {
- describe('', function() {
+ describe('', function () {
var hosts = Em.A([
Em.Object.create({name: 'host1', status: 'failed', expectedStatus: 'heartbeat_lost'}),
Em.Object.create({name: 'host2', status: 'info', expectedStatus: 'heartbeat_lost'}),
@@ -1046,7 +1072,7 @@ describe('App.InstallerStep9Controller', function () {
});
- describe('', function() {
+ describe('', function () {
var noHeartbeatLostData = {
"items": [
{
@@ -1076,9 +1102,10 @@ describe('App.InstallerStep9Controller', function () {
// INSTALL FAILED -> INSTALL FAILED. No transition should happen when install all services request fails and then user hits refresh
// Cluster is not expected to enter this function in other states: INSTALLED, START FAILED, STARTED
- var statuses = Em.A(['INSTALL FAILED', 'INSTALLED','START FAILED', 'STARTED']); // Cluster in any of this states should have no effect on the state from this function
+ var statuses = Em.A(['INSTALL FAILED', 'INSTALLED', 'START FAILED', 'STARTED']); // Cluster in any of this states should have no effect on the state from this function
statuses.forEach(function (priorStatus) {
- var controller = App.WizardStep9Controller.create({hosts: hosts, content: {controllerName: 'installerController', cluster: {status: priorStatus}},togglePreviousSteps: function(){}});
+ var controller = App.WizardStep9Controller.create({hosts: hosts, content: {controllerName: 'installerController', cluster: {status: priorStatus}}, togglePreviousSteps: function () {
+ }});
// Action
controller.isAllComponentsInstalledSuccessCallback(noHeartbeatLostData);
// Validation for the cluster state.
@@ -1090,25 +1117,25 @@ describe('App.InstallerStep9Controller', function () {
});
});
- // isServicesInstalled is called after every poll for "Install All Services" request.
- // This function should result into a call to "Start All Services" request only if install request completed successfully.
+ // isServicesInstalled is called after every poll for "Install All Services" request.
+ // This function should result into a call to "Start All Services" request only if install request completed successfully.
describe('#isServicesInstalled', function () {
- var hostStateJsonData = {
- "items" : [
+ var hostStateJsonData = {
+ "items": [
{
- "Hosts" : {
- "cluster_name" : "c1",
- "host_name" : "ambari-1.c.apache.internal",
- "host_state" : "HEALTHY"
+ "Hosts": {
+ "cluster_name": "c1",
+ "host_name": "ambari-1.c.apache.internal",
+ "host_state": "HEALTHY"
},
- "host_components" : [
+ "host_components": [
{
- "HostRoles" : {
- "cluster_name" : "c1",
- "component_name" : "GANGLIA_MONITOR",
- "host_name" : "ambari-1.c.apache.internal",
- "state" : "STARTED"
+ "HostRoles": {
+ "cluster_name": "c1",
+ "component_name": "GANGLIA_MONITOR",
+ "host_name": "ambari-1.c.apache.internal",
+ "state": "STARTED"
}
}
]
@@ -1116,38 +1143,40 @@ describe('App.InstallerStep9Controller', function () {
]
};
var hosts = Em.A([Em.Object.create({name: 'host1', progress: '33', status: 'info'}),
- Em.Object.create({name: 'host2', progress: '33', status: 'info'})]);
+ Em.Object.create({name: 'host2', progress: '33', status: 'info'})]);
// polledData has all hosts with status completed to trigger transition from install->start request.
- var polledData = Em.A([Em.Object.create({Tasks: {name: 'host1', status: 'COMPLETED'}}),
- Em.Object.create({Tasks: {name: 'host2', status: 'COMPLETED'}})]);
+ var polledData = Em.A([Em.Object.create({Tasks: {name: 'host1', status: 'COMPLETED'}}),
+ Em.Object.create({Tasks: {name: 'host2', status: 'COMPLETED'}})]);
var controller = App.WizardStep9Controller.create({hosts: hosts, content: {controllerName: 'installerController',
- cluster: {status: 'PENDING',name: 'c1'}},launchStartServices: function() {return true;}});
+ cluster: {status: 'PENDING', name: 'c1'}}, launchStartServices: function () {
+ return true;
+ }});
var tests = Em.A([
// controller has "status" value as "info" initially. If no errors are encountered then wizard stages
// transition info->success, on error info->error, on warning info->warning
- {status: 'info' , e:{startServicesCalled:true}, m:'If no failed tasks then start services request should be called'},
- {status: 'failed', e:{startServicesCalled:false}, m: 'If install request has failed tasks then start services call should not be called'}
+ {status: 'info', e: {startServicesCalled: true}, m: 'If no failed tasks then start services request should be called'},
+ {status: 'failed', e: {startServicesCalled: false}, m: 'If install request has failed tasks then start services call should not be called'}
]);
- beforeEach(function() {
+ beforeEach(function () {
App.testMode = true;
sinon.spy(controller, 'launchStartServices');
sinon.stub($, 'ajax').yieldsTo('success', hostStateJsonData);
});
- afterEach(function() {
+ afterEach(function () {
App.testMode = false;
controller.launchStartServices.restore();
$.ajax.restore();
});
- tests.forEach(function(test){
- it(test.m, function() {
- controller.set('status',test.status);
+ tests.forEach(function (test) {
+ it(test.m, function () {
+ controller.set('status', test.status);
//Action
controller.isServicesInstalled(polledData);
//Validation
- expect(controller.launchStartServices.called).to.equal(test.e.startServicesCalled);
+ expect(controller.launchStartServices.called).to.equal(test.e.startServicesCalled);
});
});
});
@@ -1161,15 +1190,16 @@ describe('App.InstallerStep9Controller', function () {
App.testMode = true;
// override the actual function
App.popup = {
- setErrorPopup: function() {
+ setErrorPopup: function () {
return true;
}
};
- var hosts = Em.A([Em.Object.create({name: 'host1', progress: '33', status: 'info'}),Em.Object.create({name: 'host2', progress: '33', status: 'info'})]);
- var controller = App.WizardStep9Controller.create({hosts: hosts, content: {controllerName: 'installerController', cluster: {status: 'PENDING',name: 'c1'}},togglePreviousSteps: function(){}});
+ var hosts = Em.A([Em.Object.create({name: 'host1', progress: '33', status: 'info'}), Em.Object.create({name: 'host2', progress: '33', status: 'info'})]);
+ var controller = App.WizardStep9Controller.create({hosts: hosts, content: {controllerName: 'installerController', cluster: {status: 'PENDING', name: 'c1'}}, togglePreviousSteps: function () {
+ }});
//Action
- controller.launchStartServicesErrorCallback({status:500, statusTesxt: 'Server Error'}, {}, '', {});
+ controller.launchStartServicesErrorCallback({status: 500, statusTesxt: 'Server Error'}, {}, '', {});
it('Cluster Status should be INSTALL FAILED', function () {
expect(controller.get('content.cluster.status')).to.equal('INSTALL FAILED');
});
@@ -1180,7 +1210,7 @@ describe('App.InstallerStep9Controller', function () {
});
it('All Host progress bars on the screen should be finished (100%) with blue color', function () {
- controller.get('hosts').forEach(function(host){
+ controller.get('hosts').forEach(function (host) {
expect(host.get('progress')).to.equal('100');
expect(host.get('status')).to.equal('info');
});
@@ -1196,4 +1226,748 @@ describe('App.InstallerStep9Controller', function () {
});
-});
+ describe('#submit', function () {
+ it('should call App.router.send', function () {
+ sinon.stub(App.router, 'send', Em.K);
+ c.submit();
+ expect(App.router.send.calledWith('next')).to.equal(true);
+ App.router.send.restore();
+ });
+ });
+
+ describe('#back', function () {
+ beforeEach(function () {
+ sinon.stub(App.router, 'send', Em.K);
+ });
+ afterEach(function () {
+ App.router.send.restore();
+ });
+ it('should call App.router.send', function () {
+ c.reopen({isSubmitDisabled: false});
+ c.back();
+ expect(App.router.send.calledWith('back')).to.equal(true);
+ });
+ it('shouldn\'t call App.router.send', function () {
+ c.reopen({isSubmitDisabled: true});
+ c.back();
+ expect(App.router.send.called).to.equal(false);
+ });
+ });
+
+ describe('#loadStep', function () {
+ beforeEach(function () {
+ sinon.stub(c, 'clearStep', Em.K);
+ sinon.stub(c, 'loadHosts', Em.K);
+ });
+ afterEach(function () {
+ c.clearStep.restore();
+ c.loadHosts.restore();
+ });
+ it('should call clearStep', function () {
+ c.loadStep();
+ expect(c.clearStep.calledOnce).to.equal(true);
+ });
+ it('should call loadHosts', function () {
+ c.loadStep();
+ expect(c.loadHosts.calledOnce).to.equal(true);
+ });
+ });
+
+ describe('#startPolling', function () {
+ beforeEach(function () {
+ sinon.stub(c, 'getLogsByRequestErrorCallback', Em.K);
+ });
+ afterEach(function () {
+ c.getLogsByRequestErrorCallback.restore();
+ });
+ it('should set isSubmitDisabled to true', function () {
+ c.set('isSubmitDisabled', false);
+ c.startPolling();
+ expect(c.get('isSubmitDisabled')).to.equal(true);
+ });
+ it('should call doPolling', function () {
+ sinon.stub(c, 'doPolling', Em.K);
+ c.startPolling();
+ expect(c.doPolling.calledOnce).to.equal(true);
+ c.doPolling.restore();
+ });
+ });
+
+ describe('#loadLogData', function () {
+ beforeEach(function () {
+ sinon.stub(c, 'getLogsByRequest', Em.K);
+ c.set('wizardController', Em.Object.create({
+ cluster: {oldRequestsId: []},
+ getDBProperty: function (name) {
+ return this.get(name);
+ }
+ }));
+ });
+ afterEach(function () {
+ c.getLogsByRequest.restore();
+ });
+ it('shouldn\'t call getLogsByRequest if no requestIds', function () {
+ c.set('wizardController.cluster.oldRequestsId', []);
+ c.loadLogData();
+ expect(c.getLogsByRequest.called).to.equal(false);
+ });
+ it('should call getLogsByRequest 3 times', function () {
+ c.set('wizardController.cluster.oldRequestsId', [1, 2, 3]);
+ c.loadLogData();
+ expect(c.getLogsByRequest.calledThrice).to.equal(true);
+ });
+ it('should set POLL_INTERVAL to 1 if testMode enabled', function () {
+ App.set('testMode', true);
+ c.set('wizardController.cluster.oldRequestsId', [1, 2, 3]);
+ c.loadLogData();
+ expect(c.get('POLL_INTERVAL')).to.equal(1);
+ App.set('testMode', false);
+ });
+ });
+
+ describe('#loadCurrentTaskLog', function () {
+ beforeEach(function () {
+ sinon.spy(App.ajax, 'send');
+ });
+ afterEach(function () {
+ App.ajax.send.restore();
+ });
+ it('shouldn\'t call App.ajax.send if no currentOpenTaskId', function () {
+ c.set('currentOpenTaskId', null);
+ c.loadCurrentTaskLog();
+ expect(App.ajax.send.called).to.equal(false);
+ });
+ it('should call App.ajax.send with provided data', function () {
+ sinon.stub(c, 'togglePreviousSteps', Em.K);
+ c.set('currentOpenTaskId', 1);
+ c.set('currentOpenTaskRequestId', 2);
+ c.set('content', {cluster: {name: 3}});
+ c.loadCurrentTaskLog();
+ expect(App.ajax.send.args[0][0].data).to.eql({taskId: 1, requestId: 2, clusterName: 3, sync: true});
+ c.togglePreviousSteps.restore();
+ });
+ });
+
+ describe('#loadCurrentTaskLogSuccessCallback', function () {
+ it('should increment logTasksChangesCounter', function () {
+ c.set('logTasksChangesCounter', 0);
+ c.loadCurrentTaskLogSuccessCallback();
+ expect(c.get('logTasksChangesCounter')).to.equal(1);
+ });
+ it('should update stdout, stderr', function () {
+ c.set('currentOpenTaskId', 1);
+ c.reopen({
+ hosts: [
+ Em.Object.create({
+ name: 'h1',
+ logTasks: [
+ {Tasks: {id: 1, stdout: '', stderr: ''}}
+ ]
+ })
+ ]
+ });
+ var data = {Tasks: {host_name: 'h1', id: 1, stderr: 'stderr', stdout: 'stdout'}};
+ c.loadCurrentTaskLogSuccessCallback(data);
+ var t = c.get('hosts')[0].logTasks[0].Tasks;
+ expect(t.stdout).to.equal('stdout');
+ expect(t.stderr).to.equal('stderr');
+ });
+ it('shouldn\'t update stdout, stderr', function () {
+ c.set('currentOpenTaskId', 1);
+ c.reopen({
+ hosts: [
+ Em.Object.create({
+ name: 'h1',
+ logTasks: [
+ {Tasks: {id: 2, stdout: '', stderr: ''}}
+ ]
+ })
+ ]
+ });
+ var data = {Tasks: {host_name: 'h1', id: 1, stderr: 'stderr', stdout: 'stdout'}};
+ c.loadCurrentTaskLogSuccessCallback(data);
+ var t = c.get('hosts')[0].logTasks[0].Tasks;
+ expect(t.stdout).to.equal('');
+ expect(t.stderr).to.equal('');
+ });
+ it('shouldn\'t update stdout, stderr (2)', function () {
+ c.set('currentOpenTaskId', 1);
+ c.reopen({
+ hosts: [
+ Em.Object.create({
+ name: 'h2',
+ logTasks: [
+ {Tasks: {id: 1, stdout: '', stderr: ''}}
+ ]
+ })
+ ]
+ });
+ var data = {Tasks: {host_name: 'h1', id: 1, stderr: 'stderr', stdout: 'stdout'}};
+ c.loadCurrentTaskLogSuccessCallback(data);
+ var t = c.get('hosts')[0].logTasks[0].Tasks;
+ expect(t.stdout).to.equal('');
+ expect(t.stderr).to.equal('');
+ });
+ });
+
+ describe('#loadCurrentTaskLogErrorCallback', function () {
+ it('should set currentOpenTaskId to 0', function () {
+ c.set('currentOpenTaskId', 123);
+ c.loadCurrentTaskLogErrorCallback();
+ expect(c.get('currentOpenTaskId')).to.equal(0);
+ });
+ });
+
+ describe('#getLogsByRequest', function () {
+ beforeEach(function () {
+ sinon.spy(App.ajax, 'send');
+ sinon.stub(c, 'togglePreviousSteps', Em.K);
+ });
+ afterEach(function () {
+ App.ajax.send.restore();
+ c.togglePreviousSteps.restore();
+ });
+ it('should call App.ajax.send with provided data', function () {
+ var polling = 1;
+ var requestId = 2;
+ c.set('content', {cluster: {name: 3}});
+ c.set('numPolls', 4);
+ c.getLogsByRequest(polling, requestId);
+ expect(App.ajax.send.args[0][0].data).to.eql({polling: polling, requestId: requestId, cluster: 3, numPolls: 4});
+ });
+ });
+
+ describe('#doPolling', function () {
+ beforeEach(function () {
+ sinon.stub(c, 'getLogsByRequest', Em.K);
+ sinon.stub(c, 'togglePreviousSteps', Em.K);
+ });
+ afterEach(function () {
+ c.getLogsByRequest.restore();
+ c.togglePreviousSteps.restore();
+ });
+ it('should increment numPolls if testMode', function () {
+ App.set('testMode', true);
+ c.set('numPolls', 0);
+ c.doPolling();
+ expect(c.get('numPolls')).to.equal(1);
+ App.set('testMode', false);
+ });
+ it('should call getLogsByRequest', function () {
+ c.set('content', {cluster: {requestId: 1}});
+ c.doPolling();
+ expect(c.getLogsByRequest.calledWith(true, 1)).to.equal(true);
+ });
+ });
+
+ describe('#isAllComponentsInstalled', function () {
+ beforeEach(function () {
+ sinon.spy(App.ajax, 'send');
+ sinon.stub(c, 'togglePreviousSteps', Em.K);
+ sinon.stub(c, 'saveClusterStatus', Em.K);
+ });
+ afterEach(function () {
+ App.ajax.send.restore();
+ c.togglePreviousSteps.restore();
+ c.saveClusterStatus.restore();
+ });
+ it('shouldn\'t call App.ajax.send', function () {
+ c.set('content', {controllerName: 'addServiceController'});
+ c.isAllComponentsInstalled();
+ expect(App.ajax.send.called).to.equal(false);
+ });
+ it('shouldn\'t call App.ajax.send (2)', function () {
+ c.set('content', {controllerName: 'addHostController'});
+ c.isAllComponentsInstalled();
+ expect(App.ajax.send.called).to.equal(false);
+ });
+ it('should call App.ajax.send', function () {
+ c.set('content', {cluster: {name: 'n'}, controllerName: 'installerController'});
+ c.isAllComponentsInstalled();
+ expect(App.ajax.send.args[0][0].data).to.eql({cluster: 'n'});
+ });
+ });
+
+ describe('#isAllComponentsInstalledErrorCallback', function () {
+ beforeEach(function () {
+ sinon.stub(c, 'saveClusterStatus', Em.K);
+ sinon.stub(c, 'togglePreviousSteps', Em.K);
+ });
+ afterEach(function () {
+ c.saveClusterStatus.restore();
+ c.togglePreviousSteps.restore();
+ });
+ it('should call saveClusterStatus', function () {
+ c.isAllComponentsInstalledErrorCallback({});
+ expect(c.saveClusterStatus.calledOnce).to.equal(true);
+ });
+ });
+
+ describe('#saveClusterStatus', function () {
+ beforeEach(function () {
+ sinon.stub(c, 'togglePreviousSteps', Em.K);
+ });
+ afterEach(function () {
+ c.togglePreviousSteps.restore();
+ });
+ it('in testMode should set content.cluster', function () {
+ var d = {n: 'n'};
+ c.set('content', {cluster: ''});
+ App.set('testMode', true);
+ c.saveClusterStatus(d);
+ expect(c.get('content.cluster')).to.eql(d);
+ App.set('testMode', false);
+ });
+ it('if testMode is false should use content.controller', function () {
+ var d = {n: 'n'},
+ obj = Em.Object.create({
+ saveClusterStatus: Em.K
+ });
+ sinon.stub(App.router, 'get', function () {
+ return obj;
+ });
+ sinon.spy(obj, 'saveClusterStatus');
+ c.set('content', {cluster: ''});
+ App.set('testMode', false);
+ c.saveClusterStatus(d);
+ expect(obj.saveClusterStatus.calledWith(d)).to.eql(true);
+ App.set('testMode', true);
+ obj.saveClusterStatus.restore();
+ App.router.get.restore();
+ });
+ });
+
+ describe('#saveInstalledHosts', function () {
+ beforeEach(function () {
+ sinon.stub(c, 'togglePreviousSteps', Em.K);
+ });
+ afterEach(function () {
+ c.togglePreviousSteps.restore();
+ });
+ it('if testMode is false should use content.controller', function () {
+ var d = {n: 'n'},
+ obj = Em.Object.create({
+ saveInstalledHosts: Em.K
+ });
+ sinon.stub(App.router, 'get', function () {
+ return obj;
+ });
+ sinon.spy(obj, 'saveInstalledHosts');
+ c.set('content', {cluster: ''});
+ App.set('testMode', false);
+ c.saveInstalledHosts(d);
+ expect(obj.saveInstalledHosts.calledWith(d)).to.eql(true);
+ App.set('testMode', true);
+ obj.saveInstalledHosts.restore();
+ App.router.get.restore();
+ });
+ });
+
+ describe('#getComponentMessage', function () {
+ var tests = Em.A([
+ {
+ clients: ['c1'],
+ m: 'One client',
+ e: 'c1'
+ },
+ {
+ clients: ['c1', 'c2'],
+ m: 'Two clients',
+ e: 'c1 and c2'
+ },
+ {
+ clients: ['c1', 'c2', 'c3'],
+ m: 'Three clients',
+ e: 'c1, c2 and c3'
+ },
+ {
+ clients: ['c1', 'c2', 'c3', 'c4'],
+ m: 'Four clients',
+ e: 'c1, c2, c3 and c4'
+ },
+ {
+ clients: ['c1', 'c2', 'c3', 'c4', 'c5'],
+ m: 'Five clients',
+ e: 'c1, c2, c3, c4 and c5'
+ }
+ ]);
+ tests.forEach(function (test) {
+ it(test.m, function () {
+ var label = c.getComponentMessage(test.clients);
+ expect(label).to.equal(test.e);
+ });
+ });
+ });
+
+ describe('#togglePreviousSteps', function () {
+ beforeEach(function () {
+ sinon.stub(obj, 'setStepsEnable', Em.K);
+ sinon.stub(obj, 'setLowerStepsDisable', Em.K);
+ sinon.stub(App.router, 'get', function () {
+ return obj;
+ });
+ });
+ afterEach(function () {
+ App.router.get.restore();
+ obj.setStepsEnable.restore();
+ obj.setLowerStepsDisable.restore();
+ });
+ it('shouldn\'t do nothing on testMode', function () {
+ App.set('testMode', true);
+ c.togglePreviousSteps();
+ expect(App.router.get.called).to.equal(false);
+ App.set('testMode', false);
+ });
+ Em.A([
+ {
+ status: 'INSTALL FAILED',
+ controllerName: 'installerController',
+ e: {
+ setStepsEnable: true,
+ setLowerStepsDisable: false
+ }
+ },
+ {
+ status: 'STARTED',
+ controllerName: 'installerController',
+ e: {
+ setStepsEnable: false,
+ setLowerStepsDisable: true
+ }
+ },
+ {
+ status: 'INSTALL FAILED',
+ controllerName: 'addServiceController',
+ e: {
+ setStepsEnable: false,
+ setLowerStepsDisable: true
+ }
+ },
+ {
+ status: 'STARTED',
+ controllerName: 'addServiceController',
+ e: {
+ setStepsEnable: false,
+ setLowerStepsDisable: true
+ }
+ }
+ ]).forEach(function (test) {
+ it(test.status + ' ' + test.controllerName, function () {
+ App.set('testMode', false);
+ c.reopen({content: {cluster: {status: test.status}, controllerName: test.controllerName}});
+ c.togglePreviousSteps();
+ expect(App.router.get.calledWith('installerController')).to.equal(true);
+ if (test.e.setStepsEnable) {
+ expect(obj.setStepsEnable.calledOnce).to.equal(true);
+ }
+ else {
+ expect(obj.setStepsEnable.called).to.equal(false);
+ }
+ if (test.e.setLowerStepsDisable) {
+ expect(obj.setLowerStepsDisable.calledWith(9)).to.equal(true);
+ }
+ else {
+ expect(obj.setLowerStepsDisable.called).to.equal(false);
+ }
+ });
+ });
+ });
+
+ describe('#navigateStep', function () {
+ beforeEach(function () {
+ sinon.stub(c, 'togglePreviousSteps', Em.K);
+ sinon.stub(c, 'loadStep', Em.K);
+ sinon.stub(c, 'loadLogData', Em.K);
+ sinon.stub(c, 'startPolling', Em.K);
+ });
+ afterEach(function () {
+ c.togglePreviousSteps.restore();
+ c.loadStep.restore();
+ c.loadLogData.restore();
+ c.startPolling.restore();
+ });
+ it('should set custom data in testMode', function () {
+ App.set('testMode', true);
+ c.reopen({content: {cluster: {status: 'st', isCompleted: true, requestId: 0}}});
+ c.navigateStep();
+ expect(c.get('content.cluster.status')).to.equal('PENDING');
+ expect(c.get('content.cluster.isCompleted')).to.equal(false);
+ expect(c.get('content.cluster.requestId')).to.equal(1);
+ App.set('testMode', false);
+ });
+ it('isCompleted = true, requestId = 1', function () {
+ App.set('testMode', false);
+ c.reopen({content: {cluster: {isCompleted: true, requestId: 1}}});
+ c.navigateStep();
+ expect(c.loadStep.calledOnce).to.equal(true);
+ expect(c.loadLogData.calledWith(1)).to.equal(true);
+ expect(c.get('progress')).to.equal('100');
+ });
+ it('isCompleted = false, requestId = 1, status = INSTALL FAILED', function () {
+ App.set('testMode', false);
+ c.reopen({content: {cluster: {status: 'INSTALL FAILED', isCompleted: false, requestId: 1}}});
+ c.navigateStep();
+ expect(c.loadStep.calledOnce).to.equal(true);
+ expect(c.loadLogData.calledWith(1)).to.equal(true);
+ });
+ it('isCompleted = false, requestId = 1, status = START FAILED', function () {
+ App.set('testMode', false);
+ c.reopen({content: {cluster: {status: 'START FAILED', isCompleted: false, requestId: 1}}});
+ c.navigateStep();
+ expect(c.loadStep.calledOnce).to.equal(true);
+ expect(c.loadLogData.calledWith(1)).to.equal(true);
+ });
+ it('isCompleted = false, requestId = 1, status = OTHER', function () {
+ App.set('testMode', false);
+ c.reopen({content: {cluster: {status: 'STARTED', isCompleted: false, requestId: 1}}});
+ c.navigateStep();
+ expect(c.loadStep.calledOnce).to.equal(true);
+ expect(c.loadLogData.calledWith(1)).to.equal(true);
+ expect(c.startPolling.calledOnce).to.equal(true);
+ });
+ });
+
+ describe('#launchStartServices', function () {
+ beforeEach(function () {
+ sinon.spy(App.ajax, 'send');
+ sinon.stub(c, 'togglePreviousSteps', Em.K);
+ sinon.stub(c, 'saveClusterStatus', Em.K);
+ c.reopen({content: {}});
+ });
+ afterEach(function () {
+ App.ajax.send.restore();
+ c.togglePreviousSteps.restore();
+ c.saveClusterStatus.restore();
+ });
+ it('should set numPolls to 6 in testMode', function () {
+ App.set('testMode', true);
+ c.set('numPolls', 0);
+ c.launchStartServices();
+ expect(c.get('numPolls')).to.equal(6);
+ App.set('testMode', false);
+ });
+ Em.A([
+ {
+ controllerName: 'installerController',
+ clusterName: 'c1',
+ e: {
+ name: 'wizard.step9.installer.launch_start_services'
+ }
+ },
+ {
+ controllerName: 'addHostController',
+ clusterName: 'c1',
+ wizardController: Em.Object.create({
+ getDBProperty: function () {
+ return {h1: '', h2: ''};
+ }
+ }),
+ e: {
+ name: 'wizard.step9.add_host.launch_start_services',
+ data: 'host_name.in(h1,h2)'
+ }
+ }
+ ]).forEach(function (test) {
+ it(test.controllerName, function () {
+ c.reopen({content: {controllerName: test.controllerName, cluster: {name: test.clusterName}}});
+ if (test.wizardController) {
+ c.reopen({wizardController: test.wizardController});
+ }
+ c.launchStartServices();
+ var r = App.ajax.send.args[0][0];
+ expect(r.data.cluster).to.equal(test.clusterName);
+ expect(r.name).to.equal(test.e.name);
+ if (test.e.data) {
+ expect(r.data.data.contains(test.e.data)).to.equal(true);
+ }
+ });
+ });
+ });
+
+ describe('#isServicesStarted', function () {
+ beforeEach(function () {
+ sinon.stub(c, 'saveClusterStatus', Em.K);
+ sinon.stub(c, 'saveInstalledHosts', Em.K);
+ });
+ afterEach(function () {
+ c.saveClusterStatus.restore();
+ c.saveInstalledHosts.restore();
+ });
+ Em.A([
+ {
+ polledData: [
+ {Tasks: {status: 'PENDING'}}
+ ],
+ m: 'PENDING',
+ e: false
+ },
+ {
+ polledData: [
+ {Tasks: {status: 'QUEUED'}}
+ ],
+ m: 'QUEUED',
+ e: false
+ },
+ {
+ polledData: [
+ {Tasks: {status: 'IN_PROGRESS'}}
+ ],
+ m: 'IN_PROGRESS',
+ e: false
+ }
+ ]).forEach(function (test) {
+ it(test.m, function () {
+ var r = c.isServicesStarted(test.polledData);
+ expect(r).to.equal(test.e);
+ });
+ });
+ Em.A([
+ {
+ polledData: [
+ {Tasks: {status: 'SUCCESS'}}
+ ],
+ m: 'tasks ok, isSuccess true',
+ isSuccess: true,
+ e: {
+ status: 'STARTED',
+ hasInstallTime: true
+ }
+ },
+ {
+ polledData: [
+ {Tasks: {status: 'SUCCESS'}}
+ ],
+ m: 'tasks ok, isSuccess false',
+ isSuccess: false,
+ e: {
+ status: 'START FAILED',
+ hasInstallTime: false
+ }
+ }
+ ]).forEach(function (test) {
+ it(test.m, function () {
+ sinon.stub(c, 'isSuccess', function () {
+ return test.isSuccess;
+ });
+ c.reopen({content: {cluster: {requestId: 2}}});
+ var r = c.isServicesStarted(test.polledData);
+ var args = c.saveClusterStatus.args[0][0];
+ expect(r).to.equal(true);
+ expect(c.get('progress')).to.equal('100');
+ expect(args.status).to.equal(test.e.status);
+ expect(args.requestId).to.equal(2);
+ expect(args.hasOwnProperty('installTime')).to.equal(test.e.hasInstallTime);
+ expect(args.isCompleted).to.equal(true);
+ expect(c.saveInstalledHosts.calledOnce).to.equal(true);
+ c.isSuccess.restore();
+ });
+ });
+ });
+
+ describe('#launchStartServicesSuccessCallback', function () {
+ beforeEach(function () {
+ sinon.stub(c, 'saveClusterStatus', Em.K);
+ sinon.stub(c, 'doPolling', Em.K);
+ sinon.stub(c, 'hostHasClientsOnly', Em.K);
+ });
+ afterEach(function () {
+ c.saveClusterStatus.restore();
+ c.doPolling.restore();
+ c.hostHasClientsOnly.restore();
+ });
+ it('should call doPolling if some data were received', function () {
+ c.launchStartServicesSuccessCallback({Requests: {id: 2}});
+ expect(c.doPolling.calledOnce).to.equal(true);
+ });
+ Em.A([
+ {
+ jsonData: {Requests: {id: 2}},
+ e: {
+ hostHasClientsOnly: false,
+ clusterStatus: {
+ status: 'INSTALLED',
+ requestId: 2,
+ isStartError: false,
+ isCompleted: false
+ }
+ }
+ },
+ {
+ jsonData: null,
+ e: {
+ hostHasClientsOnly: true,
+ clusterStatus: {
+ status: 'STARTED',
+ isStartError: false,
+ isCompleted: true
+ },
+ status: 'success',
+ progress: '100'
+ }
+ }
+ ]).forEach(function (test) {
+ it(test.m, function () {
+ c.launchStartServicesSuccessCallback(test.jsonData);
+ expect(c.hostHasClientsOnly.calledWith(test.e.hostHasClientsOnly)).to.equal(true);
+ expect(c.saveClusterStatus.calledWith(test.e.clusterStatus)).to.equal(true);
+ if (test.e.status) {
+ expect(c.get('status')).to.equal(test.e.status);
+ }
+ if (test.e.progress) {
+ expect(c.get('progress')).to.equal(test.e.progress);
+ }
+ });
+ });
+ });
+
+ describe('#getLogsByRequestSuccessCallback', function () {
+ beforeEach(function () {
+ sinon.stub(c, 'isAllComponentsInstalled', Em.K);
+ sinon.stub(window, 'setTimeout', Em.K);
+ });
+ afterEach(function () {
+ c.isAllComponentsInstalled.restore();
+ window.setTimeout.restore();
+ });
+ Em.A([
+ {
+ polling: false,
+ status: 'INSTALL FAILED',
+ m: 'should call isAllComponentsInstalled',
+ e: true
+ },
+ {
+ polling: false,
+ status: 'INSTALLED',
+ m: 'shouldn\'t call isAllComponentsInstalled',
+ e: false
+ },
+ {
+ polling: true,
+ status: 'INSTALL FAILED',
+ m: 'shouldn\'t call isAllComponentsInstalled (2)',
+ e: false
+ },
+ {
+ polling: true,
+ status: 'INSTALLED',
+ m: 'shouldn\'t call isAllComponentsInstalled (3)',
+ e: false
+ }
+ ]).forEach(function (test) {
+ it(test.m, function () {
+ sinon.stub(c, 'parseHostInfo', Em.K);
+ c.reopen({content: {cluster: {status: test.status}}});
+ c.getLogsByRequestSuccessCallback({}, {}, {polling: test.polling});
+ if (test.e) {
+ expect(c.isAllComponentsInstalled.calledOnce).to.equal(true);
+ }
+ else {
+ expect(c.isAllComponentsInstalled.called).to.equal(false);
+ }
+ c.parseHostInfo.restore();
+ });
+ });
+ });
+
+});
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/b96edcf9/ambari-web/test/views/wizard/step9/hostLogPopupBody_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/wizard/step9/hostLogPopupBody_view_test.js b/ambari-web/test/views/wizard/step9/hostLogPopupBody_view_test.js
new file mode 100644
index 0000000..918d3d9
--- /dev/null
+++ b/ambari-web/test/views/wizard/step9/hostLogPopupBody_view_test.js
@@ -0,0 +1,145 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+var App = require('app');
+require('views/wizard/step9/hostLogPopupBody_view');
+var view;
+
+describe('App.WizardStep9HostLogPopupBodyView', function() {
+
+ beforeEach(function() {
+ view = App.WizardStep9HostLogPopupBodyView.create({
+ parentView: Em.Object.create({
+ host: Em.Object.create()
+ })
+ });
+ });
+
+ describe('#isHeartbeatLost', function() {
+ it('should depends on parentView.host.status', function() {
+ view.set('parentView.host.status', 'success');
+ expect(view.get('isHeartbeatLost')).to.equal(false);
+ view.set('parentView.host.status', 'heartbeat_lost');
+ expect(view.get('isHeartbeatLost')).to.equal(true);
+ });
+ });
+
+ describe('#isNoTasksScheduled', function() {
+ it('should be same to parentView.host.isNoTasksForInstall', function() {
+ view.set('parentView.host.isNoTasksForInstall', true);
+ expect(view.get('isNoTasksScheduled')).to.equal(true);
+ view.set('parentView.host.isNoTasksForInstall', false);
+ expect(view.get('isNoTasksScheduled')).to.equal(false);
+ });
+ });
+
+ describe('#visibleTasks', function() {
+ Em.A([
+ {
+ value: 'pending',
+ f: ['pending', 'queued']
+ },
+ {
+ value: 'in_progress',
+ f: ['in_progress']
+ },
+ {
+ value: 'failed',
+ f: ['failed']
+ },
+ {
+ value: 'completed',
+ f: ['completed']
+ },
+ {
+ value: 'aborted',
+ f: ['aborted']
+ },
+ {
+ value: 'timedout',
+ f: ['timedout']
+ },
+ {
+ value: 'all'
+ }
+ ]).forEach(function(test) {
+ it(test.value, function() {
+ view.reopen({
+ category: Em.Object.create({value: test.value}),
+ tasks: Em.A([
+ {status: 'pending', isVisible: false},
+ {status: 'queued', isVisible: false},
+ {status: 'in_progress', isVisible: false},
+ {status: 'failed', isVisible: false},
+ {status: 'completed', isVisible: false},
+ {status: 'aborted', isVisible: false},
+ {status: 'timedout', isVisible: false}
+ ])
+ });
+ view.visibleTasks();
+ var visibleTasks = view.get('tasks').filter(function(task) {
+ if (test.f) {
+ return test.f.contains(task.status);
+ }
+ return true;
+ });
+ expect(visibleTasks.everyProperty('isVisible', true)).to.equal(true);
+ });
+ });
+ });
+
+ describe('#backToTaskList', function() {
+ it('should call destroyClipBoard', function() {
+ sinon.stub(view, 'destroyClipBoard', Em.K);
+ view.backToTaskList();
+ expect(view.destroyClipBoard.calledOnce).to.equal(true);
+ view.destroyClipBoard.restore();
+ });
+ it('should set isLogWrapHidden to true', function() {
+ view.set('isLogWrapHidden', false);
+ view.backToTaskList();
+ expect(view.get('isLogWrapHidden')).to.equal(true);
+ });
+ });
+
+ describe('#getStartedTasks', function() {
+ it('should return tasks with some status', function() {
+ var logTasks = Em.A([
+ {Tasks: {}}, {Tasks: {status: 's'}}, {Tasks: {status: null}}, {Tasks: {status: 'v'}}
+ ]);
+ expect(view.getStartedTasks({logTasks: logTasks}).length).to.equal(2);
+ });
+ });
+
+ describe('#openedTask', function() {
+ it('should return currently open task', function() {
+ var task = Em.Object.create({id: 2});
+ view.reopen({
+ tasks: Em.A([
+ Em.Object.create({id: 1}),
+ Em.Object.create({id: 3}),
+ task,
+ Em.Object.create({id: 4})
+ ])
+ });
+ view.set('parentView.c', {currentOpenTaskId: 2});
+ expect(view.get('openedTask.id')).to.equal(2);
+ });
+ });
+
+});
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/b96edcf9/ambari-web/test/views/wizard/step9_view_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/views/wizard/step9_view_test.js b/ambari-web/test/views/wizard/step9_view_test.js
index 9b98019..733c3f9 100644
--- a/ambari-web/test/views/wizard/step9_view_test.js
+++ b/ambari-web/test/views/wizard/step9_view_test.js
@@ -19,10 +19,16 @@
var App = require('app');
require('views/wizard/step9_view');
-
+var v;
describe('App.WizardStep9View', function () {
+ beforeEach(function () {
+ v = App.WizardStep9View.create({
+ controller: App.WizardStep9Controller.create()
+ });
+ });
var view = App.WizardStep9View.create({
- onStatus: function () {},
+ onStatus: function () {
+ },
content: [],
pageContent: function () {
return this.get('content');
@@ -186,7 +192,7 @@ describe('App.WizardStep9View', function () {
}
];
- describe('countCategoryHosts', function () {
+ describe('#countCategoryHosts', function () {
testCases.forEach(function (test) {
it(test.title, function () {
view.set('content', test.content);
@@ -198,7 +204,7 @@ describe('App.WizardStep9View', function () {
}, this);
});
- describe('filter', function () {
+ describe('#filter', function () {
testCases.forEach(function (test) {
describe(test.title, function () {
view.get('categories').forEach(function (category) {
@@ -212,9 +218,219 @@ describe('App.WizardStep9View', function () {
});
}, this);
});
+
+ describe('#isStepCompleted', function () {
+ it('should be true if progress is 100', function () {
+ v.set('controller.progress', '100');
+ expect(v.get('isStepCompleted')).to.equal(true);
+ });
+ it('should be false if progress isn\'t 100', function () {
+ v.set('controller.progress', '50');
+ expect(v.get('isStepCompleted')).to.equal(false);
+ });
+ });
+
+ describe('#content', function () {
+ it('should be equal to controller.hosts', function () {
+ sinon.stub(v, 'hostStatusObserver', Em.K);
+ var hosts = [
+ {},
+ {},
+ {}
+ ];
+ v.set('controller.hosts', hosts);
+ expect(v.get('content')).to.eql(hosts);
+ v.hostStatusObserver.restore();
+ });
+ });
+
+ describe('#categoryObject', function () {
+ it('label should contains value and hostsCount', function () {
+ var value = 'v',
+ hostsCount = 10,
+ o = v.get('categoryObject').create({value: value, hostsCount: hostsCount});
+ expect(o.get('label')).to.equal(value + ' (' + hostsCount + ')');
+ });
+ it('itemClass should depends on isActive', function () {
+ var o = v.get('categoryObject').create();
+ o.set('isActive', false);
+ expect(o.get('itemClass')).to.equal('');
+ o.set('isActive', true);
+ expect(o.get('itemClass')).to.equal('active');
+ });
+ });
+
+ describe('#isHostHeartbeatLost', function () {
+ Em.A([
+ {
+ hostsWithHeartbeatLost: [],
+ m: 'should be false if hostsWithHeartbeatLost is empty',
+ e: false
+ },
+ {
+ hostsWithHeartbeatLost: [
+ {},
+ {}
+ ],
+ m: 'should be true if hostsWithHeartbeatLost contains some values',
+ e: true
+ }
+ ]).forEach(function (test) {
+ it(test.m, function () {
+ v.set('controller.hostsWithHeartbeatLost', test.hostsWithHeartbeatLost);
+ expect(v.get('isHostHeartbeatLost')).to.equal(test.e);
+ })
+ });
+ });
+
+ describe('#barWidth', function () {
+ it('should depends on controller.progress', function () {
+ var w = '25';
+ v.set('controller.progress', w);
+ expect(v.get('barWidth')).to.equal('width: ' + w + '%;');
+ });
+ });
+
+ describe('#progressMessage', function () {
+ it('should depends on controller.progress', function () {
+ var w = '25';
+ v.set('controller.progress', w);
+ expect(v.get('progressMessage').contains(w)).to.equal(true);
+ });
+ });
+
+ describe('#showAllHosts', function () {
+ it('should set active to category with all hosts', function () {
+ v.get('categories').findProperty('hostStatus', 'inProgress').set('isActive', true);
+ v.showAllHosts();
+ var allCategory = v.get('categories').findProperty('hostStatus', 'all');
+ expect(allCategory.get('isActive')).to.equal(true);
+ expect(v.get('categories').without(allCategory).everyProperty('isActive', false)).to.equal(true);
+ });
+ });
+
+ describe('#didInsertElement', function () {
+ beforeEach(function () {
+ sinon.stub(v, 'onStatus', Em.K);
+ sinon.stub(v.get('controller'), 'navigateStep', Em.K);
+ });
+ afterEach(function () {
+ v.onStatus.restore();
+ v.get('controller').navigateStep.restore();
+ });
+ it('should call onStatus', function () {
+ v.didInsertElement();
+ expect(v.onStatus.calledOnce).to.equal(true);
+ });
+ it('should call navigateStep', function () {
+ v.didInsertElement();
+ expect(v.get('controller').navigateStep.calledOnce).to.equal(true);
+ });
+ });
+
+ describe('#selectCategory', function () {
+ it('should set isActive true to selected category', function () {
+ var event = {context: Em.Object.create({hostStatus: 'inProgress'})},
+ c = v.get('categories').findProperty('hostStatus', 'inProgress');
+ c.set('isActive', false);
+ v.selectCategory(event);
+ expect(c.get('isActive')).to.equal(true);
+ });
+ });
+
+ describe('#onStatus', function () {
+ Em.A([
+ {
+ status: 'success',
+ e: {
+ barColor: 'progress-success',
+ resultMsg: Em.I18n.t('installer.step9.status.success'),
+ resultMsgColor: 'alert-success'
+ }
+ },
+ {
+ status: 'info',
+ e: {
+ barColor: 'progress-info',
+ resultMsg: ''
+ }
+ },
+ {
+ status: 'warning',
+ e: {
+ barColor: 'progress-warning',
+ resultMsg: Em.I18n.t('installer.step9.status.warning'),
+ resultMsgColor: 'alert-warning'
+ }
+ },
+ {
+ status: 'failed',
+ e: {
+ barColor: 'progress-danger',
+ resultMsgColor: 'alert-error'
+ }
+ }
+ ]).forEach(function (test) {
+ it(test.status, function () {
+ v.set('controller.status', test.status);
+ v.onStatus();
+ Em.keys(test.e).forEach(function (k) {
+ expect(v.get(k)).to.equal(test.e[k]);
+ });
+ });
+ });
+ Em.A([
+ {
+ hostsWithHeartbeatLost: [
+ {},
+ {}
+ ],
+ startCallFailed: false,
+ m: 'heartbeat lost for 2 hosts',
+ resultMsg: Em.I18n.t('installer.step9.status.hosts.heartbeat_lost').format(2)
+ },
+ {
+ hostsWithHeartbeatLost: [],
+ startCallFailed: true,
+ m: 'heartbeat not lost, startCallFailed true',
+ resultMsg: Em.I18n.t('installer.step9.status.start.services.failed')
+ },
+ {
+ hostsWithHeartbeatLost: [],
+ startCallFailed: false,
+ m: 'heartbeat not lost, startCallFailed false',
+ resultMsg: Em.I18n.t('installer.step9.status.failed')
+ }
+ ]).forEach(function (test) {
+ it(test.m, function () {
+ v.set('controller.hostsWithHeartbeatLost', test.hostsWithHeartbeatLost);
+ v.set('controller.startCallFailed', test.startCallFailed);
+ v.set('controller.status', 'failed');
+ v.onStatus();
+ expect(v.get('resultMsg')).to.equal(test.resultMsg);
+ });
+ });
+ });
+
+ describe('#hostWithInstallFailed', function () {
+ it('popup property failedHosts should be equal to hostsWithHeartbeatLost', function () {
+ var hostsWithHeartbeatLost = [
+ {},
+ {}
+ ];
+ v.set('controller.hostsWithHeartbeatLost', hostsWithHeartbeatLost);
+ var body = v.hostWithInstallFailed().get('bodyClass').create();
+ expect(body.get('failedHosts')).to.eql(hostsWithHeartbeatLost);
+ });
+ });
+
});
+var hv;
describe('App.HostStatusView', function () {
+ beforeEach(function () {
+ hv = App.HostStatusView.create();
+ });
var tests = [
{
p: 'isFailed',
@@ -316,15 +532,170 @@ describe('App.HostStatusView', function () {
]
}
];
- tests.forEach(function(test) {
- describe(test.p, function() {
- test.tests.forEach(function(t) {
+ tests.forEach(function (test) {
+ describe(test.p, function () {
+ test.tests.forEach(function (t) {
var hostStatusView = App.HostStatusView.create();
- it('obj.progress = ' + t.obj.progress + '; obj.status = ' + t.obj.status, function() {
+ it('obj.progress = ' + t.obj.progress + '; obj.status = ' + t.obj.status, function () {
hostStatusView.set('obj', t.obj);
expect(hostStatusView.get(test.p)).to.equal(t.e);
});
});
});
});
+
+ describe('#barWidth', function () {
+ it('should depends of obj.progress', function () {
+ hv.set('obj', {progress: '25'});
+ expect(hv.get('barWidth')).to.equal('width: 25%;');
+ });
+ });
+
+ describe('#didInsertElement', function () {
+ it('should call onStatus', function () {
+ sinon.stub(hv, 'onStatus', Em.K);
+ hv.didInsertElement();
+ expect(hv.onStatus.calledOnce).to.equal(true);
+ hv.onStatus.restore();
+ });
+ });
+
+ describe('#onStatus', function () {
+ Em.A([
+ {
+ obj: {
+ status: 'info'
+ },
+ e: {
+ barColor: 'progress-info'
+ }
+ },
+ {
+ obj: {
+ status: 'warning'
+ },
+ e: {
+ barColor: 'progress-warning'
+ }
+ },
+ {
+ obj: {
+ status: 'warning',
+ progress: '100'
+ },
+ e: {
+ barColor: 'progress-warning',
+ 'obj.message': Em.I18n.t('installer.step9.host.status.warning')
+ }
+ },
+ {
+ obj: {
+ status: 'failed'
+ },
+ e: {
+ barColor: 'progress-danger'
+ }
+ },
+ {
+ obj: {
+ status: 'failed',
+ progress: '100'
+ },
+ e: {
+ barColor: 'progress-danger',
+ 'obj.message': Em.I18n.t('installer.step9.host.status.failed')
+ }
+ },
+ {
+ obj: {
+ status: 'heartbeat_lost'
+ },
+ e: {
+ barColor: 'progress-danger'
+ }
+ },
+ {
+ obj: {
+ status: 'heartbeat_lost',
+ progress: '100'
+ },
+ e: {
+ barColor: 'progress-danger',
+ 'obj.message': Em.I18n.t('installer.step9.host.heartbeat_lost')
+ }
+ }
+ ]).forEach(function (test) {
+ it(JSON.stringify(test.obj), function () {
+ hv.set('obj', test.obj);
+ hv.onStatus();
+ Em.keys(test.e).forEach(function (k) {
+ expect(hv.get(k)).to.equal(test.e[k]);
+ });
+ });
+ });
+ Em.A([
+ {
+ obj: {
+ status: 'success',
+ progress: '100'
+ },
+ progress: '35',
+ e: true
+ },
+ {
+ obj: {
+ status: 'success',
+ progress: '100'
+ },
+ progress: '34',
+ e: false
+ },
+ {
+ obj: {
+ status: 'success',
+ progress: '99'
+ },
+ progress: '35',
+ e: false
+ },
+ {
+ obj: {
+ status: 'failed',
+ progress: '100'
+ },
+ progress: '35',
+ e: false
+ }
+ ]).forEach(function (test) {
+ it(JSON.stringify(test.obj) + ' ' + test.progress, function() {
+ hv.set('barColor', '');
+ hv.set('obj', test.obj);
+ hv.set('obj.message', '');
+ hv.set('controller', {progress: test.progress});
+ hv.onStatus();
+ expect(hv.get('obj.message') === Em.I18n.t('installer.step9.host.status.success')).to.equal(test.e);
+ expect(hv.get('barColor') === 'progress-success').to.equal(test.e);
+ });
+ });
+ });
+
+ describe('#hostLogPopup', function() {
+ describe('#onClose', function() {
+ beforeEach(function() {
+ hv.set('controller', {currentOpenTaskId: 123});
+ hv.set('obj', Em.Object.create());
+ });
+ it('popup should clear currentOpenTaskId', function() {
+ hv.hostLogPopup().onClose();
+ expect(hv.get('controller.currentOpenTaskId')).to.equal(0);
+ });
+ it('onClose popup should hide popup', function() {
+ var p = hv.hostLogPopup();
+ sinon.spy(p, 'hide');
+ p.onClose();
+ expect(p.hide.calledOnce).to.equal(true);
+ });
+ });
+ });
+
});
[2/2] git commit: AMBARI-5575. Unit tests for steps 9 (with
refactor). (onechiporenko)
Posted by on...@apache.org.
AMBARI-5575. Unit tests for steps 9 (with refactor). (onechiporenko)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/b96edcf9
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/b96edcf9
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/b96edcf9
Branch: refs/heads/trunk
Commit: b96edcf90d7d2e609aa5e2e4eb9024c8c467c000
Parents: 739d35e
Author: Oleg Nechiporenko <on...@apache.org>
Authored: Fri Apr 25 19:28:30 2014 +0300
Committer: Oleg Nechiporenko <on...@apache.org>
Committed: Fri Apr 25 19:28:30 2014 +0300
----------------------------------------------------------------------
ambari-web/app/assets/test/tests.js | 1 +
.../app/controllers/wizard/step9_controller.js | 123 +--
ambari-web/app/templates/wizard/step9.hbs | 71 +-
.../wizard/step9/step9HostTasksLogPopup.hbs | 90 ++
.../wizard/step9/step9_install_host_popup.hbs | 40 +
.../templates/wizard/step9HostTasksLogPopup.hbs | 90 --
.../wizard/step9_install_host_popup.hbs | 40 -
ambari-web/app/views.js | 1 +
.../views/wizard/step9/hostLogPopupBody_view.js | 264 ++++++
ambari-web/app/views/wizard/step9_view.js | 389 ++++-----
ambari-web/test/installer/step9_test.js | 852 ++++++++++++++++++-
.../wizard/step9/hostLogPopupBody_view_test.js | 145 ++++
ambari-web/test/views/wizard/step9_view_test.js | 387 ++++++++-
13 files changed, 1997 insertions(+), 496 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/b96edcf9/ambari-web/app/assets/test/tests.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/assets/test/tests.js b/ambari-web/app/assets/test/tests.js
index 6175b3f..1ba5922 100644
--- a/ambari-web/app/assets/test/tests.js
+++ b/ambari-web/app/assets/test/tests.js
@@ -140,6 +140,7 @@ require('test/views/wizard/step3_view_test');
require('test/views/wizard/step5_view_test');
require('test/views/wizard/step6_view_test');
require('test/views/wizard/step9_view_test');
+require('test/views/wizard/step9/hostLogPopupBody_view_test');
require('test/views/wizard/step10_view_test');
require('test/models/host_test');
require('test/models/host_component_test');
http://git-wip-us.apache.org/repos/asf/ambari/blob/b96edcf9/ambari-web/app/controllers/wizard/step9_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/wizard/step9_controller.js b/ambari-web/app/controllers/wizard/step9_controller.js
index 56f97d1..8494a87 100644
--- a/ambari-web/app/controllers/wizard/step9_controller.js
+++ b/ambari-web/app/controllers/wizard/step9_controller.js
@@ -36,17 +36,16 @@ App.WizardStep9Controller = Em.Controller.extend({
* </code>
* @type {Array.<{name: string, status: string, logTasks: object[], message: string, progress: number, isNoTasksForInstall: bool}>}
*/
-
hosts: [],
/**
- * overall progress of <Install,Start and Test> page shown as progress bar on the top of the page
+ * Overall progress of <Install,Start and Test> page shown as progress bar on the top of the page
* @type {string}
*/
progress: '0',
/*
- * json file for the mock data to be used in mock mode
+ * Json file for the mock data to be used in mock mode
* @type {string}
*/
mockDataPrefix: '/data/wizard/deploy/5_hosts',
@@ -119,10 +118,12 @@ App.WizardStep9Controller = Em.Controller.extend({
togglePreviousSteps: function () {
if (App.testMode) {
return;
- } else if ('INSTALL FAILED' === this.get('content.cluster.status') && this.get('content.controllerName') == 'installerController') {
- App.router.get('installerController').setStepsEnable();
+ }
+ var installerController = App.router.get('installerController');
+ if ('INSTALL FAILED' === this.get('content.cluster.status') && this.get('content.controllerName') == 'installerController') {
+ installerController.setStepsEnable();
} else {
- App.router.get('installerController').setLowerStepsDisable(9);
+ installerController.setLowerStepsDisable(9);
}
}.observes('content.cluster.status', 'content.controllerName'),
@@ -142,7 +143,6 @@ App.WizardStep9Controller = Em.Controller.extend({
Em.run.once(this, 'updateStatus');
}.observes('hosts.@each.status'),
-
/**
* A flag that gets set with installation failure.
* @type {bool}
@@ -150,6 +150,24 @@ App.WizardStep9Controller = Em.Controller.extend({
installFailed: false,
/**
+ * Incremental flag that triggers an event in step 9 view to change the tasks related data and icons of hosts.
+ * @type {number}
+ */
+ logTasksChangesCounter: 0,
+
+ /**
+ * <code>taskId</code> of current open task
+ * @type {number}
+ */
+ currentOpenTaskId: 0,
+
+ /**
+ * <code>requestId</code> of current open task
+ * @type {number}
+ */
+ currentOpenTaskRequestId: 0,
+
+ /**
* Observer function: Updates {status} field of the controller.
* @method updateStatus
*/
@@ -172,24 +190,6 @@ App.WizardStep9Controller = Em.Controller.extend({
}.observes('progress'),
/**
- * Incremental flag that triggers an event in step 9 view to change the tasks related data and icons of hosts.
- * @type {number}
- */
- logTasksChangesCounter: 0,
-
- /**
- * <code>taskId</code> of current open task
- * @type {number}
- */
- currentOpenTaskId: 0,
-
- /**
- * <code>requestId</code> of current open task
- * @type {number}
- */
- currentOpenTaskRequestId: 0,
-
- /**
* This function is called when a click event happens on Next button of "Install, Start and Test" page
* @method submit
*/
@@ -207,7 +207,6 @@ App.WizardStep9Controller = Em.Controller.extend({
}
},
-
/**
* navigateStep is called by App.WizardStep9View's didInsertElement and "retry" from router.
* content.cluster.status can be:
@@ -283,7 +282,6 @@ App.WizardStep9Controller = Em.Controller.extend({
this.loadHosts();
},
-
/**
* Reset status and message of all hosts when retry install
* @method resetHostsForRetry
@@ -339,6 +337,7 @@ App.WizardStep9Controller = Em.Controller.extend({
*/
displayMessage: function (task) {
var role = App.format.role(task.role);
+ /* istanbul ignore next */
switch (task.command) {
case 'INSTALL':
switch (task.status) {
@@ -431,6 +430,7 @@ App.WizardStep9Controller = Em.Controller.extend({
/**
* Run start/check services after installation phase.
* Does Ajax call to start all services
+ * @return {$.ajax|null}
* @method launchStartServices
*/
launchStartServices: function () {
@@ -465,7 +465,7 @@ App.WizardStep9Controller = Em.Controller.extend({
this.set('numPolls', 6);
}
- App.ajax.send({
+ return App.ajax.send({
name: name,
sender: this,
data: {
@@ -497,7 +497,8 @@ App.WizardStep9Controller = Em.Controller.extend({
};
this.hostHasClientsOnly(false);
this.saveClusterStatus(clusterStatus);
- } else {
+ }
+ else {
console.log('ERROR: Error occurred in parsing JSON data');
this.hostHasClientsOnly(true);
clusterStatus = {
@@ -759,7 +760,8 @@ App.WizardStep9Controller = Em.Controller.extend({
clusterStatus.status = 'STARTED';
var serviceStartTime = App.dateTime();
clusterStatus.installTime = ((parseInt(serviceStartTime) - parseInt(this.get('content.cluster.installStartTime'))) / 60000).toFixed(2);
- } else {
+ }
+ else {
clusterStatus.status = 'START FAILED'; // 'START FAILED' implies to step10 that installation was successful but start failed
}
this.saveClusterStatus(clusterStatus);
@@ -835,9 +837,6 @@ App.WizardStep9Controller = Em.Controller.extend({
var totalProgress = 0;
var tasksData = polledData.tasks;
console.log("The value of tasksData is: ", tasksData);
- if (!tasksData) {
- console.log("Step9: ERROR: NO tasks available to process");
- }
var requestId = this.get('content.cluster.requestId');
tasksData.setEach('Tasks.request_id', requestId);
if (polledData.Requests && polledData.Requests.id && polledData.Requests.id != requestId) {
@@ -947,10 +946,13 @@ App.WizardStep9Controller = Em.Controller.extend({
loadCurrentTaskLogSuccessCallback: function (data) {
var taskId = this.get('currentOpenTaskId');
if (taskId) {
- var currentTask = this.get('hosts').findProperty('name', data.Tasks.host_name).get('logTasks').findProperty('Tasks.id', data.Tasks.id);
- if (currentTask) {
- currentTask.Tasks.stderr = data.Tasks.stderr;
- currentTask.Tasks.stdout = data.Tasks.stdout;
+ var host = this.get('hosts').findProperty('name', data.Tasks.host_name);
+ if (host) {
+ var currentTask = host.get('logTasks').findProperty('Tasks.id', data.Tasks.id);
+ if (currentTask) {
+ currentTask.Tasks.stderr = data.Tasks.stderr;
+ currentTask.Tasks.stdout = data.Tasks.stdout;
+ }
}
}
this.set('logTasksChangesCounter', this.get('logTasksChangesCounter') + 1);
@@ -969,9 +971,10 @@ App.WizardStep9Controller = Em.Controller.extend({
* @param {bool} polling whether to continue polling for status or not
* @param {number} requestId
* @method getLogsByRequest
+ * @return {$.ajax|null}
*/
getLogsByRequest: function (polling, requestId) {
- App.ajax.send({
+ return App.ajax.send({
name: 'wizard.step9.load_log',
sender: this,
data: {
@@ -1015,22 +1018,15 @@ App.WizardStep9Controller = Em.Controller.extend({
self.loadCurrentTaskLog();
}
self.doPolling();
- }, this.POLL_INTERVAL);
+ }, this.get('POLL_INTERVAL'));
}
},
/**
* Error-callback for get log by request
- * @param {object} request
- * @param {object} ajaxOptions
- * @param {string} error
* @method getLogsByRequestErrorCallback
*/
- getLogsByRequestErrorCallback: function (request, ajaxOptions, error) {
- console.log("TRACE: STep9 -> In error function for the GET logs data");
- console.log("TRACE: STep9 -> value of the url is: " + url);
- console.log("TRACE: STep9 -> error code status is: " + request.status);
- },
+ getLogsByRequestErrorCallback: Em.K,
/**
* Delegates the function call to {getLogsByRequest} with appropriate params
@@ -1047,13 +1043,14 @@ App.WizardStep9Controller = Em.Controller.extend({
/**
* Check that all components are in INSTALLED state before issuing start command
* @method isAllComponentsInstalled
+ * @return {$.ajax|null}
*/
isAllComponentsInstalled: function () {
if (this.get('content.controllerName') !== 'installerController') {
- return;
+ return null;
}
var name = 'wizard.step9.installer.get_host_status';
- App.ajax.send({
+ return App.ajax.send({
name: name,
sender: this,
data: {
@@ -1109,7 +1106,6 @@ App.WizardStep9Controller = Em.Controller.extend({
* @method isAllComponentsInstalledErrorCallback
*/
isAllComponentsInstalledErrorCallback: function () {
- console.log("ERROR");
var clusterStatus = {
status: 'INSTALL FAILED',
isStartError: true,
@@ -1134,18 +1130,22 @@ App.WizardStep9Controller = Em.Controller.extend({
getComponentMessage: function (componentArr) {
var label = '';
componentArr.forEach(function (_component) {
- if (_component === componentArr[0]) {
+ if (componentArr.length === 1) {
label = _component;
- } else if (_component !== componentArr[componentArr.length - 1]) { // [clients.length - 1]
- label = label + ' ' + _component;
- if (_component !== componentArr[componentArr.length - 2]) {
- label = label + ',';
+ }
+ else {
+ if (_component !== componentArr[componentArr.length - 1]) { // [clients.length - 1]
+ label = label + ' ' + _component;
+ if (_component !== componentArr[componentArr.length - 2]) {
+ label = label + ',';
+ }
+ }
+ else {
+ label = label + ' ' + Em.I18n.t('and') + ' ' + _component;
}
- } else {
- label = label + ' ' + Em.I18n.t('and') + ' ' + _component;
}
}, this);
- return label;
+ return label.trim();
},
/**
@@ -1156,7 +1156,8 @@ App.WizardStep9Controller = Em.Controller.extend({
saveClusterStatus: function (clusterStatus) {
if (!App.testMode) {
App.router.get(this.get('content.controllerName')).saveClusterStatus(clusterStatus);
- } else {
+ }
+ else {
this.set('content.cluster', clusterStatus);
}
},
@@ -1168,8 +1169,8 @@ App.WizardStep9Controller = Em.Controller.extend({
*/
saveInstalledHosts: function (context) {
if (!App.testMode) {
- App.router.get(this.get('content.controllerName')).saveInstalledHosts(context)
+ App.router.get(this.get('content.controllerName')).saveInstalledHosts(context);
}
}
-});
+});
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/b96edcf9/ambari-web/app/templates/wizard/step9.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/wizard/step9.hbs b/ambari-web/app/templates/wizard/step9.hbs
index 988aa32..307609e 100644
--- a/ambari-web/app/templates/wizard/step9.hbs
+++ b/ambari-web/app/templates/wizard/step9.hbs
@@ -21,6 +21,7 @@
<h2>{{t installer.step9.header}}</h2>
<p class="alert alert-info">{{t installer.step9.body}}</p>
+
<div id="overallProgress">
<div class="row-fluid">
<div class="span10">
@@ -37,10 +38,10 @@
<div class="box-header">
<div class="pull-left">
{{#if controller.showRetry}}
- <a class="btn btn-primary"
- href="#" {{action retry}}><i class="icon-repeat icon-white"></i>
- {{t common.retry}}
- </a>
+ <a class="btn btn-primary" href="#" {{action retry}}>
+ <i class="icon-repeat icon-white"></i>
+ {{t common.retry}}
+ </a>
{{/if}}
</div>
<!-- filter by host level -->
@@ -75,9 +76,9 @@
</thead>
<tbody>
- {{#if view.pageContent}}
- {{#each host in view.pageContent}}
- {{#view App.HostStatusView objBinding="host" controllerBinding="controller"}}
+ {{#if view.pageContent}}
+ {{#each host in view.pageContent}}
+ {{#view App.HostStatusView objBinding="host" controllerBinding="controller"}}
<td>
{{host.name}}
</td>
@@ -91,50 +92,52 @@
</td>
<td>
<a {{bindAttr class="view.isFailed:text-error view.isSuccess:text-success view.isWarning:text-warning"}}
- href="javascript:void(null)"
- data-toggle="modal" {{action hostLogPopup target="view"}}>{{host.message}}</a>
+ href="javascript:void(null)"
+ data-toggle="modal" {{action hostLogPopup target="view"}}>{{host.message}}</a>
</td>
- {{/view}}
- {{/each}}
- {{else}}
+ {{/view}}
+ {{/each}}
+ {{else}}
<tr>
<td colspan="3"><p>{{t installer.step3.hosts.noHosts}}</p></td>
</tr>
- {{/if}}
+ {{/if}}
</tbody>
</table>
</div>
- <div id="hosts">
- <div class="page-bar">
- <div class="selected-hosts-info pull-left">
- {{view.filteredHostsInfo}}
- -
- <a {{action showAllHosts target="view"}} href="#">{{t tableView.filters.showAll}}</a>
- </div>
- <div class="items-on-page">
- <label>{{t common.show}}: {{view view.rowsPerPageSelectView selectionBinding="view.displayLength"}}</label>
- </div>
- <div class="info">{{view.paginationInfo}}</div>
- <div class="paging_two_button">
- {{view view.paginationFirst}}
- {{view view.paginationLeft}}
- {{view view.paginationRight}}
- {{view view.paginationLast}}
- </div>
+ <div id="hosts">
+ <div class="page-bar">
+ <div class="selected-hosts-info pull-left">
+ {{view.filteredHostsInfo}}
+ -
+ <a {{action showAllHosts target="view"}} href="#">{{t tableView.filters.showAll}}</a>
+ </div>
+ <div class="items-on-page">
+ <label>{{t common.show}}: {{view view.rowsPerPageSelectView selectionBinding="view.displayLength"}}</label>
+ </div>
+ <div class="info">{{view.paginationInfo}}</div>
+ <div class="paging_two_button">
+ {{view view.paginationFirst}}
+ {{view view.paginationLeft}}
+ {{view view.paginationRight}}
+ {{view view.paginationLast}}
</div>
</div>
+ </div>
</div>
<div>
{{#if view.resultMsg}}
<p {{bindAttr class="view.resultMsgColor :alert"}}>{{view.resultMsg}}
- {{#if view.isHostHeartbeatLost}}
- <a href="javascript:void(null)" data-toggle="modal" {{action hostWithInstallFailed target="view"}}>{{t common.showDetails}}</a>
- {{/if}}
+ {{#if view.isHostHeartbeatLost}}
+ <a href="javascript:void(null)"
+ data-toggle="modal" {{action hostWithInstallFailed target="view"}}>{{t common.showDetails}}</a>
+ {{/if}}
</p>
{{/if}}
<div class="btn-area">
- <button class="btn btn-success pull-right" {{bindAttr disabled="isSubmitDisabled"}} {{action submit target="controller"}}>{{t common.next}} →</button>
+ <button
+ class="btn btn-success pull-right" {{bindAttr disabled="isSubmitDisabled"}} {{action submit target="controller"}}>{{t common.next}} →</button>
</div>
</div>
http://git-wip-us.apache.org/repos/asf/ambari/blob/b96edcf9/ambari-web/app/templates/wizard/step9/step9HostTasksLogPopup.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/wizard/step9/step9HostTasksLogPopup.hbs b/ambari-web/app/templates/wizard/step9/step9HostTasksLogPopup.hbs
new file mode 100644
index 0000000..2671bbb
--- /dev/null
+++ b/ambari-web/app/templates/wizard/step9/step9HostTasksLogPopup.hbs
@@ -0,0 +1,90 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you 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.
+}}
+
+{{#if view.isHeartbeatLost}}
+ <div>
+ {{t installer.step9.host.heartbeat_lost_popup}}
+ </div>
+{{else}}
+ {{#if view.isNoTasksScheduled}}
+ {{t installer.step9.host.status.noTasks}}
+ {{else}}
+ <div {{bindAttr class="view.isLogWrapHidden::hidden :task-list-main-warp"}}>
+ <div class="task-top-wrap">
+ <div class="task-name-top task-detail-log-rolename">{{t common.tasks}}</div>
+ <div class="select-wrap">
+ {{t common.show}}:
+ {{view Ember.Select
+ contentBinding="view.categories"
+ optionValuePath="content.value"
+ optionLabelPath="content.label"
+ selectionBinding="view.category"
+ }}
+ </div>
+ </div>
+ <div id="host-log">
+ {{#each taskInfo in view.tasks}}
+ <div {{bindAttr class="taskInfo.isVisible::hidden :log-list-wrap"}}>
+ <div {{action toggleTaskLog taskInfo}} class="task-list-line-cursor">
+ <div class="operation-name-icon-wrap">
+ <i {{bindAttr class="taskInfo.status taskInfo.icon"}}></i>
+ <a href="#">
+ {{taskInfo.role}} {{taskInfo.command}}
+ </a>
+ </div>
+ <div class="show-details"><i class="icon-caret-right"></i></div>
+ </div>
+ </div>
+ {{/each}}
+ {{#if view.isEmptyList}}
+ <div class="log-list-wrap">{{t installer.step9.hostLog.popup.noTasksToShow}}</div>
+ {{/if}}
+ </div>
+ </div>
+
+ <div {{bindAttr class="view.isLogWrapHidden:hidden :task-detail-info"}}>
+ <div class="task-top-wrap">
+ <a class="task-detail-back" href="javascript:void(null)" {{action backToTaskList}} ><i
+ class="icon-arrow-left"></i> {{t common.tasks}}</a>
+
+ <div>
+ <i {{bindAttr class="view.openedTask.status :task-detail-status-ico view.openedTask.icon"}}
+ class="task-detail-status-ico"></i>
+ <span class="task-detail-log-rolename">{{view.openedTask.role}} {{view.openedTask.command}}</span>
+ </div>
+ <div class="task-detail-ico-wrap">
+ <a title="Click to Copy" {{action "textTrigger" taskInfo target="view"}} class="task-detail-copy"><i
+ class="icon-copy"></i> {{t common.copy}}</a>
+ <a title="Open in New Window" {{action openTaskLogInDialog}} class="task-detail-open-dialog"><i
+ class="icon-external-link"></i> {{t common.open}}</a>
+ </div>
+ </div>
+ <div class="task-detail-log-info">
+ <div class="content-area">
+ <div class="task-detail-log-clipboard-wrap"></div>
+ <div class="task-detail-log-maintext">
+ <h5>stderr: <span class="muted">{{view.openedTask.errorLog}} </span></h5>
+ <pre class="stderr">{{view.openedTask.stderr}}</pre>
+ <h5>stdout: <span class="muted"> {{view.openedTask.outputLog}} </span></h5>
+ <pre class="stdout">{{view.openedTask.stdout}}</pre>
+ </div>
+ </div>
+ </div>
+ </div>
+ {{/if}}
+{{/if}}
http://git-wip-us.apache.org/repos/asf/ambari/blob/b96edcf9/ambari-web/app/templates/wizard/step9/step9_install_host_popup.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/wizard/step9/step9_install_host_popup.hbs b/ambari-web/app/templates/wizard/step9/step9_install_host_popup.hbs
new file mode 100644
index 0000000..5da8642
--- /dev/null
+++ b/ambari-web/app/templates/wizard/step9/step9_install_host_popup.hbs
@@ -0,0 +1,40 @@
+{{!
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you 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.
+}}
+
+<div id="install-fail-popup" class="pre-scrollable">
+ <table class="table table-striped">
+ <thead>
+ <tr>
+ <th class="span3">{{t common.host}}</th>
+ <th class="span3">{{t common.components}}</th>
+ </tr>
+ </thead>
+ <tbody>
+ {{#each host in view.failedHosts}}
+ <tr>
+ <td>
+ {{host.hostName}}
+ </td>
+ <td>
+ {{host.componentNames}}
+ </td>
+ </tr>
+ {{/each}}
+ </tbody>
+ </table>
+</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/b96edcf9/ambari-web/app/templates/wizard/step9HostTasksLogPopup.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/wizard/step9HostTasksLogPopup.hbs b/ambari-web/app/templates/wizard/step9HostTasksLogPopup.hbs
deleted file mode 100644
index 2671bbb..0000000
--- a/ambari-web/app/templates/wizard/step9HostTasksLogPopup.hbs
+++ /dev/null
@@ -1,90 +0,0 @@
-{{!
-* Licensed to the Apache Software Foundation (ASF) under one
-* or more contributor license agreements. See the NOTICE file
-* distributed with this work for additional information
-* regarding copyright ownership. The ASF licenses this file
-* to you 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.
-}}
-
-{{#if view.isHeartbeatLost}}
- <div>
- {{t installer.step9.host.heartbeat_lost_popup}}
- </div>
-{{else}}
- {{#if view.isNoTasksScheduled}}
- {{t installer.step9.host.status.noTasks}}
- {{else}}
- <div {{bindAttr class="view.isLogWrapHidden::hidden :task-list-main-warp"}}>
- <div class="task-top-wrap">
- <div class="task-name-top task-detail-log-rolename">{{t common.tasks}}</div>
- <div class="select-wrap">
- {{t common.show}}:
- {{view Ember.Select
- contentBinding="view.categories"
- optionValuePath="content.value"
- optionLabelPath="content.label"
- selectionBinding="view.category"
- }}
- </div>
- </div>
- <div id="host-log">
- {{#each taskInfo in view.tasks}}
- <div {{bindAttr class="taskInfo.isVisible::hidden :log-list-wrap"}}>
- <div {{action toggleTaskLog taskInfo}} class="task-list-line-cursor">
- <div class="operation-name-icon-wrap">
- <i {{bindAttr class="taskInfo.status taskInfo.icon"}}></i>
- <a href="#">
- {{taskInfo.role}} {{taskInfo.command}}
- </a>
- </div>
- <div class="show-details"><i class="icon-caret-right"></i></div>
- </div>
- </div>
- {{/each}}
- {{#if view.isEmptyList}}
- <div class="log-list-wrap">{{t installer.step9.hostLog.popup.noTasksToShow}}</div>
- {{/if}}
- </div>
- </div>
-
- <div {{bindAttr class="view.isLogWrapHidden:hidden :task-detail-info"}}>
- <div class="task-top-wrap">
- <a class="task-detail-back" href="javascript:void(null)" {{action backToTaskList}} ><i
- class="icon-arrow-left"></i> {{t common.tasks}}</a>
-
- <div>
- <i {{bindAttr class="view.openedTask.status :task-detail-status-ico view.openedTask.icon"}}
- class="task-detail-status-ico"></i>
- <span class="task-detail-log-rolename">{{view.openedTask.role}} {{view.openedTask.command}}</span>
- </div>
- <div class="task-detail-ico-wrap">
- <a title="Click to Copy" {{action "textTrigger" taskInfo target="view"}} class="task-detail-copy"><i
- class="icon-copy"></i> {{t common.copy}}</a>
- <a title="Open in New Window" {{action openTaskLogInDialog}} class="task-detail-open-dialog"><i
- class="icon-external-link"></i> {{t common.open}}</a>
- </div>
- </div>
- <div class="task-detail-log-info">
- <div class="content-area">
- <div class="task-detail-log-clipboard-wrap"></div>
- <div class="task-detail-log-maintext">
- <h5>stderr: <span class="muted">{{view.openedTask.errorLog}} </span></h5>
- <pre class="stderr">{{view.openedTask.stderr}}</pre>
- <h5>stdout: <span class="muted"> {{view.openedTask.outputLog}} </span></h5>
- <pre class="stdout">{{view.openedTask.stdout}}</pre>
- </div>
- </div>
- </div>
- </div>
- {{/if}}
-{{/if}}
http://git-wip-us.apache.org/repos/asf/ambari/blob/b96edcf9/ambari-web/app/templates/wizard/step9_install_host_popup.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/wizard/step9_install_host_popup.hbs b/ambari-web/app/templates/wizard/step9_install_host_popup.hbs
deleted file mode 100644
index 5da8642..0000000
--- a/ambari-web/app/templates/wizard/step9_install_host_popup.hbs
+++ /dev/null
@@ -1,40 +0,0 @@
-{{!
-* Licensed to the Apache Software Foundation (ASF) under one
-* or more contributor license agreements. See the NOTICE file
-* distributed with this work for additional information
-* regarding copyright ownership. The ASF licenses this file
-* to you 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.
-}}
-
-<div id="install-fail-popup" class="pre-scrollable">
- <table class="table table-striped">
- <thead>
- <tr>
- <th class="span3">{{t common.host}}</th>
- <th class="span3">{{t common.components}}</th>
- </tr>
- </thead>
- <tbody>
- {{#each host in view.failedHosts}}
- <tr>
- <td>
- {{host.hostName}}
- </td>
- <td>
- {{host.componentNames}}
- </td>
- </tr>
- {{/each}}
- </tbody>
- </table>
-</div>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/b96edcf9/ambari-web/app/views.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views.js b/ambari-web/app/views.js
index 2b48b42..6555313 100644
--- a/ambari-web/app/views.js
+++ b/ambari-web/app/views.js
@@ -257,6 +257,7 @@ require('views/wizard/step6_view');
require('views/wizard/step7_view');
require('views/wizard/step8_view');
require('views/wizard/step9_view');
+require('views/wizard/step9/hostLogPopupBody_view');
require('views/wizard/step10_view');
require('views/wizard/stack_upgrade/step1_view');
require('views/wizard/stack_upgrade/step2_view');
http://git-wip-us.apache.org/repos/asf/ambari/blob/b96edcf9/ambari-web/app/views/wizard/step9/hostLogPopupBody_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/wizard/step9/hostLogPopupBody_view.js b/ambari-web/app/views/wizard/step9/hostLogPopupBody_view.js
new file mode 100644
index 0000000..dd05b59
--- /dev/null
+++ b/ambari-web/app/views/wizard/step9/hostLogPopupBody_view.js
@@ -0,0 +1,264 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+var App = require('app');
+var date = require('utils/date');
+
+App.WizardStep9HostLogPopupBodyView = Em.View.extend({
+
+ templateName: require('templates/wizard/step9/step9HostTasksLogPopup'),
+
+ /**
+ * Does host lost heartbeat
+ * @type {bool}
+ */
+ isHeartbeatLost: function() {
+ return (this.get('parentView.host.status') === 'heartbeat_lost');
+ }.property('parentView.host.status'),
+
+ /**
+ * Does host doesn't have scheduled tasks for install
+ * @type {bool}
+ */
+ isNoTasksScheduled: function() {
+ return this.get('parentView.host.isNoTasksForInstall');
+ }.property('parentView.host.isNoTasksForInstall'),
+
+ /**
+ * Is log-box hidden
+ * @type {bool}
+ */
+ isLogWrapHidden: true,
+
+ /**
+ * Is log-textarea visible
+ * @type {bool}
+ */
+ showTextArea: false,
+
+ /**
+ * No tasks shown
+ * @type {bool}
+ */
+ isEmptyList: true,
+
+ /**
+ * Checks if no visible tasks are in popup
+ * @method visibleTasks
+ */
+ visibleTasks: function () {
+ this.set("isEmptyList", true);
+ if (this.get('category.value')) {
+ var filter = this.get('category.value');
+ var tasks = this.get('tasks');
+ tasks.setEach("isVisible", false);
+
+ if (filter == "all") {
+ tasks.setEach("isVisible", true);
+ }
+ else if (filter == "pending") {
+ tasks.filterProperty("status", "pending").setEach("isVisible", true);
+ tasks.filterProperty("status", "queued").setEach("isVisible", true);
+ }
+ else if (filter == "in_progress") {
+ tasks.filterProperty("status", "in_progress").setEach("isVisible", true);
+ }
+ else if (filter == "failed") {
+ tasks.filterProperty("status", "failed").setEach("isVisible", true);
+ }
+ else if (filter == "completed") {
+ tasks.filterProperty("status", "completed").setEach("isVisible", true);
+ }
+ else if (filter == "aborted") {
+ tasks.filterProperty("status", "aborted").setEach("isVisible", true);
+ }
+ else if (filter == "timedout") {
+ tasks.filterProperty("status", "timedout").setEach("isVisible", true);
+ }
+
+ if (tasks.filterProperty("isVisible", true).length > 0) {
+ this.set("isEmptyList", false);
+ }
+ }
+ }.observes('category', 'tasks'),
+
+ /**
+ * List categories (implements possible values for task status)
+ * @type {Em.Object[]}
+ */
+ categories: [
+ Em.Object.create({value: 'all', label: Em.I18n.t('installer.step9.hostLog.popup.categories.all') }),
+ Em.Object.create({value: 'pending', label: Em.I18n.t('installer.step9.hostLog.popup.categories.pending')}),
+ Em.Object.create({value: 'in_progress', label: Em.I18n.t('installer.step9.hostLog.popup.categories.in_progress')}),
+ Em.Object.create({value: 'failed', label: Em.I18n.t('installer.step9.hostLog.popup.categories.failed') }),
+ Em.Object.create({value: 'completed', label: Em.I18n.t('installer.step9.hostLog.popup.categories.completed') }),
+ Em.Object.create({value: 'aborted', label: Em.I18n.t('installer.step9.hostLog.popup.categories.aborted') }),
+ Em.Object.create({value: 'timedout', label: Em.I18n.t('installer.step9.hostLog.popup.categories.timedout') })
+ ],
+
+ /**
+ * Current category
+ * @type {Em.Object}
+ */
+ category: null,
+
+ /**
+ * List of tasks
+ * @type {Em.Object[]}
+ */
+ tasks: function () {
+ var tasksArr = [];
+ var host = this.get('parentView.host');
+ var tasks = this.getStartedTasks(host);
+ tasks = tasks.sortProperty('Tasks.id');
+ if (tasks.length) {
+ tasks.forEach(function (_task) {
+ var taskInfo = Em.Object.create({});
+ taskInfo.set('id', _task.Tasks.id);
+ taskInfo.set('requestId', _task.Tasks.request_id);
+ taskInfo.set('command', _task.Tasks.command.toLowerCase() === 'service_check' ? '' : _task.Tasks.command.toLowerCase());
+ taskInfo.set('status', App.format.taskStatus(_task.Tasks.status));
+ taskInfo.set('role', App.format.role(_task.Tasks.role));
+ taskInfo.set('stderr', _task.Tasks.stderr);
+ taskInfo.set('stdout', _task.Tasks.stdout);
+ taskInfo.set('startTime', date.startTime(_task.Tasks.start_time));
+ taskInfo.set('duration', date.durationSummary(_task.Tasks.start_time, _task.Tasks.end_time));
+ taskInfo.set('isVisible', true);
+ taskInfo.set('icon', '');
+ taskInfo.set('hostName', _task.Tasks.host_name);
+ taskInfo.set('outputLog', Em.I18n.t('common.hostLog.popup.logDir.path') + Em.I18n.t('common.hostLog.popup.outputLog.value').format(_task.Tasks.id));
+ taskInfo.set('errorLog', Em.I18n.t('common.hostLog.popup.logDir.path') + Em.I18n.t('common.hostLog.popup.errorLog.value').format(_task.Tasks.id));
+ if (taskInfo.get('status') == 'pending' || taskInfo.get('status') == 'queued') {
+ taskInfo.set('icon', 'icon-cog');
+ } else if (taskInfo.get('status') == 'in_progress') {
+ taskInfo.set('icon', 'icon-cogs');
+ } else if (taskInfo.get('status') == 'completed') {
+ taskInfo.set('icon', ' icon-ok');
+ } else if (taskInfo.get('status') == 'failed') {
+ taskInfo.set('icon', 'icon-exclamation-sign');
+ } else if (taskInfo.get('status') == 'aborted') {
+ taskInfo.set('icon', 'icon-minus');
+ } else if (taskInfo.get('status') == 'timedout') {
+ taskInfo.set('icon', 'icon-time');
+ }
+ tasksArr.push(taskInfo);
+ }, this);
+ }
+ return tasksArr;
+ }.property('parentView.c.logTasksChangesCounter'),
+
+ /**
+ * Navigate to task list from task view
+ * @method backToTaskList
+ */
+ backToTaskList: function () {
+ this.destroyClipBoard();
+ this.set("isLogWrapHidden", true);
+ },
+
+ /**
+ * Get list of host's started tasks
+ * @param {object} host
+ * @returns {object[]}
+ * @method getStartedTasks
+ */
+ getStartedTasks: function (host) {
+ return host.logTasks.filter(function (task) {
+ return task.Tasks.status;
+ });
+ },
+
+ /**
+ * Open new window with task's log
+ * @method openTaskLogInDialog
+ */
+ openTaskLogInDialog: function () {
+ var newwindow = window.open();
+ var newdocument = newwindow.document;
+ newdocument.write($(".task-detail-log-info").html());
+ newdocument.close();
+ },
+
+ /**
+ * Currently open task
+ * @type {Em.Object}
+ */
+ openedTask: function () {
+ return this.get('tasks').findProperty('id', this.get('parentView.c.currentOpenTaskId'))
+ }.property('parentView.c.currentOpenTaskId', 'tasks.@each'),
+
+ /**
+ * Click-handler for toggle task's log view (textarea to box and back)
+ * @param {object} event
+ * @method toggleTaskLog
+ */
+ toggleTaskLog: function (event) {
+ if (this.get('isLogWrapHidden')) {
+ var taskInfo = event.context;
+ this.set("isLogWrapHidden", false);
+ this.set('parentView.c.currentOpenTaskId', taskInfo.id);
+ this.set('parentView.c.currentOpenTaskRequestId', taskInfo.requestId);
+ this.get('parentView.c').loadCurrentTaskLog();
+ $(".modal").scrollTop(0);
+ $(".modal-body").scrollTop(0);
+ }
+ else {
+ this.set("isLogWrapHidden", true);
+ this.set('parentView.c.currentOpenTaskId', 0);
+ this.set('parentView.c.currentOpenTaskRequestId', 0);
+ }
+ },
+
+ /**
+ * Create (if doesn't exist) or destroy (if exists) clipboard textarea
+ * @method textTrigger
+ */
+ textTrigger: function () {
+ if ($(".task-detail-log-clipboard").length > 0) {
+ this.destroyClipBoard();
+ }
+ else {
+ this.createClipBoard();
+ }
+ },
+
+ /**
+ * Create clipboard with task's log
+ * @method createClipBoard
+ */
+ createClipBoard: function () {
+ var log = $(".task-detail-log-maintext");
+ $(".task-detail-log-clipboard-wrap").html('<textarea class="task-detail-log-clipboard"></textarea>');
+ $(".task-detail-log-clipboard")
+ .html("stderr: \n" + $(".stderr").html() + "\n stdout:\n" + $(".stdout").html())
+ .css("display", "block")
+ .width(log.width())
+ .height(log.height())
+ .select();
+ log.css("display", "none")
+ },
+
+ /**
+ * Destroy clipboard with task's log
+ * @method destroyClipBoard
+ */
+ destroyClipBoard: function () {
+ $(".task-detail-log-clipboard").remove();
+ $(".task-detail-log-maintext").css("display", "block");
+ }
+});
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/b96edcf9/ambari-web/app/views/wizard/step9_view.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/views/wizard/step9_view.js b/ambari-web/app/views/wizard/step9_view.js
index 1e08f26..ec64530 100644
--- a/ambari-web/app/views/wizard/step9_view.js
+++ b/ambari-web/app/views/wizard/step9_view.js
@@ -22,21 +22,51 @@ var date = require('utils/date');
App.WizardStep9View = App.TableView.extend({
templateName: require('templates/wizard/step9'),
+
+ /**
+ * Overall progress-bar color
+ * @type {string}
+ */
barColor: '',
+
+ /**
+ * Overall result message
+ * @type {string}
+ */
resultMsg: '',
+
+ /**
+ * Overall message color
+ * @type {string}
+ */
resultMsgColor: '',
+
+ /**
+ * When progress is 100, step is completed
+ * @type {bool}
+ */
isStepCompleted: function() {
return (this.get('controller.progress') === '100');
}.property('controller.progress'),
+ /**
+ * Number of visible hosts
+ * @type {string}
+ */
displayLength: "25",
+ /**
+ * Same to <code>controller.hosts</code>
+ * @type {object[]}
+ */
content: function () {
return this.get('controller.hosts');
}.property('controller.hosts'),
- filteredContent: [],
-
+ /**
+ * Active category
+ * @type {Ember.Object}
+ */
selectedCategory: function() {
return this.get('categories').findProperty('isActive');
}.property('categories.@each.isActive'),
@@ -62,9 +92,10 @@ App.WizardStep9View = App.TableView.extend({
return this.get('isActive') ? 'active' : '';
}.property('isActive')
}),
+
/**
- * computed property creates the category objects on the load of the page and sets 'All' as the active category
- * @Returns: All created categories which are binded and iterated in the template
+ * Domputed property creates the category objects on the load of the page and sets 'All' as the active category
+ * @Returns {Em.Object[]} All created categories which are binded and iterated in the template
*/
categories: function () {
return [
@@ -76,13 +107,49 @@ App.WizardStep9View = App.TableView.extend({
];
}.property(),
+ /**
+ * True if <code>controller.hostsWithHeartbeatLost</code> contains some values
+ * @type {bool}
+ */
+ isHostHeartbeatLost: function () {
+ return (this.get('controller.hostsWithHeartbeatLost').length > 0);
+ }.property('controller.hostsWithHeartbeatLost.@each'),
+
+ /**
+ * Css-string to overall progress-bar width-property
+ * @type {string}
+ */
+ barWidth: function () {
+ var controller = this.get('controller');
+ return 'width: ' + controller.get('progress') + '%;';
+ }.property('controller.progress'),
+
+ /**
+ * Filter hosts info shown up on bottom of the box. Set by filter function, when 'seletedCategory' changed
+ * @type {string}
+ */
+ filteredHostsInfo: '',
+
+ /**
+ * Message for overall progress
+ * @type {string}
+ */
+ progressMessage: function () {
+ return Em.I18n.t('installer.step9.overallProgress').format(this.get('controller.progress'));
+ }.property('controller.progress'),
+
+ /**
+ * Run <code>countCategoryHosts</code>, <code>filter</code> only once
+ * @method hostStatusObserver
+ */
hostStatusObserver: function(){
- Ember.run.once(this, 'countCategoryHosts');
- Ember.run.once(this, 'filter');
+ Em.run.once(this, 'countCategoryHosts');
+ Em.run.once(this, 'filter');
}.observes('content.@each.status'),
/**
- * count each category hosts to update label
+ * Count each category hosts to update label
+ * @method countCategoryHosts
*/
countCategoryHosts: function () {
var counters = {
@@ -109,7 +176,8 @@ App.WizardStep9View = App.TableView.extend({
},
/**
- * filter hosts by category
+ * Filter hosts by category
+ * @method filter
*/
filter: function () {
var self = this;
@@ -136,12 +204,8 @@ App.WizardStep9View = App.TableView.extend({
}.observes('selectedCategory'),
/**
- * filter hosts info shown up on bottom of the box. Set by filter function, when 'seletedCategory' changed
- */
- filteredHostsInfo: '',
-
- /**
* On click handler for 'show all' link
+ * @method showAllHosts
*/
showAllHosts: function () {
this.get('categories').forEach(function (category) {
@@ -152,6 +216,7 @@ App.WizardStep9View = App.TableView.extend({
/**
* Trigger on Category click
* @param {Object} event
+ * @method selectCategory
*/
selectCategory: function (event) {
var categoryStatus = event.context.get('hostStatus');
@@ -161,24 +226,15 @@ App.WizardStep9View = App.TableView.extend({
},
didInsertElement: function () {
- var controller = this.get('controller');
this.onStatus();
- controller.navigateStep();
+ this.get('controller').navigateStep();
},
- isHostHeartbeatLost: function () {
- return (this.get('controller.hostsWithHeartbeatLost').length > 0);
- }.property('controller.hostsWithHeartbeatLost.@each'),
-
- barWidth: function () {
- var controller = this.get('controller');
- return 'width: ' + controller.get('progress') + '%;';
- }.property('controller.progress'),
-
- progressMessage: function () {
- return Em.I18n.t('installer.step9.overallProgress').format(this.get('controller.progress'));
- }.property('controller.progress'),
-
+ /**
+ * Set <code>resultMsg</code>, <code>resultMsg</code>, <code>resultMsgColor</code> according to
+ * <code>controller.status</code>, <code>controller.startCallFailed</code>, <code>isHostHeartbeatLost</code>
+ * @method onStatus
+ */
onStatus: function () {
if (this.get('controller.status') === 'info') {
this.set('resultMsg', '');
@@ -208,17 +264,21 @@ App.WizardStep9View = App.TableView.extend({
}
}.observes('controller.status', 'controller.startCallFailed','isHostHeartbeatLost'),
-
- hostWithInstallFailed: function (event, context) {
+ /**
+ * Show popup with info about failed hosts
+ * @return {App.ModalPopup}
+ * @method hostWithInstallFailed
+ */
+ hostWithInstallFailed: function () {
var controller = this.get('controller');
- App.ModalPopup.show({
+ return App.ModalPopup.show({
header: Em.I18n.t('installer.step9.host.heartbeat_lost.header'),
classNames: ['sixty-percent-width-modal'],
autoHeight: false,
secondary: null,
- bodyClass: Ember.View.extend({
- templateName: require('templates/wizard/step9_install_host_popup'),
+ bodyClass: Em.View.extend({
+ templateName: require('templates/wizard/step9/step9_install_host_popup'),
c: controller,
failedHosts: function () {
return controller.get('hostsWithHeartbeatLost');
@@ -226,28 +286,80 @@ App.WizardStep9View = App.TableView.extend({
})
});
}
+
});
App.HostStatusView = Em.View.extend({
+
tagName: 'tr',
+
/**
* Current host
+ * @type {Em.Object}
*/
obj: null,
+
/**
* wizardStep9Controller
+ * @type {App.WizardStep9Controller}
*/
controller: null,
- barColor: '',
- didInsertElement: function () {
- this.onStatus();
- },
+ /**
+ * Progress-bar color for current host
+ * @type {string}
+ */
+ barColor: '',
+ /**
+ * Css-string to progress-bar width-property
+ * @type {string}
+ */
barWidth: function () {
return 'width: ' + this.get('obj.progress') + '%;';
}.property('obj.progress'),
+ /**
+ * Is current host failed
+ * @type {bool}
+ */
+ isFailed: function () {
+ return (this.get('isHostCompleted') && (this.get('obj.status') === 'failed' || this.get('obj.status') === 'heartbeat_lost'));
+ }.property('obj.status', 'isHostCompleted'),
+
+ /**
+ * Is current host successfully installed
+ * @type {bool}
+ */
+ isSuccess: function () {
+ return (this.get('isHostCompleted') && this.get('obj.status') === 'success');
+ }.property('obj.status', 'isHostCompleted'),
+
+ /**
+ * Current host has warnings
+ * @type {bool}
+ */
+ isWarning: function () {
+ return(this.get('isHostCompleted') && this.get('obj.status') === 'warning');
+ }.property('obj.status', 'isHostCompleted'),
+
+ /**
+ * Current host completed all its tasks
+ * @type {bool}
+ */
+ isHostCompleted: function () {
+ return this.get('obj.progress') == 100;
+ }.property('obj.progress'),
+
+ didInsertElement: function () {
+ this.onStatus();
+ },
+
+ /**
+ * Set <code>barColor</code>, <code>obj.progress</code>, <code>obj.message</code> according to
+ * <code>obj.status</code>, <code>obj.progress</code>, <code>controller.progress</code>
+ * @method onStatus
+ */
onStatus: function () {
if (this.get('obj.status') === 'info') {
this.set('barColor', 'progress-info');
@@ -272,37 +384,34 @@ App.HostStatusView = Em.View.extend({
}
}.observes('obj.status', 'obj.progress', 'controller.progress'),
- isFailed: function () {
- return (this.get('isHostCompleted') && (this.get('obj.status') === 'failed' || this.get('obj.status') === 'heartbeat_lost'));
- }.property('obj.status', 'isHostCompleted'),
-
- isSuccess: function () {
- return (this.get('isHostCompleted') && this.get('obj.status') === 'success');
- }.property('obj.status', 'isHostCompleted'),
-
- isWarning: function () {
- return(this.get('isHostCompleted') && this.get('obj.status') === 'warning');
- }.property('obj.status', 'isHostCompleted'),
-
- isHostCompleted: function () {
- return this.get('obj.progress') == 100;
- }.property('obj.progress'),
-
- hostLogPopup: function (event, context) {
+ /**
+ * Show popup with host logs
+ * @return {App.ModalPopup}
+ * @method hostLogPopup
+ */
+ hostLogPopup: function () {
var controller = this.get('controller');
var host = this.get('obj');
- App.ModalPopup.show({
+ return App.ModalPopup.show({
+
header: host.get('name'),
+
classNames: ['sixty-percent-width-modal'],
+
autoHeight: false,
+
secondary: null,
+
/**
* Current host
+ * @type {Em.Object}
*/
host: host,
+
/**
* wizardStep9Controller
+ * @type {App.WizardStep9Controller}
*/
c: controller,
@@ -311,175 +420,7 @@ App.HostStatusView = Em.View.extend({
this.hide();
},
- bodyClass: Ember.View.extend({
- templateName: require('templates/wizard/step9HostTasksLogPopup'),
- isHeartbeatLost: function() {
- return (host.get('status') === 'heartbeat_lost');
- }.property('host.status'),
- isNoTasksScheduled: function() {
- return host.get('isNoTasksForInstall');
- }.property('host.isNoTasksForInstall'),
-
- isLogWrapHidden: true,
-
- showTextArea: false,
-
- isEmptyList: true,
-
- visibleTasks: function () {
- this.set("isEmptyList", true);
- if (this.get('category.value')) {
- var filter = this.get('category.value');
- var tasks = this.get('tasks');
- tasks.setEach("isVisible", false);
-
- if (filter == "all") {
- tasks.setEach("isVisible", true);
- }
- else if (filter == "pending") {
- tasks.filterProperty("status", "pending").setEach("isVisible", true);
- tasks.filterProperty("status", "queued").setEach("isVisible", true);
- }
- else if (filter == "in_progress") {
- tasks.filterProperty("status", "in_progress").setEach("isVisible", true);
- }
- else if (filter == "failed") {
- tasks.filterProperty("status", "failed").setEach("isVisible", true);
- }
- else if (filter == "completed") {
- tasks.filterProperty("status", "completed").setEach("isVisible", true);
- }
- else if (filter == "aborted") {
- tasks.filterProperty("status", "aborted").setEach("isVisible", true);
- }
- else if (filter == "timedout") {
- tasks.filterProperty("status", "timedout").setEach("isVisible", true);
- }
-
- if (tasks.filterProperty("isVisible", true).length > 0) {
- this.set("isEmptyList", false);
- }
- }
- }.observes('category', 'tasks'),
-
- categories: [
- Ember.Object.create({value: 'all', label: Em.I18n.t('installer.step9.hostLog.popup.categories.all') }),
- Ember.Object.create({value: 'pending', label: Em.I18n.t('installer.step9.hostLog.popup.categories.pending')}),
- Ember.Object.create({value: 'in_progress', label: Em.I18n.t('installer.step9.hostLog.popup.categories.in_progress')}),
- Ember.Object.create({value: 'failed', label: Em.I18n.t('installer.step9.hostLog.popup.categories.failed') }),
- Ember.Object.create({value: 'completed', label: Em.I18n.t('installer.step9.hostLog.popup.categories.completed') }),
- Ember.Object.create({value: 'aborted', label: Em.I18n.t('installer.step9.hostLog.popup.categories.aborted') }),
- Ember.Object.create({value: 'timedout', label: Em.I18n.t('installer.step9.hostLog.popup.categories.timedout') })
- ],
-
- category: null,
-
- tasks: function () {
- var tasksArr = [];
- var host = this.get('parentView.host');
- var tasks = this.getStartedTasks(host);
- tasks = tasks.sortProperty('Tasks.id');
- if (tasks.length) {
- tasks.forEach(function (_task) {
- var taskInfo = Ember.Object.create({});
- taskInfo.set('id', _task.Tasks.id);
- taskInfo.set('requestId', _task.Tasks.request_id);
- taskInfo.set('command', _task.Tasks.command.toLowerCase() === 'service_check' ? '' : _task.Tasks.command.toLowerCase());
- taskInfo.set('status', App.format.taskStatus(_task.Tasks.status));
- taskInfo.set('role', App.format.role(_task.Tasks.role));
- taskInfo.set('stderr', _task.Tasks.stderr);
- taskInfo.set('stdout', _task.Tasks.stdout);
- taskInfo.set('startTime', date.startTime(_task.Tasks.start_time));
- taskInfo.set('duration', date.durationSummary(_task.Tasks.start_time, _task.Tasks.end_time));
- taskInfo.set('isVisible', true);
- taskInfo.set('icon', '');
- taskInfo.set('hostName', _task.Tasks.host_name);
- taskInfo.set('outputLog', Em.I18n.t('common.hostLog.popup.logDir.path') + Em.I18n.t('common.hostLog.popup.outputLog.value').format(_task.Tasks.id));
- taskInfo.set('errorLog', Em.I18n.t('common.hostLog.popup.logDir.path') + Em.I18n.t('common.hostLog.popup.errorLog.value').format(_task.Tasks.id));
- if (taskInfo.get('status') == 'pending' || taskInfo.get('status') == 'queued') {
- taskInfo.set('icon', 'icon-cog');
- } else if (taskInfo.get('status') == 'in_progress') {
- taskInfo.set('icon', 'icon-cogs');
- } else if (taskInfo.get('status') == 'completed') {
- taskInfo.set('icon', ' icon-ok');
- } else if (taskInfo.get('status') == 'failed') {
- taskInfo.set('icon', 'icon-exclamation-sign');
- } else if (taskInfo.get('status') == 'aborted') {
- taskInfo.set('icon', 'icon-minus');
- } else if (taskInfo.get('status') == 'timedout') {
- taskInfo.set('icon', 'icon-time');
- }
- tasksArr.push(taskInfo);
- }, this);
- }
- return tasksArr;
- }.property('parentView.c.logTasksChangesCounter'),
-
- backToTaskList: function (event, context) {
- this.destroyClipBoard();
- this.set("isLogWrapHidden", true);
- },
-
- getStartedTasks: function (host) {
- return host.logTasks.filter(function (task) {
- return task.Tasks.status;
- });
- },
-
- openTaskLogInDialog: function () {
- var newwindow = window.open();
- var newdocument = newwindow.document;
- newdocument.write($(".task-detail-log-info").html());
- newdocument.close();
- },
-
- openedTask: function () {
- return this.get('tasks').findProperty('id', this.get('parentView.c.currentOpenTaskId'))
- }.property('parentView.c.currentOpenTaskId', 'tasks.@each'),
-
- toggleTaskLog: function (event, context) {
- if (this.get('isLogWrapHidden')) {
- var taskInfo = event.context;
- this.set("isLogWrapHidden", false);
- this.set('parentView.c.currentOpenTaskId', taskInfo.id);
- this.set('parentView.c.currentOpenTaskRequestId', taskInfo.requestId);
- this.get('parentView.c').loadCurrentTaskLog();
- $(".modal").scrollTop(0);
- $(".modal-body").scrollTop(0);
- }
- else {
- this.set("isLogWrapHidden", true);
- this.set('parentView.c.currentOpenTaskId', 0);
- this.set('parentView.c.currentOpenTaskRequestId', 0);
- }
- },
-
- textTrigger: function (event) {
- if ($(".task-detail-log-clipboard").length > 0) {
- this.destroyClipBoard();
- }
- else {
- this.createClipBoard();
- }
- },
-
- createClipBoard: function () {
- var log = $(".task-detail-log-maintext");
- $(".task-detail-log-clipboard-wrap").html('<textarea class="task-detail-log-clipboard"></textarea>');
- $(".task-detail-log-clipboard")
- .html("stderr: \n" + $(".stderr").html() + "\n stdout:\n" + $(".stdout").html())
- .css("display", "block")
- .width(log.width())
- .height(log.height())
- .select();
- log.css("display", "none")
- },
-
- destroyClipBoard: function () {
- $(".task-detail-log-clipboard").remove();
- $(".task-detail-log-maintext").css("display", "block");
- }
- })
+ bodyClass: App.WizardStep9HostLogPopupBodyView
});
}