Repository: ambari Updated Branches: refs/heads/trunk 91155dd15 -> 16e96dda7
AMBARI-10312. Split utils/configs to separated mixins (onechiporenko) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/16e96dda Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/16e96dda Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/16e96dda Branch: refs/heads/trunk Commit: 16e96dda71bce3ed900c9dfb7adea6821b2a1458 Parents: 91155dd Author: Oleg Nechiporenko <[email protected]> Authored: Wed Apr 1 18:34:40 2015 +0300 Committer: Oleg Nechiporenko <[email protected]> Committed: Wed Apr 1 18:34:40 2015 +0300 ---------------------------------------------------------------------- .../controllers/main/service/info/configs.js | 6 +- ambari-web/app/controllers/wizard.js | 4 +- .../app/controllers/wizard/step7_controller.js | 25 +- ambari-web/app/mixins.js | 4 +- .../app/mixins/main/service/groups_mapping.js | 64 ++++ .../app/mixins/main/service/themes_mapping.js | 106 ++++++ .../app/mixins/main/service/versions_mapping.js | 107 ++++++ ambari-web/app/utils/config.js | 328 +++++-------------- .../main/service/info/config_test.js | 5 +- .../test/controllers/wizard/step7_test.js | 33 ++ ambari-web/test/utils/config_test.js | 243 ++++++++------ 11 files changed, 575 insertions(+), 350 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/16e96dda/ambari-web/app/controllers/main/service/info/configs.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/main/service/info/configs.js b/ambari-web/app/controllers/main/service/info/configs.js index e2b8299..185fb48 100644 --- a/ambari-web/app/controllers/main/service/info/configs.js +++ b/ambari-web/app/controllers/main/service/info/configs.js @@ -22,7 +22,7 @@ var batchUtils = require('utils/batch_scheduled_requests'); var dataManipulationUtils = require('utils/data_manipulation'); var lazyLoading = require('utils/lazy_loading'); -App.MainServiceInfoConfigsController = Em.Controller.extend(App.ServerValidatorMixin, App.EnhancedConfigsMixin, App.ConfigOverridable, App.PreloadRequestsChainMixin, { +App.MainServiceInfoConfigsController = Em.Controller.extend(App.ServerValidatorMixin, App.EnhancedConfigsMixin, App.ConfigOverridable, App.PreloadRequestsChainMixin, App.ThemesMappingMixin, App.VersionsMappingMixin, { name: 'mainServiceInfoConfigsController', @@ -325,11 +325,11 @@ App.MainServiceInfoConfigsController = Em.Controller.extend(App.ServerValidatorM var self = this; this.clearStep(); if (App.get('supports.enhancedConfigs')) { - App.config.loadConfigTheme(this.get('content.serviceName')).always(function() { + this.loadConfigTheme(this.get('content.serviceName')).always(function() { self.setDependentServices(self.get('content.serviceName')); App.themesMapper.generateAdvancedTabs([self.get('content.serviceName')]); if (self.get('dependentServiceNames.length') > 0) { - App.config.loadConfigCurrentVersions(self.get('dependentServiceNames')); + self.loadConfigCurrentVersions(self.get('dependentServiceNames')); } }); } http://git-wip-us.apache.org/repos/asf/ambari/blob/16e96dda/ambari-web/app/controllers/wizard.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/wizard.js b/ambari-web/app/controllers/wizard.js index b5ebafd..a8e66bf 100644 --- a/ambari-web/app/controllers/wizard.js +++ b/ambari-web/app/controllers/wizard.js @@ -20,7 +20,7 @@ var App = require('app'); require('models/host'); -App.WizardController = Em.Controller.extend(App.LocalStorage, { +App.WizardController = Em.Controller.extend(App.LocalStorage, App.ThemesMappingMixin, { isStepDisabled: null, @@ -1170,7 +1170,7 @@ App.WizardController = Em.Controller.extend(App.LocalStorage, { }).mapProperty('serviceName'); // Load stack configs before loading themes App.config.loadConfigsFromStack(serviceNames).done(function() { - App.config.loadConfigThemeForServices(serviceNames).always(function() { + self.loadConfigThemeForServices(serviceNames).always(function() { self.set('stackConfigsLoaded', true); App.themesMapper.generateAdvancedTabs(serviceNames); dfd.resolve(); http://git-wip-us.apache.org/repos/asf/ambari/blob/16e96dda/ambari-web/app/controllers/wizard/step7_controller.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/controllers/wizard/step7_controller.js b/ambari-web/app/controllers/wizard/step7_controller.js index d466c51..e91f6cb 100644 --- a/ambari-web/app/controllers/wizard/step7_controller.js +++ b/ambari-web/app/controllers/wizard/step7_controller.js @@ -633,7 +633,7 @@ App.WizardStep7Controller = Em.Controller.extend(App.ServerValidatorMixin, { self.set('isRecommendedLoaded', true); // format descriptor configs if (self.get('securityEnabled') && self.get('wizardController.name') == 'addServiceController') { - App.config.addKerberosDescriptorConfigs(configs, self.get('wizardController.kerberosDescriptorConfigs') || []); + self.addKerberosDescriptorConfigs(configs, self.get('wizardController.kerberosDescriptorConfigs') || []); } self.setStepConfigs(configs, storedConfigs); self.checkHostOverrideInstaller(); @@ -644,6 +644,29 @@ App.WizardStep7Controller = Em.Controller.extend(App.ServerValidatorMixin, { } }); }, + + /** + * Mark descriptor properties in configuration object. + * + * @param {Object[]} configs - config properties to change + * @param {App.ServiceConfigProperty[]} descriptor - parsed kerberos descriptor + * @method addKerberosDescriptorConfigs + */ + addKerberosDescriptorConfigs: function (configs, descriptor) { + descriptor.forEach(function (item) { + var property = configs.findProperty('name', item.get('name')); + if (property) { + Em.setProperties(property, { + isSecureConfig: true, + displayName: Em.get(item, 'name'), + isUserProperty: false, + isOverridable: false, + category: 'Advanced ' + Em.get(item, 'filename') + }); + } + }); + }, + /** * Load config groups * and (if some services are already installed) load config groups for installed services http://git-wip-us.apache.org/repos/asf/ambari/blob/16e96dda/ambari-web/app/mixins.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/mixins.js b/ambari-web/app/mixins.js index 04aed32..3a25abc 100644 --- a/ambari-web/app/mixins.js +++ b/ambari-web/app/mixins.js @@ -27,7 +27,9 @@ require('mixins/common/serverValidator'); require('mixins/common/table_server_view_mixin'); require('mixins/common/table_server_mixin'); require('mixins/main/host/details/host_components/decommissionable'); -//require('mixins/main/service/themes_support'); +require('mixins/main/service/groups_mapping'); +require('mixins/main/service/themes_mapping'); +require('mixins/main/service/versions_mapping'); require('mixins/main/service/configs/config_overridable'); require('mixins/main/service/configs/preload_requests_chain'); require('mixins/main/service/configs/widget_popover_support'); http://git-wip-us.apache.org/repos/asf/ambari/blob/16e96dda/ambari-web/app/mixins/main/service/groups_mapping.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/mixins/main/service/groups_mapping.js b/ambari-web/app/mixins/main/service/groups_mapping.js new file mode 100644 index 0000000..aaf42d7 --- /dev/null +++ b/ambari-web/app/mixins/main/service/groups_mapping.js @@ -0,0 +1,64 @@ +/** + * 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'); + +/** + * Provide methods for config-groups loading from server and saving them into models + * + * @type {Em.Mixin} + */ +App.GroupsMappingMixin = Em.Mixin.create({ + + /** + * Load config groups + * @param {String[]} serviceNames + * @returns {$.Deferred()} + * @method loadConfigGroups + */ + loadConfigGroups: function (serviceNames) { + var dfd = $.Deferred(); + if (!serviceNames || serviceNames.length === 0) { + dfd.resolve(); + } else { + App.ajax.send({ + name: 'configs.config_groups.load.services', + sender: this, + data: { + serviceList: serviceNames.join(','), + dfd: dfd + }, + success: 'saveConfigGroupsToModel' + }); + } + return dfd.promise(); + }, + + /** + * Runs <code>configGroupsMapper<code> + * @param {object} data + * @param {object} opt + * @param {object} params + * @method saveConfigGroupsToModel + */ + saveConfigGroupsToModel: function (data, opt, params) { + App.configGroupsMapper.map(data, params.serviceList.split(',')); + params.dfd.resolve(); + } + +}); http://git-wip-us.apache.org/repos/asf/ambari/blob/16e96dda/ambari-web/app/mixins/main/service/themes_mapping.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/mixins/main/service/themes_mapping.js b/ambari-web/app/mixins/main/service/themes_mapping.js new file mode 100644 index 0000000..a6988f8 --- /dev/null +++ b/ambari-web/app/mixins/main/service/themes_mapping.js @@ -0,0 +1,106 @@ +/** + * 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'); + +/** + * Provide methods for config-themes loading from server and saving them into models + * + * @type {Em.Mixin} + */ +App.ThemesMappingMixin = Em.Mixin.create({ + + /** + * Load config themes from server and save them into models + * @param {string} serviceName + * @returns {$.ajax} + * @method loadConfigTheme + */ + loadConfigTheme: function(serviceName) { + return App.ajax.send({ + name: 'configs.theme', + sender: this, + data: { + serviceName: serviceName, + stackVersionUrl: App.get('stackVersionURL') + }, + success: '_saveThemeToModel' + }); + }, + + /** + * Success-callback for <code>loadConfigTheme</code> + * runs <code>themeMapper<code> + * @param {object} data + * @private + * @method saveThemeToModel + */ + _saveThemeToModel: function(data) { + App.themesMapper.map(data); + }, + + /** + * Load themes for specified services by one API call + * + * @method loadConfigThemeForServices + * @param {String|String[]} serviceNames + * @returns {$.ajax} + */ + loadConfigThemeForServices: function (serviceNames) { + return App.ajax.send({ + name: 'configs.theme.services', + sender: this, + data: { + serviceNames: Em.makeArray(serviceNames).join(','), + stackVersionUrl: App.get('stackVersionURL') + }, + success: '_loadConfigThemeForServicesSuccess', + error: '_loadConfigThemeForServicesError' + }); + }, + + /** + * Success-callback for <code>loadConfigThemeForServices</code> + * @param {object} data + * @private + * @method _loadConfigThemeForServicesSuccess + */ + _loadConfigThemeForServicesSuccess: function(data) { + if (!data.items.length) return; + App.themesMapper.map({ + items: data.items.mapProperty('themes').reduce(function(p,c) { + return p.concat(c); + }) + }); + }, + + /** + * Error-callback for <code>loadConfigThemeForServices</code> + * @param {object} request + * @param {object} ajaxOptions + * @param {string} error + * @param {object} opt + * @param {object} params + * @private + * @method _loadConfigThemeForServicesError + */ + _loadConfigThemeForServicesError: function(request, ajaxOptions, error, opt, params) { + console.log('ERROR: failed to load theme configs for', params.serviceNames); + } + +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/16e96dda/ambari-web/app/mixins/main/service/versions_mapping.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/mixins/main/service/versions_mapping.js b/ambari-web/app/mixins/main/service/versions_mapping.js new file mode 100644 index 0000000..a6a3dcf --- /dev/null +++ b/ambari-web/app/mixins/main/service/versions_mapping.js @@ -0,0 +1,107 @@ +/** + * 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'); + +/** + * Provide methods for config-versions loading from server and saving them into models + * + * @type {Em.Mixin} + */ +App.VersionsMappingMixin = Em.Mixin.create({ + + /** + * load config groups + * @param {string} [serviceName=null] + * @param {number} [configGroupId=null] + * @param {number} [configVersion=null] + * @param {boolean} [isForCompare=false] + * @returns {$.ajax} + * @method loadConfigVersions + */ + loadConfigVersions: function (serviceName, configGroupId, configVersion, isForCompare) { + var info = this._generateAjaxDataForVersions(serviceName, configGroupId, configVersion, isForCompare); + return App.ajax.send($.extend({sender: this, success: 'saveConfigVersionsToModel'}, info)); + }, + + /** + * Generate ajax info + * @param {string} [serviceName=null] + * @param {number} [configGroupId=null] + * @param {number} [configVersion=null] + * @param {boolean} [isForCompare=false] + * @returns {{name: string, data: {}}} + * @private + * @method generateAjaxDataForVersions + */ + _generateAjaxDataForVersions: function (serviceName, configGroupId, configVersion, isForCompare) { + var result = { + name: 'configs.config_versions.load.all.min', + data: {} + }; + if (serviceName) { + result.data.serviceName = serviceName; + if (configVersion) { + result.name = 'configs.config_versions.load'; + result.data.configVersion = configVersion; + result.data.isForCompare = isForCompare; + } + else { + if (configGroupId) { + result.name = 'configs.config_versions.load.group'; + result.data.configGroupId = configGroupId; + } + else { + result.name = 'configs.config_versions.load.service.min'; + } + } + } + return result; + }, + + /** + * + * @param {string[]} serviceNames + * @returns {$.ajax} + * @method loadConfigCurrentVersions + */ + loadConfigCurrentVersions: function (serviceNames) { + Em.assert('`serviceNames` should not be empty array', Em.isArray(serviceNames) && serviceNames.length > 0); + return App.ajax.send({ + name: 'configs.config_versions.load.current_versions', + sender: this, + data: { + serviceNames: serviceNames.join(",") + }, + success: '_saveConfigVersionsToModel' + }); + }, + + /** + * Runs <code>configGroupsMapper<code> + * @param {object} data + * @param {object} opt + * @param {object} params + * @method _saveConfigVersionsToModel + * @private + */ + _saveConfigVersionsToModel: function (data, opt, params) { + App.configVersionsMapper.map(data, params.isForCompare); + } + +}); \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/16e96dda/ambari-web/app/utils/config.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/utils/config.js b/ambari-web/app/utils/config.js index 0ad7de4..a7686d4 100644 --- a/ambari-web/app/utils/config.js +++ b/ambari-web/app/utils/config.js @@ -19,18 +19,18 @@ var App = require('app'); var stringUtils = require('utils/string_utils'); -var configGroupsByTag = []; - App.config = Em.Object.create({ CONFIG_GROUP_NAME_MAX_LENGTH: 18, /** * filename exceptions used to support substandard sitenames which don't have "xml" extension + * @type {string[]} */ filenameExceptions: [], preDefinedServiceConfigs: [], + /** * * Returns file name version that stored on server. @@ -231,6 +231,7 @@ App.config = Em.Object.create({ } return category; }, + /** * additional handling for special properties such as * checkbox and digital which values with 'm' at the end @@ -242,6 +243,7 @@ App.config = Em.Object.create({ config.defaultValue = config.value; } }, + /** * calculate config properties: * category, filename, isUserProperty, description @@ -281,6 +283,7 @@ App.config = Em.Object.create({ return (yarnRegex.test(_config.name)); } }.property(), + /** * return: * configs, @@ -570,7 +573,6 @@ App.config = Em.Object.create({ configData.supportsFinal = !!(advanced && advanced.supportsFinal); }, - /** * look over advanced configs and add missing configs to serviceConfigs * filter fetched configs by service if passed @@ -648,6 +650,7 @@ App.config = Em.Object.create({ * @param allSelectedServiceNames * @param installedServiceNames * @param localDB + * @param recommended * @return {Array} */ renderConfigs: function (configs, storedConfigs, allSelectedServiceNames, installedServiceNames, localDB, recommended) { @@ -718,6 +721,7 @@ App.config = Em.Object.create({ }, this); return renderedServiceConfigs; }, + /** Takes care of the "dynamic defaults" for the GLUSTERFS configs. Sets some of the config defaults to previously user-entered data. @@ -739,24 +743,6 @@ App.config = Em.Object.create({ }, /** - * Mark descriptor properties in configuration object. - * - * @param {Object[]} configs - config properties to change - * @param {App.ServiceConfigProperty[]} descriptor - parsed kerberos descriptor - */ - addKerberosDescriptorConfigs: function (configs, descriptor) { - descriptor.forEach(function (item) { - var property = configs.findProperty('name', item.get('name')); - if (property) { - Em.set(property, 'isSecureConfig', true); - Em.set(property, 'displayName', Em.get(item, 'name')); - Em.set(property, 'isUserProperty', false); - Em.set(property, 'isOverridable', false); - Em.set(property, 'category', 'Advanced ' + Em.get(item, 'filename')); - } - }); - }, - /** * create new child configs from overrides, attach them to parent config * override - value of config, related to particular host(s) * @param configProperty @@ -781,25 +767,28 @@ App.config = Em.Object.create({ configProperty.set('overrides', overrides); } }, + /** * create new ServiceConfig object by service name - * @param serviceName + * @param {string} serviceName + * @return {App.ServiceConfig} + * @method createServiceConfig */ createServiceConfig: function (serviceName) { var preDefinedServiceConfig = App.config.get('preDefinedServiceConfigs').findProperty('serviceName', serviceName); - var serviceConfig = App.ServiceConfig.create({ + return App.ServiceConfig.create({ serviceName: preDefinedServiceConfig.get('serviceName'), displayName: preDefinedServiceConfig.get('displayName'), configCategories: preDefinedServiceConfig.get('configCategories'), configs: [], configGroups: [] }); - return serviceConfig; }, + /** * GETs all cluster level sites in one call. * - * @return {object} + * @return {$.ajax} */ loadConfigsByTags: function (tags) { var urlParams = []; @@ -820,7 +809,7 @@ App.config = Em.Object.create({ * Fetch cluster configs from server * * @param callback - * @return {object|null} + * @return {$.ajax} */ loadClusterConfig: function (callback) { return App.ajax.send({ @@ -888,7 +877,7 @@ App.config = Em.Object.create({ * @param {String[]} serviceNames * @param {Object} opt * @param {Function} callback - * @returns {jqXHR} + * @returns {$.ajax} */ loadAdvancedConfigPartial: function (serviceNames, opt, callback) { var data = { @@ -1082,6 +1071,7 @@ App.config = Em.Object.create({ callback.call(sender, serviceConfigs); } }, + loadServiceConfigGroupOverridesSuccess: function (data, opt, params) { data.items.forEach(function (config) { App.config.loadedConfigurationsCache[config.type + "_" + config.tag] = config.properties; @@ -1104,6 +1094,7 @@ App.config = Em.Object.create({ }, this); params.callback.call(params.sender, params.serviceConfigs); }, + /** * Create config with non default config group. Some custom config properties * can be created and assigned to non-default config group. @@ -1135,6 +1126,7 @@ App.config = Em.Object.create({ group.set('switchGroupTextFull', Em.I18n.t('services.service.config_groups.switchGroupTextFull').format(group.get('name'))); return App.ServiceConfigProperty.create(propertyObject); }, + /** * format value of override of config * @param serviceConfig @@ -1151,6 +1143,27 @@ App.config = Em.Object.create({ /** * Set all site property that are derived from other site-properties + * Replace <foreignKey[0]>, <foreignKey[1]>, ... (in the name and value) to values from configs with names in foreignKey-array + * Replace <templateName[0]>, <templateName[1]>, ... (in the value) to values from configs with names in templateName-array + * Example: + * <code> + * config: { + * name: "name.<foreignKey[0]>.name", + * foreignKey: ["name1"], + * templateName: ["name2"], + * value: "<foreignKey[0]><templateName[0]>" + * } + * </code> + * "<foreignKey[0]>" in the name will be replaced with value from config with name "name1" (this config will be found + * in the mappedConfigs or allConfigs). New name will be set to the '_name'-property. If config with name "name1" won't + * be found, updated config will be marked as skipped (<code>noMatchSoSkipThisConfig</code>-property is set to true) + * "<templateName[0]>" in the value will be replace with value from config with name "name2" (it also will be found + * in the mappedConfigs or allConfigs). + * + * @param {object[]} mappedConfigs + * @param {object[]} allConfigs + * @param {object} config + * @method setConfigValue */ setConfigValue: function (mappedConfigs, allConfigs, config) { var globalValue; @@ -1160,54 +1173,66 @@ App.config = Em.Object.create({ var fkValue = config.value.match(/<(foreignKey.*?)>/g); var fkName = config.name.match(/<(foreignKey.*?)>/g); var templateValue = config.value.match(/<(templateName.*?)>/g); + if (fkValue) { fkValue.forEach(function (_fkValue) { + var index = parseInt(_fkValue.match(/\[([\d]*)(?=\])/)[1]); - if (mappedConfigs.someProperty('name', config.foreignKey[index])) { - globalValue = mappedConfigs.findProperty('name', config.foreignKey[index]).value; - config.value = config.value.replace(_fkValue, globalValue); - } else if (allConfigs.someProperty('name', config.foreignKey[index])) { - if (allConfigs.findProperty('name', config.foreignKey[index]).value === '') { - globalValue = allConfigs.findProperty('name', config.foreignKey[index]).defaultValue; - } else { - globalValue = allConfigs.findProperty('name', config.foreignKey[index]).value; + var cfk = config.foreignKey[index]; + var cFromMapped = mappedConfigs.findProperty('name', cfk); + if (Em.isNone(cFromMapped)) { + var cFromAll = allConfigs.findProperty('name', cfk); + if (!Em.isNone(cFromAll)) { + globalValue = Em.get(cFromAll, 'value') === '' ? Em.get(cFromAll, 'defaultValue') : Em.get(cFromAll, 'value'); + config.value = config.value.replace(_fkValue, globalValue); } + } + else { + globalValue = Em.get(cFromMapped, 'value'); config.value = config.value.replace(_fkValue, globalValue); } - }, this); + }); } // config._name - formatted name from original config name if (fkName) { fkName.forEach(function (_fkName) { + var index = parseInt(_fkName.match(/\[([\d]*)(?=\])/)[1]); - if (mappedConfigs.someProperty('name', config.foreignKey[index])) { - globalValue = mappedConfigs.findProperty('name', config.foreignKey[index]).value; - config._name = config.name.replace(_fkName, globalValue); - } else if (allConfigs.someProperty('name', config.foreignKey[index])) { - if (allConfigs.findProperty('name', config.foreignKey[index]).value === '') { - globalValue = allConfigs.findProperty('name', config.foreignKey[index]).defaultValue; - } else { - globalValue = allConfigs.findProperty('name', config.foreignKey[index]).value; + var cfk = config.foreignKey[index]; + var cFromMapped = mappedConfigs.findProperty('name', cfk); + + if (Em.isNone(cFromMapped)) { + var cFromAll = allConfigs.findProperty('name', cfk); + if (Em.isNone(cFromAll)) { + config.noMatchSoSkipThisConfig = true; } + else { + globalValue = Em.get(cFromAll, 'value') === '' ? Em.get(cFromAll, 'defaultValue') : Em.get(cFromAll, 'value'); + config._name = config.name.replace(_fkName, globalValue); + } + } + else { + globalValue = Em.get(cFromMapped, 'value'); config._name = config.name.replace(_fkName, globalValue); - } else { - config.noMatchSoSkipThisConfig = true; } - }, this); + }); } //For properties in the configMapping file having foreignKey and templateName properties. if (templateValue) { templateValue.forEach(function (_value) { var index = parseInt(_value.match(/\[([\d]*)(?=\])/)[1]); - if (allConfigs.someProperty('name', config.templateName[index])) { - var globalValue = allConfigs.findProperty('name', config.templateName[index]).value; - config.value = config.value.replace(_value, globalValue); - } else { + var cfk = config.templateName[index]; + var cFromAll = allConfigs.findProperty('name', cfk); + if (Em.isNone(cFromAll)) { config.value = null; } - }, this); + else { + var globalValue = Em.get(cFromAll, 'value'); + config.value = config.value.replace(_value, globalValue); + } + }); } }, @@ -1412,6 +1437,10 @@ App.config = Em.Object.create({ * exclude configs that depends on services which are uninstalled * if config doesn't have serviceName or dependent service is installed then * config not excluded + * @param {object[]} configs + * @param {string[]} installedServices + * @return {object[]} + * @method excludeUnsupportedConfigs */ excludeUnsupportedConfigs: function (configs, installedServices) { return configs.filter(function (config) { @@ -1419,28 +1448,6 @@ App.config = Em.Object.create({ }); }, - - - /** - * Gets all the configuration-groups for the given service. - * - * @param serviceId - * (string) ID of the service. Ex: HDFS - */ - getConfigGroupsForService: function (serviceId) { - - }, - - /** - * Gets all the configuration-groups for a host. - * - * @param hostName - * (string) host name used to register - */ - getConfigGroupsForHost: function (hostName) { - - }, - /** * Generate minimal config property object used in *_properties.js files. * Example: @@ -1460,9 +1467,10 @@ App.config = Em.Object.create({ * ....... * ] * </code> - * @param {Array} names + * @param {string[]} names * @param {Object} properties - additional properties which will merge with base object definition - * @returns {*} + * @returns {object[]} + * @method generateConfigPropertiesByName */ generateConfigPropertiesByName: function (names, properties) { return names.map(function (item) { @@ -1515,174 +1523,12 @@ App.config = Em.Object.create({ }, /** - * runs <code>stackConfigPropertiesMapper<code> - * @param data + * Runs <code>stackConfigPropertiesMapper<code> + * @param {object} data + * @method saveConfigsToModel */ saveConfigsToModel: function (data) { App.stackConfigPropertiesMapper.map(data); - }, - - /** - * load config groups - * @param {String[]} serviceNames - * @returns {$.Deferred()} - * @method loadConfigGroups - */ - loadConfigGroups: function (serviceNames) { - var dfd = $.Deferred(); - if (!serviceNames || serviceNames.length === 0) { - dfd.resolve(); - } else { - App.ajax.send({ - name: 'configs.config_groups.load.services', - sender: this, - data: { - serviceList: serviceNames.join(','), - dfd: dfd - }, - success: 'saveConfigGroupsToModel' - }); - } - return dfd.promise(); - }, - - /** - * runs <code>configGroupsMapper<code> - * @param data - * @param opt - * @param params - */ - saveConfigGroupsToModel: function (data, opt, params) { - App.configGroupsMapper.map(data, params.serviceList.split(',')); - params.dfd.resolve(); - }, - - /** - * load config groups - * @param {string} [serviceName=null] - * @param {number} [configGroupId=null] - * @param {number} [configVersion=null] - * @param {boolean} [isForCompare=false] - * @returns {$.ajax} - * @method loadConfigGroups - */ - loadConfigVersions: function (serviceName, configGroupId, configVersion, isForCompare) { - var info = this.generateAjaxDataForVersions(serviceName, configGroupId, configVersion, isForCompare); - return App.ajax.send($.extend({sender: this, success: 'saveConfigVersionsToModel'}, info)); - }, - - /** - * - * @param serviceNames - * @returns {$.ajax} - */ - loadConfigCurrentVersions: function (serviceNames) { - Em.assert('serviceNames should be not empty array', Em.isArray(serviceNames) && serviceNames.length > 0); - return App.ajax.send({ - name: 'configs.config_versions.load.current_versions', - sender: this, - data: { - serviceNames: serviceNames.join(",") - }, - success: 'saveConfigVersionsToModel' - }); - }, - /** - * generate ajax info - * @param {string} [serviceName=null] - * @param {number} [configGroupId=null] - * @param {number} [configVersion=null] - * @param {boolean} [isForCompare=false] - * @returns {{name: string, data: {}}} - */ - generateAjaxDataForVersions: function (serviceName, configGroupId, configVersion, isForCompare) { - var result = { - name: 'configs.config_versions.load.all.min', - data: {} - }; - if (serviceName) { - result.data.serviceName = serviceName; - if (configVersion) { - result.name = 'configs.config_versions.load'; - result.data.configVersion = configVersion; - result.data.isForCompare = isForCompare; - } else if (configGroupId) { - result.name = 'configs.config_versions.load.group'; - result.data.configGroupId = configGroupId; - } else { - result.name = 'configs.config_versions.load.service.min'; - } - } - return result; - }, - - /** - * runs <code>configGroupsMapper<code> - * @param data - * @param opt - * @param params - */ - saveConfigVersionsToModel: function (data, opt, params) { - App.configVersionsMapper.map(data, params.isForCompare); - }, - - /** - * load config themes - * @param {string} serviceName - * @returns {$.ajax} - */ - loadConfigTheme: function(serviceName) { - return App.ajax.send({ - name: 'configs.theme', - sender: this, - data: { - serviceName: serviceName, - stackVersionUrl: App.get('stackVersionURL') - }, - success: 'saveThemeToModel' - }); - }, - - /** - * runs <code>themeMapper<code> - * @param data - */ - saveThemeToModel: function(data) { - App.themesMapper.map(data); - }, - - /** - * Load themes for specified services by one API call. - * - * @method loadConfigThemeForServices - * @param {String|String[]} serviceNames - * @returns {$.Deferred} - */ - loadConfigThemeForServices: function (serviceNames) { - var data = { - serviceNames: Em.isArray(serviceNames) ? serviceNames.join(',') : serviceNames, - stackVersionUrl: App.get('stackVersionURL') - }; - return App.ajax.send({ - name: 'configs.theme.services', - sender: this, - data: data, - success: 'loadConfigThemeForServicesSuccess', - error: 'loadConfigThemeForServicesError' - }); - }, - - loadConfigThemeForServicesSuccess: function(data) { - if (!data.items.length) return; - App.themesMapper.map({ - items: data.items.mapProperty('themes').reduce(function(p,c) { - return p.concat(c); - }) - }); - }, - - loadConfigThemeForServicesError: function(request, ajaxOptions, error, opt, params) { - console.log('ERROR: failed to load theme configs for', params.serviceNames); } }); http://git-wip-us.apache.org/repos/asf/ambari/blob/16e96dda/ambari-web/test/controllers/main/service/info/config_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/main/service/info/config_test.js b/ambari-web/test/controllers/main/service/info/config_test.js index cdf0056..9100741 100644 --- a/ambari-web/test/controllers/main/service/info/config_test.js +++ b/ambari-web/test/controllers/main/service/info/config_test.js @@ -23,17 +23,18 @@ var mainServiceInfoConfigsController = null; describe("App.MainServiceInfoConfigsController", function () { beforeEach(function () { - sinon.stub(App.config, 'loadConfigTheme').returns($.Deferred().resolve().promise()); sinon.stub(App.themesMapper, 'generateAdvancedTabs').returns(Em.K); mainServiceInfoConfigsController = App.MainServiceInfoConfigsController.create({ loadDependentConfigs: function () { return {done: Em.K} + }, + loadConfigTheme: function () { + return $.Deferred().resolve().promise(); } }); }); afterEach(function() { - App.config.loadConfigTheme.restore(); App.themesMapper.generateAdvancedTabs.restore(); }); http://git-wip-us.apache.org/repos/asf/ambari/blob/16e96dda/ambari-web/test/controllers/wizard/step7_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/controllers/wizard/step7_test.js b/ambari-web/test/controllers/wizard/step7_test.js index eade984..64dc91e 100644 --- a/ambari-web/test/controllers/wizard/step7_test.js +++ b/ambari-web/test/controllers/wizard/step7_test.js @@ -1548,4 +1548,37 @@ describe('App.InstallerStep7Controller', function () { }); }); + describe('#addKerberosDescriptorConfigs', function() { + var configs = [ + { name: 'prop1', displayName: 'Prop1' }, + { name: 'prop2', displayName: 'Prop2' }, + { name: 'prop3', displayName: 'Prop3' } + ]; + var descriptor = [ + Em.Object.create({ name: 'prop4', filename: 'file-1'}), + Em.Object.create({ name: 'prop1', filename: 'file-1'}) + ]; + var propertiesAttrTests = [ + { + attr: 'isUserProperty', val: false, + m: 'descriptor properties should not be marked as custom' + }, + { + attr: 'category', val: 'Advanced file-1', + m: 'descriptor properties should be added to Advanced category' + }, + { + attr: 'isOverridable', val: false, + m: 'descriptor properties should not be overriden' + } + ]; + + propertiesAttrTests.forEach(function(test) { + it(test.m, function() { + installerStep7Controller.addKerberosDescriptorConfigs(configs, descriptor); + expect(configs.findProperty('name', 'prop1')[test.attr]).to.be.eql(test.val); + }); + }); + }); + }); http://git-wip-us.apache.org/repos/asf/ambari/blob/16e96dda/ambari-web/test/utils/config_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/utils/config_test.js b/ambari-web/test/utils/config_test.js index 97ff712..98b6b1c 100644 --- a/ambari-web/test/utils/config_test.js +++ b/ambari-web/test/utils/config_test.js @@ -34,7 +34,7 @@ describe('App.config', function () { var loadAllServicesConfigs = function(context, serviceNames) { context.configGroups = modelSetup.setupConfigGroupsObject(); - } + }; var loadServiceModelsData = function(serviceNames) { serviceNames.forEach(function(serviceName) { @@ -467,72 +467,6 @@ describe('App.config', function () { }); - describe('#generateConfigPropertiesByName', function() { - var tests = [ - { - names: ['property_1', 'property_2'], - properties: undefined, - e: { - keys: ['name', 'displayName', 'isVisible', 'isReconfigurable'] - }, - m: 'Should generate base property object without additional fields' - }, - { - names: ['property_1', 'property_2'], - properties: { category: 'SomeCat', serviceName: 'SERVICE_NAME' }, - e: { - keys: ['name', 'displayName', 'isVisible', 'isReconfigurable', 'category', 'serviceName'] - }, - m: 'Should generate base property object without additional fields' - } - ]; - - tests.forEach(function(test) { - it(test.m, function() { - expect(App.config.generateConfigPropertiesByName(test.names, test.properties).length).to.eql(test.names.length); - expect(App.config.generateConfigPropertiesByName(test.names, test.properties).map(function(property) { - return Em.keys(property); - }).reduce(function(p, c) { - return p.concat(c); - }).uniq()).to.eql(test.e.keys); - }); - }); - - }); - - describe('#generateConfigPropertiesByName', function() { - var tests = [ - { - names: ['property_1', 'property_2'], - properties: undefined, - e: { - keys: ['name', 'displayName', 'isVisible', 'isReconfigurable'] - }, - m: 'Should generate base property object without additional fields' - }, - { - names: ['property_1', 'property_2'], - properties: { category: 'SomeCat', serviceName: 'SERVICE_NAME' }, - e: { - keys: ['name', 'displayName', 'isVisible', 'isReconfigurable', 'category', 'serviceName'] - }, - m: 'Should generate base property object without additional fields' - } - ]; - - tests.forEach(function(test) { - it(test.m, function() { - expect(App.config.generateConfigPropertiesByName(test.names, test.properties).length).to.eql(test.names.length); - expect(App.config.generateConfigPropertiesByName(test.names, test.properties).map(function(property) { - return Em.keys(property); - }).reduce(function(p, c) { - return p.concat(c); - }).uniq()).to.eql(test.e.keys); - }); - }); - - }); - describe('#setPreDefinedServiceConfigs', function() { beforeEach(function() { sinon.stub(App.StackService, 'find', function() { @@ -800,39 +734,6 @@ describe('App.config', function () { }); - describe('#addKerberosDescriptorConfigs', function() { - var configs = [ - { name: 'prop1', displayName: 'Prop1' }, - { name: 'prop2', displayName: 'Prop2' }, - { name: 'prop3', displayName: 'Prop3' }, - ]; - var descriptor = [ - Em.Object.create({ name: 'prop4', filename: 'file-1'}), - Em.Object.create({ name: 'prop1', filename: 'file-1'}), - ]; - App.config.addKerberosDescriptorConfigs(configs, descriptor); - var propertiesAttrTests = [ - { - attr: 'isUserProperty', val: false, - m: 'descriptor properties should not be marked as custom' - }, - { - attr: 'category', val: 'Advanced file-1', - m: 'descriptor properties should be added to Advanced category' - }, - { - attr: 'isOverridable', val: false, - m: 'descriptor properties should not be overriden' - }, - ]; - - propertiesAttrTests.forEach(function(test) { - it(test.m, function() { - expect(configs.findProperty('name', 'prop1')[test.attr]).to.be.eql(test.val); - }); - }); - }); - describe('#advancedConfigIdentityData', function () { var configs = [ @@ -1186,4 +1087,146 @@ describe('App.config', function () { }); + describe('#setConfigValue', function () { + + Em.A([ + { + mappedConfigs: [ + { + name: 'falcon_user', + value: 'fu' + } + ], + allConfigs: [], + m: 'in mapped, value used', + e: { + _name: 'hadoop.proxyuser.fu.groups', + value: 'fu', + noMatchSoSkipThisConfig: false + } + }, + { + mappedConfigs: [], + allConfigs: [ + { + name: 'falcon_user', + value: 'fu' + } + ], + m: 'in all, value used', + e: { + _name: 'hadoop.proxyuser.fu.groups', + value: 'fu', + noMatchSoSkipThisConfig: false + } + }, + { + mappedConfigs: [], + allConfigs: [ + { + name: 'falcon_user', + value: '', + defaultValue: 'fu' + } + ], + m: 'in all, default value used', + e: { + _name: 'hadoop.proxyuser.fu.groups', + value: 'fu', + noMatchSoSkipThisConfig: false + } + }, + { + mappedConfigs: [], + allConfigs: [], + m: 'not found', + e: { + _name: 'hadoop.proxyuser.<foreignKey[0]>.groups', + value: '<foreignKey[0]>', + noMatchSoSkipThisConfig: true + } + } + ]).forEach(function (test) { + it(test.m, function () { + var config = { + name: "hadoop.proxyuser.<foreignKey[0]>.groups", + templateName: ["proxyuser_group"], + foreignKey: ["falcon_user"], + noMatchSoSkipThisConfig: false, + value: "<foreignKey[0]>" + }; + App.config.setConfigValue(test.mappedConfigs, test.allConfigs, config); + expect(config.value).to.equal(test.e.value); + if(test.e.noMatchSoSkipThisConfig) { + expect(Em.isNone(config._name)).to.be.true; + } + else { + expect(config._name).to.equal(test.e._name); + } + expect(config.noMatchSoSkipThisConfig).to.equal(test.e.noMatchSoSkipThisConfig); + }); + + Em.A([ + { + mappedConfigs: [], + allConfigs: [ + { + name: 'falcon_user', + value: 'fu' + }, + { + name: 'proxyuser_group', + value: 'pg' + } + ], + m: 'in all, template in all', + e: { + _name: 'hadoop.proxyuser.fu.groups', + value: 'fupg' + } + }, + { + mappedConfigs: [ + { + name: 'falcon_user', + value: 'fu' + }, + { + name: 'proxyuser_group', + value: 'pg' + } + ], + allConfigs: [], + m: 'in mapped, template in mapped', + e: { + _name: 'hadoop.proxyuser.fu.groups', + value: 'fupg' + } + }, + { + mappedConfigs: [], + allConfigs: [], + m: 'not found (template not found too)', + e: { + _name: 'hadoop.proxyuser.<foreignKey[0]>.groups', + value: null + } + } + ]).forEach(function (test) { + it(test.m, function () { + var config = { + name: "hadoop.proxyuser.<foreignKey[0]>.groups", + templateName: ["proxyuser_group"], + foreignKey: ["falcon_user"], + noMatchSoSkipThisConfig: false, + value: "<foreignKey[0]><templateName[0]>" + }; + App.config.setConfigValue(test.mappedConfigs, test.allConfigs, config); + }); + }); + + }); + + }); + });
