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': [

Reply via email to