Repository: ambari Updated Branches: refs/heads/trunk 354b0a975 -> 7d70695a0
AMBARI-15592: Auto-start services - support blueprint deployment Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/7d70695a Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/7d70695a Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/7d70695a Branch: refs/heads/trunk Commit: 7d70695a0d80189ef7f72184d1908997afa694b4 Parents: 354b0a9 Author: Nahappan Somasundaram <[email protected]> Authored: Tue Mar 29 19:12:05 2016 -0700 Committer: Nahappan Somasundaram <[email protected]> Committed: Thu Mar 31 11:48:57 2016 -0700 ---------------------------------------------------------------------- .../server/orm/entities/BlueprintEntity.java | 21 +++ .../orm/entities/BlueprintSettingEntity.java | 142 ++++++++++++++++++ .../ambari/server/topology/AmbariContext.java | 3 +- .../ambari/server/topology/Blueprint.java | 20 +++ .../server/topology/BlueprintFactory.java | 7 +- .../ambari/server/topology/BlueprintImpl.java | 118 ++++++++++++++- .../apache/ambari/server/topology/Setting.java | 75 ++++++++++ .../ambari/server/topology/SettingFactory.java | 101 +++++++++++++ .../server/upgrade/UpgradeCatalog240.java | 55 +++++-- .../main/resources/Ambari-DDL-Derby-CREATE.sql | 11 ++ .../main/resources/Ambari-DDL-MySQL-CREATE.sql | 10 ++ .../main/resources/Ambari-DDL-Oracle-CREATE.sql | 10 ++ .../resources/Ambari-DDL-Postgres-CREATE.sql | 13 +- .../Ambari-DDL-Postgres-EMBEDDED-CREATE.sql | 14 +- .../resources/Ambari-DDL-SQLAnywhere-CREATE.sql | 10 ++ .../resources/Ambari-DDL-SQLServer-CREATE.sql | 13 +- .../src/main/resources/META-INF/persistence.xml | 1 + .../src/main/resources/properties.json | 3 +- .../orm/entities/BlueprintEntityTest.java | 11 ++ .../entities/BlueprintSettingEntityTest.java | 72 +++++++++ .../server/topology/SettingFactoryTest.java | 149 +++++++++++++++++++ .../ambari/server/topology/SettingTest.java | 99 ++++++++++++ .../server/upgrade/UpgradeCatalog240Test.java | 35 ++++- 23 files changed, 968 insertions(+), 25 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintEntity.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintEntity.java index 8578d6b..94b59da 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintEntity.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintEntity.java @@ -71,6 +71,9 @@ public class BlueprintEntity { @OneToMany(cascade = CascadeType.ALL, mappedBy = "blueprint") private Collection<BlueprintConfigEntity> configurations; + @OneToMany(cascade = CascadeType.ALL, mappedBy = "blueprint") + private Collection<BlueprintSettingEntity> settings; + /** * Get the blueprint name. @@ -145,6 +148,24 @@ public class BlueprintEntity { this.configurations = configurations; } + /** + * Get the collection of associated setting. + * + * @return collection of setting + */ + public Collection<BlueprintSettingEntity> getSettings() { + return settings; + } + + /** + * Set the settings collection. + * + * @param settings collection of associated setting + */ + public void setSettings(Collection<BlueprintSettingEntity> settings) { + this.settings = settings; + } + public SecurityType getSecurityType() { return securityType; } http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintSettingEntity.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintSettingEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintSettingEntity.java new file mode 100644 index 0000000..776e5e9 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/BlueprintSettingEntity.java @@ -0,0 +1,142 @@ +/** + * 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. + */ + +package org.apache.ambari.server.orm.entities; + +import javax.persistence.Basic; +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.Lob; +import javax.persistence.ManyToOne; +import javax.persistence.Table; +import javax.persistence.TableGenerator; +import javax.persistence.UniqueConstraint; + +/** + * Represents a blueprint setting. + */ +@Table(name = "blueprint_setting", uniqueConstraints = +@UniqueConstraint( + name = "UQ_blueprint_setting_name", columnNames = {"blueprint_name", "setting_name"} + ) +) + +@TableGenerator(name = "blueprint_setting_id_generator", + table = "ambari_sequences", pkColumnName = "sequence_name", valueColumnName = "sequence_value", + pkColumnValue = "blueprint_setting_id_seq", initialValue = 0) + +@Entity +public class BlueprintSettingEntity { + + @Id + @Column(name = "id", nullable = false, insertable = true, updatable = false) + @GeneratedValue(strategy = GenerationType.TABLE, generator = "blueprint_setting_id_generator") + private long id; + + @Column(name = "blueprint_name", nullable = false, insertable = false, updatable = false) + private String blueprintName; + + @Column(name = "setting_name", nullable = false, insertable = true, updatable = false) + private String settingName; + + @Column(name = "setting_data", nullable = false, insertable = true, updatable = false) + @Basic(fetch = FetchType.LAZY) + @Lob + private String settingData; + + @ManyToOne + @JoinColumn(name = "blueprint_name", referencedColumnName = "blueprint_name", nullable = false) + private BlueprintEntity blueprint; + + /** + * Get the blueprint entity instance. + * + * @return blueprint entity + */ + public BlueprintEntity getBlueprintEntity() { + return blueprint; + } + + /** + * Set the blueprint entity instance. + * + * @param entity blueprint entity + */ + public void setBlueprintEntity(BlueprintEntity entity) { + this.blueprint = entity; + } + + /** + * Get the name of the associated blueprint. + * + * @return blueprint name + */ + public String getBlueprintName() { + return blueprintName; + } + + /** + * Set the name of the associated blueprint. + * ' + * @param blueprintName blueprint name + */ + public void setBlueprintName(String blueprintName) { + this.blueprintName = blueprintName; + } + + /** + * Get the setting name. + * + * @return setting name + */ + public String getSettingName() { + return settingName; + } + + /** + * Set the setting name. + * + * @param settingName setting name + */ + public void setSettingName(String settingName) { + this.settingName = settingName; + } + + /** + * Get the setting data. + * + * @return setting data in json format + */ + public String getSettingData() { + return settingData; + } + + /** + * Set the setting data. + * + * @param settingData all config data in json format + */ + public void setSettingData(String settingData) { + this.settingData = settingData; + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java index a5e2fa1..dd2b7c6 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/AmbariContext.java @@ -191,7 +191,8 @@ public class AmbariContext { for (String service : services) { serviceRequests.add(new ServiceRequest(clusterName, service, null)); for (String component : topology.getBlueprint().getComponents(service)) { - componentRequests.add(new ServiceComponentRequest(clusterName, service, component, null)); + String recoveryEnabled = String.valueOf(topology.getBlueprint().isRecoveryEnabled(service, component)); + componentRequests.add(new ServiceComponentRequest(clusterName, service, component, null, recoveryEnabled)); } } try { http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/java/org/apache/ambari/server/topology/Blueprint.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/Blueprint.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/Blueprint.java index 11311db..2fc74de 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/topology/Blueprint.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/Blueprint.java @@ -62,6 +62,15 @@ public interface Blueprint { public Configuration getConfiguration(); /** + * Get the Blueprint cluster scoped setting. + * The blueprint cluster scoped setting has the setting properties + * with the setting names associated with the blueprint. + * + * @return blueprint cluster scoped setting + */ + public Setting getSetting(); + + /** * Get all of the services represented in the blueprint. * * @return collection of all represented service names @@ -78,6 +87,17 @@ public interface Blueprint { public Collection<String> getComponents(String service); /** + * Get whether a component is enabled for auto start. + * + * @param serviceName - Service name. + * @param componentName - Component name. + * + * @return True or false. + */ + public boolean isRecoveryEnabled(String serviceName, String componentName); + + + /** * Get the stack associated with the blueprint. * * @return associated stack http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintFactory.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintFactory.java index cca28ca..cb9d239 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintFactory.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintFactory.java @@ -66,6 +66,8 @@ public class BlueprintFactory { protected static final String PROPERTIES_PROPERTY_ID = "properties"; protected static final String PROPERTIES_ATTRIBUTES_PROPERTY_ID = "properties_attributes"; + protected static final String SETTINGS_PROPERTY_ID = "settings"; + private static BlueprintDAO blueprintDAO; private ConfigurationFactory configFactory = new ConfigurationFactory(); @@ -104,9 +106,10 @@ public class BlueprintFactory { Stack stack = createStack(properties); Collection<HostGroup> hostGroups = processHostGroups(name, stack, properties); Configuration configuration = configFactory.getConfiguration((Collection<Map<String, String>>) - properties.get(CONFIGURATION_PROPERTY_ID)); + properties.get(CONFIGURATION_PROPERTY_ID)); + Setting setting = SettingFactory.getSetting((Collection<Map<String, Object>>) properties.get(SETTINGS_PROPERTY_ID)); - return new BlueprintImpl(name, hostGroups, stack, configuration, securityConfiguration); + return new BlueprintImpl(name, hostGroups, stack, configuration, securityConfiguration, setting); } protected Stack createStack(Map<String, Object> properties) throws NoSuchStackException { http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImpl.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImpl.java index bea0364..0bb4874 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImpl.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/BlueprintImpl.java @@ -27,17 +27,21 @@ import org.apache.ambari.server.controller.internal.Stack; import org.apache.ambari.server.orm.entities.BlueprintConfigEntity; import org.apache.ambari.server.orm.entities.BlueprintConfiguration; import org.apache.ambari.server.orm.entities.BlueprintEntity; +import org.apache.ambari.server.orm.entities.BlueprintSettingEntity; import org.apache.ambari.server.orm.entities.HostGroupComponentEntity; import org.apache.ambari.server.orm.entities.HostGroupConfigEntity; import org.apache.ambari.server.orm.entities.HostGroupEntity; import org.apache.ambari.server.orm.entities.StackEntity; import org.apache.ambari.server.stack.NoSuchStackException; +import org.apache.commons.lang.StringUtils; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.Map; +import java.util.Set; /** * Blueprint implementation. @@ -50,6 +54,7 @@ public class BlueprintImpl implements Blueprint { private Configuration configuration; private BlueprintValidator validator; private SecurityConfiguration security; + private Setting setting; public BlueprintImpl(BlueprintEntity entity) throws NoSuchStackException { this.name = entity.getBlueprintName(); @@ -65,9 +70,16 @@ public class BlueprintImpl implements Blueprint { parseBlueprintHostGroups(entity); configuration.setParentConfiguration(stack.getConfiguration(getServices())); validator = new BlueprintValidatorImpl(this); + processSetting(entity.getSettings()); } - public BlueprintImpl(String name, Collection<HostGroup> groups, Stack stack, Configuration configuration, SecurityConfiguration security) { + public BlueprintImpl(String name, Collection<HostGroup> groups, Stack stack, Configuration configuration, + SecurityConfiguration security) { + this(name, groups, stack, configuration, security, null); + } + + public BlueprintImpl(String name, Collection<HostGroup> groups, Stack stack, Configuration configuration, + SecurityConfiguration security, Setting setting) { this.name = name; this.stack = stack; this.security = security; @@ -82,6 +94,7 @@ public class BlueprintImpl implements Blueprint { configuration.setParentConfiguration(stack.getConfiguration(getServices())); } validator = new BlueprintValidatorImpl(this); + this.setting = setting; } public String getName() { @@ -117,6 +130,11 @@ public class BlueprintImpl implements Blueprint { return configuration; } + @Override + public Setting getSetting() { + return setting; + } + /** * Get all services represented in blueprint. * @@ -141,6 +159,50 @@ public class BlueprintImpl implements Blueprint { return components; } + /** + * Get whether the specified component in the service is enabled + * for auto start. + * + * @param serviceName - Service name. + * @param componentName - Component name. + * + * @return True or false. + */ + @Override + public boolean isRecoveryEnabled(String serviceName, String componentName) { + if (setting == null) + return false; + + Set<HashMap<String, String>> settingValue; + + // If component name was specified in the list of "component_settings", + // determine if recovery_enabled is true or false and return it. + settingValue = setting.getSettingValue(Setting.SETTING_NAME_COMPONENT_SETTINGS); + for (Map<String, String> setting : settingValue) { + String name = setting.get(Setting.SETTING_NAME_NAME); + if (StringUtils.equals(name, componentName)) { + return Boolean.parseBoolean(setting.get(Setting.SETTING_NAME_RECOVERY_ENABLED)); + } + } + + // If component name is not specified, look up it's service. + settingValue = setting.getSettingValue(Setting.SETTING_NAME_SERVICE_SETTINGS); + for ( Map<String, String> setting : settingValue){ + String name = setting.get(Setting.SETTING_NAME_NAME); + if (StringUtils.equals(name, serviceName)) { + return Boolean.parseBoolean(setting.get(Setting.SETTING_NAME_RECOVERY_ENABLED)); + } + } + + // If service name is not specified, look up the cluster setting. + settingValue = setting.getSettingValue(Setting.SETTING_NAME_RECOVERY_SETTINGS); + for (Map<String, String> setting : settingValue) { + return Boolean.parseBoolean(setting.get(Setting.SETTING_NAME_RECOVERY_ENABLED)); + } + + return false; + } + @Override public Stack getStack() { return stack; @@ -209,6 +271,7 @@ public class BlueprintImpl implements Blueprint { createHostGroupEntities(entity); createBlueprintConfigEntities(entity); + createBlueprintSettingEntities(entity); return entity; } @@ -255,6 +318,17 @@ public class BlueprintImpl implements Blueprint { } /** + * Process blueprint setting. + * + * @param blueprintSetting + */ + private void processSetting(Collection<BlueprintSettingEntity> blueprintSetting) { + if (blueprintSetting != null) { + setting = new Setting(parseSetting(blueprintSetting)); + } + } + + /** * Obtain configuration as a map of config type to corresponding properties. * * @return map of config type to map of properties @@ -266,13 +340,31 @@ public class BlueprintImpl implements Blueprint { for (BlueprintConfiguration config : configs) { String type = config.getType(); Map<String, String> typeProperties = gson.<Map<String, String>>fromJson( - config.getConfigData(), Map.class); + config.getConfigData(), Map.class); properties.put(type, typeProperties); } return properties; } /** + * Deserialization: Obtain setting as a map of setting name to corresponding properties. + * + * @return map of setting name to map of properties + */ + private Map<String, Set<HashMap<String, String>>> parseSetting(Collection<BlueprintSettingEntity> blueprintSetting) { + + Map<String, Set<HashMap<String, String>>> properties = new HashMap<String, Set<HashMap<String, String>>>(); + Gson gson = new Gson(); + for (BlueprintSettingEntity setting : blueprintSetting) { + String settingName = setting.getSettingName(); + Set<HashMap<String, String>> settingProperties = gson.<Set<HashMap<String, String>>>fromJson( + setting.getSettingData(), Set.class); + properties.put(settingName, settingProperties); + } + return properties; + } + + /** * Process cluster scoped configuration attributes contained in blueprint. * * @return cluster scoped property attributes contained within in blueprint @@ -417,4 +509,26 @@ public class BlueprintImpl implements Blueprint { blueprintEntity.setConfigurations(configEntityMap.values()); } + /** + * Populate setting for serialization to DB. + */ + private void createBlueprintSettingEntities(BlueprintEntity blueprintEntity) { + Gson jsonSerializer = new Gson(); + Setting blueprintSetting = getSetting(); + if (blueprintSetting != null) { + Map<String, BlueprintSettingEntity> settingEntityMap = new HashMap<>(); + for (Map.Entry<String, Set<HashMap<String, String>>> propEntry : blueprintSetting.getProperties().entrySet()) { + String settingName = propEntry.getKey(); + Set<HashMap<String, String>> properties = propEntry.getValue(); + + BlueprintSettingEntity settingEntity = new BlueprintSettingEntity(); + settingEntityMap.put(settingName, settingEntity); + settingEntity.setBlueprintName(getName()); + settingEntity.setBlueprintEntity(blueprintEntity); + settingEntity.setSettingName(settingName); + settingEntity.setSettingData(jsonSerializer.toJson(properties)); + } + blueprintEntity.setSettings(settingEntityMap.values()); + } + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/java/org/apache/ambari/server/topology/Setting.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/Setting.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/Setting.java new file mode 100644 index 0000000..c03d833 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/Setting.java @@ -0,0 +1,75 @@ +/** + * 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. + */ + +package org.apache.ambari.server.topology; + +import java.util.Collections; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +public class Setting { + /** + * Settings for this configuration instance + */ + private Map<String, Set<HashMap<String, String>>> properties; + + public static final String SETTING_NAME_RECOVERY_SETTINGS = "recovery_settings"; + + public static final String SETTING_NAME_SERVICE_SETTINGS = "service_settings"; + + public static final String SETTING_NAME_COMPONENT_SETTINGS = "component_settings"; + + public static final String SETTING_NAME_RECOVERY_ENABLED = "recovery_enabled"; + + public static final String SETTING_NAME_NAME = "name"; + + /** + * Settings. + * + * @param properties setting name-->Set(property name-->property value) + */ + public Setting(Map<String, Set<HashMap<String, String>>> properties) { + + this.properties = properties; + } + + /** + * Get the properties for this instance. + * + * @return map of properties for this settings instance keyed by setting name. + */ + public Map<String, Set<HashMap<String, String>>> getProperties() { + return properties; + } + + /** + * Get the setting properties for a specified setting name. + * + * @param settingName + * @return Set of Map of properties. + */ + public Set<HashMap<String, String>> getSettingValue(String settingName) { + if (properties.containsKey(settingName)) { + return properties.get(settingName); + } + + return Collections.emptySet(); + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/java/org/apache/ambari/server/topology/SettingFactory.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/topology/SettingFactory.java b/ambari-server/src/main/java/org/apache/ambari/server/topology/SettingFactory.java new file mode 100644 index 0000000..4aca1ca --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/topology/SettingFactory.java @@ -0,0 +1,101 @@ +/** + * 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. + */ + +package org.apache.ambari.server.topology; + +import com.google.inject.Singleton; + +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +/** + * Creates the Setting object from the parsed blueprint. Expects the settings JSON + * that was parsed to follow the schema here: + * + * "settings" : [ + * { + * "recovery_settings" : [{ + * "recovery_enabled" : "true" + * } + * ] + * }, + * { + * "service_settings" : [ + * { + * "name" : "HDFS", + * "recovery_enabled" : "false" + * }, + * { + * "name" : "TEZ", + * "recovery_enabled" : "false" + * } + * ] + * }, + * { + * "component_settings" : [ + * { + * "name" : "DATANODE", + * "recovery_enabled" : "true" + * } + * ] + * } + * ] + */ +@Singleton +public class SettingFactory { + /** + * Attempts to build the list of settings in the following format: + * setting_name1-->[propertyName1-->propertyValue1, propertyName2-->propertyValue2] + * @param blueprintSetting + * @return + */ + public static Setting getSetting(Collection<Map<String, Object>> blueprintSetting) { + Map<String, Set<HashMap<String, String>>> properties = new HashMap<>(); + Setting setting = new Setting(properties); + + if (blueprintSetting != null) { + for (Map<String, Object> settingMap : blueprintSetting) { + for (Map.Entry<String, Object> entry : settingMap.entrySet()) { + final String[] propertyNames = entry.getKey().split("/"); + Set<HashMap<String, String>> settingValue; + if (entry.getValue() instanceof Set) { + settingValue = (HashSet<HashMap<String, String>>)entry.getValue(); + } + else if (propertyNames.length > 1){ + HashMap<String, String> property = new HashMap<>(); + property.put(propertyNames[1], String.valueOf(entry.getValue())); + settingValue = properties.get(propertyNames[0]); + if (settingValue == null) { + settingValue = new HashSet<>(); + } + settingValue.add(property); + } + else { + throw new IllegalArgumentException("Invalid setting schema: " + String.valueOf(entry.getValue())); + } + properties.put(propertyNames[0], settingValue); + } + } + } + + return setting; + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java index d8b84ec..a73a526 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog240.java @@ -83,7 +83,12 @@ public class UpgradeCatalog240 extends AbstractUpgradeCatalog { protected static final String CLUSTER_TABLE = "clusters"; protected static final String CLUSTER_UPGRADE_ID_COLUMN = "upgrade_id"; public static final String DESIRED_VERSION_COLUMN_NAME = "desired_version"; - + public static final String BLUEPRINT_SETTING_TABLE = "blueprint_setting"; + public static final String BLUEPRINT_NAME_COL = "blueprint_name"; + public static final String SETTING_NAME_COL = "setting_name"; + public static final String SETTING_DATA_COL = "setting_data"; + public static final String ID = "id"; + public static final String BLUEPRINT_TABLE = "blueprint"; @Inject PermissionDAO permissionDAO; @@ -96,7 +101,6 @@ public class UpgradeCatalog240 extends AbstractUpgradeCatalog { */ private static final Logger LOG = LoggerFactory.getLogger(UpgradeCatalog240.class); - private static final String ID = "id"; private static final String SETTING_TABLE = "setting"; protected static final String SERVICE_COMPONENT_DESIRED_STATE_TABLE = "servicecomponentdesiredstate"; @@ -146,6 +150,7 @@ public class UpgradeCatalog240 extends AbstractUpgradeCatalog { createServiceComponentHistoryTable(); updateClusterTableDDL(); updateAlertDefinitionTable(); + createBlueprintSettingTable(); } private void updateClusterTableDDL() throws SQLException { @@ -199,7 +204,7 @@ public class UpgradeCatalog240 extends AbstractUpgradeCatalog { String administratorPermissionId = permissionDAO.findPermissionByNameAndType("AMBARI.ADMINISTRATOR", resourceTypeDAO.findByName("AMBARI")).getId().toString(); dbAccessor.insertRowIfMissing("permission_roleauthorization", new String[]{"permission_id", "authorization_id"}, - new String[]{"'" + administratorPermissionId + "'", "'AMBARI.MANAGE_SETTINGS'"}, false); + new String[]{"'" + administratorPermissionId + "'", "'AMBARI.MANAGE_SETTINGS'"}, false); } /** @@ -238,7 +243,7 @@ public class UpgradeCatalog240 extends AbstractUpgradeCatalog { permissionId = permissionDAO.findPermissionByNameAndType("CLUSTER.OPERATOR", resourceTypeDAO.findByName("CLUSTER")).getId().toString(); dbAccessor.insertRowIfMissing("permission_roleauthorization", new String[]{"permission_id", "authorization_id"}, - new String[]{"'" + permissionId + "'", "'CLUSTER.MANAGE_USER_PERSISTED_DATA'"}, false); + new String[]{"'" + permissionId + "'", "'CLUSTER.MANAGE_USER_PERSISTED_DATA'"}, false); permissionId = permissionDAO.findPermissionByNameAndType("AMBARI.ADMINISTRATOR", resourceTypeDAO.findByName("AMBARI")).getId().toString(); @@ -480,15 +485,15 @@ public class UpgradeCatalog240 extends AbstractUpgradeCatalog { dbAccessor.executeUpdate(String.format(updateStatement, 2, PermissionEntity.CLUSTER_ADMINISTRATOR_PERMISSION_NAME)); dbAccessor.executeUpdate(String.format(updateStatement, - 3, PermissionEntity.CLUSTER_OPERATOR_PERMISSION_NAME)); + 3, PermissionEntity.CLUSTER_OPERATOR_PERMISSION_NAME)); dbAccessor.executeUpdate(String.format(updateStatement, - 4, PermissionEntity.SERVICE_ADMINISTRATOR_PERMISSION_NAME)); + 4, PermissionEntity.SERVICE_ADMINISTRATOR_PERMISSION_NAME)); dbAccessor.executeUpdate(String.format(updateStatement, - 5, PermissionEntity.SERVICE_OPERATOR_PERMISSION_NAME)); + 5, PermissionEntity.SERVICE_OPERATOR_PERMISSION_NAME)); dbAccessor.executeUpdate(String.format(updateStatement, - 6, PermissionEntity.CLUSTER_USER_PERMISSION_NAME)); + 6, PermissionEntity.CLUSTER_USER_PERMISSION_NAME)); dbAccessor.executeUpdate(String.format(updateStatement, - 7, PermissionEntity.VIEW_USER_PERMISSION_NAME)); + 7, PermissionEntity.VIEW_USER_PERMISSION_NAME)); } /** @@ -642,7 +647,7 @@ public class UpgradeCatalog240 extends AbstractUpgradeCatalog { "from_stack_id", STACK_TABLE, "stack_id", false); dbAccessor.addFKConstraint(SERVICE_COMPONENT_HISTORY_TABLE, "FK_sc_history_to_stack_id", - "to_stack_id", STACK_TABLE, "stack_id", false); + "to_stack_id", STACK_TABLE, "stack_id", false); addSequence("servicecomponent_history_id_seq", 0L, false); } @@ -658,7 +663,7 @@ public class UpgradeCatalog240 extends AbstractUpgradeCatalog { new DBColumnInfo(RECOVERY_ENABLED_COL, Short.class, null, 0, false)); dbAccessor.addColumn(SERVICE_COMPONENT_DESIRED_STATE_TABLE, - new DBColumnInfo(DESIRED_VERSION_COLUMN_NAME, String.class, 255, State.UNKNOWN.toString(), false)); + new DBColumnInfo(DESIRED_VERSION_COLUMN_NAME, String.class, 255, State.UNKNOWN.toString(), false)); } /** @@ -691,7 +696,7 @@ public class UpgradeCatalog240 extends AbstractUpgradeCatalog { String content = amsEnv.getProperties().get("content"); if (content != null && !content.contains("AMS_INSTANCE_NAME")) { String newContent = content + "\n # AMS instance name\n" + - "export AMS_INSTANCE_NAME={{hostname}}\n"; + "export AMS_INSTANCE_NAME={{hostname}}\n"; updateConfigurationProperties("ams-env", Collections.singletonMap("content", newContent), true, true); } @@ -700,4 +705,30 @@ public class UpgradeCatalog240 extends AbstractUpgradeCatalog { } } } + + /** + * Create blueprint_setting table for storing the "settings" section + * in the blueprint. Auto start information is specified in the "settings" section. + * + * @throws SQLException + */ + private void createBlueprintSettingTable() throws SQLException { + List<DBColumnInfo> columns = new ArrayList<>(); + + // Add blueprint_setting table + LOG.info("Creating " + BLUEPRINT_SETTING_TABLE + " table"); + + columns.add(new DBColumnInfo(ID, Long.class, null, null, false)); + columns.add(new DBColumnInfo(BLUEPRINT_NAME_COL, String.class, 255, null, false)); + columns.add(new DBColumnInfo(SETTING_NAME_COL, String.class, 255, null, false)); + columns.add(new DBColumnInfo(SETTING_DATA_COL, char[].class, null, null, false)); + dbAccessor.createTable(BLUEPRINT_SETTING_TABLE, columns); + + dbAccessor.addPKConstraint(BLUEPRINT_SETTING_TABLE, "PK_blueprint_setting", ID); + dbAccessor.addUniqueConstraint(BLUEPRINT_SETTING_TABLE, "UQ_blueprint_setting_name", BLUEPRINT_NAME_COL, SETTING_NAME_COL); + dbAccessor.addFKConstraint(BLUEPRINT_SETTING_TABLE, "FK_blueprint_setting_name", + BLUEPRINT_NAME_COL, BLUEPRINT_TABLE, BLUEPRINT_NAME_COL, false); + + addSequence("blueprint_setting_id_seq", 0L, false); + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql index 4a0479e..79f41e3 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Derby-CREATE.sql @@ -421,6 +421,15 @@ CREATE TABLE blueprint_configuration ( config_attributes VARCHAR(3000), PRIMARY KEY(blueprint_name, type_name)); +CREATE TABLE blueprint_settings ( + id BIGINT NOT NULL, + blueprint_name varchar(255) NOT NULL, + setting_name varchar(255) NOT NULL, + setting_data CLOB NOT NULL, + CONSTRAINT PK_blueprint_settings PRIMARY KEY (id), + CONSTRAINT UQ_blueprint_settings_name UNIQUE(blueprint_name,setting_name), + CONSTRAINT FK_blueprint_settings_name FOREIGN KEY (blueprint_name) REFERENCES blueprint(blueprint_name)); + CREATE TABLE hostgroup_configuration ( blueprint_name VARCHAR(255) NOT NULL, hostgroup_name VARCHAR(255) NOT NULL, @@ -1070,6 +1079,8 @@ INSERT INTO ambari_sequences (sequence_name, sequence_value) select 'servicecomponentdesiredstate_id_seq', 0 FROM SYSIBM.SYSDUMMY1 union all select 'servicecomponent_history_id_seq', 0 FROM SYSIBM.SYSDUMMY1; + union all + select 'blueprint_settings_id_seq', 0 FROM SYSIBM.SYSDUMMY1; INSERT INTO adminresourcetype (resource_type_id, resource_type_name) http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql index e40165d..90fc375 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql @@ -430,6 +430,15 @@ CREATE TABLE blueprint_configuration ( config_attributes LONGTEXT, PRIMARY KEY(blueprint_name, type_name)); +CREATE TABLE blueprint_setting ( + id BIGINT NOT NULL, + blueprint_name VARCHAR(100) NOT NULL, + setting_name VARCHAR(100) NOT NULL, + setting_data MEDIUMTEXT NOT NULL, + CONSTRAINT PK_blueprint_setting PRIMARY KEY (id), + CONSTRAINT UQ_blueprint_setting_name UNIQUE(blueprint_name,setting_name), + CONSTRAINT FK_blueprint_setting_name FOREIGN KEY (blueprint_name) REFERENCES blueprint(blueprint_name)); + CREATE TABLE hostgroup_configuration ( blueprint_name VARCHAR(100) NOT NULL, hostgroup_name VARCHAR(100) NOT NULL, @@ -1035,6 +1044,7 @@ INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('setting_id_ INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('hostcomponentstate_id_seq', 0); INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('servicecomponentdesiredstate_id_seq', 0); INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('servicecomponent_history_id_seq', 0); +INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('blueprint_setting_id_seq', 0); insert into adminresourcetype (resource_type_id, resource_type_name) select 1, 'AMBARI' http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql index e85ea49..d1880bc 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql @@ -421,6 +421,15 @@ CREATE TABLE blueprint_configuration ( config_attributes CLOB, PRIMARY KEY(blueprint_name, type_name)); +CREATE TABLE blueprint_setting ( + id NUMBER(19) NOT NULL, + blueprint_name VARCHAR2(255) NOT NULL, + setting_name VARCHAR2(255) NOT NULL, + setting_data CLOB NOT NULL, + CONSTRAINT PK_blueprint_setting PRIMARY KEY (id), + CONSTRAINT UQ_blueprint_setting_name UNIQUE(blueprint_name,setting_name), + CONSTRAINT FK_blueprint_setting_name FOREIGN KEY (blueprint_name) REFERENCES blueprint(blueprint_name)); + CREATE TABLE hostgroup_configuration ( blueprint_name VARCHAR2(255) NOT NULL, hostgroup_name VARCHAR2(255) NOT NULL, @@ -1026,6 +1035,7 @@ INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('setting_id_ INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('hostcomponentstate_id_seq', 0); INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('servicecomponentdesiredstate_id_seq', 0); INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('servicecomponent_history_id_seq', 0); +INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('blueprint_setting_id_seq', 0); INSERT INTO metainfo("metainfo_key", "metainfo_value") values ('version', '${ambariSchemaVersion}'); http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql index 8bcda31..dd1fe5f 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql @@ -422,6 +422,15 @@ CREATE TABLE blueprint_configuration ( config_attributes TEXT, PRIMARY KEY(blueprint_name, type_name)); +CREATE TABLE blueprint_setting ( + id BIGINT NOT NULL, + blueprint_name varchar(255) NOT NULL, + setting_name varchar(255) NOT NULL, + setting_data TEXT NOT NULL, + CONSTRAINT PK_blueprint_setting PRIMARY KEY(id), + CONSTRAINT UQ_blueprint_setting_name UNIQUE(blueprint_name,setting_name), + CONSTRAINT FK_blueprint_setting_name FOREIGN KEY (blueprint_name) REFERENCES blueprint(blueprint_name)); + CREATE TABLE hostgroup_configuration ( blueprint_name VARCHAR(255) NOT NULL, hostgroup_name VARCHAR(255) NOT NULL, @@ -1076,7 +1085,9 @@ INSERT INTO ambari_sequences (sequence_name, sequence_value) union all select 'servicecomponentdesiredstate_id_seq', 0 union all - select 'servicecomponent_history_id_seq', 0; + select 'servicecomponent_history_id_seq', 0 + union all + select 'blueprint_setting_id_seq', 0; INSERT INTO adminresourcetype (resource_type_id, resource_type_name) http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql index c7d7cff..e7e1997 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-EMBEDDED-CREATE.sql @@ -469,6 +469,15 @@ CREATE TABLE ambari.blueprint_configuration ( config_attributes TEXT, PRIMARY KEY(blueprint_name, type_name)); +CREATE TABLE ambari.blueprint_setting ( + id BIGINT NOT NULL, + blueprint_name varchar(255) NOT NULL, + setting_name varchar(255) NOT NULL, + setting_data TEXT NOT NULL, + CONSTRAINT PK_blueprint_setting PRIMARY KEY (id), + CONSTRAINT UQ_blueprint_setting_name UNIQUE(blueprint_name,setting_name), + CONSTRAINT FK_blueprint_setting_name FOREIGN KEY (blueprint_name) REFERENCES ambari.blueprint(blueprint_name)); + CREATE TABLE ambari.hostgroup_configuration ( blueprint_name VARCHAR(255) NOT NULL, hostgroup_name VARCHAR(255) NOT NULL, @@ -481,6 +490,7 @@ GRANT ALL PRIVILEGES ON TABLE ambari.blueprint TO :username; GRANT ALL PRIVILEGES ON TABLE ambari.hostgroup TO :username; GRANT ALL PRIVILEGES ON TABLE ambari.hostgroup_component TO :username; GRANT ALL PRIVILEGES ON TABLE ambari.blueprint_configuration TO :username; +GRANT ALL PRIVILEGES ON TABLE ambari.blueprint_setting TO :username; GRANT ALL PRIVILEGES ON TABLE ambari.hostgroup_configuration TO :username; CREATE TABLE ambari.viewmain ( @@ -1172,7 +1182,9 @@ INSERT INTO ambari.ambari_sequences (sequence_name, sequence_value) union all select 'servicecomponentdesiredstate_id_seq', 0 union all - select 'servicecomponent_history_id_seq', 0; + select 'servicecomponent_history_id_seq', 0 + union all + select 'blueprint_setting_id_seq', 0; INSERT INTO ambari.adminresourcetype (resource_type_id, resource_type_name) SELECT 1, 'AMBARI' http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql index 4bd7a7a..aa8a4d9 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-SQLAnywhere-CREATE.sql @@ -419,6 +419,15 @@ CREATE TABLE blueprint_configuration ( config_attributes TEXT, PRIMARY KEY(blueprint_name, type_name)); +CREATE TABLE blueprint_setting ( + id NUMERIC(19) NOT NULL, + blueprint_name VARCHAR(255) NOT NULL, + setting_name VARCHAR(255) NOT NULL, + setting_data TEXT NOT NULL, + CONSTRAINT PK_blueprint_setting PRIMARY KEY (id), + CONSTRAINT UQ_blueprint_setting_name UNIQUE(blueprint_name,setting_name), + CONSTRAINT FK_blueprint_setting_name FOREIGN KEY (blueprint_name) REFERENCES blueprint(blueprint_name)); + CREATE TABLE hostgroup_configuration ( blueprint_name VARCHAR(255) NOT NULL, hostgroup_name VARCHAR(255) NOT NULL, @@ -1024,6 +1033,7 @@ INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('setting_id_ INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('hostcomponentstate_id_seq', 0); INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('servicecomponentdesiredstate_id_seq', 0); INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('servicecomponent_history_id_seq', 0); +INSERT INTO ambari_sequences(sequence_name, sequence_value) values ('blueprint_setting_id_seq', 0); insert into adminresourcetype (resource_type_id, resource_type_name) select 1, 'AMBARI' http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql index 063db3a..504c910 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql @@ -483,6 +483,16 @@ CREATE TABLE blueprint_configuration ( ) ); +CREATE TABLE blueprint_setting ( + id BIGINT NOT NULL, + blueprint_name VARCHAR(255) NOT NULL, + setting_name VARCHAR(255) NOT NULL, + setting_data TEXT NOT NULL, + CONSTRAINT PK_blueprint_setting PRIMARY KEY (id), + CONSTRAINT UQ_blueprint_setting_name UNIQUE(blueprint_name,setting_name), + CONSTRAINT FK_blueprint_setting_name FOREIGN KEY (blueprint_name) REFERENCES blueprint(blueprint_name) + ); + CREATE TABLE hostgroup_configuration ( blueprint_name VARCHAR(255) NOT NULL, hostgroup_name VARCHAR(255) NOT NULL, @@ -1137,7 +1147,8 @@ BEGIN TRANSACTION ('setting_id_seq', 0), ('hostcomponentstate_id_seq', 0), ('servicecomponentdesiredstate_id_seq', 0), - ('servicecomponent_history_id_seq', 0); + ('servicecomponent_history_id_seq', 0), + ('blueprint_setting_id_seq', 0); insert into adminresourcetype (resource_type_id, resource_type_name) values http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/resources/META-INF/persistence.xml ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/META-INF/persistence.xml b/ambari-server/src/main/resources/META-INF/persistence.xml index 513035f..3eff96f 100644 --- a/ambari-server/src/main/resources/META-INF/persistence.xml +++ b/ambari-server/src/main/resources/META-INF/persistence.xml @@ -21,6 +21,7 @@ <class>org.apache.ambari.server.orm.entities.AlertTargetEntity</class> <class>org.apache.ambari.server.orm.entities.ArtifactEntity</class> <class>org.apache.ambari.server.orm.entities.BlueprintConfigEntity</class> + <class>org.apache.ambari.server.orm.entities.BlueprintSettingEntity</class> <class>org.apache.ambari.server.orm.entities.BlueprintEntity</class> <class>org.apache.ambari.server.orm.entities.ClusterConfigEntity</class> <class>org.apache.ambari.server.orm.entities.ClusterConfigMappingEntity</class> http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/main/resources/properties.json ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/properties.json b/ambari-server/src/main/resources/properties.json index 01c15f2..2f7fa86 100644 --- a/ambari-server/src/main/resources/properties.json +++ b/ambari-server/src/main/resources/properties.json @@ -358,7 +358,8 @@ "host_groups/components", "host_groups/cardinality", "configurations", - "validate_topology" + "validate_topology", + "settings" ], "Recommendation":[ "Recommendation/id", http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/BlueprintEntityTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/BlueprintEntityTest.java b/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/BlueprintEntityTest.java index c660d19..279346b 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/BlueprintEntityTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/BlueprintEntityTest.java @@ -72,4 +72,15 @@ public class BlueprintEntityTest { entity.setConfigurations(configurations); assertSame(configurations, entity.getConfigurations()); } + + /** + * Test get and set of Setting object. + */ + @Test + public void testSetGetSetting() { + BlueprintEntity entity = new BlueprintEntity(); + Collection<BlueprintSettingEntity> setting = Collections.emptyList(); + entity.setSettings(setting); + assertSame(setting, entity.getSettings()); + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/BlueprintSettingEntityTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/BlueprintSettingEntityTest.java b/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/BlueprintSettingEntityTest.java new file mode 100644 index 0000000..507a9111 --- /dev/null +++ b/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/BlueprintSettingEntityTest.java @@ -0,0 +1,72 @@ +/** + * 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. + */ + +package org.apache.ambari.server.orm.entities; + +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; + +/** + * Test all the methods of BlueprintSettingEntity + */ +public class BlueprintSettingEntityTest { + /** + * Verify setSettingName() + */ + @Test + public void testSetGetSettingName() { + BlueprintSettingEntity entity = new BlueprintSettingEntity(); + entity.setSettingName("component_settings"); + assertEquals("component_settings", entity.getSettingName()); + } + + /** + * Verify referencing BlueprintEntity object + */ + @Test + public void testSetGetBlueprintEntity() { + BlueprintEntity bp = new BlueprintEntity(); + + BlueprintSettingEntity entity = new BlueprintSettingEntity(); + entity.setBlueprintEntity(bp); + assertSame(bp, entity.getBlueprintEntity()); + } + + /** + * Verify setBlueprintName() + */ + @Test + public void testSetGetBlueprintName() { + BlueprintSettingEntity entity = new BlueprintSettingEntity(); + entity.setBlueprintName("bp2"); + assertEquals("bp2", entity.getBlueprintName()); + } + + /** + * Verify setSettingData() + */ + @Test + public void testSetGetSettingData() { + BlueprintSettingEntity entity = new BlueprintSettingEntity(); + String settingData = "[{'recovery_settings':[{'recovery_enabled':'true'}]}]"; + entity.setSettingData(settingData); + assertEquals(settingData, entity.getSettingData()); + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/test/java/org/apache/ambari/server/topology/SettingFactoryTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/topology/SettingFactoryTest.java b/ambari-server/src/test/java/org/apache/ambari/server/topology/SettingFactoryTest.java new file mode 100644 index 0000000..e017fb3 --- /dev/null +++ b/ambari-server/src/test/java/org/apache/ambari/server/topology/SettingFactoryTest.java @@ -0,0 +1,149 @@ +/** + * 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 distribut + * ed 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. + */ + +package org.apache.ambari.server.topology; + +import org.junit.Test; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import static org.junit.Assert.assertEquals; + +/** + * Test the SettingFactory class + */ +public class SettingFactoryTest { + /** + * Test collection of recovery_settings + */ + @Test + public void testGetSettingWithSetOfProperties() { + SettingFactory settingFactory = new SettingFactory(); + Map<String, Set<HashMap<String, String>>> properties; + + Setting setting = settingFactory.getSetting(createSettingWithSetOfProperties()); + Set<HashMap<String, String>> propertyValues = setting.getSettingValue(Setting.SETTING_NAME_RECOVERY_SETTINGS); + assertEquals(propertyValues.size(), 1); + + assertEquals(propertyValues.iterator().next().get(Setting.SETTING_NAME_RECOVERY_ENABLED), "true"); + } + + /** + * Test single recovery_settings at root level + */ + @Test + public void testGetSettingWithoutSetOfProperties() { + SettingFactory settingFactory = new SettingFactory(); + Map<String, Set<HashMap<String, String>>> properties; + + Setting setting = settingFactory.getSetting(createSettingWithoutSetOfProperties()); + Set<HashMap<String, String>> propertyValues = setting.getSettingValue(Setting.SETTING_NAME_RECOVERY_SETTINGS); + assertEquals(propertyValues.size(), 1); + + assertEquals(propertyValues.iterator().next().get(Setting.SETTING_NAME_RECOVERY_ENABLED), "true"); + } + + /** + * { + * "recovery_settings":[ + * { + * "recovery_enabled":"true" + * } + * ] + * } + * + * @return + */ + private Collection<Map<String, Object>> createSettingWithSetOfProperties() { + + Set<HashMap<String, String>> setting1 = new HashSet<>(); + Set<HashMap<String, String>> setting2 = new HashSet<>(); + + // Setting 1: Property1 + HashMap<String, String> setting1Properties1 = new HashMap<>(); + setting1Properties1.put(Setting.SETTING_NAME_RECOVERY_ENABLED, "true"); + setting1.add(setting1Properties1); + + // Setting 2: Property1 and Property2 + HashMap<String, String> setting2Properties1 = new HashMap<>(); + setting2Properties1.put(Setting.SETTING_NAME_NAME, "HDFS"); + setting2Properties1.put(Setting.SETTING_NAME_RECOVERY_ENABLED, "false"); + + HashMap<String, String> setting2Properties2 = new HashMap<>(); + setting2Properties2.put(Setting.SETTING_NAME_NAME, "TEZ"); + setting2Properties2.put(Setting.SETTING_NAME_RECOVERY_ENABLED, "false"); + + setting2.add(setting2Properties1); + setting2.add(setting2Properties2); + + Collection<Map<String, Object>> setting = new ArrayList<>(); + Map<String, Object> properties; + properties = new HashMap<>(); + properties.put(Setting.SETTING_NAME_RECOVERY_SETTINGS, setting1); + setting.add(properties); + + properties = new HashMap<>(); + properties.put(Setting.SETTING_NAME_SERVICE_SETTINGS, setting2); + setting.add(properties); + + return setting; + } + + /** + * { + * "recovery_settings": + * { + * "recovery_enabled":"true" + * } + * } + * + * @return + */ + private Collection<Map<String, Object>> createSettingWithoutSetOfProperties() { + // Setting 2: Property1 and Property2 + HashMap<String, String> setting2Properties1 = new HashMap<>(); + setting2Properties1.put(Setting.SETTING_NAME_NAME, "HDFS"); + setting2Properties1.put(Setting.SETTING_NAME_RECOVERY_ENABLED, "false"); + + HashMap<String, String> setting2Properties2 = new HashMap<>(); + setting2Properties2.put(Setting.SETTING_NAME_NAME, "TEZ"); + setting2Properties2.put(Setting.SETTING_NAME_RECOVERY_ENABLED, "false"); + + Set<HashMap<String, String>> setting2 = new HashSet<>(); + setting2.add(setting2Properties1); + setting2.add(setting2Properties2); + + Collection<Map<String, Object>> setting = new ArrayList<>(); + Map<String, Object> properties; + properties = new HashMap<>(); + properties.put(Setting.SETTING_NAME_RECOVERY_SETTINGS + "/" + Setting.SETTING_NAME_RECOVERY_ENABLED, "true"); + setting.add(properties); + + properties = new HashMap<>(); + properties.put(Setting.SETTING_NAME_SERVICE_SETTINGS, setting2); + setting.add(properties); + + return setting; + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/test/java/org/apache/ambari/server/topology/SettingTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/topology/SettingTest.java b/ambari-server/src/test/java/org/apache/ambari/server/topology/SettingTest.java new file mode 100644 index 0000000..5615d12 --- /dev/null +++ b/ambari-server/src/test/java/org/apache/ambari/server/topology/SettingTest.java @@ -0,0 +1,99 @@ +/** + * 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. + */ + +package org.apache.ambari.server.topology; + +import org.junit.Test; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import static org.junit.Assert.assertEquals; + +/** + * Test the Setting class + */ +public class SettingTest { + /** + * Test get and set of entire setting. + */ + @Test + public void testGetProperties() { + Map<String, Set<HashMap<String, String>>> properties = new HashMap<>(); + Set<HashMap<String, String>> setting1 = new HashSet<>(); + Set<HashMap<String, String>> setting2 = new HashSet<>(); + + // Setting 1: Property1 + HashMap<String, String> setting1Properties1 = new HashMap<String, String>(); + setting1Properties1.put(Setting.SETTING_NAME_RECOVERY_ENABLED, "true"); + setting1.add(setting1Properties1); + + // Setting 2: Property1 and Property2 + HashMap<String, String> setting2Properties1 = new HashMap<String, String>(); + setting2Properties1.put(Setting.SETTING_NAME_NAME, "HDFS"); + setting2Properties1.put(Setting.SETTING_NAME_RECOVERY_ENABLED, "false"); + + HashMap<String, String> setting2Properties2 = new HashMap<String, String>(); + setting2Properties2.put(Setting.SETTING_NAME_NAME, "TEZ"); + setting2Properties2.put(Setting.SETTING_NAME_RECOVERY_ENABLED, "false"); + + setting2.add(setting2Properties1); + setting2.add(setting2Properties2); + + properties.put(Setting.SETTING_NAME_RECOVERY_SETTINGS, setting1); + properties.put(Setting.SETTING_NAME_SERVICE_SETTINGS, setting2); + + Setting setting = new Setting(properties); + assertEquals(properties, setting.getProperties()); + } + + /** + * Validate the properties for a given setting. + */ + @Test + public void testGetSettingProperties() { + Map<String, Set<HashMap<String, String>>> properties = new HashMap<>(); + Set<HashMap<String, String>> setting1 = new HashSet<>(); + Set<HashMap<String, String>> setting2 = new HashSet<>(); + + // Setting 1: Property1 + HashMap<String, String> setting1Properties1 = new HashMap<String, String>(); + setting1Properties1.put(Setting.SETTING_NAME_RECOVERY_ENABLED, "true"); + setting1.add(setting1Properties1); + + // Setting 2: Property1 and Property2 + HashMap<String, String> setting2Properties1 = new HashMap<String, String>(); + setting2Properties1.put(Setting.SETTING_NAME_NAME, "HDFS"); + setting2Properties1.put(Setting.SETTING_NAME_RECOVERY_ENABLED, "false"); + + HashMap<String, String> setting2Properties2 = new HashMap<String, String>(); + setting2Properties2.put(Setting.SETTING_NAME_NAME, "TEZ"); + setting2Properties2.put(Setting.SETTING_NAME_RECOVERY_ENABLED, "false"); + + setting2.add(setting2Properties1); + setting2.add(setting2Properties2); + + properties.put(Setting.SETTING_NAME_RECOVERY_SETTINGS, setting1); + properties.put(Setting.SETTING_NAME_SERVICE_SETTINGS, setting2); + + Setting setting = new Setting(properties); + assertEquals(setting2, setting.getSettingValue(Setting.SETTING_NAME_SERVICE_SETTINGS)); + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/7d70695a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java index 5cd3bdc..f66f21b 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog240Test.java @@ -141,7 +141,7 @@ public class UpgradeCatalog240Test { Capture<List<DBAccessor.DBColumnInfo>> capturedHistoryColumns = EasyMock.newCapture(); dbAccessor.createTable(eq("servicecomponent_history"), capture(capturedHistoryColumns), - eq((String[]) null)); + eq((String[]) null)); dbAccessor.addPKConstraint("servicecomponent_history", "PK_sc_history", "id"); dbAccessor.addFKConstraint("servicecomponent_history", "FK_sc_history_component_id", @@ -151,10 +151,10 @@ public class UpgradeCatalog240Test { "upgrade", "upgrade_id", false); dbAccessor.addFKConstraint("servicecomponent_history", "FK_sc_history_from_stack_id", - "from_stack_id", "stack", "stack_id", false); + "from_stack_id", "stack", "stack_id", false); dbAccessor.addFKConstraint("servicecomponent_history", "FK_sc_history_to_stack_id", - "to_stack_id", "stack", "stack_id", false); + "to_stack_id", "stack", "stack_id", false); expect(dbAccessor.getConnection()).andReturn(connection); @@ -164,7 +164,7 @@ public class UpgradeCatalog240Test { Capture<DBAccessor.DBColumnInfo> capturedClusterUpgradeColumnInfo = newCapture(); dbAccessor.addColumn(eq(UpgradeCatalog240.CLUSTER_TABLE), capture(capturedClusterUpgradeColumnInfo)); dbAccessor.addFKConstraint(UpgradeCatalog240.CLUSTER_TABLE, "FK_clusters_upgrade_id", - UpgradeCatalog240.CLUSTER_UPGRADE_ID_COLUMN, UpgradeCatalog240.UPGRADE_TABLE, "upgrade_id", false); + UpgradeCatalog240.CLUSTER_UPGRADE_ID_COLUMN, UpgradeCatalog240.UPGRADE_TABLE, "upgrade_id", false); Capture<DBAccessor.DBColumnInfo> capturedHelpURLColumnInfo = newCapture(); Capture<DBAccessor.DBColumnInfo> capturedRepeatToleranceColumnInfo = newCapture(); @@ -173,6 +173,19 @@ public class UpgradeCatalog240Test { dbAccessor.addColumn(eq(UpgradeCatalog240.ALERT_DEFINITION_TABLE), capture(capturedRepeatToleranceColumnInfo)); dbAccessor.addColumn(eq(UpgradeCatalog240.ALERT_DEFINITION_TABLE), capture(capturedRepeatToleranceEnabledColumnInfo)); + // Test creation of blueprint_setting table + Capture<List<DBAccessor.DBColumnInfo>> capturedBlueprintSettingColumns = EasyMock.newCapture(); + dbAccessor.createTable(eq(UpgradeCatalog240.BLUEPRINT_SETTING_TABLE), capture(capturedBlueprintSettingColumns)); + dbAccessor.addPKConstraint(UpgradeCatalog240.BLUEPRINT_SETTING_TABLE, "PK_blueprint_setting", UpgradeCatalog240.ID); + dbAccessor.addUniqueConstraint(UpgradeCatalog240.BLUEPRINT_SETTING_TABLE, "UQ_blueprint_setting_name", + UpgradeCatalog240.BLUEPRINT_NAME_COL, UpgradeCatalog240.SETTING_NAME_COL); + dbAccessor.addFKConstraint(UpgradeCatalog240.BLUEPRINT_SETTING_TABLE, "FK_blueprint_setting_name", + UpgradeCatalog240.BLUEPRINT_NAME_COL, UpgradeCatalog240.BLUEPRINT_TABLE, + UpgradeCatalog240.BLUEPRINT_NAME_COL, false); + expect(dbAccessor.getConnection()).andReturn(connection); + expect(connection.createStatement()).andReturn(statement); + expect(statement.executeQuery(anyObject(String.class))).andReturn(resultSet); + replay(dbAccessor, configuration, connection, statement, resultSet); Module module = new Module() { @@ -273,6 +286,20 @@ public class UpgradeCatalog240Test { assertEquals(expectedCaptures, actualCaptures); + // Verify blueprint_setting columns + expectedCaptures = new HashMap<>(); + expectedCaptures.put(UpgradeCatalog240.ID, Long.class); + expectedCaptures.put(UpgradeCatalog240.BLUEPRINT_NAME_COL, String.class); + expectedCaptures.put(UpgradeCatalog240.SETTING_NAME_COL, String.class); + expectedCaptures.put(UpgradeCatalog240.SETTING_DATA_COL, char[].class); + + actualCaptures = new HashMap<>(); + for(DBAccessor.DBColumnInfo blueprintSettingsColumnInfo : capturedBlueprintSettingColumns.getValue()) { + actualCaptures.put(blueprintSettingsColumnInfo.getName(), blueprintSettingsColumnInfo.getType()); + } + + assertEquals(expectedCaptures, actualCaptures); + verify(dbAccessor); }
