You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by rl...@apache.org on 2016/06/23 19:31:30 UTC

[2/2] ambari git commit: AMBARI-17226. When requesting a Kerberos Descriptor via the REST API, 'when' clauses should optionally be processed. (rlevas)

AMBARI-17226. When requesting a Kerberos Descriptor via the REST API, 'when' clauses should optionally be processed. (rlevas)


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

Branch: refs/heads/trunk
Commit: 628f81922cc099d5fa7ca8299d860176486f07c4
Parents: 8b0b903
Author: Robert Levas <rl...@hortonworks.com>
Authored: Thu Jun 23 15:31:06 2016 -0400
Committer: Robert Levas <rl...@hortonworks.com>
Committed: Thu Jun 23 15:31:11 2016 -0400

----------------------------------------------------------------------
 .../resources/ResourceInstanceFactoryImpl.java  |  26 +-
 .../server/controller/KerberosHelper.java       |  66 ++-
 .../server/controller/KerberosHelperImpl.java   | 237 +++++----
 ...usterKerberosDescriptorResourceProvider.java | 184 +++----
 .../kerberos/AbstractKerberosDescriptor.java    |  41 +-
 .../AbstractKerberosDescriptorContainer.java    |  39 +-
 .../kerberos/KerberosComponentDescriptor.java   |  13 +
 .../state/kerberos/KerberosDescriptor.java      |  19 +-
 .../state/kerberos/KerberosDescriptorType.java  |  55 ---
 .../kerberos/KerberosIdentityDescriptor.java    |   8 +-
 .../kerberos/KerberosServiceDescriptor.java     |  24 +-
 .../server/controller/KerberosHelperTest.java   | 475 +++++--------------
 ...rKerberosDescriptorResourceProviderTest.java | 231 +++++++--
 .../KerberosComponentDescriptorTest.java        |   6 +-
 .../state/kerberos/KerberosDescriptorTest.java  |   8 +-
 .../kerberos/KerberosServiceDescriptorTest.java |   8 +-
 16 files changed, 705 insertions(+), 735 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/628f8192/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
index a2aeffa..5e7f0da 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/api/resources/ResourceInstanceFactoryImpl.java
@@ -19,12 +19,14 @@
 
 package org.apache.ambari.server.api.resources;
 
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Set;
 
 import org.apache.ambari.server.api.query.QueryImpl;
+import org.apache.ambari.server.controller.internal.ClusterKerberosDescriptorResourceProvider;
 import org.apache.ambari.server.controller.spi.Resource;
 import org.apache.ambari.server.controller.utilities.ClusterControllerHelper;
 import org.apache.ambari.server.view.ViewRegistry;
