ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jonathanhur...@apache.org
Subject [26/31] ambari git commit: AMBARI-18939. Add Service wizard: Allow adding slave components from different service conditionally (akovalenko)
Date Mon, 21 Nov 2016 16:08:57 GMT
AMBARI-18939. Add Service wizard: Allow adding slave components from different service conditionally
(akovalenko)


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/3b0c35b6
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/3b0c35b6
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/3b0c35b6

Branch: refs/heads/branch-feature-AMBARI-18456
Commit: 3b0c35b65c144acaaa2b677ee345c92348b4d6ec
Parents: 08ca96e
Author: Aleksandr Kovalenko <akovalenko@hortonworks.com>
Authored: Sat Nov 19 00:56:47 2016 +0200
Committer: Aleksandr Kovalenko <akovalenko@hortonworks.com>
Committed: Sat Nov 19 00:57:48 2016 +0200

----------------------------------------------------------------------
 .../controllers/main/service/add_controller.js  | 17 +++-
 ambari-web/app/controllers/wizard.js            | 45 ++++++++++-
 .../app/controllers/wizard/step6_controller.js  | 41 ++++++++++
 ambari-web/app/mappers/stack_service_mapper.js  |  2 +-
 ambari-web/app/utils/ajax/ajax.js               |  2 +-
 .../main/service/add_controller_test.js         | 81 +++++++++++++++++++
 .../test/controllers/wizard/step6_test.js       | 85 ++++++++++++++++++++
 7 files changed, 269 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/3b0c35b6/ambari-web/app/controllers/main/service/add_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/main/service/add_controller.js b/ambari-web/app/controllers/main/service/add_controller.js
