AMBARI-21700 Expose Patch Reversion in the Web Client. (atkach)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/8f0bcc01 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/8f0bcc01 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/8f0bcc01 Branch: refs/heads/feature-branch-AMBARI-21307 Commit: 8f0bcc0197a5aee36aa0a38b8e8b16dbda1182f0 Parents: cad2539 Author: Andrii Tkach <atk...@apache.org> Authored: Mon Aug 28 13:03:00 2017 +0300 Committer: Andrii Tkach <atk...@apache.org> Committed: Mon Aug 28 13:03:00 2017 +0300 ---------------------------------------------------------------------- .../controllers/global/cluster_controller.js | 3 + .../main/admin/stack_and_upgrade_controller.js | 71 ++++++++++++++ .../app/mappers/stack_upgrade_history_mapper.js | 1 + ambari-web/app/messages.js | 1 + .../stack_version/stack_upgrade_history.js | 1 + ambari-web/app/routes/stack_upgrade_routes.js | 4 +- ambari-web/app/styles/stack_versions.less | 3 +- .../revert_patch_upgrade_confirmation.hbs | 48 ++++++++++ ambari-web/app/utils/ajax/ajax.js | 17 +++- .../stack_upgrade/upgrade_version_box_view.js | 11 ++- .../global/cluster_controller_test.js | 5 + .../admin/stack_and_upgrade_controller_test.js | 99 ++++++++++++++++++++ .../upgrade_version_box_view_test.js | 13 +++ 13 files changed, 273 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/8f0bcc01/ambari-web/app/controllers/global/cluster_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/global/cluster_controller.js b/ambari-web/app/controllers/global/cluster_controller.js index 586a457..d61d61b 100644 --- a/ambari-web/app/controllers/global/cluster_controller.js +++ b/ambari-web/app/controllers/global/cluster_controller.js @@ -287,6 +287,8 @@ App.ClusterController = Em.Controller.extend(App.ReloadPopupMixin, { /** * restore upgrade status from server * and make call to get latest status from server + * Also loading all upgrades to App.StackUpgradeHistory model + * TODO should be called even if recent background operations doesn't have Upgrade request */ restoreUpgradeState: function () { var self = this; @@ -334,6 +336,7 @@ App.ClusterController = Em.Controller.extend(App.ReloadPopupMixin, { App.set('upgradeState', dbUpgradeState); } + App.stackUpgradeHistoryMapper.map(data); upgradeController.loadStackVersionsToModel(true).done(function () { upgradeController.loadCompatibleVersions(); App.set('stackVersionsAvailable', App.StackVersion.find().content.length > 0); http://git-wip-us.apache.org/repos/asf/ambari/blob/8f0bcc01/ambari-web/app/controllers/main/admin/stack_and_upgrade_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/main/admin/stack_and_upgrade_controller.js b/ambari-web/app/controllers/main/admin/stack_and_upgrade_controller.js index 7ef779d..b33c55d 100644 --- a/ambari-web/app/controllers/main/admin/stack_and_upgrade_controller.js +++ b/ambari-web/app/controllers/main/admin/stack_and_upgrade_controller.js @@ -1978,6 +1978,77 @@ App.MainAdminStackAndUpgradeController = Em.Controller.extend(App.LocalStorage, }, /** + * + * @param {Em.Object} version + */ + confirmRevertPatchUpgrade: function(version) { + var self = this; + var currentStack = App.RepositoryVersion.find(this.get('currentVersion.id')); + + App.ModalPopup.show({ + header: Em.I18n.t('popup.confirmation.commonHeader'), + popupBody: Em.I18n.t('admin.stackVersions.upgrade.patch.revert.confirmation'), + bodyClass: Em.View.extend({ + classNames: ['revert-patch-upgrade-confirmation'], + servicesToBeReverted: this.getServicesToBeReverted(version, currentStack), + stackFromVersion: version.get('displayName'), + stackToVersion: currentStack.get('displayNameSimple'), + templateName: require('templates/common/modal_popups/revert_patch_upgrade_confirmation') + }), + onPrimary: function () { + self.revertPatchUpgrade(version); + this._super(); + } + }); + }, + + /** + * + * @param {Em.Object} version + * @param {Em.Object} currentStack + * @returns {Array} + */ + getServicesToBeReverted: function(version, currentStack) { + return version.get('stackServices').filter(function(_service) { + return (App.Service.find(_service.get('name')).get('isLoaded') && _service.get('isAvailable')); + }).map(function(_service) { + return { + displayName: _service.get('displayName'), + fromVersion: _service.get('latestVersion'), + toVersion: currentStack.get('stackServices').findProperty('name', _service.get('name')).get('latestVersion') + } + }); + }, + + /** + * + * @param {Em.Object} version + * @returns {$.ajax} + */ + revertPatchUpgrade: function (version) { + this.set('requestInProgress', true); + var upgrade = App.StackUpgradeHistory.find().findProperty('associatedVersion', version.get('repositoryVersion')); + return App.ajax.send({ + name: 'admin.upgrade.revert', + sender: this, + success: 'upgradeSuccessCallback', + error: 'upgradeErrorCallback', + callback: function () { + this.sender.set('requestInProgress', false); + }, + data: { + upgradeId: upgrade && upgrade.get('upgradeId'), + id: version.get('id'), + value: version.get('id'), + label: version.get('displayName'), + type: version.get('upgradeType'), + skipComponentFailures: version.get('skipComponentFailures') ? 'true' : 'false', + skipSCFailures: version.get('skipSCFailures') ? 'true' : 'false' + } + }); + }, + + /** * restore last Upgrade data * @param {object} lastUpgradeData */ http://git-wip-us.apache.org/repos/asf/ambari/blob/8f0bcc01/ambari-web/app/mappers/stack_upgrade_history_mapper.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/mappers/stack_upgrade_history_mapper.js b/ambari-web/app/mappers/stack_upgrade_history_mapper.js index 47d248a..318818b 100644 --- a/ambari-web/app/mappers/stack_upgrade_history_mapper.js +++ b/ambari-web/app/mappers/stack_upgrade_history_mapper.js @@ -24,6 +24,7 @@ App.stackUpgradeHistoryMapper = App.QuickDataMapper.create({ config: { "id": "Upgrade.request_id", "request_id": "Upgrade.request_id", + "upgrade_id": "Upgrade.upgrade_id", "cluster_name": "Upgrade.cluster_name", "direction": "Upgrade.direction", "associated_version": "Upgrade.associated_version", http://git-wip-us.apache.org/repos/asf/ambari/blob/8f0bcc01/ambari-web/app/messages.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js index a24bd7f..805a760 100644 --- a/ambari-web/app/messages.js +++ b/ambari-web/app/messages.js @@ -1726,6 +1726,7 @@ Em.I18n.translations = { 'admin.stackVersions.upgrade.installPackage.fail.title':'Packages could not be installed', 'admin.stackVersions.upgrade.installPackage.fail.timeout':'Request timed out.', + 'admin.stackVersions.upgrade.patch.revert.confirmation':'Are you sure you want to revert the following services:', 'admin.stackVersions.editRepositories.info': 'Provide Base URLs for the Operating Systems you are configuring.', 'admin.stackVersions.editRepositories.validation.warning': 'Some of the repositories failed validation. Make changes to the base url or skip validation if you are sure that urls are correct', 'admin.stackVersions.version.install.confirm': 'You are about to install packages for version <strong>{0}</strong> on all hosts.', http://git-wip-us.apache.org/repos/asf/ambari/blob/8f0bcc01/ambari-web/app/models/stack_version/stack_upgrade_history.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/models/stack_version/stack_upgrade_history.js b/ambari-web/app/models/stack_version/stack_upgrade_history.js index cf38277..3694558 100644 --- a/ambari-web/app/models/stack_version/stack_upgrade_history.js +++ b/ambari-web/app/models/stack_version/stack_upgrade_history.js @@ -22,6 +22,7 @@ var stringUtils = require('utils/string_utils'); App.StackUpgradeHistory = DS.Model.extend({ requestId: DS.attr('number'), + upgradeId: DS.attr('number'), clusterName: DS.attr('string'), direction: DS.attr('string'), associatedVersion: DS.attr('string'), http://git-wip-us.apache.org/repos/asf/ambari/blob/8f0bcc01/ambari-web/app/routes/stack_upgrade_routes.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/routes/stack_upgrade_routes.js b/ambari-web/app/routes/stack_upgrade_routes.js index 42dc4dd..24fa5e8 100644 --- a/ambari-web/app/routes/stack_upgrade_routes.js +++ b/ambari-web/app/routes/stack_upgrade_routes.js @@ -70,7 +70,9 @@ module.exports = App.WizardRoute.extend({ App.router.get('updateController').set('isWorking', true); App.router.transitionTo('main.admin.stackAndUpgrade.versions'); this.hide(); - location.reload(); + if (['NOT_REQUIRED', 'COMPLETED'].contains(App.get('upgradeState'))) { + location.reload(); + } } }); }); http://git-wip-us.apache.org/repos/asf/ambari/blob/8f0bcc01/ambari-web/app/styles/stack_versions.less ---------------------------------------------------------------------- diff --git a/ambari-web/app/styles/stack_versions.less b/ambari-web/app/styles/stack_versions.less index d584aa6..f525b7a 100644 --- a/ambari-web/app/styles/stack_versions.less +++ b/ambari-web/app/styles/stack_versions.less @@ -360,7 +360,8 @@ } } -.install-repo-confirmation { +.install-repo-confirmation, +.revert-patch-upgrade-confirmation { .available-services-list { margin: 10px 0 30px; .service-version-info { http://git-wip-us.apache.org/repos/asf/ambari/blob/8f0bcc01/ambari-web/app/templates/common/modal_popups/revert_patch_upgrade_confirmation.hbs ---------------------------------------------------------------------- diff --git a/ambari-web/app/templates/common/modal_popups/revert_patch_upgrade_confirmation.hbs b/ambari-web/app/templates/common/modal_popups/revert_patch_upgrade_confirmation.hbs new file mode 100644 index 0000000..b122a8b --- /dev/null +++ b/ambari-web/app/templates/common/modal_popups/revert_patch_upgrade_confirmation.hbs @@ -0,0 +1,48 @@ +{{! +* 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. +}} +<p>{{{popupBody}}}</p> +<div> + <div class="row-fluid"> + <div class="span3 offset3"> + <strong>{{view.stackToVersion}}</strong> + </div> + <div class="span3"> + <strong>{{view.stackFromVersion}}</strong> + </div> + </div> + {{#each service in view.servicesToBeReverted}} + <div class="row-fluid service-version-info"> + <div class="span3"> + {{service.displayName}} + </div> + <div class="span2"> + <span class="label available"> + {{service.toVersion}} + </span> + </div> + <div class="span1"> + <i class="icon-arrow-left"></i> + </div> + <div class="span2"> + <span class="label available"> + {{service.fromVersion}} + </span> + </div> + </div> + {{/each}} +</div> http://git-wip-us.apache.org/repos/asf/ambari/blob/8f0bcc01/ambari-web/app/utils/ajax/ajax.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/utils/ajax/ajax.js b/ambari-web/app/utils/ajax/ajax.js index 4a1f9ef..0dcc945 100644 --- a/ambari-web/app/utils/ajax/ajax.js +++ b/ambari-web/app/utils/ajax/ajax.js @@ -1357,7 +1357,7 @@ var urls = { 'mock': '/data/clusters/info.json' }, 'cluster.load_last_upgrade': { - 'real': `/clusters/{clusterName}/upgrades?fields=Upgrade/request_status,Upgrade/request_id,Upgrade/versions,Upgrade/associated_version,Upgrade/direction,Upgrade/upgrade_type,Upgrade/downgrade_allowed,Upgrade/skip_failures,Upgrade/skip_service_check_failures`, + 'real': '/clusters/{clusterName}/upgrades', 'mock': '/data/stack_versions/upgrades.json' }, 'cluster.update_upgrade_version': { @@ -1781,6 +1781,21 @@ var urls = { } } }, + 'admin.upgrade.revert': { + 'real': '/clusters/{clusterName}/upgrades', + 'mock': '/data/stack_versions/start_upgrade.json', + 'type': 'POST', + 'format': function (data) { + return { + timeout : 600000, + data: JSON.stringify({ + "Upgrade": { + "revert_upgrade_id": data.upgradeId + } + }) + } + } + }, 'admin.upgrade.upgradeItem.setState': { 'real': '/clusters/{clusterName}/upgrades/{upgradeId}/upgrade_groups/{groupId}/upgrade_items/{itemId}', 'mock': '', http://git-wip-us.apache.org/repos/asf/ambari/blob/8f0bcc01/ambari-web/app/views/main/admin/stack_upgrade/upgrade_version_box_view.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/main/admin/stack_upgrade/upgrade_version_box_view.js b/ambari-web/app/views/main/admin/stack_upgrade/upgrade_version_box_view.js index 3462b58..b93b097 100644 --- a/ambari-web/app/views/main/admin/stack_upgrade/upgrade_version_box_view.js +++ b/ambari-web/app/views/main/admin/stack_upgrade/upgrade_version_box_view.js @@ -144,6 +144,11 @@ App.UpgradeVersionBoxView = Em.View.extend({ isButton: true, text: Em.I18n.t('admin.stackUpgrade.dialog.resume'), action: 'resumeUpgrade' + }, + 'CURRENT_PATCH': { + isButton: true, + text: Em.I18n.t('common.revert'), + action: 'confirmRevertPatchUpgrade' } }, @@ -168,7 +173,11 @@ App.UpgradeVersionBoxView = Em.View.extend({ var isSuspended = App.get('upgradeSuspended'); if (['INSTALLING', 'CURRENT'].contains(status)) { - element.setProperties(statePropertiesMap[status]); + if (this.get('content.isPatch') && status === 'CURRENT') { + element.setProperties(statePropertiesMap['CURRENT_PATCH']); + } else { + element.setProperties(statePropertiesMap[status]); + } } else if (status === 'NOT_REQUIRED') { requestInProgressRepoId && requestInProgressRepoId == this.get('content.id') ? element.setProperties(statePropertiesMap['LOADING']) : element.setProperties(statePropertiesMap[status]); http://git-wip-us.apache.org/repos/asf/ambari/blob/8f0bcc01/ambari-web/test/controllers/global/cluster_controller_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/global/cluster_controller_test.js b/ambari-web/test/controllers/global/cluster_controller_test.js index 170ed78..7f68efc 100644 --- a/ambari-web/test/controllers/global/cluster_controller_test.js +++ b/ambari-web/test/controllers/global/cluster_controller_test.js @@ -459,6 +459,7 @@ describe('App.clusterController', function () { sinon.spy(upgradeController, 'initDBProperties'); sinon.spy(upgradeController, 'loadUpgradeData'); sinon.spy(upgradeController, 'loadStackVersionsToModel'); + sinon.stub(App.stackUpgradeHistoryMapper, 'map'); }); afterEach(function () { @@ -470,6 +471,7 @@ describe('App.clusterController', function () { upgradeController.initDBProperties.restore(); upgradeController.loadUpgradeData.restore(); upgradeController.loadStackVersionsToModel.restore(); + App.stackUpgradeHistoryMapper.map.restore(); }); describe("has upgrade request", function() { @@ -509,6 +511,9 @@ describe('App.clusterController', function () { expect(upgradeController.loadUpgradeData.called).to.be.false; }); + it('App.stackUpgradeHistoryMapper.map should be called', function () { + expect(App.stackUpgradeHistoryMapper.map.calledOnce).to.be.true; + }); }); describe("has completed upgrade request", function() { http://git-wip-us.apache.org/repos/asf/ambari/blob/8f0bcc01/ambari-web/test/controllers/main/admin/stack_and_upgrade_controller_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/main/admin/stack_and_upgrade_controller_test.js b/ambari-web/test/controllers/main/admin/stack_and_upgrade_controller_test.js index 8c6f690..918c92f 100644 --- a/ambari-web/test/controllers/main/admin/stack_and_upgrade_controller_test.js +++ b/ambari-web/test/controllers/main/admin/stack_and_upgrade_controller_test.js @@ -3412,5 +3412,104 @@ describe('App.MainAdminStackAndUpgradeController', function() { expect(mock.mapProperty('isCompatible')).to.be.eql([false, true]) }); }); + + describe('#confirmRevertPatchUpgrade', function() { + beforeEach(function() { + sinon.stub(App.RepositoryVersion, 'find').returns(Em.Object.create()); + sinon.stub(App.ModalPopup, 'show'); + sinon.stub(controller, 'getServicesToBeReverted'); + }); + afterEach(function() { + App.RepositoryVersion.find.restore(); + App.ModalPopup.show.restore(); + controller.getServicesToBeReverted.restore(); + }); + + it('App.ModalPopup.show should be called', function() { + controller.confirmRevertPatchUpgrade(Em.Object.create()); + expect(App.ModalPopup.show.calledOnce).to.be.true; + }); + }); + + describe('#getServicesToBeReverted', function() { + beforeEach(function() { + sinon.stub(App.Service, 'find').returns(Em.Object.create({isLoaded: true})); + }); + afterEach(function() { + App.Service.find.restore(); + }); + + it('should return services which will be reverted', function() { + var version = Em.Object.create({ + stackServices: [ + Em.Object.create({ + name: 'S1', + isAvailable: false, + displayName: 's1', + latestVersion: '1.0' + }), + Em.Object.create({ + name: 'S2', + isAvailable: true, + displayName: 's2', + latestVersion: '2.0' + }) + ] + }); + var currentStack = Em.Object.create({ + stackServices: [ + Em.Object.create({ + name: 'S2', + latestVersion: '2.1' + }) + ] + }); + expect(controller.getServicesToBeReverted(version, currentStack)).to.be.eql([ + { + displayName: 's2', + fromVersion: '2.0', + toVersion: '2.1' + } + ]); + }); + }); + + describe('#revertPatchUpgrade', function() { + beforeEach(function() { + sinon.stub(App.StackUpgradeHistory, 'find').returns([ + Em.Object.create({ + associatedVersion: '1.1', + upgradeId: 1 + }) + ]); + }); + afterEach(function() { + App.StackUpgradeHistory.find.restore(); + }); + + it('App.ajax.send should be called', function() { + var version = Em.Object.create({ + repositoryVersion: '1.1', + id: 2, + displayName: '1.2', + upgradeType: 'EXPRESS' + }); + controller.revertPatchUpgrade(version); + expect(controller.get('requestInProgress')).to.be.true; + var args = testHelpers.findAjaxRequest('name', 'admin.upgrade.revert'); + expect(args[0]).to.exists; + expect(args[0].data).to.be.eql({ + upgradeId: 1, + id: 2, + value: 2, + label: '1.2', + type: 'EXPRESS', + skipComponentFailures: 'false', + skipSCFailures: 'false' + }); + args[0].callback(); + expect(controller.get('requestInProgress')).to.be.false; + }); + }); }); http://git-wip-us.apache.org/repos/asf/ambari/blob/8f0bcc01/ambari-web/test/views/main/admin/stack_upgrade/upgrade_version_box_view_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/views/main/admin/stack_upgrade/upgrade_version_box_view_test.js b/ambari-web/test/views/main/admin/stack_upgrade/upgrade_version_box_view_test.js index 0b8eb1e..0337913 100644 --- a/ambari-web/test/views/main/admin/stack_upgrade/upgrade_version_box_view_test.js +++ b/ambari-web/test/views/main/admin/stack_upgrade/upgrade_version_box_view_test.js @@ -450,6 +450,19 @@ describe('App.UpgradeVersionBoxView', function () { }, { inputData: { + 'content.status': 'CURRENT', + 'content.isPatch': true + }, + expected: { + status: 'CURRENT', + isButton: true, + text: Em.I18n.t('common.revert'), + action: 'confirmRevertPatchUpgrade' + }, + title: 'current patch version' + }, + { + inputData: { 'content.status': 'NOT_REQUIRED', 'controller.requestInProgress': false, 'parentView.repoVersions': [