@@ -397,17 +399,7 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory {
         break;
 
       case StackArtifact:
-        resourceDefinition = new BaseResourceDefinition(Resource.Type.StackArtifact) {
-          @Override
-          public String getPluralName() {
-            return "artifacts";
-          }
-
-          @Override
-          public String getSingularName() {
-            return "artifact";
-          }
-        };
+        resourceDefinition = new SimpleResourceDefinition(Resource.Type.StackArtifact, "artifact", "artifacts");
         break;
 
       case Artifact:
@@ -463,7 +455,17 @@ public class ResourceInstanceFactoryImpl implements ResourceInstanceFactory {
         break;
 
       case ClusterKerberosDescriptor:
-        resourceDefinition = new SimpleResourceDefinition(Resource.Type.ClusterKerberosDescriptor, "kerberos_descriptor", "kerberos_descriptors");
+        resourceDefinition = new SimpleResourceDefinition(
+            Resource.Type.ClusterKerberosDescriptor,
+            "kerberos_descriptor",
+            "kerberos_descriptors",
+            null,
+            Collections.singletonMap(SimpleResourceDefinition.DirectiveType.READ,
+                Arrays.asList(
+                    ClusterKerberosDescriptorResourceProvider.DIRECTIVE_EVALUATE_WHEN_CLAUSE,
+                    ClusterKerberosDescriptorResourceProvider.DIRECTIVE_ADDITIONAL_SERVICES
+                ))
+        );
         break;
 
       case LoggingQuery:

http://git-wip-us.apache.org/repos/asf/ambari/blob/628f8192/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelper.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelper.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelper.java
index 5ffc8a3..8170f17 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelper.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelper.java
@@ -238,10 +238,10 @@ public interface KerberosHelper {
    * Returns the updates configurations that are expected when the given set of services are configured
    * for Kerberos.
    *
-   * @param cluster                the cluster
-   * @param existingConfigurations the cluster's existing configurations
-   * @param services               the set of services to process
-   * @param kerberosEnabled        true if kerberos is (to be) enabled; otherwise false
+   * @param cluster                  the cluster
+   * @param existingConfigurations   the cluster's existing configurations
+   * @param services                 the set of services to process
+   * @param kerberosEnabled          true if kerberos is (to be) enabled; otherwise false
    * @param applyStackAdvisorUpdates true to invoke the stack advisor to validate property updates; false to skip
    * @return a map of configuration updates
    * @throws AmbariException
@@ -407,10 +407,40 @@ public interface KerberosHelper {
    * @param cluster cluster instance
    * @return the kerberos descriptor associated with the specified cluster
    * @throws AmbariException if unable to obtain the descriptor
+   * @see #getKerberosDescriptor(KerberosDescriptorType, Cluster, boolean, Collection)
    */
   KerberosDescriptor getKerberosDescriptor(Cluster cluster) throws AmbariException;
 
   /**
+   * Gets the requested Kerberos descriptor.
+   * <p>
+   * One of the following Kerberos descriptors will be returned - with or without pruning identity
+   * definitions based on the evaluation of their <code>when</code> clauses:
+   * <dl>
+   * <dt>{@link KerberosDescriptorType#STACK}</dt>
+   * <dd>A Kerberos descriptor built using data from the current stack definition, only</dd>
+   * <dt>{@link KerberosDescriptorType#USER}</dt>
+   * <dd>A Kerberos descriptor built using user-specified data stored as an artifact of the cluster, only</dd>
+   * <dt>{@link KerberosDescriptorType#COMPOSITE}</dt>
+   * <dd>A Kerberos descriptor built using data from the current stack definition with user-specified data stored as an artifact of the cluster applied
+   * - see {@link #getKerberosDescriptor(Cluster)}</dd>
+   * </dl>
+   *
+   * @param kerberosDescriptorType the type of Kerberos descriptor to retrieve - see {@link KerberosDescriptorType}
+   * @param cluster                the relevant Cluster
+   * @param evaluateWhenClauses    true to evaluate Kerberos identity <code>when</code> clauses and
+   *                               prune if necessary; false otherwise.
+   * @param additionalServices     an optional collection of service names declaring additional
+   *                               services to add to the set of currently installed services to use
+   *                               while evaluating <code>when</code> clauses
+   * @return a Kerberos descriptor
+   * @throws AmbariException
+   */
+  KerberosDescriptor getKerberosDescriptor(KerberosDescriptorType kerberosDescriptorType, Cluster cluster,
+                                           boolean evaluateWhenClauses, Collection<String> additionalServices)
+      throws AmbariException;
+
+  /**
    * Merges configuration from a Map of configuration updates into a main configurations Map.  Each
    * property in the updates Map is processed to replace variables using the replacement Map.
    * <p/>
@@ -571,6 +601,34 @@ public interface KerberosHelper {
   PrincipalKeyCredential getKDCAdministratorCredentials(String clusterName) throws AmbariException;
 
   /**
+   * Types of Kerberos descriptors related to where the data is stored.
+   * <dl>
+   * <dt>STACK</dt>
+   * <dd>A Kerberos descriptor built using data from a stack definition, only</dd>
+   * <dt>USER</dt>
+   * <dd>A Kerberos descriptor built using user-specified data stored as an artifact of a cluster, only</dd>
+   * <dt>COMPOSITE</dt>
+   * <dd>A Kerberos descriptor built using data from a stack definition with user-specified data stored as an artifact of a cluster applied</dd>
+   * </dl>
+   */
+  enum KerberosDescriptorType {
+    /**
+     * A Kerberos descriptor built using data from a stack definition, only
+     */
+    STACK,
+
+    /**
+     * A Kerberos descriptor built using user-specified data stored as an artifact of a cluster, only
+     */
+    USER,
+
+    /**
+     * A Kerberos descriptor built using data from a stack definition with user-specified data stored as an artifact of a cluster applied
+     */
+    COMPOSITE
+  }
+
+  /**
    * Command to invoke against the Ambari backend.
    *
    * @param <T> the response type

http://git-wip-us.apache.org/repos/asf/ambari/blob/628f8192/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelperImpl.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelperImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelperImpl.java
index cd79e46..cc48240 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelperImpl.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/KerberosHelperImpl.java
@@ -31,6 +31,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import java.util.TreeMap;
 import java.util.regex.Matcher;
 
 import org.apache.ambari.server.AmbariException;
@@ -45,27 +46,14 @@ import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorHelper;
 import org.apache.ambari.server.api.services.stackadvisor.StackAdvisorRequest;
 import org.apache.ambari.server.api.services.stackadvisor.recommendations.RecommendationResponse;
 import org.apache.ambari.server.configuration.Configuration;
-import org.apache.ambari.server.controller.internal.ArtifactResourceProvider;
-import org.apache.ambari.server.controller.internal.RequestImpl;
 import org.apache.ambari.server.controller.internal.RequestResourceFilter;
 import org.apache.ambari.server.controller.internal.RequestStageContainer;
-import org.apache.ambari.server.controller.spi.ClusterController;
-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.ResourceProvider;
-import org.apache.ambari.server.controller.spi.SystemException;
-import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
-import org.apache.ambari.server.controller.utilities.ClusterControllerHelper;
 import org.apache.ambari.server.controller.utilities.KerberosChecker;
-import org.apache.ambari.server.controller.utilities.PredicateBuilder;
 import org.apache.ambari.server.metadata.RoleCommandOrder;
+import org.apache.ambari.server.orm.dao.ArtifactDAO;
 import org.apache.ambari.server.orm.dao.KerberosPrincipalDAO;
+import org.apache.ambari.server.orm.entities.ArtifactEntity;
 import org.apache.ambari.server.orm.entities.KerberosPrincipalEntity;
-import org.apache.ambari.server.security.SecurePasswordHelper;
-import org.apache.ambari.server.security.authorization.AuthorizationException;
 import org.apache.ambari.server.security.credential.Credential;
 import org.apache.ambari.server.security.credential.PrincipalKeyCredential;
 import org.apache.ambari.server.security.encryption.CredentialStoreService;
@@ -110,6 +98,7 @@ import org.apache.ambari.server.state.ServiceComponentHost;
 import org.apache.ambari.server.state.StackId;
 import org.apache.ambari.server.state.State;
 import org.apache.ambari.server.state.ValueAttributesInfo;
+import org.apache.ambari.server.state.kerberos.AbstractKerberosDescriptorContainer;
 import org.apache.ambari.server.state.kerberos.KerberosComponentDescriptor;
 import org.apache.ambari.server.state.kerberos.KerberosConfigurationDescriptor;
 import org.apache.ambari.server.state.kerberos.KerberosDescriptor;
@@ -183,10 +172,10 @@ public class KerberosHelperImpl implements KerberosHelper {
   private KerberosIdentityDataFileWriterFactory kerberosIdentityDataFileWriterFactory;
 
   @Inject
-  private SecurePasswordHelper securePasswordHelper;
+  private KerberosPrincipalDAO kerberosPrincipalDAO;
 
   @Inject
-  private KerberosPrincipalDAO kerberosPrincipalDAO;
+  private ArtifactDAO artifactDAO;
 
   /**
    * The injector used to create new instances of helper classes like CreatePrincipalsServerAction
@@ -204,13 +193,6 @@ public class KerberosHelperImpl implements KerberosHelper {
   @Inject
   private StackAdvisorHelper stackAdvisorHelper;
 
-  /**
-   * Used to get kerberos descriptors associated with the cluster or stack.
-   * Currently not available via injection.
-   */
-  private static ClusterController clusterController = null;
-
-
   @Override
   public RequestStageContainer toggleKerberos(Cluster cluster, SecurityType securityType,
                                               RequestStageContainer requestStageContainer,
@@ -1047,89 +1029,80 @@ public class KerberosHelperImpl implements KerberosHelper {
 
   @Override
   public KerberosDescriptor getKerberosDescriptor(Cluster cluster) throws AmbariException {
-    StackId stackId = cluster.getCurrentStackVersion();
+    return getKerberosDescriptor(KerberosDescriptorType.COMPOSITE, cluster, false, null);
+  }
 
-    // -------------------------------
-    // Get the default Kerberos descriptor from the stack, which is the same as the value from
-    // stacks/:stackName/versions/:version/artifacts/kerberos_descriptor
-    KerberosDescriptor defaultDescriptor = ambariMetaInfo.getKerberosDescriptor(stackId.getStackName(), stackId.getStackVersion());
-    // -------------------------------
+  @Override
+  public KerberosDescriptor getKerberosDescriptor(KerberosDescriptorType kerberosDescriptorType, Cluster cluster,
+                                                  boolean evaluateWhenClauses, Collection<String> additionalServices)
+      throws AmbariException {
+    KerberosDescriptor kerberosDescriptor;
 
-    // Get the user-supplied Kerberos descriptor from cluster/:clusterName/artifacts/kerberos_descriptor
-    KerberosDescriptor descriptor = null;
+    KerberosDescriptor stackDescriptor = (kerberosDescriptorType == KerberosDescriptorType.STACK || kerberosDescriptorType == KerberosDescriptorType.COMPOSITE)
+        ? getKerberosDescriptorFromStack(cluster)
+        : null;
 
-    PredicateBuilder pb = new PredicateBuilder();
-    Predicate predicate = pb.begin().property("Artifacts/cluster_name").equals(cluster.getClusterName()).and().
-        property(ArtifactResourceProvider.ARTIFACT_NAME_PROPERTY).equals("kerberos_descriptor").
-        end().toPredicate();
+    KerberosDescriptor userDescriptor = (kerberosDescriptorType == KerberosDescriptorType.USER || kerberosDescriptorType == KerberosDescriptorType.COMPOSITE)
+        ? getKerberosDescriptorUpdates(cluster)
+        : null;
 
-    synchronized (KerberosHelperImpl.class) {
-      if (clusterController == null) {
-        clusterController = ClusterControllerHelper.getClusterController();
+    if (stackDescriptor == null) {
+      if (userDescriptor == null) {
+        return new KerberosDescriptor();  // return an empty Kerberos descriptor since we have no data
+      } else {
+        kerberosDescriptor = userDescriptor;
+      }
+    } else {
+      if (userDescriptor != null) {
+        stackDescriptor.update(userDescriptor);
       }
+      kerberosDescriptor = stackDescriptor;
     }
 
-    ResourceProvider artifactProvider =
-        clusterController.ensureResourceProvider(Resource.Type.Artifact);
+    if (evaluateWhenClauses) {
+      Set<String> services = new HashSet<String>(cluster.getServices().keySet());
+
+      if(additionalServices != null) {
+        services.addAll(additionalServices);
+      }
 
-    Request request = new RequestImpl(Collections.<String>emptySet(),
-        Collections.<Map<String, Object>>emptySet(), Collections.<String, String>emptyMap(), null);
+      // Build the context needed to filter out Kerberos identities...
+      // This includes the current set of configurations for the cluster and the set of installed services
+      Map<String, Object> context = new HashMap<String, Object>();
+      context.put("configurations", calculateConfigurations(cluster, null, kerberosDescriptor.getProperties()));
+      context.put("services", services);
 
-    Set<Resource> response = null;
-    try {
-      response = artifactProvider.getResources(request, predicate);
-    } catch (AuthorizationException e) {
-      e.printStackTrace();
-      throw new AmbariException(e.getMessage(), e);
-    } catch (SystemException e) {
-      e.printStackTrace();
-      throw new AmbariException("An unknown error occurred while trying to obtain the cluster kerberos descriptor", e);
-    } catch (UnsupportedPropertyException e) {
-      e.printStackTrace();
-      throw new AmbariException("An unknown error occurred while trying to obtain the cluster kerberos descriptor", e);
-    } catch (NoSuchParentResourceException e) {
-      // parent cluster doesn't exist.  shouldn't happen since we have the cluster instance
-      e.printStackTrace();
-      throw new AmbariException("An unknown error occurred while trying to obtain the cluster kerberos descriptor", e);
-    } catch (NoSuchResourceException e) {
-      // no descriptor registered, use the default from the stack
-    }
-
-    if (response != null && !response.isEmpty()) {
-      Resource descriptorResource = response.iterator().next();
-      Map<String, Map<String, Object>> propertyMap = descriptorResource.getPropertiesMap();
-      if (propertyMap != null) {
-        Map<String, Object> artifactData = propertyMap.get(ArtifactResourceProvider.ARTIFACT_DATA_PROPERTY);
-        Map<String, Object> artifactDataProperties = propertyMap.get(ArtifactResourceProvider.ARTIFACT_DATA_PROPERTY + "/properties");
-        HashMap<String, Object> data = new HashMap<String, Object>();
-
-        if (artifactData != null) {
-          data.putAll(artifactData);
-        }
+      // Get the Kerberos identities that need to be pruned
+      Map<String, Set<String>> identitiesToRemove = processWhenClauses("", kerberosDescriptor, context, new HashMap<String, Set<String>>());
 
-        if (artifactDataProperties != null) {
-          data.put("properties", artifactDataProperties);
+      // Prune off the Kerberos identities that need to be removed due to the evaluation of its _when_ clause
+      for (Map.Entry<String, Set<String>> identity : identitiesToRemove.entrySet()) {
+        String[] path = identity.getKey().split("/");
+        AbstractKerberosDescriptorContainer container = null;
+
+        // Follow the path to the container that contains the identities to remove
+        for (String name : path) {
+          if (container == null) {
+            container = kerberosDescriptor;
+          } else {
+            container = container.getChildContainer(name);
+
+            if (container == null) {
+              break;
+            }
+          }
         }
 
-        descriptor = kerberosDescriptorFactory.createInstance(data);
+        // Remove the relevant identities from the found container
+        if (container != null) {
+          for (String identityName : identity.getValue()) {
+            container.removeIdentity(identityName);
+          }
+        }
       }
     }
-    // -------------------------------
 
-    // -------------------------------
-    // Attempt to build and return a composite of the default Kerberos descriptor and the user-supplied
-    // Kerberos descriptor. If the default descriptor exists, overlay the user-supplied Kerberos
-    // descriptor on top of it (if it exists) and return the composite; else return the user-supplied
-    // Kerberos descriptor. If both values are null, null may be returned.
-    if (defaultDescriptor == null) {
-      return descriptor;
-    } else {
-      if (descriptor != null) {
-        defaultDescriptor.update(descriptor);
-      }
-      return defaultDescriptor;
-    }
-    // -------------------------------
+    return kerberosDescriptor;
   }
 
   @Override
@@ -2501,6 +2474,86 @@ public class KerberosHelperImpl implements KerberosHelper {
     }
   }
 
+  /**
+   * Get the user-supplied Kerberos descriptor from the set of cluster artifacts
+   *
+   * @param cluster the cluster
+   * @return a Kerberos descriptor
+   */
+  private KerberosDescriptor getKerberosDescriptorUpdates(Cluster cluster) throws AmbariException {
+    // find instance using name and foreign keys
+    TreeMap<String, String> foreignKeys = new TreeMap<String, String>();
+    foreignKeys.put("cluster", String.valueOf(cluster.getClusterId()));
+
+    ArtifactEntity entity = artifactDAO.findByNameAndForeignKeys("kerberos_descriptor", foreignKeys);
+    return (entity == null) ? null : kerberosDescriptorFactory.createInstance(entity.getArtifactData());
+  }
+
+  /**
+   * Get the default Kerberos descriptor from the stack, which is the same as the value from
+   * <code>stacks/:stackName/versions/:version/artifacts/kerberos_descriptor</code>
+   *
+   * @param cluster the cluster
+   * @return a Kerberos Descriptor
+   * @throws AmbariException if an error occurs while retrieving the Kerberos descriptor
+   */
+  private KerberosDescriptor getKerberosDescriptorFromStack(Cluster cluster) throws AmbariException {
+    StackId stackId = cluster.getCurrentStackVersion();
+
+    // -------------------------------
+    // Get the default Kerberos descriptor from the stack, which is the same as the value from
+    // stacks/:stackName/versions/:version/artifacts/kerberos_descriptor
+    return ambariMetaInfo.getKerberosDescriptor(stackId.getStackName(), stackId.getStackVersion());
+    // -------------------------------
+  }
+
+  /**
+   * Recursively walk the Kerberos descriptor tree to find all Kerberos identity definitions and
+   * determine which should be filtered out.
+   *
+   * No actual filtering is performed while processing since any referenced Kerberos identities need
+   * to be accessible throughout the process. So a map of container path to a list of identities is
+   * created an returned
+   *
+   * @param currentPath
+   * @param container
+   * @param context
+   * @param identitiesToRemove
+   * @return
+   * @throws AmbariException
+   */
+  private Map<String,Set<String>> processWhenClauses(String currentPath, AbstractKerberosDescriptorContainer container, Map<String, Object> context, Map<String,Set<String>> identitiesToRemove) throws AmbariException {
+
+    // Get the list of this container's identities.
+    // Do not filter these identities using KerberosIdentityDescriptor#shouldInclude since we will do
+    // that later.
+    List<KerberosIdentityDescriptor> identities = container.getIdentities(true, null);
+
+    if((identities != null) && !identities.isEmpty()) {
+      Set<String> set = null;
+
+      for (KerberosIdentityDescriptor identity : identities) {
+        if (!identity.shouldInclude(context)) {
+          if (set == null) {
+            set = new HashSet<String>();
+            identitiesToRemove.put(currentPath, set);
+          }
+
+          set.add(identity.getName());
+        }
+      }
+    }
+
+    Collection<? extends AbstractKerberosDescriptorContainer> children = container.getChildContainers();
+    if(children != null) {
+      for(AbstractKerberosDescriptorContainer child: children) {
+        identitiesToRemove = processWhenClauses(currentPath + "/" + child.getName(), child, context, identitiesToRemove);
+      }
+    }
+
+    return identitiesToRemove;
+  }
+
   /* ********************************************************************************************
    * Helper classes and enums
    * ******************************************************************************************** *\

http://git-wip-us.apache.org/repos/asf/ambari/blob/628f8192/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterKerberosDescriptorResourceProvider.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterKerberosDescriptorResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterKerberosDescriptorResourceProvider.java
index 1f5d1d8..a86e95e 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterKerberosDescriptorResourceProvider.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/ClusterKerberosDescriptorResourceProvider.java
@@ -18,35 +18,28 @@
 
 package org.apache.ambari.server.controller.internal;
 
-import com.google.inject.Inject;
 import org.apache.ambari.server.AmbariException;
-import org.apache.ambari.server.StaticallyInject;
-import org.apache.ambari.server.api.services.AmbariMetaInfo;
 import org.apache.ambari.server.controller.AmbariManagementController;
-import org.apache.ambari.server.controller.spi.ClusterController;
+import org.apache.ambari.server.controller.KerberosHelper;
 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.ResourceProvider;
 import org.apache.ambari.server.controller.spi.SystemException;
 import org.apache.ambari.server.controller.spi.UnsupportedPropertyException;
-import org.apache.ambari.server.controller.utilities.ClusterControllerHelper;
-import org.apache.ambari.server.controller.utilities.PredicateBuilder;
 import org.apache.ambari.server.controller.utilities.PropertyHelper;
-import org.apache.ambari.server.security.authorization.AuthorizationException;
 import org.apache.ambari.server.security.authorization.AuthorizationHelper;
 import org.apache.ambari.server.security.authorization.ResourceType;
 import org.apache.ambari.server.security.authorization.RoleAuthorization;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
-import org.apache.ambari.server.state.StackId;
 import org.apache.ambari.server.state.kerberos.KerberosDescriptor;
-import org.apache.ambari.server.state.kerberos.KerberosDescriptorFactory;
 import org.apache.commons.lang.StringUtils;
 
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.Collections;
 import java.util.EnumSet;
 import java.util.HashMap;
@@ -64,9 +57,22 @@ import java.util.Set;
  * <li>COMPOSITE - the default descriptor for the relevant stack with the the user-supplied updates applied</li>
  * </ul>
  */
-@StaticallyInject
 public class ClusterKerberosDescriptorResourceProvider extends ReadOnlyResourceProvider {
 
+  /**
+   * A directive to indicate whether or not the <code>when</code> clauses for Kerberos Identity
+   * definitions are to be evaluated or not.  By default, they are not evaluated since historically
+   * this provider returned unprocessed Kerberos descriptors.
+   */
+  public static final String DIRECTIVE_EVALUATE_WHEN_CLAUSE = "evaluate_when";
+
+  /**
+   * A directive to indicate additional services to consider when evaluating <code>when</code>
+   * clauses.  This value is expcected to be a comma-delimited string that is only used when
+   * <code>evaluate_when</code> is <code>true</code>.
+   */
+  public static final String DIRECTIVE_ADDITIONAL_SERVICES = "additional_services";
+
   // ----- Property ID constants ---------------------------------------------
 
   public static final String CLUSTER_KERBEROS_DESCRIPTOR_CLUSTER_NAME_PROPERTY_ID = PropertyHelper.getPropertyId("KerberosDescriptor", "cluster_name");
@@ -101,16 +107,6 @@ public class ClusterKerberosDescriptorResourceProvider extends ReadOnlyResourceP
     KEY_PROPERTY_IDS = Collections.unmodifiableMap(map);
   }
 
-  @Inject
-  private static KerberosDescriptorFactory kerberosDescriptorFactory;
-
-  /**
-   * Used to get kerberos descriptors associated with the cluster or stack.
-   * Currently not available via injection.
-   */
-  private static ClusterController clusterController = null;
-
-
   /**
    * Create a new resource provider.
    */
@@ -148,15 +144,21 @@ public class ClusterKerberosDescriptorResourceProvider extends ReadOnlyResourceP
       // Ensure the authenticated use has access to this data for the requested cluster...
       AuthorizationHelper.verifyAuthorization(ResourceType.CLUSTER, cluster.getResourceId(), REQUIRED_GET_AUTHORIZATIONS);
 
-      KerberosDescriptorType kerberosDescriptorType = getKerberosDescriptorType(propertyMap);
+      KerberosHelper.KerberosDescriptorType kerberosDescriptorType = getKerberosDescriptorType(propertyMap);
       if (kerberosDescriptorType == null) {
-        for (KerberosDescriptorType type : KerberosDescriptorType.values()) {
+        for (KerberosHelper.KerberosDescriptorType type : KerberosHelper.KerberosDescriptorType.values()) {
           resources.add(toResource(clusterName, type, null, requestedIds));
         }
       } else {
         KerberosDescriptor kerberosDescriptor;
         try {
-          kerberosDescriptor = getKerberosDescriptor(cluster, kerberosDescriptorType);
+          KerberosHelper kerberosHelper = getManagementController().getKerberosHelper();
+          Map<String, String> requestInfoProperties= request.getRequestInfoProperties();
+
+          kerberosDescriptor = kerberosHelper.getKerberosDescriptor(kerberosDescriptorType,
+              cluster,
+              getEvaluateWhen(requestInfoProperties),
+              getAdditionalServices(requestInfoProperties));
         } catch (AmbariException e) {
           throw new SystemException("An unexpected error occurred building the cluster's composite Kerberos Descriptor", e);
         }
@@ -170,6 +172,11 @@ public class ClusterKerberosDescriptorResourceProvider extends ReadOnlyResourceP
     return resources;
   }
 
+  @Override
+  protected Set<String> getPKPropertyIds() {
+    return PK_PROPERTY_IDS;
+  }
+
   /**
    * Retrieves the cluster name from the request property map.
    *
@@ -190,20 +197,20 @@ public class ClusterKerberosDescriptorResourceProvider extends ReadOnlyResourceP
   /**
    * Retrieves the Kerberos descriptor type from the request property map, if one was specified.
    * <p/>
-   * See {@link org.apache.ambari.server.controller.internal.ClusterKerberosDescriptorResourceProvider.KerberosDescriptorType}
+   * See {@link KerberosHelper.KerberosDescriptorType}
    * for expected values.
    *
    * @param propertyMap the request property map
    * @return a KerberosDescriptorType; or null is not specified in the request propery map
    * @throws IllegalArgumentException if the Kerberos descriptor type value is specified but not an expected value.
    */
-  private KerberosDescriptorType getKerberosDescriptorType(Map<String, Object> propertyMap) {
+  private KerberosHelper.KerberosDescriptorType getKerberosDescriptorType(Map<String, Object> propertyMap) {
     String type = (String) propertyMap.get(CLUSTER_KERBEROS_DESCRIPTOR_TYPE_PROPERTY_ID);
-    KerberosDescriptorType kerberosDescriptorType = null;
+    KerberosHelper.KerberosDescriptorType kerberosDescriptorType = null;
 
     if (!StringUtils.isEmpty(type)) {
       try {
-        kerberosDescriptorType = KerberosDescriptorType.valueOf(type.trim().toUpperCase());
+        kerberosDescriptorType = KerberosHelper.KerberosDescriptorType.valueOf(type.trim().toUpperCase());
       } catch (IllegalArgumentException e) {
         throw new IllegalArgumentException("Invalid argument, kerberos descriptor type of 'STACK', 'USER', or 'COMPOSITE' is required");
       }
@@ -212,107 +219,37 @@ public class ClusterKerberosDescriptorResourceProvider extends ReadOnlyResourceP
     return kerberosDescriptorType;
   }
 
-  @Override
-  protected Set<String> getPKPropertyIds() {
-    return PK_PROPERTY_IDS;
-  }
-
-  protected KerberosDescriptor getKerberosDescriptor(Cluster cluster, KerberosDescriptorType type) throws AmbariException {
-
-    KerberosDescriptor stackDescriptor = (type == KerberosDescriptorType.STACK || type == KerberosDescriptorType.COMPOSITE)
-        ? getKerberosDescriptorFromStack(cluster.getCurrentStackVersion())
-        : null;
-
-    KerberosDescriptor userDescriptor = (type == KerberosDescriptorType.USER || type == KerberosDescriptorType.COMPOSITE)
-        ? getKerberosDescriptorUpdates(cluster.getClusterName())
-        : null;
-
-    if (stackDescriptor == null) {
-      if (userDescriptor == null) {
-        return new KerberosDescriptor();
-      } else {
-        return userDescriptor;
-      }
-    } else {
-      if (userDescriptor != null) {
-        stackDescriptor.update(userDescriptor);
-      }
-      return stackDescriptor;
-    }
+  /**
+   * Determine if <code>when</code> chauses should be evaluated or not.
+   * <p>
+   * This is determined by the existance and value of the <code>evaluate_when</code> directive.
+   * If it exists and is set to "true", then <code>when</code> clauses should be evaluated, else
+   * they should not.
+   *
+   * @param requestInfoProperties a map a request info properties
+   * @return true if <code>when</code> clauses are to be evaluted; false otherwise
+   */
+  private boolean getEvaluateWhen(Map<String, String> requestInfoProperties) {
+    return (requestInfoProperties != null) && "true".equalsIgnoreCase(requestInfoProperties.get(DIRECTIVE_EVALUATE_WHEN_CLAUSE));
   }
 
   /**
-   * Get the user-supplied Kerberos descriptor from <code>cluster/:clusterName/artifacts/kerberos_descriptor</code>
+   * Get the optional list of services indicated as <code>additional_servides</code> which are to be
+   * used in addtion to currently installed services when evaluating <code>when</code> clauses.
    *
-   * @param clusterName the cluster name
-   * @return a Kerberos descriptor
+   * @param requestInfoProperties a map a request info properties
+   * @return a collection of service names, or <code>null</code> if not specified
    */
-  private KerberosDescriptor getKerberosDescriptorUpdates(String clusterName) throws AmbariException {
-    //
-    KerberosDescriptor descriptor = null;
-
-    PredicateBuilder pb = new PredicateBuilder();
-    Predicate predicate = pb.begin().property("Artifacts/cluster_name").equals(clusterName).and().
-        property(ArtifactResourceProvider.ARTIFACT_NAME_PROPERTY).equals("kerberos_descriptor").
-        end().toPredicate();
-
-    synchronized (ClusterKerberosDescriptorResourceProvider.class) {
-      if (clusterController == null) {
-        clusterController = ClusterControllerHelper.getClusterController();
-      }
-    }
-
-    ResourceProvider artifactProvider = clusterController.ensureResourceProvider(Resource.Type.Artifact);
-
-    Request request = new RequestImpl(Collections.<String>emptySet(),
-        Collections.<Map<String, Object>>emptySet(), Collections.<String, String>emptyMap(), null);
-
-    Set<Resource> response = null;
-    try {
-      response = artifactProvider.getResources(request, predicate);
-    } catch (AuthorizationException e) {
-      throw new AmbariException(e.getMessage(), e);
-    } catch (SystemException | UnsupportedPropertyException | NoSuchParentResourceException e) {
-      throw new AmbariException("An unknown error occurred while trying to obtain the cluster's kerberos descriptor artifact", e);
-    } catch (NoSuchResourceException e) {
-      // no descriptor registered, use the default from the stack
-    }
+  private Collection<String> getAdditionalServices(Map<String, String> requestInfoProperties) {
+    if (requestInfoProperties != null) {
+      String value = requestInfoProperties.get(DIRECTIVE_ADDITIONAL_SERVICES);
 
-    if (response != null && !response.isEmpty()) {
-      Resource descriptorResource = response.iterator().next();
-      Map<String, Map<String, Object>> propertyMap = descriptorResource.getPropertiesMap();
-      if (propertyMap != null) {
-        Map<String, Object> artifactData = propertyMap.get(ArtifactResourceProvider.ARTIFACT_DATA_PROPERTY);
-        Map<String, Object> artifactDataProperties = propertyMap.get(ArtifactResourceProvider.ARTIFACT_DATA_PROPERTY + "/properties");
-        HashMap<String, Object> data = new HashMap<String, Object>();
-
-        if (artifactData != null) {
-          data.putAll(artifactData);
-        }
-
-        if (artifactDataProperties != null) {
-          data.put("properties", artifactDataProperties);
-        }
-
-        descriptor = kerberosDescriptorFactory.createInstance(data);
+      if(!StringUtils.isEmpty(value)) {
+        return Arrays.asList(value.split("\\s*,\\s*"));
       }
     }
 
-    return descriptor;
-  }
-
-  /**
-   * Get the default Kerberos descriptor from the stack, which is the same as the value from
-   * <code>stacks/:stackName/versions/:version/artifacts/kerberos_descriptor</code>
-   *
-   * @param stackId the stack id
-   * @return a Kerberos Descriptor
-   * @throws AmbariException if an error occurs while retrieving the Kerberos descriptor
-   */
-  private KerberosDescriptor getKerberosDescriptorFromStack(StackId stackId) throws AmbariException {
-    AmbariManagementController managementController = getManagementController();
-    AmbariMetaInfo metaInfo = managementController.getAmbariMetaInfo();
-    return metaInfo.getKerberosDescriptor(stackId.getStackName(), stackId.getStackVersion());
+    return null;
   }
 
   /**
@@ -324,7 +261,7 @@ public class ClusterKerberosDescriptorResourceProvider extends ReadOnlyResourceP
    * @param requestedIds           the properties to include in the resulting resource instance
    * @return a resource
    */
-  private Resource toResource(String clusterName, KerberosDescriptorType kerberosDescriptorType,
+  private Resource toResource(String clusterName, KerberosHelper.KerberosDescriptorType kerberosDescriptorType,
                               KerberosDescriptor kerberosDescriptor, Set<String> requestedIds) {
     Resource resource = new ResourceImpl(Type.ClusterKerberosDescriptor);
 
@@ -341,9 +278,4 @@ public class ClusterKerberosDescriptorResourceProvider extends ReadOnlyResourceP
     return resource;
   }
 
-  public enum KerberosDescriptorType {
-    STACK,
-    USER,
-    COMPOSITE
-  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/628f8192/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/AbstractKerberosDescriptor.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/AbstractKerberosDescriptor.java b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/AbstractKerberosDescriptor.java
index 79b9a55..84a9111 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/AbstractKerberosDescriptor.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/AbstractKerberosDescriptor.java
@@ -160,7 +160,7 @@ public abstract class AbstractKerberosDescriptor {
    * @param name a String indicating the name of the requested descriptor
    * @return a AbstractKerberosDescriptor representing the requested descriptor or null if not found
    */
-  protected AbstractKerberosDescriptor getDescriptor(KerberosDescriptorType type, String name) {
+  protected AbstractKerberosDescriptor getDescriptor(Type type, String name) {
     return null;
   }
 
@@ -206,4 +206,43 @@ public abstract class AbstractKerberosDescriptor {
       return false;
     }
   }
+
+  /**
+   * An enumeration of the different Kerberos (sub)descriptors for internal use.
+   */
+  public enum Type {
+    SERVICE("service", "services"),
+    COMPONENT("component", "components"),
+    IDENTITY("identity", "identities"),
+    PRINCIPAL("principal", "principals"),
+    KEYTAB("keytab", "keytabs"),
+    CONFIGURATION("configuration", "configurations"),
+    AUTH_TO_LOCAL_PROPERTY("auth_to_local_property", "auth_to_local_properties");
+
+    private final String descriptorName;
+    private final String descriptorPluralName;
+
+    private Type(String descriptorName, String descriptorPluralName) {
+      this.descriptorName = descriptorName;
+      this.descriptorPluralName = descriptorPluralName;
+    }
+
+    /**
+     * Gets the identifying name for this Type
+     *
+     * @return a String declaring the identifying name for this Type
+     */
+    public String getDescriptorName() {
+      return descriptorName;
+    }
+
+    /**
+     * Gets the identifying name for a group of this Type
+     *
+     * @return a String declaring the identifying name for a group of this Type
+     */
+    public String getDescriptorPluralName() {
+      return descriptorPluralName;
+    }
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/628f8192/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/AbstractKerberosDescriptorContainer.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/AbstractKerberosDescriptorContainer.java b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/AbstractKerberosDescriptorContainer.java
index 64d9292..fc4e7ad 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/AbstractKerberosDescriptorContainer.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/AbstractKerberosDescriptorContainer.java
@@ -125,7 +125,7 @@ public abstract class AbstractKerberosDescriptorContainer extends AbstractKerber
       Object list;
 
       // (Safely) Get the set of KerberosIdentityDescriptors
-      list = data.get(KerberosDescriptorType.IDENTITY.getDescriptorPluralName());
+      list = data.get(Type.IDENTITY.getDescriptorPluralName());
       if (list instanceof Collection) {
         for (Object item : (Collection) list) {
           if (item instanceof Map) {
@@ -135,7 +135,7 @@ public abstract class AbstractKerberosDescriptorContainer extends AbstractKerber
       }
 
       // (Safely) Get the set of KerberosConfigurationDescriptors
-      list = data.get(KerberosDescriptorType.CONFIGURATION.getDescriptorPluralName());
+      list = data.get(Type.CONFIGURATION.getDescriptorPluralName());
       if (list instanceof Collection) {
         for (Object item : (Collection) list) {
           if (item instanceof Map) {
@@ -145,7 +145,7 @@ public abstract class AbstractKerberosDescriptorContainer extends AbstractKerber
       }
 
       // (Safely) Get the set of KerberosConfigurationDescriptors
-      list = data.get(KerberosDescriptorType.AUTH_TO_LOCAL_PROPERTY.getDescriptorPluralName());
+      list = data.get(Type.AUTH_TO_LOCAL_PROPERTY.getDescriptorPluralName());
       if (list instanceof Collection) {
         for (Object item : (Collection) list) {
           if (item instanceof String) {
@@ -157,6 +157,21 @@ public abstract class AbstractKerberosDescriptorContainer extends AbstractKerber
   }
 
   /**
+   * Returns the child containers associated with this container.
+   *
+   * @return an immutable collection of {@link AbstractKerberosDescriptorContainer}s
+   */
+  public abstract Collection<? extends AbstractKerberosDescriptorContainer> getChildContainers();
+
+  /**
+   * Returns a specific named child container
+   * @param name the name of the child container to retrieve
+   *
+   * @return an {@link AbstractKerberosDescriptorContainer}
+   */
+  public abstract AbstractKerberosDescriptorContainer getChildContainer(String name);
+
+  /**
    * Returns the raw List of KerberosIdentityDescriptors contained within this
    * AbstractKerberosDescriptorContainer.
    * <p/>
@@ -639,15 +654,15 @@ public abstract class AbstractKerberosDescriptorContainer extends AbstractKerber
 
           if (descriptor != null) {
             if ((serviceName != null) && !serviceName.isEmpty()) {
-              descriptor = descriptor.getDescriptor(KerberosDescriptorType.SERVICE, serviceName);
+              descriptor = descriptor.getDescriptor(Type.SERVICE, serviceName);
 
               if ((descriptor != null) && (componentName != null) && !componentName.isEmpty()) {
-                descriptor = descriptor.getDescriptor(KerberosDescriptorType.COMPONENT, componentName);
+                descriptor = descriptor.getDescriptor(Type.COMPONENT, componentName);
               }
             }
 
             if (descriptor != null) {
-              descriptor = descriptor.getDescriptor(KerberosDescriptorType.IDENTITY, identityName);
+              descriptor = descriptor.getDescriptor(Type.IDENTITY, identityName);
 
               if (descriptor instanceof KerberosIdentityDescriptor) {
                 identityDescriptor = (KerberosIdentityDescriptor) descriptor;
@@ -676,10 +691,10 @@ public abstract class AbstractKerberosDescriptorContainer extends AbstractKerber
    * @return a AbstractKerberosDescriptor representing the requested descriptor or null if not found
    */
   @Override
-  protected AbstractKerberosDescriptor getDescriptor(KerberosDescriptorType type, String name) {
-    if (KerberosDescriptorType.IDENTITY == type) {
+  protected AbstractKerberosDescriptor getDescriptor(Type type, String name) {
+    if (Type.IDENTITY == type) {
       return getIdentity(name);
-    } else if (KerberosDescriptorType.CONFIGURATION == type) {
+    } else if (Type.CONFIGURATION == type) {
       return getConfiguration(name);
     } else {
       return null;
@@ -703,7 +718,7 @@ public abstract class AbstractKerberosDescriptorContainer extends AbstractKerber
       for (KerberosIdentityDescriptor identity : identities) {
         list.add(identity.toMap());
       }
-      map.put(KerberosDescriptorType.IDENTITY.getDescriptorPluralName(), list);
+      map.put(Type.IDENTITY.getDescriptorPluralName(), list);
     }
 
     if (configurations != null) {
@@ -711,12 +726,12 @@ public abstract class AbstractKerberosDescriptorContainer extends AbstractKerber
       for (KerberosConfigurationDescriptor configuration : configurations.values()) {
         list.add(configuration.toMap());
       }
-      map.put(KerberosDescriptorType.CONFIGURATION.getDescriptorPluralName(), list);
+      map.put(Type.CONFIGURATION.getDescriptorPluralName(), list);
     }
 
     if (authToLocalProperties != null) {
       List<String> list = new ArrayList<String>(authToLocalProperties);
-      map.put(KerberosDescriptorType.AUTH_TO_LOCAL_PROPERTY.getDescriptorPluralName(), list);
+      map.put(Type.AUTH_TO_LOCAL_PROPERTY.getDescriptorPluralName(), list);
     }
 
     return map;

http://git-wip-us.apache.org/repos/asf/ambari/blob/628f8192/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosComponentDescriptor.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosComponentDescriptor.java b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosComponentDescriptor.java
index 19d3f5e..ca9f013 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosComponentDescriptor.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosComponentDescriptor.java
@@ -17,6 +17,7 @@
  */
 package org.apache.ambari.server.state.kerberos;
 
+import java.util.Collection;
 import java.util.Map;
 
 /**
@@ -99,6 +100,18 @@ public class KerberosComponentDescriptor extends AbstractKerberosDescriptorConta
   }
 
   @Override
+  public Collection<? extends AbstractKerberosDescriptorContainer> getChildContainers() {
+    // KerberosComponentDescriptors do not have child components
+    return null;
+  }
+
+  @Override
+  public AbstractKerberosDescriptorContainer getChildContainer(String name) {
+    // KerberosComponentDescriptors do not have child components
+    return null;
+  }
+
+  @Override
   public int hashCode() {
     return 35 * super.hashCode();
   }

http://git-wip-us.apache.org/repos/asf/ambari/blob/628f8192/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosDescriptor.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosDescriptor.java b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosDescriptor.java
index 98f8883..484f65c 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosDescriptor.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosDescriptor.java
@@ -19,6 +19,7 @@ package org.apache.ambari.server.state.kerberos;
 
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -116,7 +117,7 @@ public class KerberosDescriptor extends AbstractKerberosDescriptorContainer {
     super(data);
 
     if (data != null) {
-      Object list = data.get(KerberosDescriptorType.SERVICE.getDescriptorPluralName());
+      Object list = data.get(Type.SERVICE.getDescriptorPluralName());
       if (list instanceof Collection) {
         for (Object item : (Collection) list) {
           if (item instanceof Map) {
@@ -135,6 +136,16 @@ public class KerberosDescriptor extends AbstractKerberosDescriptorContainer {
     }
   }
 
+  @Override
+  public Collection<? extends AbstractKerberosDescriptorContainer> getChildContainers() {
+    return (services == null) ? null : Collections.unmodifiableCollection(services.values());
+  }
+
+  @Override
+  public AbstractKerberosDescriptorContainer getChildContainer(String name) {
+    return getService(name);
+  }
+
   /**
    * Returns a Map of the KerberosServiceDescriptors in this KerberosDescriptor
    *
@@ -264,8 +275,8 @@ public class KerberosDescriptor extends AbstractKerberosDescriptorContainer {
    * @return a AbstractKerberosDescriptor representing the requested descriptor or null if not found
    */
   @Override
-  protected AbstractKerberosDescriptor getDescriptor(KerberosDescriptorType type, String name) {
-    if (KerberosDescriptorType.SERVICE == type) {
+  protected AbstractKerberosDescriptor getDescriptor(Type type, String name) {
+    if (Type.SERVICE == type) {
       return getService(name);
     } else {
       return super.getDescriptor(type, name);
@@ -289,7 +300,7 @@ public class KerberosDescriptor extends AbstractKerberosDescriptorContainer {
       for (KerberosServiceDescriptor service : services.values()) {
         list.add(service.toMap());
       }
-      map.put(KerberosDescriptorType.SERVICE.getDescriptorPluralName(), list);
+      map.put(Type.SERVICE.getDescriptorPluralName(), list);
     }
 
     if (properties != null) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/628f8192/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosDescriptorType.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosDescriptorType.java b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosDescriptorType.java
deleted file mode 100644
index 0677de6..0000000
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosDescriptorType.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.kerberos;
-
-public enum KerberosDescriptorType {
-  SERVICE("service", "services"),
-  COMPONENT("component", "components"),
-  IDENTITY("identity", "identities"),
-  PRINCIPAL("principal", "principals"),
-  KEYTAB("keytab", "keytabs"),
-  CONFIGURATION("configuration", "configurations"),
-  AUTH_TO_LOCAL_PROPERTY("auth_to_local_property", "auth_to_local_properties");
-
-  private final String descriptorName;
-  private final String descriptorPluralName;
-
-  private KerberosDescriptorType(String descriptorName, String descriptorPluralName) {
-    this.descriptorName = descriptorName;
-    this.descriptorPluralName = descriptorPluralName;
-  }
-
-  /**
-   * Gets the identifying name for this KerberosDescriptorType
-   *
-   * @return a String declaring the identifying name for this KerberosDescriptorType
-   */
-  public String getDescriptorName() {
-    return descriptorName;
-  }
-
-  /**
-   * Gets the identifying name for a group of this KerberosDescriptorType
-   *
-   * @return a String declaring the identifying name for a group of this KerberosDescriptorType
-   */
-  public String getDescriptorPluralName() {
-    return descriptorPluralName;
-  }
-}

http://git-wip-us.apache.org/repos/asf/ambari/blob/628f8192/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosIdentityDescriptor.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosIdentityDescriptor.java b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosIdentityDescriptor.java
index 2631d35..12ade93 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosIdentityDescriptor.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosIdentityDescriptor.java
@@ -129,12 +129,12 @@ public class KerberosIdentityDescriptor extends AbstractKerberosDescriptor {
 
       setPassword(getStringValue(data, "password"));
 
-      item = data.get(KerberosDescriptorType.PRINCIPAL.getDescriptorName());
+      item = data.get(Type.PRINCIPAL.getDescriptorName());
       if (item instanceof Map) {
         setPrincipalDescriptor(new KerberosPrincipalDescriptor((Map<?, ?>) item));
       }
 
-      item = data.get(KerberosDescriptorType.KEYTAB.getDescriptorName());
+      item = data.get(Type.KEYTAB.getDescriptorName());
       if (item instanceof Map) {
         setKeytabDescriptor(new KerberosKeytabDescriptor((Map<?, ?>) item));
       }
@@ -299,11 +299,11 @@ public class KerberosIdentityDescriptor extends AbstractKerberosDescriptor {
     Map<String, Object> dataMap = super.toMap();
 
     if (principal != null) {
-      dataMap.put(KerberosDescriptorType.PRINCIPAL.getDescriptorName(), principal.toMap());
+      dataMap.put(Type.PRINCIPAL.getDescriptorName(), principal.toMap());
     }
 
     if (keytab != null) {
-      dataMap.put(KerberosDescriptorType.KEYTAB.getDescriptorName(), keytab.toMap());
+      dataMap.put(Type.KEYTAB.getDescriptorName(), keytab.toMap());
     }
 
     if (password != null) {

http://git-wip-us.apache.org/repos/asf/ambari/blob/628f8192/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosServiceDescriptor.java
----------------------------------------------------------------------
diff --git a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosServiceDescriptor.java b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosServiceDescriptor.java
index 9eeb802..72dbcfe 100644
--- a/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosServiceDescriptor.java
+++ b/ambari-server/src/main/java/org/apache/ambari/server/state/kerberos/KerberosServiceDescriptor.java
@@ -17,13 +17,9 @@
  */
 package org.apache.ambari.server.state.kerberos;
 
-import org.apache.ambari.server.AmbariException;
-
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -125,6 +121,16 @@ public class KerberosServiceDescriptor extends AbstractKerberosDescriptorContain
     this(getStringValue(data, "name"), data);
   }
 
+  @Override
+  public Collection<? extends AbstractKerberosDescriptorContainer> getChildContainers() {
+    return (components == null) ? null : Collections.unmodifiableCollection(components.values());
+  }
+
+  @Override
+  public AbstractKerberosDescriptorContainer getChildContainer(String name) {
+    return getComponent(name);
+  }
+
   /**
    * Creates a new KerberosServiceDescriptor
    * <p/>
@@ -142,7 +148,7 @@ public class KerberosServiceDescriptor extends AbstractKerberosDescriptorContain
     setName(name);
 
     if (data != null) {
-      Object list = data.get(KerberosDescriptorType.COMPONENT.getDescriptorPluralName());
+      Object list = data.get(Type.COMPONENT.getDescriptorPluralName());
       if (list instanceof Collection) {
         // Assume list is Collection<Map<String, Object>>
         for (Object item : (Collection) list) {
@@ -235,8 +241,8 @@ public class KerberosServiceDescriptor extends AbstractKerberosDescriptorContain
    * @return a AbstractKerberosDescriptor representing the requested descriptor or null if not found
    */
   @Override
-  protected AbstractKerberosDescriptor getDescriptor(KerberosDescriptorType type, String name) {
-    if (KerberosDescriptorType.COMPONENT == type) {
+  protected AbstractKerberosDescriptor getDescriptor(Type type, String name) {
+    if (Type.COMPONENT == type) {
       return getComponent(name);
     } else {
       return super.getDescriptor(type, name);
@@ -260,7 +266,7 @@ public class KerberosServiceDescriptor extends AbstractKerberosDescriptorContain
       for (KerberosComponentDescriptor component : components.values()) {
         list.add(component.toMap());
       }
-      map.put(KerberosDescriptorType.COMPONENT.getDescriptorPluralName(), list);
+      map.put(Type.COMPONENT.getDescriptorPluralName(), list);
     }
 
     return map;