Repository: ambari Updated Branches: refs/heads/trunk 8abab3106 -> b4991a03c
AMBARI-12818. Properties autotrimming works incorrectly (alexantonenko) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/b4991a03 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/b4991a03 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/b4991a03 Branch: refs/heads/trunk Commit: b4991a03ca57ca31edb0820f1930fff93ec3e54b Parents: 8abab31 Author: Alex Antonenko <[email protected]> Authored: Wed Aug 19 17:49:11 2015 +0300 Committer: Alex Antonenko <[email protected]> Committed: Wed Aug 19 17:49:11 2015 +0300 ---------------------------------------------------------------------- .../mappers/service_config_version_mapper.js | 14 +++++++++++- ambari-web/app/messages.js | 1 + .../app/mixins/common/configs/configs_loader.js | 11 +++++++--- .../configs/objects/service_config_property.js | 15 +++++++++++++ ambari-web/app/utils/config.js | 9 ++++++++ ambari-web/app/utils/validator.js | 23 ++++++++++++++++++-- ambari-web/test/utils/validator_test.js | 9 +++++--- 7 files changed, 73 insertions(+), 9 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/b4991a03/ambari-web/app/mappers/service_config_version_mapper.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/mappers/service_config_version_mapper.js b/ambari-web/app/mappers/service_config_version_mapper.js index 0ae9879..23dcdcb 100644 --- a/ambari-web/app/mappers/service_config_version_mapper.js +++ b/ambari-web/app/mappers/service_config_version_mapper.js @@ -51,7 +51,7 @@ App.serviceConfigVersionsMapper = App.QuickDataMapper.create({ json.items.forEach(function (item, index) { var parsedItem = this.parseIt(item, this.get('config')); - parsedItem.id = parsedItem.service_name + '_' + parsedItem.version; + parsedItem.id = this.makeId(parsedItem.service_name, parsedItem.version); parsedItem.is_requested = true; itemIds[parsedItem.id] = true; parsedItem.index = index; @@ -99,5 +99,17 @@ App.serviceConfigVersionsMapper = App.QuickDataMapper.create({ App.store.loadMany(this.get('model'), result); console.timeEnd('App.serviceConfigVersionsMapper'); } + }, + + /** + * Conventional method to generate id for instances of <code>App.ServiceConfigVersion</code> model. + * + * @param {String} serviceName + * @param {Number|String} version + * @returns {String} + */ + makeId: function(serviceName, version) { + return serviceName + '_' + version; } + }); http://git-wip-us.apache.org/repos/asf/ambari/blob/b4991a03/ambari-web/app/messages.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js index a990bcd..47aa21f 100644 --- a/ambari-web/app/messages.js +++ b/ambari-web/app/messages.js @@ -906,6 +906,7 @@ Em.I18n.translations = { 'form.validator.alertGroupName':'Invalid Alert Group Name. Only alphanumerics, hyphens, spaces and underscores are allowed.', 'form.validator.alertGroupPlaceHolder':'Alert Group Name', 'form.validator.configKey.specific':'"{0}" is invalid Key. Only alphanumerics, hyphens, underscores, asterisks and periods are allowed.', + 'form.validator.error.trailingSpaces': 'Cannot contain trailing whitespace', 'alerts.add.header': 'Create Alert Definition', 'alerts.add.step1.header': 'Choose Type', http://git-wip-us.apache.org/repos/asf/ambari/blob/b4991a03/ambari-web/app/mixins/common/configs/configs_loader.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/mixins/common/configs/configs_loader.js b/ambari-web/app/mixins/common/configs/configs_loader.js index 5546f6b..3d2fd17 100644 --- a/ambari-web/app/mixins/common/configs/configs_loader.js +++ b/ambari-web/app/mixins/common/configs/configs_loader.js @@ -68,17 +68,22 @@ App.ConfigsLoader = Em.Mixin.create(App.GroupsMappingMixin, { } this.set('allVersionsLoaded', true); if (this.get('preSelectedConfigVersion')) { + var preSelectedId = App.serviceConfigVersionsMapper.makeId(this.get('preSelectedConfigVersion.serviceName'), this.get('preSelectedConfigVersion.version')); + var defaultConfigVersion = App.ServiceConfigVersion.find(App.serviceConfigVersionsMapper.makeId(this.get('content.serviceName'), this.get('currentDefaultVersion'))); + var preSelectedVersion = App.ServiceConfigVersion.find().someProperty('id', preSelectedId) ? this.get('preSelectedConfigVersion') : defaultConfigVersion; + this.set('selectedVersion', this.get('preSelectedConfigVersion.version')); /** handling redirecting from config history page **/ var self = this; this.loadConfigGroups(this.get('servicesToLoad')).done(function() { var selectedGroup = App.ServiceConfigGroup.find().find(function(g) { - return g.get('serviceName') == self.get('preSelectedConfigVersion.serviceName') - && (g.get('name') == self.get('preSelectedConfigVersion.groupName') || (self.get('preSelectedConfigVersion.groupName') == 'default' && g.get('isDefault'))); + return g.get('serviceName') == preSelectedVersion.get('serviceName') + && (g.get('name') == preSelectedVersion.get('groupName') || (preSelectedVersion.get('groupName') == 'default' && g.get('isDefault'))); }); self.set('selectedConfigGroup', selectedGroup); - self.loadSelectedVersion(self.get('preSelectedConfigVersion.version'), selectedGroup); + self.loadSelectedVersion(preSelectedVersion.get('version'), selectedGroup); self.set('preSelectedConfigVersion', null); + preSelectedVersion = null; }); } else { this.set('selectedVersion', this.get('currentDefaultVersion')); http://git-wip-us.apache.org/repos/asf/ambari/blob/b4991a03/ambari-web/app/models/configs/objects/service_config_property.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/models/configs/objects/service_config_property.js b/ambari-web/app/models/configs/objects/service_config_property.js index db88152..15c5451 100644 --- a/ambari-web/app/models/configs/objects/service_config_property.js +++ b/ambari-web/app/models/configs/objects/service_config_property.js @@ -417,6 +417,12 @@ App.ServiceConfigProperty = Em.Object.extend({ if (!validator.isAllowedDir(value)) { this.set('errorMessage', 'Can\'t start with "home(s)"'); isError = true; + } else { + // Invalidate values which end with spaces. + if (value !== ' ' && validator.isNotTrimmedRight(value)) { + this.set('errorMessage', Em.I18n.t('form.validator.error.trailingSpaces')); + isError = true; + } } } break; @@ -445,6 +451,8 @@ App.ServiceConfigProperty = Em.Object.extend({ } } break; + case 'multiLine': + case 'content': case 'advanced': if(this.get('name')=='javax.jdo.option.ConnectionURL' || this.get('name')=='oozie.service.JPAService.jdbc.url') { if (validator.isConfigValueLink(value)) { @@ -453,6 +461,13 @@ App.ServiceConfigProperty = Em.Object.extend({ this.set('errorMessage', Em.I18n.t('host.trimspacesValidation')); isError = true; } + } else { + // Avoid single space values which is work around for validate empty properties. + // Invalidate values which end with spaces. + if (value !== ' ' && validator.isNotTrimmedRight(value)) { + this.set('errorMessage', Em.I18n.t('form.validator.error.trailingSpaces')); + isError = true; + } } break; case 'password': http://git-wip-us.apache.org/repos/asf/ambari/blob/b4991a03/ambari-web/app/utils/config.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/utils/config.js b/ambari-web/app/utils/config.js index 06fa9af..11b2f8e 100644 --- a/ambari-web/app/utils/config.js +++ b/ambari-web/app/utils/config.js @@ -494,6 +494,11 @@ App.config = Em.Object.create({ displayType = Em.get(serviceConfigProperty, 'displayType') || Em.get(serviceConfigProperty, 'valueAttributes.type'), category = Em.get(serviceConfigProperty, 'category'); switch (displayType) { + case 'content': + case 'advanced': + case 'multiLine': + return this.trimProperty({ displayType: displayType, value: value }); + break; case 'directories': if (['DataNode', 'NameNode'].contains(category)) { return value.split(',').sort().join(',');//TODO check if this code is used @@ -612,6 +617,10 @@ App.config = Em.Object.create({ if (['directory' ,'directories'].contains(configData.displayType) && configData.defaultDirectory) { configData.value = configData.defaultDirectory; + } else if (advanced && advanced.get('id')) { + var configValue = this.formatPropertyValue(advanced, advanced.get('value')); + // for property which value is single/multiple spaces set single space as well + configData.value = configData.recommendedValue = /^\s+$/.test("" + configValue) ? " " : configValue; } mergedConfigs.push(configData); http://git-wip-us.apache.org/repos/asf/ambari/blob/b4991a03/ambari-web/app/utils/validator.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/utils/validator.js b/ambari-web/app/utils/validator.js index f00d050..3822c67 100644 --- a/ambari-web/app/utils/validator.js +++ b/ambari-web/app/utils/validator.js @@ -49,7 +49,10 @@ module.exports = { var floatRegex = /^\/[0-9a-z]*/; var winRegex = /^[a-z]:\\[0-9a-zA-Z]*/; var winUrlRegex = /^file:\/\/\/[a-zA-Z]:\/[0-9a-zA-Z]*/; - var dirs = value.replace(/,/g,' ').trim().split(new RegExp("\\s+", "g")); + var dirs = value.split(','); + if (dirs.some(function(i) { return i.startsWith(' '); })) { + return false; + } for(var i = 0; i < dirs.length; i++){ if(!floatRegex.test(dirs[i]) && !winRegex.test(dirs[i]) && !winUrlRegex.test(dirs[i])){ return false; @@ -76,7 +79,10 @@ module.exports = { var dirRegex = /^(\[[0-9a-zA-Z]+\])?(\/[0-9a-z]*)/; var winRegex = /^(\[[0-9a-zA-Z]+\])?[a-zA-Z]:\\[0-9a-zA-Z]*/; var winUrlRegex = /^(\[[0-9a-zA-Z]+\])?file:\/\/\/[a-zA-Z]:\/[0-9a-zA-Z]*/; - var dirs = value.replace(/,/g,' ').trim().split(new RegExp("\\s+", "g")); + var dirs = value.split(','); + if (dirs.some(function (i) {return i.startsWith(' '); })) { + return false; + } for(var i = 0; i < dirs.length; i++){ if(!dirRegex.test(dirs[i]) && !winRegex.test(dirs[i]) && !winUrlRegex.test(dirs[i])){ return false; @@ -129,6 +135,19 @@ module.exports = { var regex = /(^\s+|\s+$)/; return regex.test(value); }, + + /** + * Check if string ends with spaces. + * For multiline content only last line will be checked. + * + * @method isNotTrimmedLeft + * @param {String} value + * @returns {Boolean} - <code>true</code> if ends with spaces + */ + isNotTrimmedRight: function(value) { + return /\s+$/.test(("" + value).split(/\n/).slice(-1)[0]); + }, + /** * validate domain name with port * @param value http://git-wip-us.apache.org/repos/asf/ambari/blob/b4991a03/ambari-web/test/utils/validator_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/utils/validator_test.js b/ambari-web/test/utils/validator_test.js index a28fb2f..5591aee 100644 --- a/ambari-web/test/utils/validator_test.js +++ b/ambari-web/test/utils/validator_test.js @@ -283,8 +283,10 @@ describe('validator', function () { describe('#isValidDir(value)', function() { var tests = [ {m:'"dir" - invalid',i:'dir',e:false}, + {m:'" /dir" - invalid',i:' /dir',e:false}, {m:'"/dir" - valid',i:'/dir',e:true}, {m:'"/dir1,dir2" - invalid',i:'/dir1,dir2',e:false}, + {m:'"/dir1, /dir2" - invalid',i:'/dir1,dir2',e:false}, {m:'"/dir1,/dir2" - valid',i:'/dir1,/dir2',e:true}, {m:'"/123" - valid',i:'/111',e:true}, {m:'"/abc" - valid',i:'/abc',e:true}, @@ -317,6 +319,8 @@ describe('validator', function () { {m:'"/dir" - valid',i:'/dir',e:true}, {m:'"/dir1,dir2" - invalid',i:'/dir1,dir2',e:false}, {m:'"/dir1,/dir2" - valid',i:'/dir1,/dir2',e:true}, + {m:'" /dir1,/dir2" - valid',i:' /dir1,/dir2',e:false}, + {m:'"/dir1, /dir2" - valid',i:' /dir1,/dir2',e:false}, {m:'"/123" - valid',i:'/111',e:true}, {m:'"/abc" - valid',i:'/abc',e:true}, {m:'"/1a2b3c" - valid',i:'/1a2b3c',e:true}, @@ -325,9 +329,8 @@ describe('validator', function () { {m:'"[] /1a2b3c" - invalid',i:'[] /1a2b3c',e:false}, {m:'"[ssd] /1a2b3c" - invalid',i:'[ssd] /1a2b3c',e:false}, {m:'"[/1a2b3c]" - invalid',i:'[/1a2b3c]',e:false}, - {m:'"[s]ss /sd" - invalid',i:'[s]ss /sd',e:false} - - + {m:'"[s]ss /sd" - invalid',i:'[s]ss /sd',e:false}, + {m:'" [s]ss/sd" - invalid',i:' [s]ss/sd',e:false} ]; tests.forEach(function(test) { it(test.m + ' ', function () {
