Repository: ambari Updated Branches: refs/heads/trunk e508a5fbf -> acdaae986
AMBARI-10306 - Views: Ability for a view instance to be associated to a cluster for configuration (tbeerbower) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/acdaae98 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/acdaae98 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/acdaae98 Branch: refs/heads/trunk Commit: acdaae986b428b09310c06f08ec42fc98b93d3b4 Parents: e508a5f Author: tbeerbower <[email protected]> Authored: Wed Apr 1 17:23:37 2015 -0400 Committer: tbeerbower <[email protected]> Committed: Wed Apr 1 17:23:57 2015 -0400 ---------------------------------------------------------------------- .../internal/ViewInstanceResourceProvider.java | 31 +++-- .../internal/ViewVersionResourceProvider.java | 3 + .../ambari/server/orm/entities/ViewEntity.java | 32 ++++- .../server/orm/entities/ViewInstanceEntity.java | 24 ++++ .../orm/entities/ViewParameterEntity.java | 26 ++++ .../server/upgrade/UpgradeCatalog210.java | 6 + .../apache/ambari/server/view/ClusterImpl.java | 61 +++++++++ .../ambari/server/view/ViewContextImpl.java | 127 ++++++++++++------- .../apache/ambari/server/view/ViewRegistry.java | 41 +++++- .../view/configuration/ParameterConfig.java | 15 +++ .../main/resources/Ambari-DDL-MySQL-CREATE.sql | 2 + .../main/resources/Ambari-DDL-Oracle-CREATE.sql | 2 + .../resources/Ambari-DDL-Postgres-CREATE.sql | 2 + .../Ambari-DDL-Postgres-EMBEDDED-CREATE.sql | 2 + .../resources/Ambari-DDL-SQLServer-CREATE.sql | 4 +- .../ViewInstanceResourceProviderTest.java | 12 +- .../server/orm/entities/ViewEntityTest.java | 15 +++ .../server/upgrade/UpgradeCatalog210Test.java | 20 +++ .../ambari/server/view/ClusterImplTest.java | 76 +++++++++++ .../ambari/server/view/ViewContextImplTest.java | 32 ++++- .../ambari/server/view/ViewRegistryTest.java | 2 +- .../view/configuration/ParameterConfigTest.java | 9 ++ .../view/configuration/ViewConfigTest.java | 1 + .../org/apache/ambari/view/ViewContext.java | 15 +++ .../ambari/view/ViewInstanceDefinition.java | 8 ++ .../org/apache/ambari/view/cluster/Cluster.java | 42 ++++++ ambari-views/src/main/resources/view.xsd | 5 + 27 files changed, 546 insertions(+), 69 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/acdaae98/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewInstanceResourceProvider.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewInstanceResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewInstanceResourceProvider.java index 28e5e12..7cecedc 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewInstanceResourceProvider.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewInstanceResourceProvider.java @@ -55,18 +55,19 @@ public class ViewInstanceResourceProvider extends AbstractResourceProvider { /** * View instance property id constants. */ - public static final String VIEW_NAME_PROPERTY_ID = "ViewInstanceInfo/view_name"; - public static final String VIEW_VERSION_PROPERTY_ID = "ViewInstanceInfo/version"; - public static final String INSTANCE_NAME_PROPERTY_ID = "ViewInstanceInfo/instance_name"; - public static final String LABEL_PROPERTY_ID = "ViewInstanceInfo/label"; - public static final String DESCRIPTION_PROPERTY_ID = "ViewInstanceInfo/description"; - public static final String VISIBLE_PROPERTY_ID = "ViewInstanceInfo/visible"; - public static final String ICON_PATH_ID = "ViewInstanceInfo/icon_path"; - public static final String ICON64_PATH_ID = "ViewInstanceInfo/icon64_path"; - public static final String PROPERTIES_PROPERTY_ID = "ViewInstanceInfo/properties"; - public static final String DATA_PROPERTY_ID = "ViewInstanceInfo/instance_data"; - public static final String CONTEXT_PATH_PROPERTY_ID = "ViewInstanceInfo/context_path"; - public static final String STATIC_PROPERTY_ID = "ViewInstanceInfo/static"; + public static final String VIEW_NAME_PROPERTY_ID = "ViewInstanceInfo/view_name"; + public static final String VIEW_VERSION_PROPERTY_ID = "ViewInstanceInfo/version"; + public static final String INSTANCE_NAME_PROPERTY_ID = "ViewInstanceInfo/instance_name"; + public static final String LABEL_PROPERTY_ID = "ViewInstanceInfo/label"; + public static final String DESCRIPTION_PROPERTY_ID = "ViewInstanceInfo/description"; + public static final String VISIBLE_PROPERTY_ID = "ViewInstanceInfo/visible"; + public static final String ICON_PATH_ID = "ViewInstanceInfo/icon_path"; + public static final String ICON64_PATH_ID = "ViewInstanceInfo/icon64_path"; + public static final String PROPERTIES_PROPERTY_ID = "ViewInstanceInfo/properties"; + public static final String DATA_PROPERTY_ID = "ViewInstanceInfo/instance_data"; + public static final String CONTEXT_PATH_PROPERTY_ID = "ViewInstanceInfo/context_path"; + public static final String STATIC_PROPERTY_ID = "ViewInstanceInfo/static"; + public static final String CLUSTER_HANDLE_PROPERTY_ID = "ViewInstanceInfo/cluster_handle"; // validation properties public static final String VALIDATION_RESULT_PROPERTY_ID = "ViewInstanceInfo/validation_result"; @@ -105,6 +106,7 @@ public class ViewInstanceResourceProvider extends AbstractResourceProvider { propertyIds.add(DATA_PROPERTY_ID); propertyIds.add(CONTEXT_PATH_PROPERTY_ID); propertyIds.add(STATIC_PROPERTY_ID); + propertyIds.add(CLUSTER_HANDLE_PROPERTY_ID); propertyIds.add(VALIDATION_RESULT_PROPERTY_ID); propertyIds.add(PROPERTY_VALIDATION_RESULTS_PROPERTY_ID); } @@ -229,6 +231,7 @@ public class ViewInstanceResourceProvider extends AbstractResourceProvider { setResourceProperty(resource, DESCRIPTION_PROPERTY_ID, viewInstanceEntity.getDescription(), requestedIds); setResourceProperty(resource, VISIBLE_PROPERTY_ID, viewInstanceEntity.isVisible(), requestedIds); setResourceProperty(resource, STATIC_PROPERTY_ID, viewInstanceEntity.isXmlDriven(), requestedIds); + setResourceProperty(resource, CLUSTER_HANDLE_PROPERTY_ID, viewInstanceEntity.getClusterHandle(), requestedIds); // only allow an admin to access the view properties if (ViewRegistry.getInstance().checkAdmin()) { @@ -326,6 +329,10 @@ public class ViewInstanceResourceProvider extends AbstractResourceProvider { viewInstanceEntity.setIcon64((String) properties.get(ICON64_PATH_ID)); } + if (properties.containsKey(CLUSTER_HANDLE_PROPERTY_ID)) { + viewInstanceEntity.setClusterHandle((String) properties.get(CLUSTER_HANDLE_PROPERTY_ID)); + } + Map<String, String> instanceProperties = new HashMap<String, String>(); boolean isUserAdmin = viewRegistry.checkAdmin(); http://git-wip-us.apache.org/repos/asf/ambari/blob/acdaae98/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewVersionResourceProvider.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewVersionResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewVersionResourceProvider.java index 95703fd..6352817 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewVersionResourceProvider.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ViewVersionResourceProvider.java @@ -56,6 +56,7 @@ public class ViewVersionResourceProvider extends AbstractResourceProvider { public static final String MASKER_CLASS_PROPERTY_ID = "ViewVersionInfo/masker_class"; public static final String VIEW_STATUS_PROPERTY_ID = "ViewVersionInfo/status"; public static final String VIEW_STATUS_DETAIL_PROPERTY_ID = "ViewVersionInfo/status_detail"; + public static final String CLUSTER_CONFIG_PROPERTY_ID = "ViewVersionInfo/cluster_configurable"; public static final String SYSTEM_PROPERTY_ID = "ViewVersionInfo/system"; /** @@ -84,6 +85,7 @@ public class ViewVersionResourceProvider extends AbstractResourceProvider { propertyIds.add(MASKER_CLASS_PROPERTY_ID); propertyIds.add(VIEW_STATUS_PROPERTY_ID); propertyIds.add(VIEW_STATUS_DETAIL_PROPERTY_ID); + propertyIds.add(CLUSTER_CONFIG_PROPERTY_ID); propertyIds.add(SYSTEM_PROPERTY_ID); } @@ -145,6 +147,7 @@ public class ViewVersionResourceProvider extends AbstractResourceProvider { setResourceProperty(resource, MASKER_CLASS_PROPERTY_ID, viewDefinition.getMask(), requestedIds); setResourceProperty(resource, VIEW_STATUS_PROPERTY_ID, viewDefinition.getStatus().toString(), requestedIds); setResourceProperty(resource, VIEW_STATUS_DETAIL_PROPERTY_ID, viewDefinition.getStatusDetail(), requestedIds); + setResourceProperty(resource, CLUSTER_CONFIG_PROPERTY_ID, viewDefinition.isClusterConfigurable(), requestedIds); setResourceProperty(resource, SYSTEM_PROPERTY_ID, viewDefinition.isSystem(), requestedIds); resources.add(resource); http://git-wip-us.apache.org/repos/asf/ambari/blob/acdaae98/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewEntity.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewEntity.java index f77c97e..6039fb6 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewEntity.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewEntity.java @@ -22,6 +22,7 @@ import org.apache.ambari.server.configuration.Configuration; import org.apache.ambari.server.controller.spi.Resource; import org.apache.ambari.server.controller.spi.ResourceProvider; import org.apache.ambari.server.view.ViewSubResourceDefinition; +import org.apache.ambari.server.view.configuration.ParameterConfig; import org.apache.ambari.server.view.configuration.ResourceConfig; import org.apache.ambari.server.view.configuration.ViewConfig; import org.apache.ambari.view.validation.Validator; @@ -229,6 +230,12 @@ public class ViewEntity implements ViewDefinition { @Transient private String statusDetail; + /** + * Indicates whether or not this view is configurable through cluster association. + */ + @Transient + private boolean clusterConfigurable; + // ----- Constructors ------------------------------------------------------ @@ -241,6 +248,7 @@ public class ViewEntity implements ViewDefinition { this.archive = null; this.externalResourceType = null; this.system = 0; + this.clusterConfigurable = false; } /** @@ -252,7 +260,8 @@ public class ViewEntity implements ViewDefinition { */ public ViewEntity(ViewConfig configuration, Configuration ambariConfiguration, String archivePath) { - this.configuration = configuration; + setConfiguration(configuration); + this.ambariConfiguration = ambariConfiguration; this.archive = archivePath; @@ -690,7 +699,17 @@ public class ViewEntity implements ViewDefinition { * @param configuration the view configuration */ public void setConfiguration(ViewConfig configuration) { - this.configuration = configuration; + this.configuration = configuration; + this.clusterConfigurable = false; + + // if any of the parameters contain a cluster config element then the view is cluster configurable + for (ParameterConfig parameterConfig : configuration.getParameters()) { + String clusterConfig = parameterConfig.getClusterConfig(); + if (clusterConfig != null && !clusterConfig.isEmpty()) { + this.clusterConfigurable = true; + return; + } + } } /** @@ -820,6 +839,15 @@ public class ViewEntity implements ViewDefinition { } /** + * Determine whether or not this view is configurable through a cluster association. + * + * @return true if this view is cluster configurable + */ + public boolean isClusterConfigurable() { + return clusterConfigurable; + } + + /** * Determine whether or not the entity is deployed. * * @return true if the entity is deployed http://git-wip-us.apache.org/repos/asf/ambari/blob/acdaae98/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java index d55f949..a66f1bd 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewInstanceEntity.java @@ -112,6 +112,12 @@ public class ViewInstanceEntity implements ViewInstanceDefinition { private String description; /** + * The associated cluster handle. + */ + @Column(name = "cluster_handle", nullable = true) + private String clusterHandle; + + /** * Visible flag. */ @Column @@ -217,6 +223,7 @@ public class ViewInstanceEntity implements ViewInstanceDefinition { this.view = view; this.viewName = view.getName(); this.description = instanceConfig.getDescription(); + this.clusterHandle = null; this.visible = instanceConfig.isVisible() ? 'Y' : 'N'; String label = instanceConfig.getLabel(); @@ -252,6 +259,7 @@ public class ViewInstanceEntity implements ViewInstanceDefinition { this.view = view; this.viewName = view.getName(); this.description = null; + this.clusterHandle = null; this.visible = 'Y'; this.label = label; } @@ -315,6 +323,11 @@ public class ViewInstanceEntity implements ViewInstanceDefinition { } @Override + public String getClusterHandle() { + return clusterHandle; + } + + @Override public boolean isVisible() { return visible == 'y' || visible == 'Y'; } @@ -386,6 +399,17 @@ public class ViewInstanceEntity implements ViewInstanceDefinition { } /** + * Set a cluster association for this view instance with the Ambari cluster + * identified by the given cluster handle. For a local cluster reference, + * the cluster handle is simply the unique cluster name. + * + * @param clusterHandle the cluster identifier + */ + public void setClusterHandle(String clusterHandle) { + this.clusterHandle = clusterHandle; + } + + /** * Set the visible flag. * * @param visible visible flag http://git-wip-us.apache.org/repos/asf/ambari/blob/acdaae98/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewParameterEntity.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewParameterEntity.java b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewParameterEntity.java index a8ddcdb..5419d58 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewParameterEntity.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/orm/entities/ViewParameterEntity.java @@ -69,6 +69,12 @@ public class ViewParameterEntity { private String defaultValue; /** + * The cluster configuration id used to populate the property through cluster association. + */ + @Column(name = "cluster_config") + private String clusterConfig; + + /** * Indicates whether or not the parameter is required. */ @Column @@ -249,4 +255,24 @@ public class ViewParameterEntity { public void setDefaultValue(String defaultValue) { this.defaultValue = defaultValue; } + + /** + * Get the cluster configuration id used to populate the property for this parameter through + * cluster association. + * + * @return the cluster configuration id + */ + public String getClusterConfig() { + return clusterConfig; + } + + /** + * Set the cluster configuration id used to populate the property for this parameter through + * cluster association. + * + * @param clusterConfig the cluster configuration id + */ + public void setClusterConfig(String clusterConfig) { + this.clusterConfig = clusterConfig; + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/acdaae98/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog210.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog210.java b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog210.java index 064f536..7bdfb4f 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog210.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/upgrade/UpgradeCatalog210.java @@ -57,6 +57,8 @@ public class UpgradeCatalog210 extends AbstractUpgradeCatalog { private static final String USER_WIDGET_TABLE = "user_widget"; private static final String WIDGET_LAYOUT_TABLE = "widget_layout"; private static final String WIDGET_LAYOUT_USER_WIDGET_TABLE = "widget_layout_user_widget"; + private static final String VIEW_INSTANCE_TABLE = "viewinstance"; + private static final String VIEW_PARAMETER_TABLE = "viewparameter"; /** * {@inheritDoc} @@ -230,6 +232,10 @@ public class UpgradeCatalog210 extends AbstractUpgradeCatalog { "host_id", HOSTS_TABLE, "id", false); dbAccessor.dropColumn(CLUSTER_HOST_MAPPING_TABLE, "host_name"); + + // view columns for cluster association + dbAccessor.addColumn(VIEW_INSTANCE_TABLE, new DBColumnInfo("cluster_handle", String.class, 255, null, true)); + dbAccessor.addColumn(VIEW_PARAMETER_TABLE, new DBColumnInfo("cluster_config", String.class, 255, null, true)); } private void executeWidgetDDLUpdates() throws AmbariException, SQLException { http://git-wip-us.apache.org/repos/asf/ambari/blob/acdaae98/ambari-server/src/main/java/org/apache/ambari/server/view/ClusterImpl.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/ClusterImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/view/ClusterImpl.java new file mode 100644 index 0000000..529e09a --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/view/ClusterImpl.java @@ -0,0 +1,61 @@ +/** + * 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.view; + +import org.apache.ambari.server.state.Config; +import org.apache.ambari.view.cluster.Cluster; + +/** + * View associated cluster implementation. + */ +public class ClusterImpl implements Cluster { + + /** + * The associated Ambari cluster. + */ + private final org.apache.ambari.server.state.Cluster cluster; + + + // ----- Constructors ------------------------------------------------------ + + /** + * Create a view associated cluster from an Ambari cluster. + * + * @param cluster the Ambari cluster + */ + public ClusterImpl(org.apache.ambari.server.state.Cluster cluster) { + this.cluster = cluster; + } + + + // ----- Cluster ----------------------------------------------------------- + + @Override + public String getName() { + return cluster.getClusterName(); + } + + @Override + public String getConfigurationValue(String type, String key) { + + Config config = cluster.getDesiredConfigByType(type); + + return config == null ? null : config.getProperties().get(key); + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/acdaae98/ambari-server/src/main/java/org/apache/ambari/server/view/ViewContextImpl.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewContextImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewContextImpl.java index b7a48a8..9a4aae2 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewContextImpl.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewContextImpl.java @@ -42,9 +42,9 @@ import org.apache.ambari.view.ViewContext; import org.apache.ambari.view.ViewController; import org.apache.ambari.view.ViewDefinition; import org.apache.ambari.view.ViewInstanceDefinition; +import org.apache.ambari.view.cluster.Cluster; import org.apache.ambari.view.events.Event; import org.apache.ambari.view.events.Listener; -import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.velocity.VelocityContext; @@ -55,6 +55,7 @@ import java.io.StringWriter; import java.io.Writer; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Map.Entry; @@ -104,8 +105,12 @@ public class ViewContextImpl implements ViewContext, ViewController { */ private Masker masker; + /** + * The velocity context used to evaluate property templates. + */ private final VelocityContext velocityContext; + // ---- Constructors ------------------------------------------------------- /** @@ -163,40 +168,7 @@ public class ViewContextImpl implements ViewContext, ViewController { if (viewInstanceEntity == null) { return null; } else { - Map<String, String> properties = viewInstanceEntity.getPropertyMap(); - - // unmasking - for (Entry<String, String> entry: properties.entrySet()) { - ParameterConfig parameterConfig = null; - for (ParameterConfig paramConfig : viewEntity.getConfiguration().getParameters()) { - if (StringUtils.equals(paramConfig.getName(), entry.getKey())) { - parameterConfig = paramConfig; - break; - } - } - if (parameterConfig == null || !parameterConfig.isMasked()) { - properties.put(entry.getKey(), entry.getValue()); - } else { - try { - properties.put(entry.getKey(), masker.unmask(entry.getValue())); - } catch (MaskException e) { - LOG.error("Failed to unmask view property", e); - } - } - } - - // parametrizing - - String rawValue; - for (String key : properties.keySet()) { - rawValue = properties.get(key); - try { - properties.put(key, parameterize(rawValue)); - } catch (ParseErrorException ex) { - LOG.warn(String.format("Error during parsing '%s' parameter. Leaving original value.", key)); - } - } - return Collections.unmodifiableMap(properties); + return Collections.unmodifiableMap(getPropertyValues()); } } @@ -339,6 +311,11 @@ public class ViewContextImpl implements ViewContext, ViewController { return new ImpersonatorSettingImpl(this); } + @Override + public Cluster getCluster() { + return viewRegistry.getCluster(viewInstanceEntity); + } + // ----- ViewController ---------------------------------------------------- @@ -396,24 +373,86 @@ public class ViewContextImpl implements ViewContext, ViewController { } /** - * Parameterize string using VelocityContext instance + * Get the property values for the associated view instance. * - * @param raw original string with parameters in formal or shorthand notation + * @return the property values for the instance + */ + private Map<String, String> getPropertyValues() { + Map<String, String> properties = viewInstanceEntity.getPropertyMap(); + + Map<String, ParameterConfig> parameters = new HashMap<String, ParameterConfig>(); + + for (ParameterConfig paramConfig : viewEntity.getConfiguration().getParameters()) { + parameters.put(paramConfig.getName(), paramConfig); + } + + Cluster cluster = getCluster(); + + for (Entry<String, String> entry: properties.entrySet()) { + String propertyName = entry.getKey(); + String propertyValue = entry.getValue(); + + ParameterConfig parameterConfig = parameters.get(propertyName); + + if (parameterConfig != null) { + + String clusterConfig = parameterConfig.getClusterConfig(); + if (clusterConfig != null && cluster != null) { + propertyValue = getClusterConfigurationValue(cluster, clusterConfig); + } else { + if (parameterConfig.isMasked()) { + try { + propertyValue = masker.unmask(propertyValue); + } catch (MaskException e) { + LOG.error("Failed to unmask view property", e); + } + } + } + } + properties.put(propertyName, evaluatePropertyTemplates(propertyValue)); + } + return properties; + } + + /** + * Get a specified configuration value from the given cluster. * - * @return parameterized string + * @param cluster the cluster + * @param clusterConfig the cluster configuration identifier * - * @throws ParseErrorException if original string cannot be parsed by Velocity + * @return the configuration value or <code>null</code> if the desired configuration can not be found */ - private String parameterize(String raw) throws ParseErrorException { - if (raw != null) { - Writer templateWriter = new StringWriter(); - Velocity.evaluate(velocityContext, templateWriter, raw, raw); - return templateWriter.toString(); + private static String getClusterConfigurationValue(Cluster cluster, String clusterConfig) { + if (clusterConfig != null) { + String[] parts = clusterConfig.split("/"); + if (parts.length == 2) { + return cluster.getConfigurationValue(parts[0], parts[1]); + } } return null; } /** + * Evaluate any templates in the given property value. + * + * @param rawValue original string with parameters in formal or shorthand notation + * + * @return the evaluated property value + */ + private String evaluatePropertyTemplates(String rawValue) { + if (rawValue != null) { + try { + Writer templateWriter = new StringWriter(); + Velocity.evaluate(velocityContext, templateWriter, rawValue, rawValue); + return templateWriter.toString(); + } catch (ParseErrorException e) { + LOG.warn(String.format("Error during parsing '%s' parameter. Leaving original value.", rawValue)); + } + } + return rawValue; + } + + /** * Instantiate and initialize context for parameters processing using Velocity. * * @return initialized context instance http://git-wip-us.apache.org/repos/asf/ambari/blob/acdaae98/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java index 419ba02..1ae1dfd 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/view/ViewRegistry.java @@ -24,6 +24,7 @@ import com.google.inject.Guice; import com.google.inject.Injector; import com.google.inject.persist.Transactional; +import org.apache.ambari.server.AmbariException; import org.apache.ambari.server.api.resources.ResourceInstanceFactoryImpl; import org.apache.ambari.server.api.resources.SubResourceDefinition; import org.apache.ambari.server.api.resources.ViewExternalSubResourceDefinition; @@ -60,6 +61,7 @@ import org.apache.ambari.server.orm.entities.ViewParameterEntity; import org.apache.ambari.server.orm.entities.ViewResourceEntity; import org.apache.ambari.server.security.SecurityHelper; import org.apache.ambari.server.security.authorization.AmbariGrantedAuthority; +import org.apache.ambari.server.state.Clusters; import org.apache.ambari.server.utils.VersionUtils; import org.apache.ambari.server.view.configuration.EntityConfig; import org.apache.ambari.server.view.configuration.InstanceConfig; @@ -70,6 +72,8 @@ import org.apache.ambari.server.view.configuration.PropertyConfig; import org.apache.ambari.server.view.configuration.ResourceConfig; import org.apache.ambari.server.view.configuration.ViewConfig; import org.apache.ambari.server.view.validation.ValidationException; +import org.apache.ambari.view.ViewInstanceDefinition; +import org.apache.ambari.view.cluster.Cluster; import org.apache.ambari.view.validation.Validator; import org.apache.ambari.view.Masker; import org.apache.ambari.view.SystemException; @@ -211,10 +215,16 @@ public class ViewRegistry { ResourceTypeDAO resourceTypeDAO; /** + * The Ambari managed clusters. + */ + @Inject + Provider<Clusters> clustersProvider; + + /** * Ambari meta info. */ @Inject - Provider<AmbariMetaInfo> ambariMetaInfo; + Provider<AmbariMetaInfo> ambariMetaInfoProvider; /** * Ambari configuration. @@ -811,6 +821,27 @@ public class ViewRegistry { } } + /** + * Get the cluster associated with the given view instance. + * + * @param viewInstance the view instance + * + * @return the cluster + */ + public Cluster getCluster(ViewInstanceDefinition viewInstance) { + if (viewInstance != null) { + String clusterId = viewInstance.getClusterHandle(); + + if (clusterId != null) { + try { + return new ClusterImpl(clustersProvider.get().getCluster(clusterId)); + } catch (AmbariException e) { + LOG.warn("Could not find the cluster identified by " + clusterId + "."); + } + } + } + return null; + } // ----- helper methods ---------------------------------------------------- @@ -861,6 +892,7 @@ public class ViewRegistry { viewParameterEntity.setLabel(parameterConfiguration.getLabel()); viewParameterEntity.setPlaceholder(parameterConfiguration.getPlaceholder()); viewParameterEntity.setDefaultValue(parameterConfiguration.getDefaultValue()); + viewParameterEntity.setClusterConfig(parameterConfiguration.getClusterConfig()); viewParameterEntity.setRequired(parameterConfiguration.isRequired()); viewParameterEntity.setMasked(parameterConfiguration.isMasked()); viewParameterEntity.setViewEntity(viewDefinition); @@ -1016,8 +1048,8 @@ public class ViewRegistry { // Set the entities defined in the view persistence element for the given view instance private static void setPersistenceEntities(ViewInstanceEntity viewInstanceDefinition) { - ViewEntity viewDefinition = viewInstanceDefinition.getViewEntity(); - ViewConfig viewConfig = viewDefinition.getConfiguration(); + ViewEntity viewDefinition = viewInstanceDefinition.getViewEntity(); + ViewConfig viewConfig = viewDefinition.getConfiguration(); Collection<ViewEntityEntity> entities = new HashSet<ViewEntityEntity>(); @@ -1205,6 +1237,7 @@ public class ViewRegistry { instance1.setVisible(instance2.isVisible()); instance1.setResource(instance2.getResource()); instance1.setViewInstanceId(instance2.getViewInstanceId()); + instance1.setClusterHandle(instance2.getClusterHandle()); instance1.setData(instance2.getData()); instance1.setEntities(instance2.getEntities()); instance1.setProperties(instance2.getProperties()); @@ -1292,7 +1325,7 @@ public class ViewRegistry { Set<Runnable> extractionRunnables = new HashSet<Runnable>(); - final String serverVersion = ambariMetaInfo.get().getServerVersion(); + final String serverVersion = ambariMetaInfoProvider.get().getServerVersion(); for (final File archiveFile : files) { if (!archiveFile.isDirectory()) { http://git-wip-us.apache.org/repos/asf/ambari/blob/acdaae98/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ParameterConfig.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ParameterConfig.java b/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ParameterConfig.java index e983609..8e686eb 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ParameterConfig.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/view/configuration/ParameterConfig.java @@ -54,6 +54,12 @@ public class ParameterConfig { private String defaultValue; /** + * The parameter cluster configuration id value. + */ + @XmlElement(name="cluster-config") + private String clusterConfig; + + /** * Indicates whether or not the parameter is required. */ private boolean required; @@ -109,6 +115,15 @@ public class ParameterConfig { } /** + * Get the cluster configuration id used to pull configuration from an associated Ambari cluster. + * + * @return the cluster configuration id + */ + public String getClusterConfig() { + return clusterConfig; + } + + /** * Indicates whether or not the parameter is required. * * @return true if the parameter is required; false otherwise http://git-wip-us.apache.org/repos/asf/ambari/blob/acdaae98/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 26ff9bb..e28edfd 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-MySQL-CREATE.sql @@ -456,6 +456,7 @@ CREATE TABLE viewinstance ( icon VARCHAR(255), icon64 VARCHAR(255), xml_driven CHAR(1), + cluster_handle VARCHAR(255), PRIMARY KEY(view_instance_id)); CREATE TABLE viewinstanceproperty ( @@ -472,6 +473,7 @@ CREATE TABLE viewparameter ( label VARCHAR(255), placeholder VARCHAR(255), default_value VARCHAR(2000), + cluster_config VARCHAR(255), required CHAR(1), masked CHAR(1), PRIMARY KEY(view_name, name)); http://git-wip-us.apache.org/repos/asf/ambari/blob/acdaae98/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 13e8939..513d951 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Oracle-CREATE.sql @@ -445,6 +445,7 @@ CREATE TABLE viewinstance ( icon VARCHAR(255), icon64 VARCHAR(255), xml_driven CHAR(1), + cluster_handle VARCHAR(255), PRIMARY KEY(view_instance_id)); CREATE TABLE viewinstanceproperty ( @@ -461,6 +462,7 @@ CREATE TABLE viewparameter ( label VARCHAR(255), placeholder VARCHAR(255), default_value VARCHAR(2000), + cluster_config VARCHAR(255), required CHAR(1), masked CHAR(1), PRIMARY KEY(view_name, name)); http://git-wip-us.apache.org/repos/asf/ambari/blob/acdaae98/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 622fca3..6361edb 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-Postgres-CREATE.sql @@ -448,6 +448,7 @@ CREATE TABLE viewinstance ( icon VARCHAR(255), icon64 VARCHAR(255), xml_driven CHAR(1), + cluster_handle VARCHAR(255), PRIMARY KEY(view_instance_id)); CREATE TABLE viewinstanceproperty ( @@ -464,6 +465,7 @@ CREATE TABLE viewparameter ( label VARCHAR(255), placeholder VARCHAR(255), default_value VARCHAR(2000), + cluster_config VARCHAR(255), required CHAR(1), masked CHAR(1), PRIMARY KEY(view_name, name)); http://git-wip-us.apache.org/repos/asf/ambari/blob/acdaae98/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 9fe9cd7..2121805 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 @@ -501,6 +501,7 @@ CREATE TABLE ambari.viewinstance ( icon VARCHAR(255), icon64 VARCHAR(255), xml_driven CHAR(1), + cluster_handle VARCHAR(255), PRIMARY KEY(view_instance_id)); CREATE TABLE ambari.viewinstanceproperty ( @@ -517,6 +518,7 @@ CREATE TABLE ambari.viewparameter ( label VARCHAR(255), placeholder VARCHAR(255), default_value VARCHAR(2000), + cluster_config VARCHAR(255), required CHAR(1), masked CHAR(1), PRIMARY KEY(view_name, name)); http://git-wip-us.apache.org/repos/asf/ambari/blob/acdaae98/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 a722d2a..40b00d9 100644 --- a/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql +++ b/ambari-server/src/main/resources/Ambari-DDL-SQLServer-CREATE.sql @@ -97,9 +97,9 @@ CREATE TABLE blueprint_configuration (blueprint_name varchar(255) NOT NULL, type CREATE TABLE hostgroup_configuration (blueprint_name VARCHAR(255) NOT NULL, hostgroup_name VARCHAR(255) NOT NULL, type_name VARCHAR(255) NOT NULL, config_data TEXT NOT NULL, config_attributes TEXT, PRIMARY KEY(blueprint_name, hostgroup_name, type_name)); CREATE TABLE viewmain (view_name VARCHAR(255) NOT NULL, label VARCHAR(255), description VARCHAR(2048), version VARCHAR(255), resource_type_id INTEGER NOT NULL, icon VARCHAR(255), icon64 VARCHAR(255), archive VARCHAR(255), mask VARCHAR(255), system_view BIT NOT NULL DEFAULT 0, PRIMARY KEY(view_name)); CREATE TABLE viewinstancedata (view_instance_id BIGINT, view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, user_name VARCHAR(255) NOT NULL, value VARCHAR(2000) NOT NULL, PRIMARY KEY(view_instance_id, name, user_name)); -CREATE TABLE viewinstance (view_instance_id BIGINT, resource_id BIGINT NOT NULL, view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, label VARCHAR(255), description VARCHAR(2048), visible CHAR(1), icon VARCHAR(255), icon64 VARCHAR(255), xml_driven CHAR(1), PRIMARY KEY(view_instance_id)); +CREATE TABLE viewinstance (view_instance_id BIGINT, resource_id BIGINT NOT NULL, view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, label VARCHAR(255), description VARCHAR(2048), visible CHAR(1), icon VARCHAR(255), icon64 VARCHAR(255), xml_driven CHAR(1), cluster_handle VARCHAR(255), PRIMARY KEY(view_instance_id)); CREATE TABLE viewinstanceproperty (view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, value VARCHAR(2000) NOT NULL, PRIMARY KEY(view_name, view_instance_name, name)); -CREATE TABLE viewparameter (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, description VARCHAR(2048), label VARCHAR(255), placeholder VARCHAR(255), default_value VARCHAR(2000), required CHAR(1), masked CHAR(1), PRIMARY KEY(view_name, name)); +CREATE TABLE viewparameter (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, description VARCHAR(2048), label VARCHAR(255), placeholder VARCHAR(255), default_value VARCHAR(2000), cluster_config VARCHAR(255), required CHAR(1), masked CHAR(1), PRIMARY KEY(view_name, name)); CREATE TABLE viewresource (view_name VARCHAR(255) NOT NULL, name VARCHAR(255) NOT NULL, plural_name VARCHAR(255), id_property VARCHAR(255), subResource_names VARCHAR(255), provider VARCHAR(255), service VARCHAR(255), resource VARCHAR(255), PRIMARY KEY(view_name, name)); CREATE TABLE viewentity (id BIGINT NOT NULL, view_name VARCHAR(255) NOT NULL, view_instance_name VARCHAR(255) NOT NULL, class_name VARCHAR(255) NOT NULL, id_property VARCHAR(255), PRIMARY KEY(id)); CREATE TABLE adminresourcetype (resource_type_id INTEGER NOT NULL, resource_type_name VARCHAR(255) NOT NULL, PRIMARY KEY(resource_type_id)); http://git-wip-us.apache.org/repos/asf/ambari/blob/acdaae98/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ViewInstanceResourceProviderTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ViewInstanceResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ViewInstanceResourceProviderTest.java index 31c65c3..1af7264 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ViewInstanceResourceProviderTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ViewInstanceResourceProviderTest.java @@ -62,6 +62,7 @@ public class ViewInstanceResourceProviderTest { ViewInstanceResourceProvider provider = new ViewInstanceResourceProvider(); Set<String> propertyIds = new HashSet<String>(); propertyIds.add(ViewInstanceResourceProvider.PROPERTIES_PROPERTY_ID); + propertyIds.add(ViewInstanceResourceProvider.CLUSTER_HANDLE_PROPERTY_ID); ViewInstanceEntity viewInstanceEntity = createNiceMock(ViewInstanceEntity.class); ViewEntity viewEntity = createNiceMock(ViewEntity.class); expect(viewInstanceEntity.getViewEntity()).andReturn(viewEntity).anyTimes(); @@ -78,13 +79,20 @@ public class ViewInstanceResourceProviderTest { expect(singleton.checkAdmin()).andReturn(true); expect(singleton.checkAdmin()).andReturn(false); + expect(viewInstanceEntity.getClusterHandle()).andReturn("c1"); + replay(singleton, viewEntity, viewInstanceEntity); // as admin Resource resource = provider.toResource(viewInstanceEntity, propertyIds); Map<String, Map<String, Object>> properties = resource.getPropertiesMap(); - assertEquals(1, properties.size()); - Map<String, Object> props = properties.get("ViewInstanceInfo/properties"); + assertEquals(2, properties.size()); + Map<String, Object> props = properties.get("ViewInstanceInfo"); + assertNotNull(props); + assertEquals(1, props.size()); + assertEquals("c1", props.get("cluster_handle")); + + props = properties.get("ViewInstanceInfo/properties"); assertNotNull(props); assertEquals(2, props.size()); assertEquals("val1", props.get("par1")); http://git-wip-us.apache.org/repos/asf/ambari/blob/acdaae98/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/ViewEntityTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/ViewEntityTest.java b/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/ViewEntityTest.java index a9ceb93..ac2715c 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/ViewEntityTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/orm/entities/ViewEntityTest.java @@ -140,6 +140,21 @@ public class ViewEntityTest { } @Test + public void testIsClusterConfigurable() throws Exception { + ViewConfig viewConfig = ViewConfigTest.getConfig(); + ViewEntity viewDefinition = getViewEntity(viewConfig); + Assert.assertEquals(viewConfig, viewDefinition.getConfiguration()); + + ViewConfig newViewConfig = ViewConfigTest.getConfig(); + viewDefinition.setConfiguration(newViewConfig); + Assert.assertTrue(viewDefinition.isClusterConfigurable()); + + newViewConfig = ViewConfigTest.getConfig(with_ambari_versions); + viewDefinition.setConfiguration(newViewConfig); + Assert.assertFalse(viewDefinition.isClusterConfigurable()); + } + + @Test public void testGetAmbariProperty() throws Exception { ViewConfig viewConfig = ViewConfigTest.getConfig(); ViewEntity viewDefinition = getViewEntity(viewConfig); http://git-wip-us.apache.org/repos/asf/ambari/blob/acdaae98/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog210Test.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog210Test.java b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog210Test.java index 07b8410..47cadf3 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog210Test.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/upgrade/UpgradeCatalog210Test.java @@ -98,10 +98,15 @@ public class UpgradeCatalog210Test { // Column Capture section Capture<DBAccessor.DBColumnInfo> hostsColumnCapture = new Capture<DBAccessor.DBColumnInfo>(); + Capture<DBAccessor.DBColumnInfo> viewInstanceColumnCapture = new Capture<DBAccessor.DBColumnInfo>(); + Capture<DBAccessor.DBColumnInfo> viewParamColumnCapture = new Capture<DBAccessor.DBColumnInfo>(); // Add columns and alter table section dbAccessor.addColumn(eq("hosts"), capture(hostsColumnCapture)); + dbAccessor.addColumn(eq("viewinstance"), capture(viewInstanceColumnCapture)); + dbAccessor.addColumn(eq("viewparameter"), capture(viewParamColumnCapture)); + Capture<List<DBColumnInfo>> userWidgetColumnsCapture = new Capture<List<DBColumnInfo>>(); Capture<List<DBColumnInfo>> widgetLayoutColumnsCapture = new Capture<List<DBColumnInfo>>(); Capture<List<DBColumnInfo>> widgetLayoutUserWidgetColumnsCapture = new Capture<List<DBColumnInfo>>(); @@ -133,6 +138,8 @@ public class UpgradeCatalog210Test { // Verification section verifyHosts(hostsColumnCapture); + verifyViewInstance(viewInstanceColumnCapture); + verifyViewParameter(viewParamColumnCapture); // Verify widget tables @@ -147,6 +154,19 @@ public class UpgradeCatalog210Test { Assert.assertEquals("id", hostsIdColumn.getName()); } + private void verifyViewInstance(Capture<DBAccessor.DBColumnInfo> viewInstanceColumnCapture) { + DBColumnInfo clusterIdColumn = viewInstanceColumnCapture.getValue(); + Assert.assertEquals(String.class, clusterIdColumn.getType()); + Assert.assertEquals("cluster_handle", clusterIdColumn.getName()); + } + + + private void verifyViewParameter(Capture<DBAccessor.DBColumnInfo> viewParamColumnCapture) { + DBColumnInfo clusterConfigColumn = viewParamColumnCapture.getValue(); + Assert.assertEquals(String.class, clusterConfigColumn.getType()); + Assert.assertEquals("cluster_config", clusterConfigColumn.getName()); + } + /** * @param dbAccessor * @return http://git-wip-us.apache.org/repos/asf/ambari/blob/acdaae98/ambari-server/src/test/java/org/apache/ambari/server/view/ClusterImplTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/view/ClusterImplTest.java b/ambari-server/src/test/java/org/apache/ambari/server/view/ClusterImplTest.java new file mode 100644 index 0000000..daf87ec --- /dev/null +++ b/ambari-server/src/test/java/org/apache/ambari/server/view/ClusterImplTest.java @@ -0,0 +1,76 @@ +/** + * 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.view; + +import org.apache.ambari.server.state.Cluster; +import org.apache.ambari.server.state.Config; +import org.apache.ambari.server.view.configuration.InstanceConfig; +import org.junit.Assert; +import org.junit.Test; + +import java.util.HashMap; +import java.util.Map; + +import static org.easymock.EasyMock.createNiceMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; +import static org.junit.Assert.*; + +/** + * ClusterImpl tests. + */ +public class ClusterImplTest { + + @Test + public void testGetName() throws Exception { + Cluster cluster = createNiceMock(Cluster.class); + + expect(cluster.getClusterName()).andReturn("c1").anyTimes(); + + replay(cluster); + + ClusterImpl clusterImpl = new ClusterImpl(cluster); + + Assert.assertEquals("c1", clusterImpl.getName()); + + verify(cluster); + } + + @Test + public void testGetConfigurationValue() throws Exception { + Cluster cluster = createNiceMock(Cluster.class); + Config config = createNiceMock(Config.class); + + Map<String, String> properties = new HashMap<String, String>(); + + properties.put("foo", "bar"); + + expect(cluster.getDesiredConfigByType("core-site")).andReturn(config).anyTimes(); + expect(config.getProperties()).andReturn(properties).anyTimes(); + + replay(cluster, config); + + ClusterImpl clusterImpl = new ClusterImpl(cluster); + + Assert.assertEquals("bar", clusterImpl.getConfigurationValue("core-site", "foo")); + + verify(cluster, config); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ambari/blob/acdaae98/ambari-server/src/test/java/org/apache/ambari/server/view/ViewContextImplTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/view/ViewContextImplTest.java b/ambari-server/src/test/java/org/apache/ambari/server/view/ViewContextImplTest.java index 84794e8..b470da2 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/view/ViewContextImplTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/view/ViewContextImplTest.java @@ -27,6 +27,7 @@ import org.apache.ambari.server.view.configuration.InstanceConfig; import org.apache.ambari.server.view.configuration.InstanceConfigTest; import org.apache.ambari.server.view.configuration.ViewConfigTest; import org.apache.ambari.view.ResourceProvider; +import org.apache.ambari.view.cluster.Cluster; import org.junit.Assert; import org.junit.Test; @@ -73,6 +74,9 @@ public class ViewContextImplTest { ViewEntity viewDefinition = ViewEntityTest.getViewEntity(); ViewInstanceEntity viewInstanceDefinition = new ViewInstanceEntity(viewDefinition, instanceConfig); ViewRegistry viewRegistry = createNiceMock(ViewRegistry.class); + + expect(viewRegistry.getCluster(viewInstanceDefinition)).andReturn(null).anyTimes(); + viewInstanceDefinition.putProperty("p1", "v1"); viewInstanceDefinition.putProperty("p2", new DefaultMasker().mask("v2")); viewInstanceDefinition.putProperty("p3", "v3"); @@ -90,8 +94,10 @@ public class ViewContextImplTest { @Test public void testGetPropertiesWithParameters() throws Exception { InstanceConfig instanceConfig = createNiceMock(InstanceConfig.class); + expect(instanceConfig.getName()).andReturn("Instance").anyTimes(); replay(instanceConfig); ViewEntity viewDefinition = createNiceMock(ViewEntity.class); + expect(viewDefinition.getName()).andReturn("View").anyTimes(); expect(viewDefinition.getCommonName()).andReturn("View").times(2); expect(viewDefinition.getClassLoader()).andReturn(ViewContextImplTest.class.getClassLoader()).anyTimes(); expect(viewDefinition.getConfiguration()).andReturn(ViewConfigTest.getConfig()).anyTimes(); @@ -110,10 +116,12 @@ public class ViewContextImplTest { .withConstructor(viewDefinition, instanceConfig).createMock(); expect(viewInstanceDefinition.getUsername()).andReturn("User").times(1); expect(viewInstanceDefinition.getUsername()).andReturn("User2").times(1); - expect(viewInstanceDefinition.getName()).andReturn("Instance").times(3); - expect(viewInstanceDefinition.getViewEntity()).andReturn(viewDefinition).times(1); + expect(viewInstanceDefinition.getName()).andReturn("Instance").anyTimes(); + expect(viewInstanceDefinition.getViewEntity()).andReturn(viewDefinition).anyTimes(); replay(viewInstanceDefinition); ViewRegistry viewRegistry = createNiceMock(ViewRegistry.class); + expect(viewRegistry.getCluster(viewInstanceDefinition)).andReturn(null).anyTimes(); + replay(viewRegistry); viewInstanceDefinition.putProperty("p1", "/tmp/some/path/${username}"); viewInstanceDefinition.putProperty("p2", new DefaultMasker().mask("/tmp/path/$viewName")); viewInstanceDefinition.putProperty("p3", "/path/$instanceName"); @@ -212,4 +220,24 @@ public class ViewContextImplTest { verify(viewRegistry); } + + @Test + public void testGetCluster() throws Exception { + InstanceConfig instanceConfig = InstanceConfigTest.getInstanceConfigs().get(0); + ViewEntity viewDefinition = ViewEntityTest.getViewEntity(); + ViewInstanceEntity viewInstanceDefinition = new ViewInstanceEntity(viewDefinition, instanceConfig); + ViewRegistry viewRegistry = createNiceMock(ViewRegistry.class); + + Cluster cluster = createNiceMock(Cluster.class); + + expect(viewRegistry.getCluster(viewInstanceDefinition)).andReturn(cluster); + + replay(viewRegistry); + + ViewContextImpl viewContext = new ViewContextImpl(viewInstanceDefinition, viewRegistry); + + Assert.assertEquals(cluster, viewContext.getCluster()); + + verify(viewRegistry); + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/acdaae98/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java b/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java index f5118e2..3a57b1b 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/view/ViewRegistryTest.java @@ -1617,7 +1617,7 @@ public class ViewRegistryTest { instance.extractor.archiveUtility = instance.archiveUtility; final AmbariMetaInfo finalMetaInfo = ambariMetaInfo; - instance.ambariMetaInfo = new Provider<AmbariMetaInfo>() { + instance.ambariMetaInfoProvider = new Provider<AmbariMetaInfo>() { @Override public AmbariMetaInfo get() { return finalMetaInfo; http://git-wip-us.apache.org/repos/asf/ambari/blob/acdaae98/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ParameterConfigTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ParameterConfigTest.java b/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ParameterConfigTest.java index 278e441..ce599b6 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ParameterConfigTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ParameterConfigTest.java @@ -74,6 +74,15 @@ public class ParameterConfigTest { } @Test + public void testGetClusterConfig() throws Exception { + List<ParameterConfig> parameters = getParameterConfigs(); + + Assert.assertEquals(2, parameters.size()); + Assert.assertNull(parameters.get(0).getClusterConfig()); + Assert.assertEquals("hdfs-site/dfs.namenode.http-address", parameters.get(1).getClusterConfig()); + } + + @Test public void testIsRequired() throws Exception { List<ParameterConfig> parameters = getParameterConfigs(); http://git-wip-us.apache.org/repos/asf/ambari/blob/acdaae98/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ViewConfigTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ViewConfigTest.java b/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ViewConfigTest.java index 75ab10a..1875238 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ViewConfigTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/view/configuration/ViewConfigTest.java @@ -66,6 +66,7 @@ public class ViewConfigTest { " <name>p2</name>\n" + " <description>Parameter 2.</description>\n" + " <default-value>Default value 1.</default-value>\n" + + " <cluster-config>hdfs-site/dfs.namenode.http-address</cluster-config>\n" + " <required>false</required>\n" + " <masked>true</masked>" + " </parameter>\n" + http://git-wip-us.apache.org/repos/asf/ambari/blob/acdaae98/ambari-views/src/main/java/org/apache/ambari/view/ViewContext.java ---------------------------------------------------------------------- diff --git a/ambari-views/src/main/java/org/apache/ambari/view/ViewContext.java b/ambari-views/src/main/java/org/apache/ambari/view/ViewContext.java index 432babb..2522486 100644 --- a/ambari-views/src/main/java/org/apache/ambari/view/ViewContext.java +++ b/ambari-views/src/main/java/org/apache/ambari/view/ViewContext.java @@ -18,6 +18,8 @@ package org.apache.ambari.view; +import org.apache.ambari.view.cluster.Cluster; + import java.util.Collection; import java.util.Map; @@ -187,13 +189,26 @@ public interface ViewContext { * Get the HTTP Impersonator. * * @return the HTTP Impersonator, which internally uses the App Cookie Manager + * + * @deprecated As of release 2.0 */ + @Deprecated public HttpImpersonator getHttpImpersonator(); /** * Get the default settings for the Impersonator. * * @return the Impersonator settings. + * + * @deprecated As of release 2.0 */ + @Deprecated public ImpersonatorSetting getImpersonatorSetting(); + + /** + * Get the cluster associated with this view instance. + * + * @return the associated cluster; <code>null</code> if no cluster is associated + */ + public Cluster getCluster(); } http://git-wip-us.apache.org/repos/asf/ambari/blob/acdaae98/ambari-views/src/main/java/org/apache/ambari/view/ViewInstanceDefinition.java ---------------------------------------------------------------------- diff --git a/ambari-views/src/main/java/org/apache/ambari/view/ViewInstanceDefinition.java b/ambari-views/src/main/java/org/apache/ambari/view/ViewInstanceDefinition.java index ff9090b..d694459 100644 --- a/ambari-views/src/main/java/org/apache/ambari/view/ViewInstanceDefinition.java +++ b/ambari-views/src/main/java/org/apache/ambari/view/ViewInstanceDefinition.java @@ -54,6 +54,14 @@ public interface ViewInstanceDefinition { public String getDescription(); /** + * Get the cluster handle associated with this view instance. For a local cluster reference, + * the cluster handle is simply the unique cluster name. + * + * @return the associated cluster handle; <code>null</code> if no cluster is associated + */ + public String getClusterHandle(); + + /** * Indicates whether or not the view instance should be visible. * * @return true if the view instance should be visible; false otherwise http://git-wip-us.apache.org/repos/asf/ambari/blob/acdaae98/ambari-views/src/main/java/org/apache/ambari/view/cluster/Cluster.java ---------------------------------------------------------------------- diff --git a/ambari-views/src/main/java/org/apache/ambari/view/cluster/Cluster.java b/ambari-views/src/main/java/org/apache/ambari/view/cluster/Cluster.java new file mode 100644 index 0000000..f1b8177 --- /dev/null +++ b/ambari-views/src/main/java/org/apache/ambari/view/cluster/Cluster.java @@ -0,0 +1,42 @@ +/** + * 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.view.cluster; + +/** + * View associated cluster. A cluster may be associated with a view instance so that the view instance may pull + * configuration values from the cluster. + */ +public interface Cluster { + /** + * Get the cluster name. + * + * @return the cluster name + */ + public String getName(); + + /** + * Get a value for the given configuration type and key. + * + * @param type the configuration id (i.e. hdfs-site) + * @param key the configuration key (i.e. dfs.namenode.http-address) + * + * @return the configuration value + */ + public String getConfigurationValue(String type, String key); +} http://git-wip-us.apache.org/repos/asf/ambari/blob/acdaae98/ambari-views/src/main/resources/view.xsd ---------------------------------------------------------------------- diff --git a/ambari-views/src/main/resources/view.xsd b/ambari-views/src/main/resources/view.xsd index e994faf..b5ed669 100644 --- a/ambari-views/src/main/resources/view.xsd +++ b/ambari-views/src/main/resources/view.xsd @@ -48,6 +48,11 @@ <xs:documentation>The default value of the configuration parameter.</xs:documentation> </xs:annotation> </xs:element> + <xs:element type="xs:string" name="cluster-config" minOccurs="0" maxOccurs="1"> + <xs:annotation> + <xs:documentation>The cluster configuration id. The presence of this element indicates that the property value may be obtained through a cluster association.</xs:documentation> + </xs:annotation> + </xs:element> <xs:element type="xs:boolean" name="required" minOccurs="0" maxOccurs="1" default="false"> <xs:annotation> <xs:documentation>If true, the configuration parameter is required in order to create a view instance. The default is false (not required).</xs:documentation>