index 04427a2..4310f8d 100644
--- a/ambari-web/app/controllers/main/service/add_controller.js
+++ b/ambari-web/app/controllers/main/service/add_controller.js
@@ -467,7 +467,8 @@ App.AddServiceController = App.WizardController.extend(App.AddSecurityConfigs,
{
   installSelectedServices: function (callback) {
     var name = 'common.services.update';
     var selectedServices = this.get('content.services').filterProperty('isInstalled', false).filterProperty('isSelected',
true).mapProperty('serviceName');
-    var data = this.generateDataForInstallServices(selectedServices);
+    var dependentServices = this.getDependentServices();
+    var data = this.generateDataForInstallServices(selectedServices.concat(dependentServices));
     this.installServicesRequest(name, data, callback.bind(this));
   },
 
@@ -483,6 +484,20 @@ App.AddServiceController = App.WizardController.extend(App.AddSecurityConfigs,
{
   },
 
   /**
+   * return list of services by dependent slave components
+   * @returns {Array}
+   */
+  getDependentServices: function () {
+    var result = [];
+    this.get('content.slaveComponentHosts').forEach(function (slaveComponent) {
+      if (slaveComponent.hosts.someProperty('isInstalled', false)) {
+        result.push(App.StackServiceComponent.find().findProperty('componentName', slaveComponent.componentName).get('serviceName'));
+      }
+    });
+    return result.uniq();
+  },
+
+  /**
    * installs clients before install new services
    * on host where some components require this
    * @method installAdditionalClients

http://git-wip-us.apache.org/repos/asf/ambari/blob/3b0c35b6/ambari-web/app/controllers/wizard.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/wizard.js b/ambari-web/app/controllers/wizard.js
index 89d439a..765f0cd 100644
--- a/ambari-web/app/controllers/wizard.js
+++ b/ambari-web/app/controllers/wizard.js
@@ -1307,13 +1307,56 @@ App.WizardController = Em.Controller.extend(App.LocalStorage, App.ThemesMappingM
     var hasServicesWithSlave = services.someProperty('hasSlave');
     var hasServicesWithClient = services.someProperty('hasClient');
     var hasServicesWithCustomAssignedNonMasters = services.someProperty('hasNonMastersWithCustomAssignment');
-    this.set('content.skipSlavesStep', !hasServicesWithSlave && !hasServicesWithClient
|| !hasServicesWithCustomAssignedNonMasters);
+    var hasDependentSlaveComponent = this.hasDependentSlaveComponent(services);
+    this.set('content.skipSlavesStep', (!hasServicesWithSlave && !hasServicesWithClient
|| !hasServicesWithCustomAssignedNonMasters) && !hasDependentSlaveComponent);
     if (this.get('content.skipSlavesStep')) {
       this.get('isStepDisabled').findProperty('step', step).set('value', this.get('content.skipSlavesStep'));
     }
   },
 
   /**
+   * Determine if there is some service with some component, that has dependent slave component
already installed in cluster, but not on all hosts
+   * @param services
+   * @returns {boolean}
+   */
+  hasDependentSlaveComponent: function (services) {
+    var result = false;
+    var dependentSlaves = [];
+    var hosts = this.get('content.hosts');
+
+    if (hosts) {
+      services.forEach(function (service) {
+        service.get('serviceComponents').forEach(function (component) {
+          component.get('dependencies').forEach(function (dependency) {
+            var dependentService = App.StackService.find().findProperty('serviceName', dependency.serviceName);
+            var dependentComponent = dependentService.get('serviceComponents').findProperty('componentName',
dependency.componentName);
+            if (dependentComponent.get('isSlave') && dependentService.get('isInstalled'))
{
+              dependentSlaves.push({component: dependentComponent.get('componentName'), count:
0});
+            }
+          });
+        });
+      });
+
+      var hostNames = Em.keys(hosts);
+      for (var i = 0; i < dependentSlaves.length; i++) {
+        var maxToInstall = App.StackServiceComponent.find().findProperty('componentName',
dependentSlaves[i].component).get('maxToInstall');
+        maxToInstall = maxToInstall === Infinity ? hostNames.length : maxToInstall;
+        hostNames.forEach(function (hostName) {
+          var hostComponents = hosts[hostName].hostComponents.mapProperty('HostRoles.component_name');
+          dependentSlaves[i].count += hostComponents.contains(dependentSlaves[i].component);
+        });
+
+        if (dependentSlaves[i].count < maxToInstall) {
+          result = true;
+          break;
+        }
+      }
+    }
+
+    return result;
+  },
+
+  /**
    * Load config themes for enhanced config layout.
    *
    * @method loadConfigThemes

http://git-wip-us.apache.org/repos/asf/ambari/blob/3b0c35b6/ambari-web/app/controllers/wizard/step6_controller.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/controllers/wizard/step6_controller.js b/ambari-web/app/controllers/wizard/step6_controller.js
index 87b0ee5..dfd0687 100644
--- a/ambari-web/app/controllers/wizard/step6_controller.js
+++ b/ambari-web/app/controllers/wizard/step6_controller.js
@@ -433,6 +433,7 @@ App.WizardStep6Controller = Em.Controller.extend(App.HostComponentValidationMixi
     } else {
      this.restoreComponentsSelection(hostsObj, slaveComponents);
     }
+    this.enableCheckboxesForDependentComponents(hostsObj);
     this.selectClientHost(hostsObj);
     return hostsObj;
   },
@@ -460,6 +461,46 @@ App.WizardStep6Controller = Em.Controller.extend(App.HostComponentValidationMixi
   },
 
   /**
+   * Enable checkboxes for dependent components of already installed services, that can be
added
+   * @param hostsObj
+   */
+  enableCheckboxesForDependentComponents: function (hostsObj) {
+    var dependentSlaves = {};
+    App.StackService.find().filterProperty('isSelected').forEach(function (service) {
+      service.get('serviceComponents').forEach(function (component) {
+        component.get('dependencies').forEach(function (dependency) {
+          var dependentService = App.StackService.find().findProperty('serviceName', dependency.serviceName);
+          var dependentComponent = dependentService.get('serviceComponents').findProperty('componentName',
dependency.componentName);
+          if (dependentComponent.get('isSlave') && dependentService.get('isInstalled'))
{
+            dependentSlaves[dependentComponent.get('componentName')] = [];
+          }
+        });
+      });
+    });
+
+    if (!Em.keys(dependentSlaves)) return false;
+
+    hostsObj.forEach(function (hostObj) {
+      hostObj.checkboxes.forEach(function (checkbox) {
+        if (dependentSlaves[checkbox.component] && !checkbox.isInstalled) {
+          dependentSlaves[checkbox.component].push(checkbox);
+        }
+      });
+    });
+
+    for (var component in dependentSlaves) {
+      if (dependentSlaves.hasOwnProperty(component)) {
+        var maxToInstall = App.StackServiceComponent.find().findProperty('componentName',
component).get('maxToInstall');
+        maxToInstall = maxToInstall === Infinity ? hostsObj.length : maxToInstall;
+        if (maxToInstall > hostsObj.length - dependentSlaves[component].length) {
+          dependentSlaves[component].setEach('isDisabled', false);
+        }
+      }
+    }
+    return true;
+  },
+
+  /**
    * restore previous component selection
    * @param {Array} hostsObj
    * @param {Array} slaveComponents

http://git-wip-us.apache.org/repos/asf/ambari/blob/3b0c35b6/ambari-web/app/mappers/stack_service_mapper.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mappers/stack_service_mapper.js b/ambari-web/app/mappers/stack_service_mapper.js
index 888dcdf..c0454b0 100644
--- a/ambari-web/app/mappers/stack_service_mapper.js
+++ b/ambari-web/app/mappers/stack_service_mapper.js
@@ -98,7 +98,7 @@ App.stackServiceMapper = App.QuickDataMapper.create({
       var serviceComponents = [];
       item.components.forEach(function (serviceComponent) {
         var dependencies = serviceComponent.dependencies.map(function (dependecy) {
-          return { Dependencies: App.keysUnderscoreToCamelCase(App.permit(dependecy.Dependencies,
['component_name', 'scope'])) };
+          return { Dependencies: App.keysUnderscoreToCamelCase(App.permit(dependecy.Dependencies,
['component_name', 'scope', 'service_name'])) };
         });
         serviceComponent.StackServiceComponents.id = serviceComponent.StackServiceComponents.component_name;
         serviceComponent.StackServiceComponents.dependencies = dependencies;

http://git-wip-us.apache.org/repos/asf/ambari/blob/3b0c35b6/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 6ca014a..09da497 100644
--- a/ambari-web/app/utils/ajax/ajax.js
+++ b/ambari-web/app/utils/ajax/ajax.js
@@ -1977,7 +1977,7 @@ var urls = {
     'type': 'DELETE'
   },
   'wizard.service_components': {
-    'real': '{stackUrl}/services?fields=StackServices/*,components/*,components/dependencies/Dependencies/scope,artifacts/Artifacts/artifact_name',
+    'real': '{stackUrl}/services?fields=StackServices/*,components/*,components/dependencies/Dependencies/scope,components/dependencies/Dependencies/service_name,artifacts/Artifacts/artifact_name',
     'mock': '/data/stacks/HDP-2.1/service_components.json'
   },
   'wizard.step9.installer.get_host_status': {

http://git-wip-us.apache.org/repos/asf/ambari/blob/3b0c35b6/ambari-web/test/controllers/main/service/add_controller_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/main/service/add_controller_test.js b/ambari-web/test/controllers/main/service/add_controller_test.js
index 51c8dbf..7470f89 100644
--- a/ambari-web/test/controllers/main/service/add_controller_test.js
+++ b/ambari-web/test/controllers/main/service/add_controller_test.js
@@ -316,6 +316,7 @@ describe('App.AddServiceController', function() {
       sinon.stub(this.controller, 'setDBProperty', function(key, value) {
         mock.db = value;
       });
+      sinon.stub(this.controller, 'hasDependentSlaveComponent');
       sinon.stub(App.store, 'commit', Em.K);
       this.mockStackService = sinon.stub(App.StackService, 'find');
       this.mockService = sinon.stub(App.Service, 'find');
@@ -324,6 +325,7 @@ describe('App.AddServiceController', function() {
     afterEach(function() {
       this.mockGetDBProperty.restore();
       this.controller.setDBProperty.restore();
+      this.controller.hasDependentSlaveComponent.restore();
       this.mockStackService.restore();
       this.mockService.restore();
       App.store.commit.restore();
@@ -564,4 +566,83 @@ describe('App.AddServiceController', function() {
 
   });
 
+  describe('#getDependentServices', function () {
+
+    beforeEach(function () {
+      sinon.stub(App.StackServiceComponent, 'find').returns([
+          Em.Object.create({
+            componentName: 'c1',
+            serviceName: 's1'
+          }),
+        Em.Object.create({
+          componentName: 'c2',
+          serviceName: 's2'
+        }),
+        Em.Object.create({
+          componentName: 'c3',
+          serviceName: 's3'
+        }),
+        Em.Object.create({
+          componentName: 'c4',
+          serviceName: 's1'
+        })
+      ]);
+    });
+
+    [
+      {
+        title: 'should return empty array',
+        sch: [],
+        expect: []
+      },
+      {
+        title: 'should return services for not installed slaves',
+        sch: [
+          {
+            componentName: 'c1',
+            hosts: [
+              {
+                isInstalled: false
+              },
+              {
+                isInstalled: true
+              }
+            ]
+          },
+          {
+            componentName: 'c2',
+            hosts: [
+              {
+                isInstalled: false
+              },
+              {
+                isInstalled: true
+              }
+            ]
+          },
+          {
+            componentName: 'c4',
+            hosts: [
+              {
+                isInstalled: false
+              },
+              {
+                isInstalled: true
+              }
+            ]
+          }
+        ],
+        expect: ['s1', 's2']
+      }
+    ].forEach(function (test) {
+          describe(test.title, function () {
+            it(function () {
+              addServiceController.set('content.slaveComponentHosts', test.sch);
+              expect(addServiceController.getDependentServices()).to.eql(test.expect);
+            });
+          })
+        });
+
+  });
+
 });

http://git-wip-us.apache.org/repos/asf/ambari/blob/3b0c35b6/ambari-web/test/controllers/wizard/step6_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/controllers/wizard/step6_test.js b/ambari-web/test/controllers/wizard/step6_test.js
index 4cf155c..b2bc879 100644
--- a/ambari-web/test/controllers/wizard/step6_test.js
+++ b/ambari-web/test/controllers/wizard/step6_test.js
@@ -193,6 +193,7 @@ describe('App.WizardStep6Controller', function () {
       sinon.stub(controller, 'setInstalledComponents');
       sinon.stub(controller, 'restoreComponentsSelection');
       sinon.stub(controller, 'selectClientHost');
+      sinon.stub(controller, 'enableCheckboxesForDependentComponents');
     });
 
     afterEach(function() {
@@ -200,6 +201,7 @@ describe('App.WizardStep6Controller', function () {
       controller.setInstalledComponents.restore();
       controller.restoreComponentsSelection.restore();
       controller.selectClientHost.restore();
+      controller.enableCheckboxesForDependentComponents.restore();
     });
 
     describe("slaveComponents is null", function() {
@@ -1899,4 +1901,87 @@ describe('App.WizardStep6Controller', function () {
     });   
   });
 
+  describe('#enableCheckboxesForDependentComponents', function () {
+
+    beforeEach(function () {
+      sinon.stub(App.StackService, 'find').returns([
+        Em.Object.create({
+          serviceName: 's1',
+          isInstalled: false,
+          isSelected: true,
+          serviceComponents: [
+            Em.Object.create({
+              componentName: 'c1',
+              isSlave: true,
+              dependencies: [
+                {
+                  serviceName: 's2',
+                  componentName: 'c2'
+                }
+              ]
+            })
+          ]
+        }),
+        Em.Object.create({
+          serviceName: 's2',
+          isInstalled: true,
+          isSelected: false,
+          serviceComponents: [
+            Em.Object.create({
+              componentName: 'c2',
+              isSlave: true,
+              dependencies: []
+            })
+          ]
+        })
+      ]);
+      sinon.stub(App.StackServiceComponent, 'find').returns([
+          Em.Object.create({
+            componentName: 'c2',
+            maxToInstall: 2
+          })
+      ]);
+    });
+
+    afterEach(function () {
+      App.StackService.find.restore();
+      App.StackServiceComponent.find.restore();
+    });
+
+    it('it should enable appropriate checkboxes', function() {
+      var hostObj = [
+        {
+          checkboxes: [
+            {
+              component: 'c1',
+              isInstalled: false,
+              isDisabled: false
+            },
+            {
+              component: 'c2',
+              isInstalled: false,
+              isDisabled: true
+            }
+          ]
+        },
+        {
+          checkboxes: [
+            {
+              component: 'c1',
+              isInstalled: false,
+              isDisabled: false
+            },
+            {
+              component: 'c2',
+              isInstalled: false,
+              isDisabled: true
+            }
+          ]
+        }
+      ];
+      expect(controller.enableCheckboxesForDependentComponents(hostObj)).to.be.true;
+      expect(hostObj[1].checkboxes[1].isDisabled).to.be.false;
+    })
+  });
+
 });


Mime
View raw message