ambari-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From nc...@apache.org
Subject [11/30] ambari git commit: AMBARI-18744: Ambari-server: REST API changes to GET and PUT credential store information
Date Thu, 03 Nov 2016 15:26:12 GMT
AMBARI-18744: Ambari-server: REST API changes to GET and PUT credential store information


Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/33a41195
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/33a41195
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/33a41195

Branch: refs/heads/branch-feature-AMBARI-18634
Commit: 33a4119539107b781270a4347a5364e0f40652d7
Parents: a8727af
Author: Nahappan Somasundaram <nsomasundaram@hortonworks.com>
Authored: Wed Nov 2 10:37:27 2016 -0700
Committer: Nahappan Somasundaram <nsomasundaram@hortonworks.com>
Committed: Wed Nov 2 12:18:57 2016 -0700

----------------------------------------------------------------------
 .../server/controller/ServiceRequest.java       |  32 ++-
 .../server/controller/ServiceResponse.java      |  47 +++-
 .../server/controller/StackServiceRequest.java  |  46 +++-
 .../server/controller/StackServiceResponse.java |  51 +++++
 .../internal/ServiceResourceProvider.java       |  78 ++++++-
 .../internal/StackServiceResourceProvider.java  |  16 +-
 .../server/state/CredentialStoreInfo.java       |  96 ++++++++
 .../apache/ambari/server/state/ServiceImpl.java |   5 +-
 .../apache/ambari/server/state/ServiceInfo.java |  85 ++++++-
 .../src/main/resources/properties.json          |   4 +
 .../internal/ServiceResourceProviderTest.java   |  45 +++-
 .../ambari/server/state/ServiceInfoTest.java    | 224 +++++++++++++++++++
 12 files changed, 710 insertions(+), 19 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/33a41195/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceRequest.java
index eb874b5..ec45a85 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceRequest.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceRequest.java
@@ -25,12 +25,23 @@ public class ServiceRequest {
   private String serviceName; // GET/CREATE/UPDATE/DELETE
   private String desiredState; // CREATE/UPDATE
   private String maintenanceState; // UPDATE
+  private String credentialStoreEnabled; // CREATE/UPDATE/GET
 
   public ServiceRequest(String clusterName, String serviceName,
                         String desiredState) {
+    this(clusterName, serviceName, desiredState, null);
+  }
+
+  public ServiceRequest(String clusterName, String serviceName,
+                        String desiredState,
+                        String credentialStoreEnabled) {
     this.clusterName = clusterName;
     this.serviceName = serviceName;
     this.desiredState = desiredState;
+    this.credentialStoreEnabled = credentialStoreEnabled;
+    // Credential store supported cannot be changed after
+    // creation since it comes from the stack definition.
+    // We can update credential store enabled alone.
   }
 
   /**
@@ -74,14 +85,14 @@ public class ServiceRequest {
   public void setClusterName(String clusterName) {
     this.clusterName = clusterName;
   }
-  
+
   /**
    * @param state the new maintenance state
    */
   public void setMaintenanceState(String state) {
     maintenanceState = state;
   }
-  
+
   /**
    * @return the maintenance state
    */
@@ -89,11 +100,26 @@ public class ServiceRequest {
     return maintenanceState;
   }
 
+  /**
+   * @return credential store enabled
+   */
+  public String getCredentialStoreEnabled() {
+    return credentialStoreEnabled;
+  }
+
+  /**
+   * @param credentialStoreEnabled the new credential store enabled
+   */
+  public void setCredentialStoreEnabled(String credentialStoreEnabled) {
+    this.credentialStoreEnabled = credentialStoreEnabled;
+  }
+
   public String toString() {
     StringBuilder sb = new StringBuilder();
     sb.append("clusterName=" + clusterName
         + ", serviceName=" + serviceName
-        + ", desiredState=" + desiredState);
+        + ", desiredState=" + desiredState
+        + ", credentialStoreEnabled=" + credentialStoreEnabled);
     return sb.toString();
   }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/33a41195/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceResponse.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceResponse.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceResponse.java
