AMBARI-21050. Address config-groups while exporting blueprint from UI (alexantonenko)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/90abffd7 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/90abffd7 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/90abffd7 Branch: refs/heads/branch-feature-AMBARI-12556 Commit: 90abffd706448786cc02257abd76a22b4f96fcd3 Parents: 5b44fa4 Author: Alex Antonenko <hiv...@gmail.com> Authored: Wed May 24 12:02:52 2017 +0300 Committer: Alex Antonenko <hiv...@gmail.com> Committed: Wed May 24 12:02:52 2017 +0300 ---------------------------------------------------------------------- .../app/controllers/wizard/step8_controller.js | 158 ++++++++++++++----- .../test/controllers/wizard/step8_test.js | 78 ++++++--- 2 files changed, 178 insertions(+), 58 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/90abffd7/ambari-web/app/controllers/wizard/step8_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/wizard/step8_controller.js b/ambari-web/app/controllers/wizard/step8_controller.js index 7e318e0..f2b4ca7 100644 --- a/ambari-web/app/controllers/wizard/step8_controller.js +++ b/ambari-web/app/controllers/wizard/step8_controller.js @@ -1811,9 +1811,9 @@ App.WizardStep8Controller = Em.Controller.extend(App.AddSecurityConfigs, App.wiz return configurationsDetails; }, - hostInExistingHostGroup: function (newHost, cluster_template_host_groups) { + hostInExistingHostGroup: function (newHost, host_groups) { var hostGroupMatched = false; - cluster_template_host_groups.some(function (existingHostGroup) { + host_groups.some(function (existingHostGroup) { if(!hostGroupMatched) { var fqdnInHostGroup = existingHostGroup.hosts[0].fqdn; var componentsInExistingHostGroup = this.getRegisteredHosts().filterProperty('hostName', fqdnInHostGroup)[0].hostComponents; @@ -1830,8 +1830,8 @@ App.WizardStep8Controller = Em.Controller.extend(App.AddSecurityConfigs, App.wiz }); if(!componentMismatch) { hostGroupMatched = true; - existingHostGroup["cardinality"]["cardinality"] = parseInt(existingHostGroup["cardinality"]["cardinality"]) + 1; - existingHostGroup.hosts.push({"fqdn" : newHost.hostName}) + existingHostGroup["cardinality"] = parseInt(existingHostGroup["cardinality"]) + 1; + existingHostGroup.hosts.push({"fqdn" : newHost.hostName}); return true; } } @@ -1840,6 +1840,17 @@ App.WizardStep8Controller = Em.Controller.extend(App.AddSecurityConfigs, App.wiz return hostGroupMatched; }, + hostInChildHostGroup: function (presentHostGroup, configGroupName, hostInConfigGroup) { + return presentHostGroup['childHostGroups'].some(function (childHostGroup) { + //Check if childHostGroup name is same as this configgroupname, if yes, update childHostGroup else, compare with other childhostgroups + if(childHostGroup.configGroupName === configGroupName) { + childHostGroup.hosts.push( { "fqdn" : hostInConfigGroup } ); + childHostGroup['cardinality'] = childHostGroup['cardinality'] + 1; + return true; + } + }); + }, + generateBlueprint: function () { console.log("Prepare blueprint for download..."); var blueprint = {}; @@ -1863,59 +1874,130 @@ App.WizardStep8Controller = Em.Controller.extend(App.AddSecurityConfigs, App.wiz }, this); }, this); - //TODO address configGroups var host_groups = []; var cluster_template_host_groups = []; var counter = 0; this.getRegisteredHosts().filterProperty('isInstalled', false).map(function (host) { - var clusterTemplateHostGroupDetail = {}; - if(self.hostInExistingHostGroup(host, cluster_template_host_groups)) { + if(self.hostInExistingHostGroup(host, host_groups)) { return; } - + //Create new host_group if host is not mapped to existing host_groups var hostGroupId = "host_group_" + counter; - var cardinality = {"cardinality": 1}; + var hostListForGroup = []; + hostListForGroup.push({ "fqdn": host.hostName }); var hostGroupDetail = { "name": hostGroupId, "components": self.getComponentsForHost(host), - cardinality + "hosts": hostListForGroup, + "cardinality" : 1 }; hostGroupDetail.toJSON = function () { - var hostGroupDetailResult = {}; - for (var x in this) { - if (x === "cardinality") { - hostGroupDetailResult[x] = (this[x]["cardinality"]).toString(); - } else { - hostGroupDetailResult[x] = this[x]; - } - } - return hostGroupDetailResult; - } + var hostGroupDetailResult = _.omit(this, [ "hosts", "childHostGroups" ]); + hostGroupDetailResult["cardinality"] = this["cardinality"].toString(); + return hostGroupDetailResult; + }; host_groups.push(hostGroupDetail); - var hostListForGroup = []; - var hostDetail = { - "fqdn": host.hostName - } - hostListForGroup.push(hostDetail); - clusterTemplateHostGroupDetail = { + + var clusterTemplateHostGroupDetail = { "name": hostGroupId, - "hosts": hostListForGroup, - cardinality - }; - clusterTemplateHostGroupDetail.toJSON = function () { - return _.omit(this, [ "cardinality" ]); + "hosts": hostListForGroup }; cluster_template_host_groups.push(clusterTemplateHostGroupDetail); counter++; }, this); + this.get('content.configGroups').filterProperty("is_default", false).forEach(function (configGroup) { + if (configGroup.properties.length == 0) { + return; + } + configGroup.hosts.forEach(function (hostInConfigGroup) { + return host_groups.some(function (presentHostGroup) { + return presentHostGroup.hosts.some(function (hostInPresentHostGroup, index) { + if (hostInConfigGroup !== hostInPresentHostGroup.fqdn) { + return; + } + //Check if childHostGroup already created + if (presentHostGroup['childHostGroups']) { + if (self.hostInChildHostGroup(presentHostGroup, configGroup.name, hostInConfigGroup)) { + // Update to remove parentHostGroup as all the hosts are added to childHostGroup/s + presentHostGroup.hosts.splice(index, 1); + presentHostGroup["cardinality"] = presentHostGroup['cardinality'] - 1; + return true; + } + } + //create configuration object + var hgConfigurations; + if(presentHostGroup.hosts.length === 1 && presentHostGroup["configurations"]) { + hgConfigurations = presentHostGroup["configurations"][0]; + } else if (presentHostGroup["configurations"]) { //Deep copy + hgConfigurations = jQuery.extend(true, {}, presentHostGroup["configurations"][0]); + } else { + hgConfigurations = {}; + } + configGroup.properties.forEach(function (hgProperties) { + var type = App.config.getConfigTagFromFileName(hgProperties.filename); + if (!hgConfigurations[type]) { + hgConfigurations[type] = { properties: {} }; + } + hgConfigurations[type]['properties'][hgProperties.name] = hgProperties.value; + }); + var totalHgConf = []; + totalHgConf.push(hgConfigurations); + //If only host in presentHostGroup then merge configuration and return + if (presentHostGroup.hosts.length === 1) { + //If host_group already has configuration, assigned from previously processed config_group + if(!presentHostGroup["configurations"]) { + presentHostGroup["configurations"] = totalHgConf; + } + return true; + } + + //Create new host_group from this host + var hostGroupId = "host_group_" + counter; + counter++; + var hostListForGroup = []; + hostListForGroup.push({ "fqdn": hostInPresentHostGroup.fqdn }); + var hostGroupDetail = { + "name": hostGroupId, + "components": presentHostGroup.components, + "cardinality": 1, + "hosts": hostListForGroup, + "configurations": totalHgConf, + "configGroupName": configGroup.name + }; + hostGroupDetail.toJSON = function () { + var hostGroupDetailResult = _.omit(this, [ "hosts", "configGroupName", "childHostGroups" ]); + hostGroupDetailResult["cardinality"] = this["cardinality"].toString(); + return hostGroupDetailResult; + }; + host_groups.push(hostGroupDetail); + //Update for clustertemplate file + var clusterTemplateHostGroupDetail = { + "name": hostGroupId, + "hosts": hostListForGroup + }; + cluster_template_host_groups.push(clusterTemplateHostGroupDetail); + //Add newly created host_group as child to existing host_group + if (!presentHostGroup['childHostGroups']) { + presentHostGroup['childHostGroups'] = []; + } + presentHostGroup['childHostGroups'].push(hostGroupDetail); + presentHostGroup.hosts.splice(index, 1); + presentHostGroup["cardinality"] = presentHostGroup['cardinality'] - 1; + //return true to indicate that host has been matched + return true; + }, this); + }, this); + }, this); + }, this); + var selectedStack = App.Stack.find().findProperty('isSelected', true); - blueprint = { //TODO: bp name - 'configurations':totalConf, - 'host_groups':host_groups, - 'Blueprints':{'stack_name':selectedStack.get('stackName'), 'stack_version':selectedStack.get('stackVersion')} + blueprint = { + 'configurations': totalConf, + 'host_groups': host_groups.filter(function (item) { return item.cardinality > 0; }), + 'Blueprints': {'blueprint_name' : App.clusterStatus.clusterName, 'stack_name':selectedStack.get('stackName'), 'stack_version':selectedStack.get('stackVersion')} }; fileUtils.downloadTextFile(JSON.stringify(blueprint), 'json', 'blueprint.json') @@ -1923,8 +2005,8 @@ App.WizardStep8Controller = Em.Controller.extend(App.AddSecurityConfigs, App.wiz "blueprint": App.clusterStatus.clusterName, "config_recommendation_strategy" : "NEVER_APPLY", "provision_action" : "INSTALL_AND_START", - "configurations":[], - "host_groups":cluster_template_host_groups + "configurations": [], + "host_groups": cluster_template_host_groups.filter(function (item) { return item.hosts.length > 0; }) }; fileUtils.downloadTextFile(JSON.stringify(cluster_template), 'json', 'clustertemplate.json') }, @@ -1932,4 +2014,4 @@ App.WizardStep8Controller = Em.Controller.extend(App.AddSecurityConfigs, App.wiz downloadCSV: function() { App.router.get('kerberosWizardStep5Controller').getCSVData(false); } -}); \ No newline at end of file +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/90abffd7/ambari-web/test/controllers/wizard/step8_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/wizard/step8_test.js b/ambari-web/test/controllers/wizard/step8_test.js index 1a3214e..05fa536 100644 --- a/ambari-web/test/controllers/wizard/step8_test.js +++ b/ambari-web/test/controllers/wizard/step8_test.js @@ -66,11 +66,10 @@ var services = Em.A([ isClient: true }) ]), - configTypes: Em.A([ - Em.Object.create({ - type: 'cluster-env' - }) - ]), + configTypes: { + site1 : [], + site2 : [] + }, isHiddenOnSelectServicePage: false }), Em.Object.create({ @@ -83,11 +82,9 @@ var services = Em.A([ isMaster: true }) ]), - configTypes: Em.A([ - Em.Object.create({ - type: 'hdfs-site' - }) - ]), + configTypes: { + site3 : [] + }, isHiddenOnSelectServicePage: false }), Em.Object.create({ @@ -100,7 +97,7 @@ var services = Em.A([ isHAComponentOnly: true }) ]), - configTypes: [], + configTypes: {}, isHiddenOnSelectServicePage: false }), Em.Object.create({ @@ -114,7 +111,7 @@ var services = Em.A([ isClient: true }) ]), - configTypes: [], + configTypes: {}, isHiddenOnSelectServicePage: false }) ]); @@ -2341,19 +2338,60 @@ describe('App.WizardStep8Controller', function () { }); }); - //TODO + describe('#generateBlueprint', function () { - console.log("testing.......") + beforeEach(function () { - installerStep8Controller = getController(); - installerStep8Controller.set('configs', configs); - installerStep8Controller.set('content.services', services.filterProperty('isSelected')) - installerStep8Controller.set('selectedServices', []); - sinon.spy(installerStep8Controller, 'getConfigurationDetailsForConfigType'); + var configs = Em.A([ + Em.Object.create({filename: 'cluster-env.xml', name: 'p0', value: 'v0'}), + Em.Object.create({filename: 'site1.xml', name: 'p11', value: 'v11'}), + Em.Object.create({filename: 'site1.xml', name: 'p12', value: 'v12'}), + Em.Object.create({filename: 'site2.xml', name: 'p21', value: 'v21'}), + Em.Object.create({filename: 'site2.xml', name: 'p22', value: 'v22'}), + Em.Object.create({filename: 'site3.xml', name: 'p31', value: 'v31'}), + Em.Object.create({filename: 'site3.xml', name: 'p32', value: 'v32'}) + ]); + + var hostComponents1 = Em.A([ + Em.Object.create({componentName: 'NAMENODE'}), + Em.Object.create({componentName: 'DATANODE'}) + ]); + var hostComponents2 = Em.A([ + Em.Object.create({componentName: 'JOURNALNODE'}), + Em.Object.create({componentName: 'DATANODE'}) + ]); + var hosts = Em.A([ + Em.Object.create({bootStatus: 'REGISTERED', name: 'h1', hostName: 'h1', isInstalled: false, hostComponents: hostComponents1, fqdn: 'h1'}), + Em.Object.create({bootStatus: 'REGISTERED', name: 'h2', hostName: 'h2', isInstalled: false, hostComponents: hostComponents1, fqdn: 'h2'}), + Em.Object.create({bootStatus: 'REGISTERED', name: 'h3', hostName: 'h3', isInstalled: false, hostComponents: hostComponents2, fqdn: 'h3'}), + Em.Object.create({bootStatus: 'REGISTERED', name: 'h4', hostName: 'h4', isInstalled: false, hostComponents: hostComponents2, fqdn: 'h4'}) + ]); + var configGroupProperties = Em.A([ + Em.Object.create({filename: 'site1.xml', name: 'p11', value: 'v11_overriden'}) + ]); + var configGroups = Em.A([ + Em.Object.create({is_default : true, properties: [], hosts: [] }), + Em.Object.create({is_default : false, properties: [], hosts: [] }), + Em.Object.create({name: 'hdfs_custom_group', is_default : false, properties: configGroupProperties, hosts: [hosts[0].fqdn,hosts[1].fqdn] }) + ]); + + installerStep8Controller = getController(); + installerStep8Controller.set('configs', configs); + installerStep8Controller.set('allHosts', hosts); + installerStep8Controller.set('content.services', services.filterProperty('isSelected')); + installerStep8Controller.set('content.hosts', hosts); + installerStep8Controller.set('content.configGroups', configGroups); + installerStep8Controller.set('selectedServices', services.filterProperty('isSelected')); + sinon.spy(installerStep8Controller, 'getConfigurationDetailsForConfigType'); + sinon.spy(installerStep8Controller, 'hostInExistingHostGroup'); + sinon.spy(installerStep8Controller, 'hostInChildHostGroup'); }); it('should call generateBlueprint', function() { installerStep8Controller.generateBlueprint(); - expect(installerStep8Controller.getConfigurationDetailsForConfigType.calledThrice).to.be.true; + expect(installerStep8Controller.hostInExistingHostGroup.calledAfter(installerStep8Controller.getConfigurationDetailsForConfigType)).to.be.true; + sinon.assert.callCount(installerStep8Controller.getConfigurationDetailsForConfigType, 4); + sinon.assert.callCount(installerStep8Controller.hostInExistingHostGroup, 4); + sinon.assert.callCount(installerStep8Controller.hostInChildHostGroup, 1); }); }); });