You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by nc...@apache.org on 2015/10/02 23:12:21 UTC
[17/32] ambari git commit: AMBARI-7469. Add Visibility Attributes to
Services. (Sebastian Toader via rnettleton)
AMBARI-7469. Add Visibility Attributes to Services. (Sebastian Toader via rnettleton)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/64769850
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/64769850
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/64769850
Branch: refs/heads/branch-dev-patch-upgrade
Commit: 64769850741b7aa39c5193040b9682df56cb3fbf
Parents: 3b41174
Author: Bob Nettleton <rn...@hortonworks.com>
Authored: Thu Oct 1 18:00:05 2015 -0400
Committer: Bob Nettleton <rn...@hortonworks.com>
Committed: Thu Oct 1 18:00:05 2015 -0400
----------------------------------------------------------------------
ambari-server/pom.xml | 6 +
.../server/controller/StackServiceResponse.java | 13 ++
.../internal/StackServiceResourceProvider.java | 89 +++++---
.../ambari/server/stack/ServiceModule.java | 82 ++++++-
.../apache/ambari/server/state/ServiceInfo.java | 138 ++++++++++--
.../server/state/ServicePropertyInfo.java | 77 +++++++
.../src/main/resources/properties.json | 1 +
.../controller/StackServiceResponseTest.java | 49 +++++
.../StackServiceResourceProviderTest.java | 152 +++++++++++++
.../ambari/server/stack/ServiceModuleTest.java | 183 ++++++++++++++--
.../ambari/server/state/ServiceInfoTest.java | 218 ++++++++++++++++++-
.../server/state/ServicePropertyInfoTest.java | 83 +++++++
12 files changed, 1018 insertions(+), 73 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/64769850/ambari-server/pom.xml
----------------------------------------------------------------------
diff --git a/ambari-server/pom.xml b/ambari-server/pom.xml
index 3377961..83f39ec 100644
--- a/ambari-server/pom.xml
+++ b/ambari-server/pom.xml
@@ -1913,6 +1913,12 @@
<scope>test</scope>
</dependency>
<dependency>
+ <groupId>nl.jqno.equalsverifier</groupId>
+ <artifactId>equalsverifier</artifactId>
+ <version>1.7.4</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<groupId>org.objenesis</groupId>
<artifactId>objenesis-tck</artifactId>
<version>1.2</version>
http://git-wip-us.apache.org/repos/asf/ambari/blob/64769850/ambari-server/src/main/java/org/apache/ambari/server/controller/StackServiceResponse.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/StackServiceResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/StackServiceResponse.java
index d16f4d6..ca1968e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/StackServiceResponse.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/StackServiceResponse.java
@@ -47,6 +47,8 @@ public class StackServiceResponse {
private List<String> requiredServices;
+ private Map<String, String> serviceProperties;
+
/**
* A File pointing to the service-level Kerberos descriptor file
*
@@ -84,6 +86,8 @@ public class StackServiceResponse {
}
kerberosDescriptorFile = service.getKerberosDescriptorFile();
+
+ serviceProperties = service.getServiceProperties();
}
public String getStackName() {
@@ -207,4 +211,13 @@ public String getServiceDisplayName() {
public List<String> getCustomCommands() {
return customCommands;
}
+
+ /**
+ * Get the service properties of this service.
+ * @return the properties or an empty map (never {@code null}).
+ */
+ public Map<String, String> getServiceProperties() {
+ return serviceProperties;
+ }
+
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/64769850/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackServiceResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackServiceResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackServiceResourceProvider.java
index dffc74c..6c6fa91 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackServiceResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/StackServiceResourceProvider.java
@@ -25,15 +25,23 @@ import org.apache.ambari.server.StaticallyInject;
import org.apache.ambari.server.controller.AmbariManagementController;
import org.apache.ambari.server.controller.StackServiceRequest;
import org.apache.ambari.server.controller.StackServiceResponse;
-import org.apache.ambari.server.controller.spi.*;
+import org.apache.ambari.server.controller.spi.NoSuchParentResourceException;
+import org.apache.ambari.server.controller.spi.NoSuchResourceException;
+import org.apache.ambari.server.controller.spi.Predicate;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.Resource;
import org.apache.ambari.server.controller.spi.Resource.Type;
+import org.apache.ambari.server.controller.spi.SystemException;
+import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
import org.apache.ambari.server.controller.utilities.PropertyHelper;
-import org.apache.ambari.server.state.kerberos.KerberosServiceDescriptor;
import org.apache.ambari.server.state.kerberos.KerberosServiceDescriptorFactory;
-import java.io.File;
-import java.io.IOException;
-import java.util.*;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
@StaticallyInject
public class StackServiceResourceProvider extends ReadOnlyResourceProvider {
@@ -74,9 +82,12 @@ public class StackServiceResourceProvider extends ReadOnlyResourceProvider {
private static final String CUSTOM_COMMANDS_PROPERTY_ID = PropertyHelper.getPropertyId(
"StackServices", "custom_commands");
+ private static final String SERVICE_PROPERTIES_PROPERTY_ID = PropertyHelper.getPropertyId(
+ "StackServices", "properties");
+
private static Set<String> pkPropertyIds = new HashSet<String>(
- Arrays.asList(new String[] { STACK_NAME_PROPERTY_ID,
- STACK_VERSION_PROPERTY_ID, SERVICE_NAME_PROPERTY_ID }));
+ Arrays.asList(new String[]{STACK_NAME_PROPERTY_ID,
+ STACK_VERSION_PROPERTY_ID, SERVICE_NAME_PROPERTY_ID}));
/**
* KerberosServiceDescriptorFactory used to create KerberosServiceDescriptor instances
@@ -93,7 +104,7 @@ public class StackServiceResourceProvider extends ReadOnlyResourceProvider {
@Override
public Set<Resource> getResources(Request request, Predicate predicate)
throws SystemException, UnsupportedPropertyException,
- NoSuchResourceException, NoSuchParentResourceException {
+ NoSuchResourceException, NoSuchParentResourceException {
final Set<StackServiceRequest> requests = new HashSet<StackServiceRequest>();
@@ -117,48 +128,60 @@ public class StackServiceResourceProvider extends ReadOnlyResourceProvider {
Set<Resource> resources = new HashSet<Resource>();
for (StackServiceResponse response : responses) {
- Resource resource = new ResourceImpl(Resource.Type.StackService);
+ Resource resource = createResource(response, requestedIds);
- setResourceProperty(resource, STACK_NAME_PROPERTY_ID,
- response.getStackName(), requestedIds);
+ resources.add(resource);
+ }
+
+ return resources;
+ }
- setResourceProperty(resource, STACK_VERSION_PROPERTY_ID,
- response.getStackVersion(), requestedIds);
+ private Resource createResource(StackServiceResponse response, Set<String> requestedIds) {
+ Resource resource = new ResourceImpl(Type.StackService);
+
+ setResourceProperty(resource, STACK_NAME_PROPERTY_ID,
+ response.getStackName(), requestedIds);
setResourceProperty(resource, SERVICE_NAME_PROPERTY_ID,
response.getServiceName(), requestedIds);
setResourceProperty(resource, SERVICE_TYPE_PROPERTY_ID,
- response.getServiceType(), requestedIds);
+ response.getServiceType(), requestedIds);
- setResourceProperty(resource, SERVICE_DISPLAY_NAME_PROPERTY_ID,
- response.getServiceDisplayName(), requestedIds);
+ setResourceProperty(resource, STACK_VERSION_PROPERTY_ID,
+ response.getStackVersion(), requestedIds);
- setResourceProperty(resource, USER_NAME_PROPERTY_ID,
- response.getUserName(), requestedIds);
+ setResourceProperty(resource, SERVICE_NAME_PROPERTY_ID,
+ response.getServiceName(), requestedIds);
- setResourceProperty(resource, COMMENTS_PROPERTY_ID,
- response.getComments(), requestedIds);
+ setResourceProperty(resource, SERVICE_DISPLAY_NAME_PROPERTY_ID,
+ response.getServiceDisplayName(), requestedIds);
- setResourceProperty(resource, VERSION_PROPERTY_ID,
- response.getServiceVersion(), requestedIds);
+ setResourceProperty(resource, USER_NAME_PROPERTY_ID,
+ response.getUserName(), requestedIds);
- setResourceProperty(resource, CONFIG_TYPES,
- response.getConfigTypes(), requestedIds);
+ setResourceProperty(resource, COMMENTS_PROPERTY_ID,
+ response.getComments(), requestedIds);
- setResourceProperty(resource, REQUIRED_SERVICES_ID,
- response.getRequiredServices(), requestedIds);
+ setResourceProperty(resource, VERSION_PROPERTY_ID,
+ response.getServiceVersion(), requestedIds);
- setResourceProperty(resource, SERVICE_CHECK_SUPPORTED_PROPERTY_ID,
- response.isServiceCheckSupported(), requestedIds);
+ setResourceProperty(resource, CONFIG_TYPES,
+ response.getConfigTypes(), requestedIds);
- setResourceProperty(resource, CUSTOM_COMMANDS_PROPERTY_ID,
- response.getCustomCommands(), requestedIds);
+ setResourceProperty(resource, REQUIRED_SERVICES_ID,
+ response.getRequiredServices(), requestedIds);
- resources.add(resource);
- }
+ setResourceProperty(resource, SERVICE_CHECK_SUPPORTED_PROPERTY_ID,
+ response.isServiceCheckSupported(), requestedIds);
- return resources;
+ setResourceProperty(resource, CUSTOM_COMMANDS_PROPERTY_ID,
+ response.getCustomCommands(), requestedIds);
+
+ setResourceProperty(resource, SERVICE_PROPERTIES_PROPERTY_ID,
+ response.getServiceProperties(), requestedIds);
+
+ return resource;
}
private StackServiceRequest getRequest(Map<String, Object> properties) {
http://git-wip-us.apache.org/repos/asf/ambari/blob/64769850/ambari-server/src/main/java/org/apache/ambari/server/stack/ServiceModule.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/stack/ServiceModule.java b/ambari-server/src/main/java/org/apache/ambari/server/stack/ServiceModule.java
index e51eb21..c2a2a0c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/stack/ServiceModule.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/stack/ServiceModule.java
@@ -18,6 +18,24 @@
package org.apache.ambari.server.stack;
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Multimaps;
+import com.google.common.collect.Sets;
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.api.services.AmbariMetaInfo;
+import org.apache.ambari.server.state.ComponentInfo;
+import org.apache.ambari.server.state.CustomCommandDefinition;
+import org.apache.ambari.server.state.PropertyInfo;
+import org.apache.ambari.server.state.ServiceInfo;
+import org.apache.ambari.server.state.ServicePropertyInfo;
+import org.apache.ambari.server.state.ThemeInfo;
+
+import javax.annotation.Nullable;
import java.io.File;
import java.util.Collection;
import java.util.Collections;
@@ -27,13 +45,6 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
-import org.apache.ambari.server.AmbariException;
-import org.apache.ambari.server.api.services.AmbariMetaInfo;
-import org.apache.ambari.server.state.ComponentInfo;
-import org.apache.ambari.server.state.CustomCommandDefinition;
-import org.apache.ambari.server.state.PropertyInfo;
-import org.apache.ambari.server.state.ServiceInfo;
-import org.apache.ambari.server.state.ThemeInfo;
/**
* Service module which provides all functionality related to parsing and fully
@@ -118,6 +129,8 @@ public class ServiceModule extends BaseModule<ServiceModule, ServiceInfo> implem
populateComponentModules();
populateConfigurationModules();
populateThemeModules();
+
+ validateServiceInfo();
}
@Override
@@ -129,6 +142,10 @@ public class ServiceModule extends BaseModule<ServiceModule, ServiceInfo> implem
public void resolve(
ServiceModule parentModule, Map<String, StackModule> allStacks, Map<String, ServiceModule> commonServices)
throws AmbariException {
+
+ if (!serviceInfo.isValid() || !parentModule.isValid())
+ return;
+
ServiceInfo parent = parentModule.getModuleInfo();
if (serviceInfo.getComment() == null) {
@@ -188,6 +205,47 @@ public class ServiceModule extends BaseModule<ServiceModule, ServiceInfo> implem
mergeConfigurations(parentModule, allStacks, commonServices);
mergeThemes(parentModule, allStacks, commonServices);
mergeExcludedConfigTypes(parent);
+
+
+ mergeServiceProperties(parent.getServicePropertyList());
+
+ }
+
+ /**
+ * Merges service properties from parent into the the service properties of this this service.
+ * Current properties overrides properties with same name from parent
+ * @param other service properties to merge with the current service property list
+ */
+ private void mergeServiceProperties(List<ServicePropertyInfo> other) {
+ if (!other.isEmpty()) {
+ List<ServicePropertyInfo> servicePropertyList = serviceInfo.getServicePropertyList();
+ List<ServicePropertyInfo> servicePropertiesToAdd = Lists.newArrayList();
+
+ Set<String> servicePropertyNames = Sets.newTreeSet(
+ Iterables.transform(servicePropertyList, new Function<ServicePropertyInfo, String>() {
+ @Nullable
+ @Override
+ public String apply(ServicePropertyInfo serviceProperty) {
+ return serviceProperty.getName();
+ }
+ })
+ );
+
+ for (ServicePropertyInfo otherServiceProperty : other) {
+ if (!servicePropertyNames.contains(otherServiceProperty.getName()))
+ servicePropertiesToAdd.add(otherServiceProperty);
+ }
+
+ List<ServicePropertyInfo> mergedServicePropertyList =
+ ImmutableList.<ServicePropertyInfo>builder()
+ .addAll(servicePropertyList)
+ .addAll(servicePropertiesToAdd)
+ .build();
+
+ serviceInfo.setServicePropertyList(mergedServicePropertyList);
+
+ validateServiceInfo();
+ }
}
/**
@@ -480,5 +538,13 @@ public class ServiceModule extends BaseModule<ServiceModule, ServiceInfo> implem
@Override
public void setErrors(Collection error) {
this.errorSet.addAll(error);
- }
+ }
+
+
+ private void validateServiceInfo() {
+ if (!serviceInfo.isValid()) {
+ setValid(false);
+ setErrors(serviceInfo.getErrors());
+ }
+ }
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/64769850/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java
index d9a8a51..a58cda3 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceInfo.java
@@ -18,7 +18,27 @@
package org.apache.ambari.server.state;
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
+import com.google.common.collect.Multimaps;
+import org.apache.ambari.server.api.services.AmbariMetaInfo;
+import org.apache.ambari.server.stack.Validable;
+import org.apache.ambari.server.state.stack.MetricDefinition;
+import org.codehaus.jackson.annotate.JsonIgnore;
+import org.codehaus.jackson.map.annotate.JsonFilter;
+
+import javax.xml.bind.Unmarshaller;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementWrapper;
+import javax.xml.bind.annotation.XmlElements;
+import javax.xml.bind.annotation.XmlTransient;
import java.io.File;
+import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -29,23 +49,13 @@ import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
-import javax.xml.bind.annotation.XmlAccessType;
-import javax.xml.bind.annotation.XmlAccessorType;
-import javax.xml.bind.annotation.XmlElement;
-import javax.xml.bind.annotation.XmlElementWrapper;
-import javax.xml.bind.annotation.XmlElements;
-import javax.xml.bind.annotation.XmlTransient;
-
-import org.apache.ambari.server.api.services.AmbariMetaInfo;
-import org.apache.ambari.server.stack.Validable;
-import org.apache.ambari.server.state.stack.MetricDefinition;
-import org.codehaus.jackson.annotate.JsonIgnore;
-import org.codehaus.jackson.map.annotate.JsonFilter;
-
@XmlAccessorType(XmlAccessType.FIELD)
@JsonFilter("propertiesfilter")
public class ServiceInfo implements Validable{
+ public static final AbstractMap.SimpleEntry<String, String> DEFAULT_SERVICE_INSTALLABLE_PROPERTY = new AbstractMap.SimpleEntry("installable", "true");
+ public static final AbstractMap.SimpleEntry<String, String> DEFAULT_SERVICE_MANAGED_PROPERTY = new AbstractMap.SimpleEntry("managed", "true");
+ public static final AbstractMap.SimpleEntry<String, String> DEFAULT_SERVICE_MONITORED_PROPERTY = new AbstractMap.SimpleEntry("monitored", "true");
/**
* Format version. Added at schema ver 2
*/
@@ -57,6 +67,8 @@ public class ServiceInfo implements Validable{
private String version;
private String comment;
private String serviceType;
+
+ @XmlTransient
private List<PropertyInfo> properties;
@XmlElementWrapper(name="components")
@@ -130,8 +142,17 @@ public class ServiceInfo implements Validable{
@XmlTransient
private boolean valid = true;
+ @XmlElementWrapper(name = "properties")
+ @XmlElement(name="property")
+ private List<ServicePropertyInfo> servicePropertyList = Lists.newArrayList();
+
+
+
+ @XmlTransient
+ private Map<String, String> servicePropertyMap = ImmutableMap.copyOf(ensureMandatoryServiceProperties(Maps.<String, String>newHashMap()));
+
/**
- *
+ *
* @return valid xml flag
*/
@Override
@@ -360,6 +381,7 @@ public String getVersion() {
sb.append(version);
sb.append("\ncomment:");
sb.append(comment);
+
//for (PropertyInfo property : getProperties()) {
// sb.append("\tProperty name=" + property.getName() +
//"\nproperty value=" + property.getValue() + "\ndescription=" + property.getDescription());
@@ -746,4 +768,92 @@ public String getVersion() {
public void setThemesMap(Map<String, ThemeInfo> themesMap) {
this.themesMap = themesMap;
}
+
+
+ public List<ServicePropertyInfo> getServicePropertyList() {
+ return servicePropertyList;
+ }
+
+ public void setServicePropertyList(List<ServicePropertyInfo> servicePropertyList) {
+ this.servicePropertyList = servicePropertyList;
+ afterServicePropertyListSet();
+ }
+
+ private void afterServicePropertyListSet(){
+ validateServiceProperties();
+ buildServiceProperties();
+ }
+
+
+ /**
+ * Returns the service properties defined in the xml service definition.
+ * @return Service property map
+ */
+ public Map<String, String> getServiceProperties() {
+ return servicePropertyMap;
+ }
+
+ /**
+ * Constructs the map that stores the service properties defined in the xml service definition.
+ * The keys are the property names and values the property values.
+ * It ensures that missing required service properties are added with default values.
+ */
+ private void buildServiceProperties() {
+ if (isValid()) {
+ Map<String, String> properties = Maps.newHashMap();
+ for (ServicePropertyInfo property : getServicePropertyList()) {
+ properties.put(property.getName(), property.getValue());
+ }
+ servicePropertyMap = ImmutableMap.copyOf(ensureMandatoryServiceProperties(properties));
+ }
+ else
+ servicePropertyMap = ImmutableMap.of();
+
+
+ }
+
+ private Map<String, String> ensureMandatoryServiceProperties(Map<String, String> properties) {
+ return ensureVisibilityServiceProperties(properties);
+ }
+
+ private Map<String, String> ensureVisibilityServiceProperties(Map<String, String> properties) {
+ if (!properties.containsKey(DEFAULT_SERVICE_INSTALLABLE_PROPERTY.getKey()))
+ properties.put(DEFAULT_SERVICE_INSTALLABLE_PROPERTY.getKey(), DEFAULT_SERVICE_INSTALLABLE_PROPERTY.getValue());
+
+ if (!properties.containsKey(DEFAULT_SERVICE_MANAGED_PROPERTY.getKey()))
+ properties.put(DEFAULT_SERVICE_MANAGED_PROPERTY.getKey(), DEFAULT_SERVICE_MANAGED_PROPERTY.getValue());
+
+
+ if (!properties.containsKey(DEFAULT_SERVICE_MONITORED_PROPERTY.getKey()))
+ properties.put(DEFAULT_SERVICE_MONITORED_PROPERTY.getKey(), DEFAULT_SERVICE_MONITORED_PROPERTY.getValue());
+
+ return properties;
+ }
+
+ void afterUnmarshal(Unmarshaller unmarshaller, Object parent) {
+ afterServicePropertyListSet();
+ }
+
+
+ private void validateServiceProperties() {
+ // Verify if there are duplicate service properties by name
+ Multimap<String, ServicePropertyInfo> servicePropsByName = Multimaps.index(
+ getServicePropertyList(),
+ new Function<ServicePropertyInfo, String>() {
+ @Override
+ public String apply(ServicePropertyInfo servicePropertyInfo) {
+ return servicePropertyInfo.getName();
+ }
+ }
+
+ );
+
+ for (String propertyName: servicePropsByName.keySet()) {
+ if (servicePropsByName.get(propertyName).size() > 1) {
+ setValid(false);
+ setErrors("Duplicate service property with name '" + propertyName + "' found in " + getName() + ":" + getVersion() + " service definition !");
+ }
+ }
+ }
+
}
http://git-wip-us.apache.org/repos/asf/ambari/blob/64769850/ambari-server/src/main/java/org/apache/ambari/server/state/ServicePropertyInfo.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ServicePropertyInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ServicePropertyInfo.java
new file mode 100644
index 0000000..c152cfd
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ServicePropertyInfo.java
@@ -0,0 +1,77 @@
+/**
+ * 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.state;
+
+import org.apache.commons.lang.builder.EqualsBuilder;
+import org.apache.commons.lang.builder.HashCodeBuilder;
+
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+
+@XmlAccessorType(XmlAccessType.FIELD)
+public final class ServicePropertyInfo {
+ /**
+ * Name of the service property
+ */
+ private String name;
+
+ /**
+ * Value of the service property
+ */
+ private String value;
+
+
+ public String getName() {
+ return name;
+ }
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+
+ if (o == null || !(o instanceof ServicePropertyInfo)) return false;
+
+ ServicePropertyInfo that = (ServicePropertyInfo) o;
+
+ return new EqualsBuilder()
+ .append(name, that.name)
+ .append(value, that.value)
+ .isEquals();
+ }
+
+ @Override
+ public int hashCode() {
+ return new HashCodeBuilder(17, 37)
+ .append(name)
+ .append(value)
+ .toHashCode();
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/64769850/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 0837af2..639670e 100644
--- a/ambari-server/src/main/resources/properties.json
+++ b/ambari-server/src/main/resources/properties.json
@@ -208,6 +208,7 @@
"StackServices/service_check_supported",
"StackServices/custom_commands",
"StackServices/required_services",
+ "StackServices/properties",
"_"
],
"StackConfiguration":[
http://git-wip-us.apache.org/repos/asf/ambari/blob/64769850/ambari-server/src/test/java/org/apache/ambari/server/controller/StackServiceResponseTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/StackServiceResponseTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/StackServiceResponseTest.java
new file mode 100644
index 0000000..6fcae58
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/StackServiceResponseTest.java
@@ -0,0 +1,49 @@
+/**
+ * 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.controller;
+
+import org.apache.ambari.server.state.ServiceInfo;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.junit.Assert.assertTrue;
+
+
+
+public class StackServiceResponseTest {
+
+ private ServiceInfo serviceInfo;
+
+ @Before
+ public void setUp() {
+ serviceInfo = new ServiceInfo();
+ }
+
+ @Test
+ public void testDefaultServiceVisibilityProperties() {
+ StackServiceResponse stackServiceResponse = new StackServiceResponse(serviceInfo);
+
+
+ assertTrue("true".equals(stackServiceResponse.getServiceProperties().get(ServiceInfo.DEFAULT_SERVICE_INSTALLABLE_PROPERTY.getKey())));
+ assertTrue("true".equals(stackServiceResponse.getServiceProperties().get(ServiceInfo.DEFAULT_SERVICE_MANAGED_PROPERTY.getKey())));
+ assertTrue("true".equals(stackServiceResponse.getServiceProperties().get(ServiceInfo.DEFAULT_SERVICE_MONITORED_PROPERTY.getKey())));
+ }
+
+
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/64769850/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/StackServiceResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/StackServiceResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/StackServiceResourceProviderTest.java
new file mode 100644
index 0000000..349c2bd
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/StackServiceResourceProviderTest.java
@@ -0,0 +1,152 @@
+/**
+ * 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.controller.internal;
+
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.StackServiceResponse;
+import org.apache.ambari.server.controller.spi.Request;
+import org.apache.ambari.server.controller.spi.Resource;
+import org.apache.ambari.server.controller.spi.ResourceProvider;
+import org.apache.ambari.server.controller.utilities.PropertyHelper;
+import org.apache.ambari.server.state.ServiceInfo;
+import org.apache.ambari.server.state.ServicePropertyInfo;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import static org.easymock.EasyMock.anyObject;
+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.assertEquals;
+
+
+
+public class StackServiceResourceProviderTest {
+
+ private final String SERVICE_PROPERTIES_PROPERTY_ID = PropertyHelper.getPropertyId("StackServices", "properties");
+ private final ServicePropertyInfo P1 = new ServicePropertyInfo();
+ private final ServicePropertyInfo P2 = new ServicePropertyInfo();
+
+ private Map<String, String> TEST_SERVICE_PROPERTIES = null;
+
+ private List<ServicePropertyInfo> TEST_SERVICE_PROPERTY_LIST = null;
+
+ @Before
+ public void setUp() throws Exception {
+ P1.setName("P1");
+ P1.setValue("V1");
+
+ P2.setName("P2");
+ P2.setValue("V2");
+
+ TEST_SERVICE_PROPERTY_LIST = ImmutableList.of(P1, P2);
+ TEST_SERVICE_PROPERTIES = ImmutableMap.of(P1.getName(), P1.getValue(), P2.getName(), P2.getValue());
+ }
+
+ @Test
+ public void testGetServiceProperties() throws Exception {
+ // Given
+ AmbariManagementController managementController = createNiceMock(AmbariManagementController.class);
+ Resource.Type type = Resource.Type.StackService;
+
+ StackServiceResponse stackServiceResponse = createNiceMock(StackServiceResponse.class);
+ expect(stackServiceResponse.getServiceProperties()).andReturn(TEST_SERVICE_PROPERTIES);
+
+ expect(managementController.getStackServices(anyObject(Set.class)))
+ .andReturn(ImmutableSet.of(stackServiceResponse));
+
+ replay(managementController, stackServiceResponse);
+
+ Request request = PropertyHelper.getReadRequest(SERVICE_PROPERTIES_PROPERTY_ID);
+
+ ResourceProvider stackServiceResourceProvider = AbstractControllerResourceProvider.getResourceProvider(type,
+ PropertyHelper.getPropertyIds(type),
+ PropertyHelper.getKeyPropertyIds(type),
+ managementController);
+
+ // When
+ Set<Resource> resources = stackServiceResourceProvider.getResources(request, null);
+
+ // Then
+ Resource expected = new ResourceImpl(type);
+
+
+ BaseProvider.setResourceProperty(expected, SERVICE_PROPERTIES_PROPERTY_ID, TEST_SERVICE_PROPERTIES, ImmutableSet.of(SERVICE_PROPERTIES_PROPERTY_ID));
+
+ assertEquals(ImmutableSet.of(expected), resources);
+
+ verify(managementController, stackServiceResponse);
+
+ }
+
+
+ @Test
+ public void testGetVisibilityServiceProperties() throws Exception {
+ // Given
+ AmbariManagementController managementController = createNiceMock(AmbariManagementController.class);
+ Resource.Type type = Resource.Type.StackService;
+
+
+
+ ServiceInfo serviceInfo = new ServiceInfo() ;
+ serviceInfo.setServicePropertyList(TEST_SERVICE_PROPERTY_LIST);
+
+ StackServiceResponse stackServiceResponse = new StackServiceResponse(serviceInfo);
+
+
+
+ expect(managementController.getStackServices(anyObject(Set.class)))
+ .andReturn(ImmutableSet.of(stackServiceResponse));
+
+ replay(managementController);
+
+ Request request = PropertyHelper.getReadRequest(SERVICE_PROPERTIES_PROPERTY_ID);
+
+ ResourceProvider stackServiceResourceProvider = AbstractControllerResourceProvider.getResourceProvider(type,
+ PropertyHelper.getPropertyIds(type),
+ PropertyHelper.getKeyPropertyIds(type),
+ managementController);
+
+ // When
+ Set<Resource> resources = stackServiceResourceProvider.getResources(request, null);
+ Map<String, String> expectedServiceProperties = ImmutableMap.<String, String>builder()
+ .putAll(TEST_SERVICE_PROPERTIES)
+ .put(ServiceInfo.DEFAULT_SERVICE_INSTALLABLE_PROPERTY)
+ .put(ServiceInfo.DEFAULT_SERVICE_MANAGED_PROPERTY)
+ .put(ServiceInfo.DEFAULT_SERVICE_MONITORED_PROPERTY)
+ .build();
+
+ // Then
+ Resource expected = new ResourceImpl(type);
+ BaseProvider.setResourceProperty(expected, SERVICE_PROPERTIES_PROPERTY_ID, expectedServiceProperties, ImmutableSet.of(SERVICE_PROPERTIES_PROPERTY_ID));
+
+ assertEquals(ImmutableSet.of(expected), resources);
+
+ verify(managementController);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/64769850/ambari-server/src/test/java/org/apache/ambari/server/stack/ServiceModuleTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/stack/ServiceModuleTest.java b/ambari-server/src/test/java/org/apache/ambari/server/stack/ServiceModuleTest.java
index 2737695..92c1200 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/stack/ServiceModuleTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/stack/ServiceModuleTest.java
@@ -18,14 +18,17 @@
package org.apache.ambari.server.stack;
-import static org.easymock.EasyMock.createNiceMock;
-import static org.easymock.EasyMock.createStrictMock;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.verify;
-import static org.easymock.EasyMock.anyObject;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertTrue;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import org.apache.ambari.server.AmbariException;
+import org.apache.ambari.server.state.CommandScriptDefinition;
+import org.apache.ambari.server.state.ComponentInfo;
+import org.apache.ambari.server.state.CustomCommandDefinition;
+import org.apache.ambari.server.state.PropertyInfo;
+import org.apache.ambari.server.state.ServiceInfo;
+import org.apache.ambari.server.state.ServiceOsSpecific;
+import org.apache.ambari.server.state.ServicePropertyInfo;
+import org.junit.Test;
import java.io.File;
import java.lang.reflect.Field;
@@ -38,14 +41,15 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
-import org.apache.ambari.server.AmbariException;
-import org.apache.ambari.server.state.CommandScriptDefinition;
-import org.apache.ambari.server.state.ComponentInfo;
-import org.apache.ambari.server.state.CustomCommandDefinition;
-import org.apache.ambari.server.state.PropertyInfo;
-import org.apache.ambari.server.state.ServiceInfo;
-import org.apache.ambari.server.state.ServiceOsSpecific;
-import org.junit.Test;
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.createNiceMock;
+import static org.easymock.EasyMock.createStrictMock;
+import static org.easymock.EasyMock.expect;
+import static org.easymock.EasyMock.replay;
+import static org.easymock.EasyMock.verify;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
/**
* ServiceModule unit tests.
@@ -943,6 +947,153 @@ public class ServiceModuleTest {
verify(context);
}
+ @Test
+ public void testInvalidServiceInfo() {
+ // Given
+ ServiceInfo serviceInfo = new ServiceInfo();
+ serviceInfo.setName("TEST_SERVICE");
+ serviceInfo.setVersion("1.0.0");
+ serviceInfo.setValid(false);
+ serviceInfo.setErrors("Test error message");
+
+
+ // When
+ ServiceModule serviceModule = createServiceModule(serviceInfo);
+
+ // Then
+ assertFalse("Service module should be invalid due to the service info being invalid !", serviceModule.isValid());
+
+ assertTrue("Service module error collection should contain error message that caused service info being invalid !", serviceModule.getErrors().contains("Test error message"));
+ }
+
+
+ @Test
+ public void testMergeServicePropertiesInheritFromParent() throws Exception {
+ // Given
+ ServiceInfo serviceInfo = new ServiceInfo();
+ ServiceInfo parentServiceInfo = new ServiceInfo();
+
+ ServicePropertyInfo p1 = new ServicePropertyInfo();
+ p1.setName("P1");
+ p1.setValue("V1");
+
+ ServicePropertyInfo p2 = new ServicePropertyInfo();
+ p2.setName("P2");
+ p2.setValue("V2");
+
+
+ List<ServicePropertyInfo> parentServicePropertyList = Lists.newArrayList(p1, p2);
+
+ parentServiceInfo.setServicePropertyList(parentServicePropertyList);
+
+
+ // When
+ ServiceModule serviceModule = resolveService(serviceInfo, parentServiceInfo);
+
+ // Then
+ Map<String, String> parentServiceProperties = ImmutableMap.<String, String>builder()
+ .put("P1", "V1")
+ .put("P2", "V2")
+ .put(ServiceInfo.DEFAULT_SERVICE_INSTALLABLE_PROPERTY)
+ .put(ServiceInfo.DEFAULT_SERVICE_MANAGED_PROPERTY)
+ .put(ServiceInfo.DEFAULT_SERVICE_MONITORED_PROPERTY)
+ .build();
+
+
+ assertEquals(parentServicePropertyList, serviceModule.getModuleInfo().getServicePropertyList());
+ assertEquals(parentServiceProperties, serviceModule.getModuleInfo().getServiceProperties());
+ }
+
+ @Test
+ public void testMergeServicePropertiesInheritFromEmptyParent() throws Exception {
+ // Parent has no properties defined thus no service properties inherited
+
+ // Given
+ ServiceInfo serviceInfo = new ServiceInfo();
+ ServiceInfo parentServiceInfo = new ServiceInfo();
+
+ ServicePropertyInfo p1 = new ServicePropertyInfo();
+ p1.setName("P1");
+ p1.setValue("V1");
+
+ ServicePropertyInfo p2 = new ServicePropertyInfo();
+ p2.setName("P2");
+ p2.setValue("V2");
+
+
+ List<ServicePropertyInfo> servicePropertyList = Lists.newArrayList(p1, p2);
+
+ serviceInfo.setServicePropertyList(servicePropertyList);
+
+
+ // When
+ ServiceModule serviceModule = resolveService(serviceInfo, parentServiceInfo);
+
+ // Then
+ Map<String, String> serviceProperties = ImmutableMap.<String, String>builder()
+ .put("P1", "V1")
+ .put("P2", "V2")
+ .put(ServiceInfo.DEFAULT_SERVICE_INSTALLABLE_PROPERTY)
+ .put(ServiceInfo.DEFAULT_SERVICE_MANAGED_PROPERTY)
+ .put(ServiceInfo.DEFAULT_SERVICE_MONITORED_PROPERTY)
+ .build();
+
+ assertEquals(servicePropertyList, serviceModule.getModuleInfo().getServicePropertyList());
+ assertEquals(serviceProperties, serviceModule.getModuleInfo().getServiceProperties());
+ }
+
+
+ @Test
+ public void testMergeServiceProperties() throws Exception {
+ // Given
+ ServiceInfo serviceInfo = new ServiceInfo();
+ ServiceInfo parentServiceInfo = new ServiceInfo();
+
+ ServicePropertyInfo p1 = new ServicePropertyInfo();
+ p1.setName("P1");
+ p1.setValue("V1");
+
+ ServicePropertyInfo p2 = new ServicePropertyInfo();
+ p2.setName("P2");
+ p2.setValue("V2");
+
+ ServicePropertyInfo p2Override = new ServicePropertyInfo();
+ p2Override.setName("P2");
+ p2Override.setValue("V2_OVERRIDE");
+
+ ServicePropertyInfo p3 = new ServicePropertyInfo();
+ p3.setName("P3");
+ p3.setValue("V3");
+
+ List<ServicePropertyInfo> parentServicePropertyList = Lists.newArrayList(p1, p2);
+ parentServiceInfo.setServicePropertyList(parentServicePropertyList);
+
+ List<ServicePropertyInfo> servicePropertyList = Lists.newArrayList(p2Override, p3);
+ serviceInfo.setServicePropertyList(servicePropertyList);
+
+
+ // When
+ ServiceModule serviceModule = resolveService(serviceInfo, parentServiceInfo);
+
+ // Then
+ List<ServicePropertyInfo> expectedPropertyList = Lists.newArrayList(p1, p2Override, p3);
+ Map<String, String> expectedServiceProperties = ImmutableMap.<String, String>builder()
+ .put("P1", "V1")
+ .put("P2", "V2_OVERRIDE")
+ .put("P3", "V3")
+ .put(ServiceInfo.DEFAULT_SERVICE_INSTALLABLE_PROPERTY)
+ .put(ServiceInfo.DEFAULT_SERVICE_MANAGED_PROPERTY)
+ .put(ServiceInfo.DEFAULT_SERVICE_MONITORED_PROPERTY)
+ .build();
+
+ List<ServicePropertyInfo> actualPropertyList = serviceModule.getModuleInfo().getServicePropertyList();
+
+
+ assertTrue(actualPropertyList.containsAll(expectedPropertyList) && expectedPropertyList.containsAll(actualPropertyList));
+ assertEquals(expectedServiceProperties, serviceModule.getModuleInfo().getServiceProperties());
+ }
+
+
private ServiceModule createServiceModule(ServiceInfo serviceInfo) {
String configType = "type1";
http://git-wip-us.apache.org/repos/asf/ambari/blob/64769850/ambari-server/src/test/java/org/apache/ambari/server/state/ServiceInfoTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/ServiceInfoTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/ServiceInfoTest.java
index 75e0991..43cea91 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/state/ServiceInfoTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/ServiceInfoTest.java
@@ -18,6 +18,7 @@
package org.apache.ambari.server.state;
+import com.google.common.collect.Lists;
import org.apache.ambari.server.state.stack.ServiceMetainfoXml;
import org.junit.Test;
@@ -27,6 +28,7 @@ import javax.xml.bind.Unmarshaller;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import static org.junit.Assert.*;
@@ -103,10 +105,10 @@ public class ServiceInfoTest {
Map<String, ServiceInfo> serviceInfoMap = getServiceInfo(serviceInfoXml);
- assertEquals("CUSTOM_metrics.json",serviceInfoMap.get("CUSTOM").getMetricsFileName());
+ assertEquals("CUSTOM_metrics.json", serviceInfoMap.get("CUSTOM").getMetricsFileName());
assertEquals("CUSTOM_widgets.json", serviceInfoMap.get("CUSTOM").getWidgetsFileName());
assertEquals("metrics.json", serviceInfoMap.get("DEFAULT").getMetricsFileName());
- assertEquals("widgets.json",serviceInfoMap.get("DEFAULT").getWidgetsFileName());
+ assertEquals("widgets.json", serviceInfoMap.get("DEFAULT").getWidgetsFileName());
}
@Test
@@ -120,6 +122,218 @@ public class ServiceInfoTest {
assertFalse(serviceInfo.isRestartRequiredAfterRackChange());
}
+ @Test
+ public void testServiceProperties() throws Exception {
+ String serviceInfoXml =
+ "<metainfo>" +
+ " <schemaVersion>2.0</schemaVersion>" +
+ " <services>" +
+ " <service>" +
+ " <name>WITH_PROPS</name>" +
+ " <displayName>WITH_PROPS</displayName>" +
+ " <properties>" +
+ " <property>" +
+ " <name>PROP1</name>" +
+ " <value>VAL1</value>" +
+ " </property>" +
+ " <property>" +
+ " <name>PROP2</name>" +
+ " <value>VAL2</value>" +
+ " </property>" +
+ " </properties>" +
+ " </service>" +
+ " </services>" +
+ "</metainfo>";
+
+ Map<String, ServiceInfo> serviceInfoMap = getServiceInfo(serviceInfoXml);
+
+ Map<String, String> serviceProperties = serviceInfoMap.get("WITH_PROPS").getServiceProperties();
+
+ assertTrue(serviceProperties.containsKey("PROP1"));
+ assertEquals("VAL1", serviceProperties.get("PROP1"));
+
+ assertTrue(serviceProperties.containsKey("PROP2"));
+ assertEquals("VAL2", serviceProperties.get("PROP2"));
+
+ }
+
+
+ @Test
+ public void testDefaultVisibilityServiceProperties() throws Exception {
+ // Given
+ String serviceInfoXml =
+ "<metainfo>" +
+ " <schemaVersion>2.0</schemaVersion>" +
+ " <services>" +
+ " <service>" +
+ " <name>WITH_PROPS</name>" +
+ " <displayName>WITH_PROPS</displayName>" +
+ " <properties>" +
+ " <property>" +
+ " <name>PROP1</name>" +
+ " <value>VAL1</value>" +
+ " </property>" +
+ " <property>" +
+ " <name>PROP2</name>" +
+ " <value>VAL2</value>" +
+ " </property>" +
+ " </properties>" +
+ " </service>" +
+ " </services>" +
+ "</metainfo>";
+
+ // When
+ Map<String, ServiceInfo> serviceInfoMap = getServiceInfo(serviceInfoXml);
+
+ // Then
+ Map<String, String> serviceProperties = serviceInfoMap.get("WITH_PROPS").getServiceProperties();
+
+
+ assertTrue("true".equals(serviceProperties.get(ServiceInfo.DEFAULT_SERVICE_INSTALLABLE_PROPERTY.getKey())));
+ assertTrue("true".equals(serviceProperties.get(ServiceInfo.DEFAULT_SERVICE_MANAGED_PROPERTY.getKey())));
+ assertTrue("true".equals(serviceProperties.get(ServiceInfo.DEFAULT_SERVICE_MONITORED_PROPERTY.getKey())));
+ }
+
+ @Test
+ public void testVisibilityServicePropertyOverride() throws Exception {
+ // Given
+ String serviceInfoXml =
+ "<metainfo>" +
+ " <schemaVersion>2.0</schemaVersion>" +
+ " <services>" +
+ " <service>" +
+ " <name>WITH_PROPS</name>" +
+ " <displayName>WITH_PROPS</displayName>" +
+ " <properties>" +
+ " <property>" +
+ " <name>PROP1</name>" +
+ " <value>VAL1</value>" +
+ " </property>" +
+ " <property>" +
+ " <name>PROP2</name>" +
+ " <value>VAL2</value>" +
+ " </property>" +
+ " <property>" +
+ " <name>managed</name>" +
+ " <value>false</value>" +
+ " </property>" +
+ " </properties>" +
+ " </service>" +
+ " </services>" +
+ "</metainfo>";
+
+ // When
+ Map<String, ServiceInfo> serviceInfoMap = getServiceInfo(serviceInfoXml);
+
+ // Then
+ Map<String, String> serviceProperties = serviceInfoMap.get("WITH_PROPS").getServiceProperties();
+
+
+ assertTrue("true".equals(serviceProperties.get(ServiceInfo.DEFAULT_SERVICE_INSTALLABLE_PROPERTY.getKey())));
+ assertTrue("false".equals(serviceProperties.get(ServiceInfo.DEFAULT_SERVICE_MANAGED_PROPERTY.getKey())));
+ assertTrue("true".equals(serviceProperties.get(ServiceInfo.DEFAULT_SERVICE_MONITORED_PROPERTY.getKey())));
+
+ }
+
+ @Test
+ public void testDuplicateServicePropertyValidationAfterXmlDeserialization() throws Exception
+ {
+ // Given
+ String serviceInfoXml =
+ "<metainfo>" +
+ " <schemaVersion>2.0</schemaVersion>" +
+ " <services>" +
+ " <service>" +
+ " <version>1.0</version>" +
+ " <name>WITH_DUPLICATE_PROPS</name>" +
+ " <displayName>WITH_PROPS</displayName>" +
+ " <properties>" +
+ " <property>" +
+ " <name>PROP1</name>" +
+ " <value>VAL1</value>" +
+ " </property>" +
+ " <property>" +
+ " <name>PROP1</name>" +
+ " <value>VAL2</value>" +
+ " </property>" +
+ " <property>" +
+ " <name>managed</name>" +
+ " <value>false</value>" +
+ " </property>" +
+ " </properties>" +
+ " </service>" +
+ " </services>" +
+ "</metainfo>";
+
+ // When
+ Map<String, ServiceInfo> serviceInfoMap = getServiceInfo(serviceInfoXml);
+ ServiceInfo serviceInfo = serviceInfoMap.get("WITH_DUPLICATE_PROPS");
+
+ // Then
+ assertFalse("Service info should be in invalid state due to duplicate service property names !", serviceInfo.isValid());
+
+ assertTrue("Service info error collection should contain the name of the duplicate service property !", serviceInfo.getErrors().contains("Duplicate service property with name 'PROP1' found in " + serviceInfo.getName() + ":" + serviceInfo.getVersion() + " service definition !"));
+
+ }
+
+ @Test
+ public void testDuplicateServicePropertyValidationAfterSet() {
+ // Given
+ ServicePropertyInfo p1 = new ServicePropertyInfo();
+ p1.setName("PROP1");
+ p1.setValue("V1");
+
+ ServicePropertyInfo p2 = new ServicePropertyInfo();
+ p2.setName("PROP1");
+ p2.setValue("V2");
+
+ List<ServicePropertyInfo> servicePropertyList = Lists.newArrayList(p1, p2);
+
+ ServiceInfo serviceInfo = new ServiceInfo();
+ serviceInfo.setName("TEST_NAME");
+ serviceInfo.setVersion("TEST_VERSION");
+ serviceInfo.setServicePropertyList(servicePropertyList);
+
+ // Then
+ assertFalse("Service info should be in invalid state due to duplicate service property names !", serviceInfo.isValid());
+
+ assertTrue("Service info error collection should contain the name of the duplicate service property !", serviceInfo.getErrors().contains("Duplicate service property with name 'PROP1' found in " + serviceInfo.getName() + ":" + serviceInfo.getVersion() + " service definition !"));
+
+ }
+
+ @Test
+ public void testSetServicePropertiesAfterPropertyListSet() {
+ // Given
+ ServicePropertyInfo p1 = new ServicePropertyInfo();
+ p1.setName("PROP1");
+ p1.setValue("V1");
+
+ ServicePropertyInfo p2 = new ServicePropertyInfo();
+ p2.setName("PROP2");
+ p2.setValue("V2");
+
+ List<ServicePropertyInfo> servicePropertyList = Lists.newArrayList(p1, p2);
+
+ ServiceInfo serviceInfo = new ServiceInfo();
+ serviceInfo.setName("TEST_NAME");
+ serviceInfo.setVersion("TEST_VERSION");
+ serviceInfo.setServicePropertyList(servicePropertyList);
+
+ // When
+ Map<String, String> serviceProperties = serviceInfo.getServiceProperties();
+
+ // Then
+ assertTrue(serviceProperties.containsKey("PROP1"));
+ assertEquals("V1", serviceProperties.get("PROP1"));
+
+ assertTrue(serviceProperties.containsKey("PROP2"));
+ assertEquals("V2", serviceProperties.get("PROP2"));
+
+ assertTrue("true".equals(serviceProperties.get(ServiceInfo.DEFAULT_SERVICE_INSTALLABLE_PROPERTY.getKey())));
+ assertTrue("true".equals(serviceProperties.get(ServiceInfo.DEFAULT_SERVICE_MANAGED_PROPERTY.getKey())));
+ assertTrue("true".equals(serviceProperties.get(ServiceInfo.DEFAULT_SERVICE_MONITORED_PROPERTY.getKey())));
+ }
+
public static Map<String, ServiceInfo> getServiceInfo(String xml) throws JAXBException {
InputStream configStream = new ByteArrayInputStream(xml.getBytes());
JAXBContext jaxbContext = JAXBContext.newInstance(ServiceMetainfoXml.class);
http://git-wip-us.apache.org/repos/asf/ambari/blob/64769850/ambari-server/src/test/java/org/apache/ambari/server/state/ServicePropertyInfoTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/state/ServicePropertyInfoTest.java b/ambari-server/src/test/java/org/apache/ambari/server/state/ServicePropertyInfoTest.java
new file mode 100644
index 0000000..e56d218
--- /dev/null
+++ b/ambari-server/src/test/java/org/apache/ambari/server/state/ServicePropertyInfoTest.java
@@ -0,0 +1,83 @@
+/**
+ * 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.state;
+
+import nl.jqno.equalsverifier.EqualsVerifier;
+import nl.jqno.equalsverifier.Warning;
+import org.junit.Test;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Unmarshaller;
+import javax.xml.transform.stream.StreamSource;
+import java.io.ByteArrayInputStream;
+
+import static junit.framework.Assert.assertEquals;
+
+public class ServicePropertyInfoTest {
+ private static final String XML =
+ "<property>\n" +
+ " <name>prop_name</name>\n" +
+ " <value>prop_value</value>\n"+
+ "</property>";
+
+ @Test
+ public void testName() throws Exception {
+ // Given
+ ServicePropertyInfo p = getServiceProperty(XML);
+
+ // When
+ String name = p.getName();
+
+ // Then
+ assertEquals("prop_name", name);
+ }
+
+ @Test
+ public void testValue() throws Exception {
+ // Given
+ ServicePropertyInfo p = getServiceProperty(XML);
+
+ // When
+ String value = p.getValue();
+
+ // Then
+ assertEquals("prop_value", value);
+ }
+
+ @Test
+ public void testEquals() throws Exception {
+ EqualsVerifier.forClass(ServicePropertyInfo.class)
+ .suppress(Warning.NONFINAL_FIELDS)
+ .verify();
+ }
+
+
+ public static ServicePropertyInfo getServiceProperty(String xml) throws JAXBException {
+ JAXBContext jaxbContext = JAXBContext.newInstance(ServicePropertyInfo.class);
+ Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
+
+ return unmarshaller.unmarshal(
+ new StreamSource(
+ new ByteArrayInputStream(xml.getBytes())
+ ),
+ ServicePropertyInfo.class)
+ .getValue();
+ }
+}