You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by al...@apache.org on 2016/07/26 08:30:05 UTC
ambari git commit: AMBARI-17041. Support password type for custom
properties (alexantonenko)
Repository: ambari
Updated Branches:
refs/heads/trunk 08644fa7c -> 2fb19c7b1
AMBARI-17041. Support password type for custom properties (alexantonenko)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/2fb19c7b
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/2fb19c7b
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/2fb19c7b
Branch: refs/heads/trunk
Commit: 2fb19c7b1a0497a40df8d11e7d426190836d6a24
Parents: 08644fa
Author: Alex Antonenko <hi...@gmail.com>
Authored: Tue Jul 26 11:29:37 2016 +0300
Committer: Alex Antonenko <hi...@gmail.com>
Committed: Tue Jul 26 11:30:00 2016 +0300
----------------------------------------------------------------------
.../AmbariManagementControllerImpl.java | 35 ++++++++++++----
.../controller/ConfigurationResponse.java | 2 +
.../ambari/server/utils/SecretReference.java | 23 +++++++++++
ambari-web/app/messages.js | 1 +
.../app/mixins/common/configs/configs_saver.js | 9 +++-
.../configs/objects/service_config_property.js | 7 ++++
.../common/configs/addPropertyWindow.hbs | 12 ++++++
ambari-web/app/utils/config.js | 27 ++++++++++--
.../configs/service_configs_by_category_view.js | 5 +++
.../mixins/common/configs/configs_saver_test.js | 43 ++++++++++++++++++--
10 files changed, 149 insertions(+), 15 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/2fb19c7b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
index aba45bf..075b85a 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java
@@ -224,6 +224,8 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
private static final String BASE_LOG_DIR = "/tmp/ambari";
+ private static final String PASSWORD = "password";
+
private final Clusters clusters;
private final ActionManager actionManager;
@@ -810,6 +812,25 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
Map<String, String> requestProperties = request.getProperties();
+ // Configuration attributes are optional. If not present, use default(provided by stack), otherwise merge default
+ // with request-provided
+ Map<String, Map<String, String>> requestPropertiesAttributes = request.getPropertiesAttributes();
+
+ if (requestPropertiesAttributes != null && requestPropertiesAttributes.containsKey(PASSWORD)) {
+ for (Map.Entry<String, String> requestEntry : requestPropertiesAttributes.get(PASSWORD).entrySet()) {
+ String passwordProperty = requestEntry.getKey();
+ if(requestProperties.containsKey(passwordProperty) && requestEntry.getValue().equals("true")) {
+ String passwordPropertyValue = requestProperties.get(passwordProperty);
+ if (!SecretReference.isSecret(passwordPropertyValue)) {
+ continue;
+ }
+ SecretReference ref = new SecretReference(passwordPropertyValue, cluster);
+ String refValue = ref.getValue();
+ requestProperties.put(passwordProperty, refValue);
+ }
+ }
+ }
+
Map<PropertyInfo.PropertyType, Set<String>> propertiesTypes = cluster.getConfigPropertiesTypes(request.getType());
if(propertiesTypes.containsKey(PropertyType.PASSWORD)) {
for(String passwordProperty : propertiesTypes.get(PropertyType.PASSWORD)) {
@@ -833,10 +854,6 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
configs = new HashMap<String, Config>();
}
- // Configuration attributes are optional. If not present, use default(provided by stack), otherwise merge default
- // with request-provided
- Map<String, Map<String, String>> requestPropertiesAttributes = request.getPropertiesAttributes();
-
Map<String, Map<String, String>> propertiesAttributes = new HashMap<String, Map<String,String>>();
StackId currentStackId = cluster.getCurrentStackVersion();
@@ -1531,6 +1548,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
if (request.getDesiredConfig() != null) {
for (ConfigurationRequest desiredConfig : request.getDesiredConfig()) {
Map<String, String> requestConfigProperties = desiredConfig.getProperties();
+ Map<String,Map<String,String>> requestConfigAttributes = desiredConfig.getPropertiesAttributes();
// processing password properties
if(requestConfigProperties != null && !requestConfigProperties.isEmpty()) {
@@ -1540,8 +1558,11 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
for (Entry<String, String> property : requestConfigProperties.entrySet()) {
String propertyName = property.getKey();
String propertyValue = property.getValue();
- if (propertiesTypes.containsKey(PropertyType.PASSWORD) &&
- propertiesTypes.get(PropertyType.PASSWORD).contains(propertyName)) {
+ if ((propertiesTypes.containsKey(PropertyType.PASSWORD) &&
+ propertiesTypes.get(PropertyType.PASSWORD).contains(propertyName)) ||
+ (requestConfigAttributes != null && requestConfigAttributes.containsKey(PASSWORD) &&
+ requestConfigAttributes.get(PASSWORD).containsKey(propertyName) &&
+ requestConfigAttributes.get(PASSWORD).get(propertyName).equals("true"))) {
if (SecretReference.isSecret(propertyValue)) {
SecretReference ref = new SecretReference(propertyValue, cluster);
requestConfigProperties.put(propertyName, ref.getValue());
@@ -1549,7 +1570,7 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle
}
}
}
- Map<String,Map<String,String>> requestConfigAttributes = desiredConfig.getPropertiesAttributes();
+
Config clusterConfig = cluster.getDesiredConfigByType(desiredConfig.getType());
Map<String, String> clusterConfigProperties = null;
Map<String,Map<String,String>> clusterConfigAttributes = null;
http://git-wip-us.apache.org/repos/asf/ambari/blob/2fb19c7b/ambari-server/src/main/java/org/apache/ambari/server/controller/ConfigurationResponse.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ConfigurationResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ConfigurationResponse.java
index eef3474..8632c09 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ConfigurationResponse.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ConfigurationResponse.java
@@ -63,6 +63,7 @@ public class ConfigurationResponse {
this.version = version;
this.configs = configs;
this.configAttributes = configAttributes;
+ SecretReference.replacePasswordsWithReferencesForCustomProperties(configAttributes, configs, type, version);
}
public ConfigurationResponse(String clusterName, StackId stackId,
@@ -80,6 +81,7 @@ public class ConfigurationResponse {
this.configAttributes = configAttributes;
this.propertiesTypes = propertiesTypes;
SecretReference.replacePasswordsWithReferences(propertiesTypes, configs, type, version);
+ SecretReference.replacePasswordsWithReferencesForCustomProperties(configAttributes, configs, type, version);
}
/**
http://git-wip-us.apache.org/repos/asf/ambari/blob/2fb19c7b/ambari-server/src/main/java/org/apache/ambari/server/utils/SecretReference.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/utils/SecretReference.java b/ambari-server/src/main/java/org/apache/ambari/server/utils/SecretReference.java
index 84f3109..9788569 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/utils/SecretReference.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/utils/SecretReference.java
@@ -148,4 +148,27 @@ public class SecretReference {
}
}
}
+
+ /**
+ * Replace real passwords with secret references
+ * @param configAttributes map with config attributes containing properties types as part of their content
+ * @param propertiesMap map with properties in which replacement will be performed
+ * @param configType configuration type
+ * @param configVersion configuration version
+ */
+ public static void replacePasswordsWithReferencesForCustomProperties(Map<String, Map<String, String>> configAttributes,
+ Map<String, String> propertiesMap,
+ String configType,
+ Long configVersion){
+ if(configAttributes != null && configAttributes.containsKey("password")) {
+ for(String pwdPropertyName: configAttributes.get("password").keySet()) {
+ if(propertiesMap.containsKey(pwdPropertyName)){
+ if(!propertiesMap.get(pwdPropertyName).equals("")) {
+ String stub = SecretReference.generateStub(configType, configVersion, pwdPropertyName);
+ propertiesMap.put(pwdPropertyName, stub);
+ }
+ }
+ }
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/2fb19c7b/ambari-web/app/messages.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/messages.js b/ambari-web/app/messages.js
index c768749..c6aa350 100644
--- a/ambari-web/app/messages.js
+++ b/ambari-web/app/messages.js
@@ -313,6 +313,7 @@ Em.I18n.translations = {
'common.timezone': 'Timezone',
'common.loading.eclipses': 'Loading...',
'common.optional': 'Optional',
+ 'common.propertyType': 'Property Type',
'common.running': 'Running',
'common.stopped': 'Stopped',
'common.enter': 'Enter',
http://git-wip-us.apache.org/repos/asf/ambari/blob/2fb19c7b/ambari-web/app/mixins/common/configs/configs_saver.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/mixins/common/configs/configs_saver.js b/ambari-web/app/mixins/common/configs/configs_saver.js
index 43a77ce..832ec3a 100644
--- a/ambari-web/app/mixins/common/configs/configs_saver.js
+++ b/ambari-web/app/mixins/common/configs/configs_saver.js
@@ -454,7 +454,7 @@ App.ConfigsSaverMixin = Em.Mixin.create({
if (!ignoreVersionNote) {
desired_config.service_config_version_note = serviceConfigNote || "";
}
- var attributes = { final: {} };
+ var attributes = { final: {}, password: {}, user: {}, group: {}, text: {}, additional_user_property: {}, not_managed_hdfs_path: {}, value_from_property_file: {} };
if (Em.isArray(properties)) {
properties.forEach(function(property) {
@@ -466,11 +466,16 @@ App.ConfigsSaverMixin = Em.Mixin.create({
if (Em.get(property, 'isFinal')) {
attributes.final[Em.get(property, 'name')] = "true";
}
+ if (Em.get(property,'propertyType') != null) {
+ Em.get(property,'propertyType').map(function(propType) {
+ attributes[propType.toLowerCase()][Em.get(property,'name')] = "true";
+ });
+ }
}
}, this);
}
- if (Object.keys(attributes.final).length) {
+ if (Object.keys(attributes.final).length || Object.keys(attributes.password).length) {
desired_config.properties_attributes = attributes;
}
return desired_config;
http://git-wip-us.apache.org/repos/asf/ambari/blob/2fb19c7b/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 844806f..becbd19b 100644
--- a/ambari-web/app/models/configs/objects/service_config_property.js
+++ b/ambari-web/app/models/configs/objects/service_config_property.js
@@ -95,6 +95,13 @@ App.ServiceConfigProperty = Em.Object.extend({
rightSideLabel: false,
/**
+ * type of property
+ * @type {String[]}
+ * @default empty array
+ */
+ propertyType: [],
+
+ /**
* Text to be shown as placeholder
* By default savedValue is shown as placeholder
* @type {String}
http://git-wip-us.apache.org/repos/asf/ambari/blob/2fb19c7b/ambari-web/app/templates/common/configs/addPropertyWindow.hbs
----------------------------------------------------------------------
diff --git a/ambari-web/app/templates/common/configs/addPropertyWindow.hbs b/ambari-web/app/templates/common/configs/addPropertyWindow.hbs
index 659435c..1d41b04 100644
--- a/ambari-web/app/templates/common/configs/addPropertyWindow.hbs
+++ b/ambari-web/app/templates/common/configs/addPropertyWindow.hbs
@@ -87,5 +87,17 @@
{{view Ember.TextArea valueBinding="view.serviceConfigObj.value" rows="4" classNames="input-block-level"}}
</div>
</div>
+ <div class="each-row control-group">
+ <label class="control-label">{{t common.propertyType}}</label>
+
+ <div class="controls">
+ {{view Em.Select
+ classNames="input-block-level"
+ multiple="multiple"
+ contentBinding="view.serviceConfigObj.content"
+ selectionBinding="view.serviceConfigObj.propertyType"
+ }}
+ </div>
+ </div>
{{/if}}
</form>
http://git-wip-us.apache.org/repos/asf/ambari/blob/2fb19c7b/ambari-web/app/utils/config.js
----------------------------------------------------------------------
diff --git a/ambari-web/app/utils/config.js b/ambari-web/app/utils/config.js
index 9bb977a..20202e4 100644
--- a/ambari-web/app/utils/config.js
+++ b/ambari-web/app/utils/config.js
@@ -22,6 +22,7 @@ var stringUtils = require('utils/string_utils');
var validator = require('utils/validator');
var configTagFromFileNameMap = {};
+var PASSWORD = "PASSWORD";
App.config = Em.Object.create({
@@ -237,14 +238,34 @@ App.config = Em.Object.create({
var configs = [],
filename = App.config.getOriginalFileName(configJSON.type),
properties = configJSON.properties,
- finalAttributes = Em.get(configJSON, 'properties_attributes.final') || {};
+ attributes = [];
+ ['FINAL', 'PASSWORD', 'USER', 'GROUP', 'TEXT', 'ADDITIONAL_USER_PROPERTY', 'NOT_MANAGED_HDFS_PATH', 'VALUE_FROM_PROPERTY_FILE'].forEach(function (attribute){
+ var json = {};
+ json[attribute] = Em.get(configJSON, 'properties_attributes.' + attribute.toLowerCase()) || {};
+ attributes.push(json);
+ });
for (var index in properties) {
var serviceConfigObj = this.getDefaultConfig(index, filename);
if (serviceConfigObj.isRequiredByAgent !== false) {
serviceConfigObj.value = serviceConfigObj.savedValue = this.formatPropertyValue(serviceConfigObj, properties[index]);
- serviceConfigObj.isFinal = serviceConfigObj.savedIsFinal = finalAttributes[index] === "true";
+ serviceConfigObj.isFinal = serviceConfigObj.savedIsFinal = attributes[0]['FINAL'][index] === "true";
+
+ var propertyType = [];
+ // iterate through all the attributes, except for FINAL
+ for (var i=1; i<attributes.length; i++) {
+ for (var type in attributes[i]) {
+ if (attributes[i][type][index] === "true") {
+ propertyType.push(type);
+
+ if (type === PASSWORD) {
+ serviceConfigObj.displayType = "password";
+ }
+ }
+ }
+ }
+ serviceConfigObj.propertyType = propertyType;
serviceConfigObj.isEditable = serviceConfigObj.isReconfigurable;
}
@@ -305,7 +326,7 @@ App.config = Em.Object.create({
supportsAddingForbidden: this.shouldSupportAddingForbidden(serviceName, fileName),
serviceName: serviceName,
displayName: name,
- displayType: this.getDefaultDisplayType(coreObject ? coreObject.value : ''),
+ displayType: (coreObject && coreObject.propertyType && coreObject.propertyType.contains(PASSWORD)) ? 'password' : this.getDefaultDisplayType(coreObject ? coreObject.value : ''),
description: '',
category: this.getDefaultCategory(definedInStack, fileName),
isSecureConfig: this.getIsSecure(name),
http://git-wip-us.apache.org/repos/asf/ambari/blob/2fb19c7b/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 ad1a2f9..579348a 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
@@ -346,6 +346,7 @@ App.ServiceConfigsByCategoryView = Em.View.extend(App.UserPref, App.ConfigOverri
if (selectedConfigGroup.get('isDefault')) {
config = App.config.createDefaultConfig(propertyObj.name, propertyObj.filename, false, {
value: propertyObj.value,
+ propertyType: propertyObj.propertyType,
category: propertyObj.categoryName,
isNotSaved: true
});
@@ -354,6 +355,7 @@ App.ServiceConfigsByCategoryView = Em.View.extend(App.UserPref, App.ConfigOverri
propertyName: propertyObj.name,
filename: propertyObj.filename,
value: propertyObj.value,
+ propertyType: propertyObj.propertyType,
category: propertyObj.categoryName,
isNotSaved: true
}, selectedConfigGroup);
@@ -416,6 +418,8 @@ App.ServiceConfigsByCategoryView = Em.View.extend(App.UserPref, App.ConfigOverri
name: '',
value: '',
+ propertyType: [],
+ content: ['PASSWORD', 'USER', 'GROUP', 'TEXT', 'ADDITIONAL_USER_PROPERTY', 'NOT_MANAGED_HDFS_PATH', 'VALUE_FROM_PROPERTY_FILE'],
isKeyError: false,
showFilterLink: false,
errorMessage: '',
@@ -540,6 +544,7 @@ App.ServiceConfigsByCategoryView = Em.View.extend(App.UserPref, App.ConfigOverri
if (!serviceConfigObj.isKeyError) {
propertyObj.name = serviceConfigObj.get('name');
propertyObj.value = serviceConfigObj.get('value');
+ propertyObj.propertyType = serviceConfigObj.get('propertyType');
persistController.createProperty(propertyObj);
this.hide();
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/2fb19c7b/ambari-web/test/mixins/common/configs/configs_saver_test.js
----------------------------------------------------------------------
diff --git a/ambari-web/test/mixins/common/configs/configs_saver_test.js b/ambari-web/test/mixins/common/configs/configs_saver_test.js
index 4baf303..74e630b 100644
--- a/ambari-web/test/mixins/common/configs/configs_saver_test.js
+++ b/ambari-web/test/mixins/common/configs/configs_saver_test.js
@@ -150,17 +150,54 @@ describe('App.ConfigsSaverMixin', function() {
})
});
- it('generates config with final', function() {
- expect(instanceObject.createDesiredConfig('type1', 'version1', [Em.Object.create({name: 'p1', value: 'v1', isFinal: true, isRequiredByAgent: true}), Em.Object.create({name: 'p2', value: 'v2', isRequiredByAgent: true})], "note")).to.eql({
+ it('generates config with final, password, user, group, text, additional_user_property, not_managed_hdfs_path, value_from_property_file', function() {
+ expect(instanceObject.createDesiredConfig('type1', 'version1', [
+ Em.Object.create({name: 'p1', value: 'v1', isFinal: true, isRequiredByAgent: true}),
+ Em.Object.create({name: 'p2', value: 'v2', isRequiredByAgent: true}),
+ Em.Object.create({name: 'p3', value: 'v3', isRequiredByAgent: true, propertyType: ["PASSWORD", "USER", "GROUP"]}),
+ Em.Object.create({name: 'p4', value: 'v4', isRequiredByAgent: true, propertyType: ["PASSWORD", "TEXT", "ADDITIONAL_USER_PROPERTY"]}),
+ Em.Object.create({name: 'p5', value: 'v5', isRequiredByAgent: true, propertyType: ["NOT_MANAGED_HDFS_PATH"]}),
+ Em.Object.create({name: 'p6', value: 'v6', isRequiredByAgent: true, propertyType: ["TEXT", "VALUE_FROM_PROPERTY_FILE"]}),
+ Em.Object.create({name: 'p7', value: 'v7', isRequiredByAgent: true, propertyType: ["PASSWORD"]})
+ ], "note")).to.eql({
"type": 'type1',
"tag": 'version1',
"properties": {
p1: 'v1',
- p2: 'v2'
+ p2: 'v2',
+ p3: 'v3',
+ p4: 'v4',
+ p5: 'v5',
+ p6: 'v6',
+ p7: 'v7'
},
"properties_attributes": {
final: {
'p1': "true"
+ },
+ password: {
+ "p3": "true",
+ "p4": "true",
+ "p7": "true"
+ },
+ user: {
+ "p3": "true"
+ },
+ group: {
+ "p3": "true"
+ },
+ text: {
+ "p4": "true",
+ "p6": "true"
+ },
+ additional_user_property: {
+ "p4": "true"
+ },
+ not_managed_hdfs_path: {
+ "p5": "true"
+ },
+ value_from_property_file: {
+ "p6": "true"
}
},
"service_config_version_note": 'note'