index c4881b8..3e35c0c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceResponse.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/ServiceResponse.java
@@ -27,15 +27,20 @@ public class ServiceResponse {
   private String desiredStackVersion;
   private String desiredState;
   private String maintenanceState;
+  private boolean credentialStoreSupported;
+  private boolean credentialStoreEnabled;
 
   public ServiceResponse(Long clusterId, String clusterName,
                          String serviceName,
-                         String desiredStackVersion, String desiredState) {
+                         String desiredStackVersion, String desiredState,
+                         boolean credentialStoreSupported, boolean credentialStoreEnabled) {
     this.clusterId = clusterId;
     this.clusterName = clusterName;
     this.serviceName = serviceName;
     this.setDesiredStackVersion(desiredStackVersion);
     this.setDesiredState(desiredState);
+    this.credentialStoreSupported = credentialStoreSupported;
+    this.credentialStoreEnabled = credentialStoreEnabled;
   }
   
   
@@ -141,6 +146,46 @@ public class ServiceResponse {
     return maintenanceState;
   }
 
+  /**
+   * Get a true or false value indicating if the service supports
+   * credential store use or not.
+   *
+   * @return true or false
+   */
+  public boolean isCredentialStoreSupported() {
+    return credentialStoreSupported;
+  }
+
+  /**
+   * Set a true or false value indicating whether the service
+   * supports credential store or not.
+   *
+   * @param credentialStoreSupported
+   */
+  public void setCredentialStoreSupported(boolean credentialStoreSupported) {
+    this.credentialStoreSupported = credentialStoreSupported;
+  }
+
+  /**
+   * Get a true or false value indicating if the service is enabled
+   * for credential store use or not.
+   *
+   * @return true or false
+   */
+  public boolean isCredentialStoreEnabled() {
+    return credentialStoreEnabled;
+  }
+
+  /**
+   * Set a true or false value indicating whether the service is
+   * enabled for credential store use or not.
+   *
+   * @param credentialStoreEnabled
+   */
+  public void setCredentialStoreEnabled(boolean credentialStoreEnabled) {
+    this.credentialStoreEnabled = credentialStoreEnabled;
+  }
+
   @Override
   public int hashCode() {
     int result = clusterId != null? clusterId.intValue() : 0;

http://git-wip-us.apache.org/repos/asf/ambari/blob/33a41195/ambari-server/src/main/java/org/apache/ambari/server/controller/StackServiceRequest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/StackServiceRequest.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/StackServiceRequest.java
index b11d47c..260e48d 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/StackServiceRequest.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/StackServiceRequest.java
@@ -22,13 +22,19 @@ package org.apache.ambari.server.controller;
 public class StackServiceRequest extends StackVersionRequest {
 
   private String serviceName;
+  private String credentialStoreSupported;
+  private String credentialStoreEnabled;
 
   public StackServiceRequest(String stackName, String stackVersion,
       String serviceName) {
+    this(stackName, stackVersion, serviceName, null, null);
+  }
+
+  public StackServiceRequest(String stackName, String stackVersion,
+      String serviceName, String credentialStoreSupported, String credentialStoreEnabled) {
     super(stackName, stackVersion);
 
     this.setServiceName(serviceName);
-
   }
 
   public String getServiceName() {
@@ -39,4 +45,42 @@ public class StackServiceRequest extends StackVersionRequest {
     this.serviceName = serviceName;
   }
 
+  /**
+   * Get whether credential store is supported. If value is null,
+   * this property was not specified.
+   *
+   * @return null, "true", "false"
+   */
+  public String getCredentialStoreSupported() {
+    return credentialStoreSupported;
+  }
+
+  /**
+   * Set whether credential store is supported. Null indicates unspecified.
+   *
+   * @param credentialStoreSupported null, "true", "false"
+   */
+  public void setCredentialStoreSupported(String credentialStoreSupported) {
+    this.credentialStoreSupported = credentialStoreSupported;
+  }
+
+  /**
+   * Get whether credential store is enabled. If value is null,
+   * this property was not specified.
+   *
+   * @return null, "true", "false"
+   */
+  public String getCredentialStoreEnabled() {
+    return credentialStoreEnabled;
+  }
+
+  /**
+   * Set whether credential store is supported. Null indicates unspecified.
+   *
+   * @param credentialStoreEnabled null, "true", "false"
+   */
+  public void setCredentialStoreEnabled(String credentialStoreEnabled) {
+    this.credentialStoreEnabled = credentialStoreEnabled;
+  }
+
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/33a41195/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 75f65c0..a6dd31f 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
@@ -58,6 +58,18 @@ public class StackServiceResponse {
   private File kerberosDescriptorFile;
 
   /**
+   * Indicates if the stack definition says this service supports
+   * credential store. If not specified, this will be false.
+   */
+  private boolean credentialStoreSupported;
+
+  /**
+   * Indicates if the stack definition says this service is enabled
+   * for credential store use. If not specified, this will be false.
+   */
+  private boolean credentialStoreEnabled;
+
+  /**
    * Constructor.
    *
    * @param service
@@ -90,6 +102,10 @@ public class StackServiceResponse {
     kerberosDescriptorFile = service.getKerberosDescriptorFile();
 
     serviceProperties = service.getServiceProperties();
+
+    credentialStoreSupported = service.isCredentialStoreSupported();
+
+    credentialStoreEnabled = service.isCredentialStoreEnabled();
   }
 
   public ServiceInfo.Selection getSelection() {
@@ -230,4 +246,39 @@ public class StackServiceResponse {
     return serviceProperties;
   }
 
+  /**
+   * Get whether credential store is supported by the service
+   *
+   * @return true or false.
+   */
+  public boolean isCredentialStoreSupported() {
+    return credentialStoreSupported;
+  }
+
+  /**
+   * Set credential store supported value
+   *
+   * @param credentialStoreSupported
+   */
+  public void setCredentialStoreSupported(boolean credentialStoreSupported) {
+    this.credentialStoreSupported = credentialStoreSupported;
+  }
+
+  /**
+   * Get whether credential store use is enabled
+   *
+   * @return true or false
+   */
+  public boolean isCredentialStoreEnabled() {
+    return credentialStoreEnabled;
+  }
+
+  /**
+   * Set credential store enabled value.
+   *
+   * @param credentialStoreEnabled
+   */
+  public void setCredentialStoreEnabled(boolean credentialStoreEnabled) {
+    this.credentialStoreEnabled = credentialStoreEnabled;
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/33a41195/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java
index 13f822e..a08d153 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ServiceResourceProvider.java
@@ -69,6 +69,7 @@ import org.apache.ambari.server.state.MaintenanceState;
 import org.apache.ambari.server.state.Service;
 import org.apache.ambari.server.state.ServiceComponent;
 import org.apache.ambari.server.state.ServiceComponentHost;
+import org.apache.ambari.server.state.ServiceInfo;
 import org.apache.ambari.server.state.StackId;
 import org.apache.ambari.server.state.State;
 import org.apache.commons.lang.StringUtils;
@@ -91,6 +92,10 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
   public static final String SERVICE_SERVICE_NAME_PROPERTY_ID    = PropertyHelper.getPropertyId("ServiceInfo", "service_name");
   public static final String SERVICE_SERVICE_STATE_PROPERTY_ID   = PropertyHelper.getPropertyId("ServiceInfo", "state");
   public static final String SERVICE_MAINTENANCE_STATE_PROPERTY_ID = PropertyHelper.getPropertyId("ServiceInfo", "maintenance_state");
+  public static final String SERVICE_CREDENTIAL_STORE_SUPPORTED_PROPERTY_ID =
+    PropertyHelper.getPropertyId("ServiceInfo", "credential_store_supported");
+  public static final String SERVICE_CREDENTIAL_STORE_ENABLED_PROPERTY_ID =
+    PropertyHelper.getPropertyId("ServiceInfo", "credential_store_enabled");
 
   public static final String SERVICE_ATTRIBUTES_PROPERTY_ID = PropertyHelper.getPropertyId("Services", "attributes");
 
@@ -197,6 +202,10 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
           requestedIds);
       setResourceProperty(resource, SERVICE_MAINTENANCE_STATE_PROPERTY_ID,
           response.getMaintenanceState(), requestedIds);
+      setResourceProperty(resource, SERVICE_CREDENTIAL_STORE_SUPPORTED_PROPERTY_ID,
+          String.valueOf(response.isCredentialStoreSupported()), requestedIds);
+      setResourceProperty(resource, SERVICE_CREDENTIAL_STORE_ENABLED_PROPERTY_ID,
+          String.valueOf(response.isCredentialStoreEnabled()), requestedIds);
 
       Map<String, Object> serviceSpecificProperties = getServiceSpecificProperties(
           response.getClusterName(), response.getServiceName(), requestedIds);
@@ -322,7 +331,8 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
     ServiceRequest svcRequest = new ServiceRequest(
         (String) properties.get(SERVICE_CLUSTER_NAME_PROPERTY_ID),
         (String) properties.get(SERVICE_SERVICE_NAME_PROPERTY_ID),
-        (String) properties.get(SERVICE_SERVICE_STATE_PROPERTY_ID));
+        (String) properties.get(SERVICE_SERVICE_STATE_PROPERTY_ID),
+        (String) properties.get(SERVICE_CREDENTIAL_STORE_ENABLED_PROPERTY_ID));
 
     Object o = properties.get(SERVICE_MAINTENANCE_STATE_PROPERTY_ID);
     if (null != o) {
@@ -350,6 +360,33 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
       // Already checked that service does not exist
       Service s = cluster.addService(request.getServiceName());
 
+      /**
+       * Get the credential_store_supported field only from the stack definition.
+       * Not possible to update the value through a request.
+       */
+      StackId stackId = cluster.getDesiredStackVersion();
+      AmbariMetaInfo ambariMetaInfo = getManagementController().getAmbariMetaInfo();
+      ServiceInfo serviceInfo = ambariMetaInfo.getService(stackId.getStackName(),
+          stackId.getStackVersion(), request.getServiceName());
+      s.setCredentialStoreSupported(serviceInfo.isCredentialStoreSupported());
+      LOG.info("Service: {}, credential_store_supported from stack definition:{}", request.getServiceName(),
+          serviceInfo.isCredentialStoreSupported());
+
+      /**
+       * If request does not have credential_store_enabled field,
+       * then get the default from the stack definition.
+       */
+      if (StringUtils.isNotEmpty(request.getCredentialStoreEnabled())) {
+        boolean credentialStoreEnabled = Boolean.parseBoolean(request.getCredentialStoreEnabled());
+        s.setCredentialStoreEnabled(credentialStoreEnabled);
+        LOG.info("Service: {}, credential_store_enabled from request: {}", request.getServiceName(),
+            credentialStoreEnabled);
+      } else {
+        s.setCredentialStoreEnabled(serviceInfo.isCredentialStoreEnabled());
+        LOG.info("Service: {}, credential_store_enabled from stack definition:{}", s.getName(),
+            serviceInfo.isCredentialStoreEnabled());
+      }
+
       // Initialize service widgets
       getManagementController().initializeWidgetsAndLayouts(cluster, s);
     }
@@ -447,6 +484,7 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
     Set<String> clusterNames = new HashSet<String>();
     Map<String, Set<String>> serviceNames = new HashMap<String, Set<String>>();
     Set<State> seenNewStates = new HashSet<State>();
+    Map<Service, Boolean> serviceCredentialStoreEnabledMap = new HashMap<>();
 
     // Determine operation level
     Resource.Type reqOpLvl;
@@ -530,6 +568,25 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
         }
       }
 
+      /**
+       * Get the credential_store_supported field only from the stack definition during creation.
+       * Not possible to update the value of credential_store_supported through a request.
+       */
+
+      /**
+       * Gather the credential_store_enabled field per service.
+       */
+      if (StringUtils.isNotEmpty(request.getCredentialStoreEnabled())) {
+        boolean credentialStoreEnabled = Boolean.parseBoolean(request.getCredentialStoreEnabled());
+        if (!s.isCredentialStoreSupported() && credentialStoreEnabled) {
+          throw new IllegalArgumentException("Invalid arguments, cannot enable credential store " +
+              "as it is not supported by the service. Service=" + s.getName());
+        }
+        serviceCredentialStoreEnabledMap.put(s, credentialStoreEnabled);
+        LOG.info("Service: {}, credential_store_enabled from request: {}", request.getServiceName(),
+            credentialStoreEnabled);
+      }
+
       if (newState == null) {
         if (LOG.isDebugEnabled()) {
           LOG.debug("Nothing to do for new updateService request"
@@ -603,6 +660,13 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
           + " changes for a set of services at the same time");
     }
 
+    // update the credential store enabled information
+    for (Map.Entry<Service, Boolean> serviceCredential : serviceCredentialStoreEnabledMap.entrySet()) {
+      Service service = serviceCredential.getKey();
+      Boolean credentialStoreEnabled = serviceCredential.getValue();
+      service.setCredentialStoreEnabled(credentialStoreEnabled);
+    }
+
     Cluster cluster = clusters.getCluster(clusterNames.iterator().next());
 
     return controller.addStages(requestStages, cluster, requestProperties,
@@ -944,6 +1008,18 @@ public class ServiceResourceProvider extends AbstractControllerResourceProvider
         throw new IllegalArgumentException("Unsupported or invalid service in stack, clusterName=" + clusterName
                 + ", serviceName=" + serviceName + ", stackInfo=" + stackId.getStackId());
       }
+
+      // validate the credential store input provided
+      ServiceInfo serviceInfo = ambariMetaInfo.getService(stackId.getStackName(),
+          stackId.getStackVersion(), request.getServiceName());
+
+      if (StringUtils.isNotEmpty(request.getCredentialStoreEnabled())) {
+        boolean credentialStoreEnabled = Boolean.parseBoolean(request.getCredentialStoreEnabled());
+        if (!serviceInfo.isCredentialStoreSupported() && credentialStoreEnabled) {
+          throw new IllegalArgumentException("Invalid arguments, cannot enable credential store " +
+              "as it is not supported by the service. Service=" + request.getServiceName());
+        }
+      }
     }
     // ensure only a single cluster update
     if (serviceNames.size() != 1) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/33a41195/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 0fc65eb..504da49 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
@@ -88,6 +88,12 @@ public class StackServiceResourceProvider extends ReadOnlyResourceProvider {
   private static final String SERVICE_PROPERTIES_PROPERTY_ID = PropertyHelper.getPropertyId(
     "StackServices", "properties");
 
+  private static final String CREDENTIAL_STORE_SUPPORTED = PropertyHelper.getPropertyId(
+          "StackServices", "credential_store_supported");
+
+  private static final String CREDENTIAL_STORE_ENABLED = PropertyHelper.getPropertyId(
+          "StackServices", "credential_store_enabled");
+
   private static Set<String> pkPropertyIds = new HashSet<String>(
       Arrays.asList(new String[]{STACK_NAME_PROPERTY_ID,
         STACK_VERSION_PROPERTY_ID, SERVICE_NAME_PROPERTY_ID}));
@@ -187,6 +193,12 @@ public class StackServiceResourceProvider extends ReadOnlyResourceProvider {
     setResourceProperty(resource, SERVICE_PROPERTIES_PROPERTY_ID,
       response.getServiceProperties(), requestedIds);
 
+    setResourceProperty(resource, CREDENTIAL_STORE_SUPPORTED,
+      response.isCredentialStoreSupported(), requestedIds);
+
+    setResourceProperty(resource, CREDENTIAL_STORE_ENABLED,
+      response.isCredentialStoreEnabled(), requestedIds);
+
     return resource;
   }
 
@@ -194,7 +206,9 @@ public class StackServiceResourceProvider extends ReadOnlyResourceProvider {
     return new StackServiceRequest(
         (String) properties.get(STACK_NAME_PROPERTY_ID),
         (String) properties.get(STACK_VERSION_PROPERTY_ID),
-        (String) properties.get(SERVICE_NAME_PROPERTY_ID));
+        (String) properties.get(SERVICE_NAME_PROPERTY_ID),
+        (String) properties.get(CREDENTIAL_STORE_SUPPORTED),
+        (String) properties.get(CREDENTIAL_STORE_ENABLED));
   }
 
   @Override

http://git-wip-us.apache.org/repos/asf/ambari/blob/33a41195/ambari-server/src/main/java/org/apache/ambari/server/state/CredentialStoreInfo.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/CredentialStoreInfo.java b/ambari-server/src/main/java/org/apache/ambari/server/state/CredentialStoreInfo.java
new file mode 100644
index 0000000..605de99
--- /dev/null
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/CredentialStoreInfo.java
@@ -0,0 +1,96 @@
+/**
+ * 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 javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+
+/**
+ * Represents credential store information
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+public class CredentialStoreInfo {
+    /**
+     * Use Boolean data-type internally, so that we can validate
+     * the XML.
+     */
+
+    @XmlElement(name="supported")
+    private Boolean supported = null;
+
+    @XmlElement(name="enabled")
+    private Boolean enabled = null;
+
+    /**
+     * Default constructor
+     */
+    public CredentialStoreInfo() {
+    }
+
+    /**
+     * Gets a value indicating if the service supports
+     * credential store. If null, this was not specified.
+     * @return
+     */
+    public Boolean isSupported() {
+        return supported;
+    }
+
+    /**
+     * Set whether a service supports credential store.
+     *
+     * @param supported
+     */
+    public void setSupported(Boolean supported) {
+        this.supported = supported;
+    }
+
+    /**
+     * Gets a value indicating whether the service is
+     * enabled for credential store use.
+     *
+     * @return - true, false, null if not specified.
+     */
+    public Boolean isEnabled() {
+        return enabled;
+    }
+
+    /**
+     * Set whether the service is enabled for credential
+     * store use.
+     *
+     * @param enabled - true, false, null.
+     */
+    public void setEnabled(Boolean enabled) {
+        this.enabled = enabled;
+    }
+
+    /**
+     * String representation of this object
+     * @return
+     */
+    @Override
+    public String toString() {
+        return "CredentialStoreInfo{" +
+                "supported=" + supported +
+                ", enabled=" + enabled +
+                '}';
+    }
+}

http://git-wip-us.apache.org/repos/asf/ambari/blob/33a41195/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceImpl.java
index 6f8d306..f87b99c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/ServiceImpl.java
@@ -307,7 +307,8 @@ public class ServiceImpl implements Service {
   @Override
   public ServiceResponse convertToResponse() {
     ServiceResponse r = new ServiceResponse(cluster.getClusterId(), cluster.getClusterName(),
-        getName(), getDesiredStackVersion().getStackId(), getDesiredState().toString());
+        getName(), getDesiredStackVersion().getStackId(), getDesiredState().toString(),
+        isCredentialStoreSupported(), isCredentialStoreEnabled());
 
     r.setMaintenanceState(getMaintenanceState().name());
     return r;
@@ -358,7 +359,7 @@ public class ServiceImpl implements Service {
 
     if (desiredStateEntity != null) {
       desiredStateEntity.setCredentialStoreSupported(credentialStoreSupported);
-      serviceDesiredStateDAO.merge(desiredStateEntity);
+      desiredStateEntity = serviceDesiredStateDAO.merge(desiredStateEntity);
 
     } else {
       LOG.warn("Setting a member on an entity object that may have been "

http://git-wip-us.apache.org/repos/asf/ambari/blob/33a41195/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 7f83604..16042e1 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
@@ -118,6 +118,12 @@ public class ServiceInfo implements Validable{
   @XmlTransient
   private volatile Map<String, PropertyInfo> requiredProperties;
 
+  /**
+   * Credential store information
+   */
+  @XmlElements(@XmlElement(name = "credential-store"))
+  private CredentialStoreInfo credentialStoreInfo;
+
   public Boolean isRestartRequiredAfterChange() {
     return restartRequiredAfterChange;
   }
@@ -156,8 +162,6 @@ public class ServiceInfo implements Validable{
   @XmlElement(name="property")
   private List<ServicePropertyInfo> servicePropertyList = Lists.newArrayList();
 
-
-
   @XmlTransient
   private Map<String, String> servicePropertyMap = ImmutableMap.copyOf(ensureMandatoryServiceProperties(Maps.<String, String>newHashMap()));
 
@@ -439,6 +443,60 @@ public String getVersion() {
     this.advisorName = advisorName;
   }
 
+  /**
+   * Indicates if this service supports credential store.
+   * False, it was not specified.
+   *
+   * @return true or false
+   */
+  public boolean isCredentialStoreSupported() {
+    if (credentialStoreInfo != null) {
+      if (credentialStoreInfo.isSupported() != null) {
+        return credentialStoreInfo.isSupported();
+      }
+    }
+
+    return false;
+  }
+
+  /**
+   * Set a value indicating if this service supports credential store.
+   * @param credentialStoreSupported
+   */
+  public void setCredentialStoreSupported(boolean credentialStoreSupported) {
+    if (credentialStoreInfo == null) {
+      credentialStoreInfo = new CredentialStoreInfo();
+    }
+    credentialStoreInfo.setSupported(credentialStoreSupported);
+  }
+
+  /**
+   * Indicates if this service is enabled for credential store use.
+   * False if it was not specified.
+   *
+   * @return true or false
+   */
+  public boolean isCredentialStoreEnabled() {
+    if (credentialStoreInfo != null) {
+      if (credentialStoreInfo.isEnabled() != null) {
+        return credentialStoreInfo.isEnabled();
+      }
+    }
+
+    return false;
+  }
+
+  /**
+   * Set a value indicating if this service is enabled for credential store use.
+   * @param credentialStoreEnabled
+   */
+  public void setCredentialStoreEnabled(boolean credentialStoreEnabled) {
+    if (credentialStoreInfo == null) {
+      credentialStoreInfo = new CredentialStoreInfo();
+    }
+    credentialStoreInfo.setEnabled(credentialStoreEnabled);
+  }
+
   @Override
   public String toString() {
     StringBuilder sb = new StringBuilder();
@@ -996,6 +1054,29 @@ public String getVersion() {
         addError("More than one primary log exists for the component " + component.getName());
       }
     }
+
+    // validate credential store information
+    if (credentialStoreInfo != null) {
+      // if both are specified, supported must be true if enabled is false or true.
+      if (credentialStoreInfo.isSupported() != null && credentialStoreInfo.isEnabled() != null) {
+        if (!credentialStoreInfo.isSupported() && credentialStoreInfo.isEnabled()) {
+          setValid(false);
+          addError("Credential store cannot be enabled for service " + getName() + " as it does not support it.");
+        }
+      }
+
+      // Must be specified
+      if (credentialStoreInfo.isSupported() == null) {
+        setValid(false);
+        addError("Credential store supported is not specified for service " + getName());
+      }
+
+      // Must be specified
+      if (credentialStoreInfo.isEnabled() == null) {
+        setValid(false);
+        addError("Credential store enabled is not specified for service " + getName());
+      }
+    }
   }
 
   public enum Selection {

http://git-wip-us.apache.org/repos/asf/ambari/blob/33a41195/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 34d4641..6bbb323 100644
--- a/ambari-server/src/main/resources/properties.json
+++ b/ambari-server/src/main/resources/properties.json
@@ -17,6 +17,8 @@
         "ServiceInfo/cluster_name",
         "ServiceInfo/state",
         "ServiceInfo/maintenance_state",
+        "ServiceInfo/credential_store_supported",
+        "ServiceInfo/credential_store_enabled",
         "Services/description",
         "Services/display_name",
         "Services/attributes",
@@ -217,6 +219,8 @@
         "StackServices/service_check_supported",
         "StackServices/custom_commands",
         "StackServices/required_services",
+        "StackServices/credential_store_supported",
+        "StackServices/credential_store_enabled",
         "StackServices/properties",
         "_"
     ],

http://git-wip-us.apache.org/repos/asf/ambari/blob/33a41195/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ServiceResourceProviderTest.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ServiceResourceProviderTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ServiceResourceProviderTest.java
index f99b5ff..716be62 100644
--- a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ServiceResourceProviderTest.java
+++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/ServiceResourceProviderTest.java
@@ -72,6 +72,7 @@ import org.apache.ambari.server.state.Service;
 import org.apache.ambari.server.state.ServiceComponent;
 import org.apache.ambari.server.state.ServiceComponentHost;
 import org.apache.ambari.server.state.ServiceFactory;
+import org.apache.ambari.server.state.ServiceInfo;
 import org.apache.ambari.server.state.StackId;
 import org.apache.ambari.server.state.State;
 import org.easymock.Capture;
@@ -114,22 +115,27 @@ public class ServiceResourceProviderTest {
     StackId stackId = createNiceMock(StackId.class);
     ServiceFactory serviceFactory = createNiceMock(ServiceFactory.class);
     AmbariMetaInfo ambariMetaInfo = createNiceMock(AmbariMetaInfo.class);
+    ServiceInfo serviceInfo = createNiceMock(ServiceInfo.class);
 
     expect(managementController.getClusters()).andReturn(clusters).anyTimes();
-    expect(managementController.getAmbariMetaInfo()).andReturn(ambariMetaInfo);
+    expect(managementController.getAmbariMetaInfo()).andReturn(ambariMetaInfo).anyTimes();
 
     expect(cluster.addService("Service100")).andReturn(service);
 
     expect(clusters.getCluster("Cluster100")).andReturn(cluster).anyTimes();
 
     expect(cluster.getService("Service100")).andReturn(null);
-    expect(cluster.getDesiredStackVersion()).andReturn(stackId);
+    expect(cluster.getDesiredStackVersion()).andReturn(stackId).anyTimes();
     expect(cluster.getClusterId()).andReturn(2L).anyTimes();
 
+    expect(stackId.getStackName()).andReturn("HDP").anyTimes();
+    expect(stackId.getStackVersion()).andReturn("2.5").anyTimes();
+
     expect(ambariMetaInfo.isValidService( (String) anyObject(), (String) anyObject(), (String) anyObject())).andReturn(true);
+    expect(ambariMetaInfo.getService((String)anyObject(), (String)anyObject(), (String)anyObject())).andReturn(serviceInfo).anyTimes();
 
     // replay
-    replay(managementController, clusters, cluster, service, ambariMetaInfo, stackId, serviceFactory);
+    replay(managementController, clusters, cluster, service, ambariMetaInfo, stackId, serviceFactory, serviceInfo);
 
     SecurityContextHolder.getContext().setAuthentication(authentication);
 
@@ -154,7 +160,7 @@ public class ServiceResourceProviderTest {
     provider.createResources(request);
 
     // verify
-    verify(managementController, clusters, cluster, service, ambariMetaInfo, stackId, serviceFactory);
+    verify(managementController, clusters, cluster, service, ambariMetaInfo, stackId, serviceFactory, serviceInfo);
   }
 
   @Test
@@ -599,6 +605,8 @@ public class ServiceResourceProviderTest {
     RequestStageContainer requestStages = createNiceMock(RequestStageContainer.class);
     RequestStatusResponse requestStatusResponse = createNiceMock(RequestStatusResponse.class);
     RoleCommandOrder rco = createNiceMock(RoleCommandOrder.class);
+    StackId stackId = createNiceMock(StackId.class);
+    ServiceInfo serviceInfo = createNiceMock(ServiceInfo.class);
 
     Map<String, String> mapRequestProps = new HashMap<String, String>();
     mapRequestProps.put("context", "Called from a test");
@@ -615,6 +623,15 @@ public class ServiceResourceProviderTest {
     expect(service0.getDesiredState()).andReturn(State.INSTALLED).anyTimes();
     expect(service0.getServiceComponents()).andReturn(Collections.<String, ServiceComponent>emptyMap()).anyTimes();
 
+    expect(stackId.getStackId()).andReturn("HDP-2.5").anyTimes();
+    expect(stackId.getStackName()).andReturn("HDP").anyTimes();
+    expect(stackId.getStackVersion()).andReturn("2.5").anyTimes();
+    expect(service0.getDesiredStackVersion()).andReturn(stackId).anyTimes();
+    expect(service0.getName()).andReturn("Service102").anyTimes();
+    expect(serviceInfo.isCredentialStoreSupported()).andReturn(true).anyTimes();
+    expect(serviceInfo.isCredentialStoreEnabled()).andReturn(false).anyTimes();
+    expect(ambariMetaInfo.getService("HDP", "2.5", "Service102")).andReturn(serviceInfo).anyTimes();
+
     Capture<Map<String, String>> requestPropertiesCapture = newCapture();
     Capture<Map<State, List<Service>>> changedServicesCapture = newCapture();
     Capture<Map<State, List<ServiceComponent>>> changedCompsCapture = newCapture();
@@ -639,7 +656,7 @@ public class ServiceResourceProviderTest {
 
     // replay
     replay(managementController, clusters, cluster, rco, maintenanceStateHelper,
-        service0, serviceFactory, ambariMetaInfo, requestStages, requestStatusResponse);
+        service0, serviceFactory, ambariMetaInfo, requestStages, requestStatusResponse, stackId, serviceInfo);
 
     SecurityContextHolder.getContext().setAuthentication(authentication);
 
@@ -660,7 +677,7 @@ public class ServiceResourceProviderTest {
 
     // verify
     verify(managementController, clusters, cluster, maintenanceStateHelper,
-        service0, serviceFactory, ambariMetaInfo, requestStages, requestStatusResponse);
+        service0, serviceFactory, ambariMetaInfo, requestStages, requestStatusResponse, stackId, serviceInfo);
   }
 
   @Test
@@ -696,6 +713,9 @@ public class ServiceResourceProviderTest {
       .class);
     RoleCommandOrder rco = createNiceMock(RoleCommandOrder.class);
 
+    StackId stackId = createNiceMock(StackId.class);
+    ServiceInfo serviceInfo = createNiceMock(ServiceInfo.class);
+
     Map<String, String> mapRequestProps = new HashMap<String, String>();
     mapRequestProps.put("context", "Called from a test");
 
@@ -716,6 +736,15 @@ public class ServiceResourceProviderTest {
     expect(cluster.getClusterId()).andReturn(2L).anyTimes();
     expect(cluster.getService("Service102")).andReturn(service0).anyTimes();
 
+    expect(stackId.getStackId()).andReturn("HDP-2.5").anyTimes();
+    expect(stackId.getStackName()).andReturn("HDP").anyTimes();
+    expect(stackId.getStackVersion()).andReturn("2.5").anyTimes();
+    expect(service0.getDesiredStackVersion()).andReturn(stackId).anyTimes();
+    expect(service0.getName()).andReturn("Service102").anyTimes();
+    expect(serviceInfo.isCredentialStoreSupported()).andReturn(true).anyTimes();
+    expect(serviceInfo.isCredentialStoreEnabled()).andReturn(false).anyTimes();
+    expect(ambariMetaInfo.getService("HDP", "2.5", "Service102")).andReturn(serviceInfo).anyTimes();
+
     expect(service0.convertToResponse()).andReturn(serviceResponse0).anyTimes();
     expect(service0.getDesiredState()).andReturn(State.INSTALLED).anyTimes();
     expect(service0.getServiceComponents()).andReturn(Collections.<String, ServiceComponent>emptyMap()).anyTimes();
@@ -759,7 +788,7 @@ public class ServiceResourceProviderTest {
 
     // replay
     replay(managementController1, response1, managementController2, requestStages1, requestStages2, response2,
-        clusters, cluster, service0, serviceResponse0, ambariMetaInfo, rco, maintenanceStateHelper);
+        clusters, cluster, service0, serviceResponse0, ambariMetaInfo, rco, maintenanceStateHelper, stackId, serviceInfo);
 
     SecurityContextHolder.getContext().setAuthentication(authentication);
 
@@ -794,7 +823,7 @@ public class ServiceResourceProviderTest {
 
     // verify
     verify(managementController1, response1, managementController2, requestStages1, requestStages2, response2,
-        clusters, cluster, service0, serviceResponse0, ambariMetaInfo, maintenanceStateHelper);
+        clusters, cluster, service0, serviceResponse0, ambariMetaInfo, maintenanceStateHelper, stackId, serviceInfo);
   }
 
   @Test

http://git-wip-us.apache.org/repos/asf/ambari/blob/33a41195/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 9986ee3..3034459 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
@@ -141,6 +141,230 @@ public class ServiceInfoTest {
     assertTrue(defaultSi.isSelectionEmpty());
   }
 
+  /**
+   * Tests the presence and absence of the credential-store block.
+   * @throws Exception
+     */
+  @Test
+  public void testCredentialStoreFields() throws Exception {
+    /*
+     * <credential-store> supported and enabled.
+     */
+    String serviceInfoXml = "<metainfo>\n" +
+            "  <schemaVersion>2.0</schemaVersion>\n" +
+            "  <services>\n" +
+            "    <service>\n" +
+            "      <name>RANGER</name>\n" +
+            "      <credential-store>\n" +
+            "          <supported>true</supported>\n" +
+            "          <enabled>true</enabled>\n" +
+            "      </credential-store>\n" +
+            "    </service>\n" +
+            "  </services>\n" +
+            "</metainfo>\n";
+    Map<String, ServiceInfo> serviceInfoMap = getServiceInfo(serviceInfoXml);
+    ServiceInfo service = serviceInfoMap.get("RANGER");
+    assertTrue(service.isCredentialStoreSupported());
+    assertTrue(service.isCredentialStoreEnabled());
+
+    /*
+     * <credential-store> supported but not enabled.
+     */
+    serviceInfoXml = "<metainfo>\n" +
+            "  <schemaVersion>2.0</schemaVersion>\n" +
+            "  <services>\n" +
+            "    <service>\n" +
+            "      <name>HIVE</name>\n" +
+            "      <credential-store>\n" +
+            "          <supported>true</supported>\n" +
+            "          <enabled>false</enabled>\n" +
+            "      </credential-store>\n" +
+            "    </service>\n" +
+            "  </services>\n" +
+            "</metainfo>\n";
+    serviceInfoMap = getServiceInfo(serviceInfoXml);
+    service = serviceInfoMap.get("HIVE");
+    assertTrue(service.isCredentialStoreSupported());
+    assertFalse(service.isCredentialStoreEnabled());
+
+    /*
+     * <credential-store> is missing
+     */
+    serviceInfoXml = "<metainfo>\n" +
+            "  <schemaVersion>2.0</schemaVersion>\n" +
+            "  <services>\n" +
+            "    <service>\n" +
+            "      <name>AMBARI_METRICS</name>\n" +
+            "    </service>\n" +
+            "  </services>\n" +
+            "</metainfo>\n";
+    serviceInfoMap = getServiceInfo(serviceInfoXml);
+    service = serviceInfoMap.get("AMBARI_METRICS");
+    assertFalse(service.isCredentialStoreSupported());
+    assertFalse(service.isCredentialStoreEnabled());
+
+    /*
+     * <credential-store><enabled> is missing. Invalid
+     * scenario. So both values should be false.
+     */
+    serviceInfoXml = "<metainfo>\n" +
+            "  <schemaVersion>2.0</schemaVersion>\n" +
+            "  <services>\n" +
+            "    <service>\n" +
+            "      <name>HBASE</name>\n" +
+            "      <credential-store>\n" +
+            "          <supported>true</supported>\n" +
+            "      </credential-store>\n" +
+            "    </service>\n" +
+            "  </services>\n" +
+            "</metainfo>\n";
+    serviceInfoMap = getServiceInfo(serviceInfoXml);
+    service = serviceInfoMap.get("HBASE");
+    assertTrue(service.isCredentialStoreSupported());
+    assertFalse(service.isCredentialStoreEnabled());
+  }
+
+  @Test
+  public void testCredentialStoreInfoValidity() throws Exception
+  {
+    // Valid: Supported->True, Enabled->False
+    String serviceInfoXml = "<metainfo>\n" +
+            "  <schemaVersion>2.0</schemaVersion>\n" +
+            "  <services>\n" +
+            "    <service>\n" +
+            "      <name>RANGER</name>\n" +
+            "      <credential-store>\n" +
+            "          <supported>true</supported>\n" +
+            "          <enabled>false</enabled>\n" +
+            "      </credential-store>\n" +
+            "    </service>\n" +
+            "  </services>\n" +
+            "</metainfo>\n";
+
+    Map<String, ServiceInfo> serviceInfoMap = getServiceInfo(serviceInfoXml);
+    ServiceInfo serviceInfo = serviceInfoMap.get("RANGER");
+    assertTrue(serviceInfo.isValid());
+
+    // Valid: Supported->True, Enabled->True
+    serviceInfoXml = "<metainfo>\n" +
+            "  <schemaVersion>2.0</schemaVersion>\n" +
+            "  <services>\n" +
+            "    <service>\n" +
+            "      <name>RANGER</name>\n" +
+            "      <credential-store>\n" +
+            "          <supported>true</supported>\n" +
+            "          <enabled>true</enabled>\n" +
+            "      </credential-store>\n" +
+            "    </service>\n" +
+            "  </services>\n" +
+            "</metainfo>\n";
+
+    serviceInfoMap = getServiceInfo(serviceInfoXml);
+    serviceInfo = serviceInfoMap.get("RANGER");
+    assertTrue(serviceInfo.isValid());
+
+    // Valid: Supported->False, Enabled->False
+    serviceInfoXml = "<metainfo>\n" +
+            "  <schemaVersion>2.0</schemaVersion>\n" +
+            "  <services>\n" +
+            "    <service>\n" +
+            "      <name>RANGER</name>\n" +
+            "      <credential-store>\n" +
+            "          <supported>false</supported>\n" +
+            "          <enabled>false</enabled>\n" +
+            "      </credential-store>\n" +
+            "    </service>\n" +
+            "  </services>\n" +
+            "</metainfo>\n";
+
+    serviceInfoMap = getServiceInfo(serviceInfoXml);
+    serviceInfo = serviceInfoMap.get("RANGER");
+    assertTrue(serviceInfo.isValid());
+
+    // Valid: credential-store not specified
+    serviceInfoXml = "<metainfo>\n" +
+            "  <schemaVersion>2.0</schemaVersion>\n" +
+            "  <services>\n" +
+            "    <service>\n" +
+            "      <name>RANGER</name>\n" +
+            "    </service>\n" +
+            "  </services>\n" +
+            "</metainfo>\n";
+
+    serviceInfoMap = getServiceInfo(serviceInfoXml);
+    serviceInfo = serviceInfoMap.get("RANGER");
+    assertTrue(serviceInfo.isValid());
+
+    // Specified but invalid
+    // Invalid: Supported->False, Enabled->True
+    serviceInfoXml = "<metainfo>\n" +
+            "  <schemaVersion>2.0</schemaVersion>\n" +
+            "  <services>\n" +
+            "    <service>\n" +
+            "      <name>RANGER</name>\n" +
+            "      <credential-store>\n" +
+            "          <supported>false</supported>\n" +
+            "          <enabled>true</enabled>\n" +
+            "      </credential-store>\n" +
+            "    </service>\n" +
+            "  </services>\n" +
+            "</metainfo>\n";
+
+    serviceInfoMap = getServiceInfo(serviceInfoXml);
+    serviceInfo = serviceInfoMap.get("RANGER");
+    assertFalse("Credential store is enabled for a service that does not support it", serviceInfo.isValid());
+
+    // Invalid: Supported->Unspecified, Enabled->Unspecified
+    serviceInfoXml = "<metainfo>\n" +
+            "  <schemaVersion>2.0</schemaVersion>\n" +
+            "  <services>\n" +
+            "    <service>\n" +
+            "      <name>RANGER</name>\n" +
+            "      <credential-store>\n" +
+            "      </credential-store>\n" +
+            "    </service>\n" +
+            "  </services>\n" +
+            "</metainfo>\n";
+
+    serviceInfoMap = getServiceInfo(serviceInfoXml);
+    serviceInfo = serviceInfoMap.get("RANGER");
+    assertFalse("Credential store details not specified", serviceInfo.isValid());
+
+    // Invalid: Supported->Specified, Enabled->Unspecified
+    serviceInfoXml = "<metainfo>\n" +
+            "  <schemaVersion>2.0</schemaVersion>\n" +
+            "  <services>\n" +
+            "    <service>\n" +
+            "      <name>RANGER</name>\n" +
+            "      <credential-store>\n" +
+            "          <supported>true</supported>\n" +
+            "      </credential-store>\n" +
+            "    </service>\n" +
+            "  </services>\n" +
+            "</metainfo>\n";
+
+    serviceInfoMap = getServiceInfo(serviceInfoXml);
+    serviceInfo = serviceInfoMap.get("RANGER");
+    assertFalse("Credential store enabled not specified", serviceInfo.isValid());
+
+    // Invalid: Supported->Unspecified, Enabled->Specified
+    serviceInfoXml = "<metainfo>\n" +
+            "  <schemaVersion>2.0</schemaVersion>\n" +
+            "  <services>\n" +
+            "    <service>\n" +
+            "      <name>RANGER</name>\n" +
+            "      <credential-store>\n" +
+            "          <enabled>true</enabled>\n" +
+            "      </credential-store>\n" +
+            "    </service>\n" +
+            "  </services>\n" +
+            "</metainfo>\n";
+
+    serviceInfoMap = getServiceInfo(serviceInfoXml);
+    serviceInfo = serviceInfoMap.get("RANGER");
+    assertFalse("Credential store supported not specified", serviceInfo.isValid());
+  }
+
   @Test
   public void testSetRestartRequiredAfterRackChange() throws Exception {
     ServiceInfo serviceInfo = new ServiceInfo();


Mime
View raw message