AMBARI-11075. Apply a property value in hdfs-site when ranger-hdfs-plugin is enabled (alexantonenko)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/81a3eebd Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/81a3eebd Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/81a3eebd Branch: refs/heads/trunk Commit: 81a3eebdd47c4c0179d3af2f5c45baf69a474db7 Parents: 17f4eca Author: Alex Antonenko <hiv...@gmail.com> Authored: Tue May 12 20:30:29 2015 +0300 Committer: Alex Antonenko <hiv...@gmail.com> Committed: Tue May 12 23:48:37 2015 +0300 ---------------------------------------------------------------------- .../utils/configs/modification_handlers/hdfs.js | 18 +++ .../configs/service_configs_by_category_view.js | 89 ++++++----- .../service_configs_by_category_view_test.js | 151 +++++++++++++++++++ ambari-web/test/views/main/host_test.js | 2 +- 4 files changed, 223 insertions(+), 37 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/81a3eebd/ambari-web/app/utils/configs/modification_handlers/hdfs.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/utils/configs/modification_handlers/hdfs.js b/ambari-web/app/utils/configs/modification_handlers/hdfs.js index 128b62b..bff1ddd 100644 --- a/ambari-web/app/utils/configs/modification_handlers/hdfs.js +++ b/ambari-web/app/utils/configs/modification_handlers/hdfs.js @@ -34,9 +34,12 @@ module.exports = App.ServiceConfigModificationHandler.create({ var affectedPropertyName = changedConfig.get("name"); if (affectedPropertyName == rangerPluginEnabledName) { var configDfsPermissionsEnabled = this.getConfig(allConfigs, 'dfs.permissions.enabled', 'hdfs-site.xml', 'HDFS'); + var configAttributesProviderClass = this.getConfig(allConfigs, 'dfs.namenode.inode.attributes.provider.class', 'hdfs-site.xml', 'HDFS'); + var isAttributesProviderClassSet = typeof configAttributesProviderClass !== 'undefined'; var rangerPluginEnabled = newValue == "Yes"; var newDfsPermissionsEnabled = rangerPluginEnabled ? "true" : "true"; + var newAttributesProviderClass = 'org.apache.ranger.authorization.hadoop.RangerHdfsAuthorizer'; // Add Hive-Ranger configs if (configDfsPermissionsEnabled != null && newDfsPermissionsEnabled !== configDfsPermissionsEnabled.get('value')) { @@ -52,6 +55,21 @@ module.exports = App.ServiceConfigModificationHandler.create({ filename : 'hdfs-site.xml' }); } + if (rangerPluginEnabled && (!isAttributesProviderClassSet || newAttributesProviderClass != configAttributesProviderClass.get('value'))) { + affectedProperties.push({ + serviceName : "HDFS", + sourceServiceName : "HDFS", + propertyName : 'dfs.namenode.inode.attributes.provider.class', + propertyDisplayName : 'dfs.namenode.inode.attributes.provider.class', + newValue : newAttributesProviderClass, + curValue : isAttributesProviderClassSet ? configAttributesProviderClass.get('value') : '', + changedPropertyName : rangerPluginEnabledName, + removed : false, + isNewProperty : !isAttributesProviderClassSet, + filename : 'hdfs-site.xml', + categoryName: 'Custom hdfs-site' + }); + } } return affectedProperties; } http://git-wip-us.apache.org/repos/asf/ambari/blob/81a3eebd/ambari-web/app/views/common/configs/service_configs_by_category_view.js ---------------------------------------------------------------------- diff --git a/ambari-web/app/views/common/configs/service_configs_by_category_view.js b/ambari-web/app/views/common/configs/service_configs_by_category_view.js index 85402f0..ab2a498 100644 --- a/ambari-web/app/views/common/configs/service_configs_by_category_view.js +++ b/ambari-web/app/views/common/configs/service_configs_by_category_view.js @@ -162,9 +162,20 @@ App.ServiceConfigsByCategoryView = Em.View.extend(App.UserPref, App.ConfigOverri header: "Warning: you must also change these Service properties", onApply: function () { self.get("newAffectedProperties").forEach(function(item) { - self.get("controller.stepConfigs").findProperty("serviceName", item.serviceName).get("configs").find(function(config) { - return item.propertyName == config.get('name') && (item.filename == null || item.filename == config.get('filename')); - }).set("value", item.newValue); + if (item.isNewProperty) { + self.createProperty({ + name: item.propertyName, + displayName: item.propertyDisplayName, + value: item.newValue, + categoryName: item.categoryName, + serviceName: item.serviceName, + filename: item.filename + }); + } else { + self.get("controller.stepConfigs").findProperty("serviceName", item.serviceName).get("configs").find(function(config) { + return item.propertyName == config.get('name') && (item.filename == null || item.filename == config.get('filename')); + }).set("value", item.newValue); + } }); self.get("controller").set("miscModalVisible", false); this.hide(); @@ -354,6 +365,34 @@ App.ServiceConfigsByCategoryView = Em.View.extend(App.UserPref, App.ConfigOverri return 'admin-bulk-add-properties-' + App.router.get('loginName'); }, + isSecureConfig: function (configName, filename) { + var secureConfigs = this.get('controller.secureConfigs').filterProperty('filename', filename); + return !!secureConfigs.findProperty('name', configName); + }, + + createProperty: function (propertyObj) { + var selectedConfigGroup = this.get('controller.selectedConfigGroup'), + isSecureConfig = this.isSecureConfig(propertyObj.name, propertyObj.filename); + this.get('serviceConfigs').pushObject(App.ServiceConfigProperty.create({ + name: propertyObj.name, + displayName: propertyObj.displayName || propertyObj.name, + value: propertyObj.value, + displayType: stringUtils.isSingleLine(propertyObj.value) ? 'advanced' : 'multiLine', + isSecureConfig: isSecureConfig, + category: propertyObj.categoryName, + id: 'site property', + serviceName: propertyObj.serviceName, + defaultValue: null, + supportsFinal: App.config.shouldSupportFinal(propertyObj.serviceName, propertyObj.filename), + filename: propertyObj.filename || '', + isUserProperty: true, + isNotSaved: true, + isRequired: false, + group: selectedConfigGroup.get('isDefault') ? null : selectedConfigGroup, + isOverridable: selectedConfigGroup.get('isDefault') + })); + }, + /** * Show popup for adding new config-properties * @method showAddPropertyWindow @@ -375,44 +414,13 @@ App.ServiceConfigsByCategoryView = Em.View.extend(App.UserPref, App.ConfigOverri var service = this.get('service'); var serviceName = service.get('serviceName'); - var secureConfigs = this.get('controller.secureConfigs').filterProperty('filename', siteFileName); - - function isSecureConfig(configName) { - return !!secureConfigs.findProperty('name', configName); - } - var configsOfFile = service.get('configs').filterProperty('filename', siteFileName); var siteFileProperties = App.config.get('configMapping').all().filterProperty('filename', siteFileName); - var supportsFinal = App.config.shouldSupportFinal(serviceName, siteFileName); - function isDuplicatedConfigKey(name) { return siteFileProperties.findProperty('name', name) || configsOfFile.findProperty('name', name); } - var serviceConfigs = this.get('serviceConfigs'); - - function createProperty(propertyName, propertyValue) { - serviceConfigs.pushObject(App.ServiceConfigProperty.create({ - name: propertyName, - displayName: propertyName, - value: propertyValue, - displayType: stringUtils.isSingleLine(propertyValue) ? 'advanced' : 'multiLine', - isSecureConfig: isSecureConfig(propertyName), - category: category.get('name'), - id: 'site property', - serviceName: serviceName, - defaultValue: null, - supportsFinal: supportsFinal, - filename: siteFileName || '', - isUserProperty: true, - isNotSaved: true, - isRequired: false, - group: selectedConfigGroup.get('isDefault') ? null : selectedConfigGroup, - isOverridable: selectedConfigGroup.get('isDefault') - })); - } - var serviceConfigObj = Ember.Object.create({ isBulkMode: isBulkMode, bulkConfigValue: '', @@ -501,6 +509,11 @@ App.ServiceConfigsByCategoryView = Em.View.extend(App.UserPref, App.ConfigOverri primary: 'Add', secondary: 'Cancel', onPrimary: function () { + var propertyObj = { + filename: siteFileName, + serviceName: serviceName, + categoryName: category.get('name') + }; if (serviceConfigObj.isBulkMode) { var popup = this; processConfig(serviceConfigObj.bulkConfigValue, function (error, parsedConfig) { @@ -510,7 +523,9 @@ App.ServiceConfigsByCategoryView = Em.View.extend(App.UserPref, App.ConfigOverri } else { for (var key in parsedConfig) { if (parsedConfig.hasOwnProperty(key)) { - createProperty(key, parsedConfig[key]); + propertyObj.name = key; + propertyObj.value = parsedConfig[key]; + persistController.createProperty(propertyObj); } } popup.hide(); @@ -523,7 +538,9 @@ App.ServiceConfigsByCategoryView = Em.View.extend(App.UserPref, App.ConfigOverri * For the first entrance use this if (serviceConfigObj.name.trim() != '') */ if (!serviceConfigObj.isKeyError) { - createProperty(serviceConfigObj.get('name'), serviceConfigObj.get('value')); + propertyObj.name = serviceConfigObj.get('name'); + propertyObj.value = serviceConfigObj.get('value'); + persistController.createProperty(propertyObj); this.hide(); } } http://git-wip-us.apache.org/repos/asf/ambari/blob/81a3eebd/ambari-web/test/views/common/configs/service_configs_by_category_view_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/views/common/configs/service_configs_by_category_view_test.js b/ambari-web/test/views/common/configs/service_configs_by_category_view_test.js index 6505cf0..aeae18b 100644 --- a/ambari-web/test/views/common/configs/service_configs_by_category_view_test.js +++ b/ambari-web/test/views/common/configs/service_configs_by_category_view_test.js @@ -370,4 +370,155 @@ describe('App.ServiceConfigsByCategoryView', function () { }); }); + describe('#isSecureConfig', function () { + + var cases = [ + { + name: 'n0', + filename: 'f0', + isSecureConfig: true, + title: 'secure config' + }, + { + name: 'n1', + filename: 'f1', + isSecureConfig: false, + title: 'secure config with the same name is present in another filename' + }, + { + name: 'n2', + filename: 'f2', + isSecureConfig: false, + title: 'no configs of the specified filename are secure' + } + ]; + + before(function () { + view.reopen({ + controller: { + secureConfigs: [ + { + name: 'n0', + filename: 'f0' + }, + { + name: 'n1', + filename: 'f0' + }, + { + name: 'n2', + filename: 'f1' + } + ] + } + }) + }); + + cases.forEach(function (item) { + it(item.title, function () { + expect(view.isSecureConfig(item.name, item.filename)).to.equal(item.isSecureConfig); + }); + }); + + }); + + describe('#createProperty', function () { + + var cases = [ + { + propertyObj: { + name: 'n0', + displayName: 'd0', + value: 'v0', + filename: 'f0', + categoryName: 'c0', + serviceName: 's0' + }, + isDefaultConfigGroup: true, + result: { + name: 'n0', + displayName: 'd0', + value: 'v0', + displayType: 'advanced', + isSecureConfig: true, + category: 'c0', + id: 'site property', + serviceName: 's0', + defaultValue: null, + supportsFinal: true, + filename: 'f0', + isUserProperty: true, + isNotSaved: true, + isRequired: false, + group: null, + isOverridable: true + }, + title: 'single line value, secure config, final attribute supported, default config group' + }, + { + propertyObj: { + name: 'n1', + value: 'v\n1', + filename: '', + categoryName: 'c1', + serviceName: 's1' + }, + isDefaultConfigGroup: false, + result: { + name: 'n1', + displayName: 'n1', + value: 'v\n1', + displayType: 'multiLine', + isSecureConfig: false, + category: 'c1', + id: 'site property', + serviceName: 's1', + defaultValue: null, + supportsFinal: false, + filename: '', + isUserProperty: true, + isNotSaved: true, + isRequired: false, + group: Em.Object.create({ + isDefault: false + }), + isOverridable: false + }, + title: 'multiline value, non-secure config, no display name and filename, final attribute not supported, custom config group' + } + ]; + + before(function () { + view.get('serviceConfigs').clear(); + sinon.stub(view, 'isSecureConfig').withArgs('n0', 'f0').returns(true).withArgs('n1', '').returns(false); + sinon.stub(App.config, 'shouldSupportFinal').withArgs('s0', 'f0').returns(true).withArgs('s1', '').returns(false); + }); + + after(function () { + view.get('serviceConfigs').clear(); + view.isSecureConfig.restore(); + App.config.shouldSupportFinal.restore(); + }); + + cases.forEach(function (item) { + it(item.title, function () { + view.reopen({ + filteredCategoryConfigs: [], + controller: { + selectedConfigGroup: Em.Object.create({ + isDefault: item.isDefaultConfigGroup + }) + } + }); + view.createProperty(item.propertyObj); + expect(view.get('serviceConfigs').filterProperty('name', item.propertyObj.name)).to.have.length(1); + expect(view.get('serviceConfigs').findProperty('name', item.propertyObj.name).getProperties([ + 'name', 'displayName', 'value', 'displayType', 'isSecureConfig', 'category', 'id', 'serviceName', 'defaultValue', + 'supportsFinal', 'filename', 'isUserProperty', 'isNotSaved', 'isRequired', 'group', 'isOverridable' + ])).to.eql(item.result); + }); + }); + + }); + }); http://git-wip-us.apache.org/repos/asf/ambari/blob/81a3eebd/ambari-web/test/views/main/host_test.js ---------------------------------------------------------------------- diff --git a/ambari-web/test/views/main/host_test.js b/ambari-web/test/views/main/host_test.js index 28871b7..8a0624b 100644 --- a/ambari-web/test/views/main/host_test.js +++ b/ambari-web/test/views/main/host_test.js @@ -98,7 +98,7 @@ describe('App.MainHostView', function () { view.updatePagination.restore(); }); - it('should execute and updatePagination', function () { + it('should execute updatePagination', function () { view.updateHostsPagination(); expect(view.updatePagination.calledOnce).to.be.true; });