Repository: ambari
Updated Branches:
  refs/heads/trunk c242beeac -> 5e930e44c


AMBARI-9364. Handle hosts/services/components being added to a kerberized 
cluster.


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

Branch: refs/heads/trunk
Commit: 1dd3ad2178dc1b1a11511ce163a64aa78d3dfdd7
Parents: c242bee
Author: John Speidel <jspei...@hortonworks.com>
Authored: Tue Jan 27 18:44:59 2015 -0500
Committer: John Speidel <jspei...@hortonworks.com>
Committed: Tue Jan 27 19:37:16 2015 -0500

----------------------------------------------------------------------
 .../server/controller/KerberosHelper.java       | 115 ++++++++++++-
 .../internal/HostComponentResourceProvider.java |  47 +++++-
 .../server/controller/KerberosHelperTest.java   | 169 +++++++++++++++++--
 .../HostComponentResourceProviderTest.java      | 129 +++++++++++++-
 4 files changed, 436 insertions(+), 24 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ambari/blob/1dd3ad21/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 c537498..6bb9bf1 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
@@ -29,8 +29,21 @@ import org.apache.ambari.server.actionmanager.Stage;
 import org.apache.ambari.server.actionmanager.StageFactory;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
 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.PredicateBuilder;
 import org.apache.ambari.server.metadata.RoleCommandOrder;
 import org.apache.ambari.server.serveraction.ServerAction;
 import org.apache.ambari.server.serveraction.kerberos.*;
@@ -64,6 +77,7 @@ import java.io.File;
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.List;
@@ -76,6 +90,16 @@ public class KerberosHelper {
 
   private static final Logger LOG = 
LoggerFactory.getLogger(KerberosHelper.class);
 
+  /**
+   * config type which contains the property used to determine if keberos is 
enabled
+   */
+  private static final String SECURITY_ENABLED_CONFIG_TYPE = "cluster-env";
+
+  /**
+   * name of property which states whether kerberos is enabled
+   */
+  private static final String SECURITY_ENABLED_PROPERTY_NAME = 
"security_enabled";
+
   @Inject
   private AmbariCustomCommandExecutionHelper customCommandExecutionHelper;
 
@@ -107,6 +131,12 @@ public class KerberosHelper {
   private KerberosOperationHandlerFactory kerberosOperationHandlerFactory;
 
   /**
+   * Used to get kerberos descriptors associated with the cluster or stack.
+   * Currently not available via injection.
+   */
+  private static ClusterController clusterController = null;
+
+  /**
    * The Handler implementation that provides the logic to enable Kerberos
    */
   private Handler enableKerberosHandler = new EnableKerberosHandler();
@@ -159,6 +189,11 @@ public class KerberosHelper {
     // Update KerberosDetails with the new security type - the current one in 
the cluster is the "old" value
     kerberosDetails.setSecurityType(securityType);
 
+    //todo: modify call from cluster state transition to not include descriptor
+    if (kerberosDescriptor == null) {
+      kerberosDescriptor = getClusterDescriptor(cluster);
+    }
+
     if (securityType == SecurityType.KERBEROS) {
       LOG.info("Configuring Kerberos for realm {} on cluster, {}", 
kerberosDetails.getDefaultRealm(), cluster.getClusterName());
       requestStageContainer = handle(cluster, kerberosDescriptor, 
kerberosDetails, null, null, requestStageContainer, enableKerberosHandler);
@@ -497,12 +532,12 @@ public class KerberosHelper {
         }
 
         // Ensure the cluster-env/security_enabled flag is set properly
-        Map<String, String> clusterEnvProperties = 
kerberosConfigurations.get("cluster-env");
+        Map<String, String> clusterEnvProperties = 
kerberosConfigurations.get(SECURITY_ENABLED_CONFIG_TYPE);
         if (clusterEnvProperties == null) {
           clusterEnvProperties = new HashMap<String, String>();
-          kerberosConfigurations.put("cluster-env", clusterEnvProperties);
+          kerberosConfigurations.put(SECURITY_ENABLED_CONFIG_TYPE, 
clusterEnvProperties);
         }
-        clusterEnvProperties.put("security_enabled",
+        clusterEnvProperties.put(SECURITY_ENABLED_PROPERTY_NAME,
             (kerberosDetails.getSecurityType() == SecurityType.KERBEROS) ? 
"true" : "false");
 
         // Always set up the necessary stages to perform the tasks needed to 
complete the operation.
@@ -655,6 +690,69 @@ public class KerberosHelper {
   }
 
   /**
+   * Get the cluster kerberos descriptor that was registered to the
+   * cluster/:clusterName/artifacts/kerberos_descriptor endpoint if
+   * it exists.  If not, obtain the default cluster descriptor which
+   * is available from the endpoint
+   * stacks/:stackName/versions/:version/artifacts/kerberos_descriptor.
+   *
+   * @param cluster  cluster instance
+   *
+   * @return the kerberos descriptor associated with the specified cluster
+   * @throws AmbariException if unable to obtain the descriptor
+   */
+  private KerberosDescriptor getClusterDescriptor(Cluster cluster) throws 
AmbariException {
+    KerberosDescriptor descriptor;
+    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();
+
+    synchronized (KerberosHelper.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 (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();
+      String descriptor_data = (String) descriptorResource.getPropertyValue(
+          ArtifactResourceProvider.ARTIFACT_DATA_PROPERTY);
+
+      descriptor = KerberosDescriptor.fromJSON(descriptor_data);
+    } else {
+      // get default descriptor from stack
+      StackId stackId = cluster.getCurrentStackVersion();
+      descriptor = 
ambariMetaInfo.getKerberosDescriptor(stackId.getStackName(), 
stackId.getStackVersion());
+    }
+    return descriptor;
+  }
+
+
+  /**
    * Creates a temporary directory within the system temporary directory
    * <p/>
    * The resulting directory is to be removed by the caller when desired.
@@ -1064,6 +1162,15 @@ public class KerberosHelper {
     return new ArrayList<String>(hostNames);
   }
 
+  /**
+   * Determine if a cluster has kerberos enabled.
+   *
+   * @param cluster  cluster to test
+   * @return true if the provided cluster has kerberos enabled; false otherwise
+   */
+  public boolean isClusterKerberosEnabled(Cluster cluster) {
+    return cluster.getSecurityType() == SecurityType.KERBEROS;
+  }
 
   /**
    * Handler is an interface that needs to be implemented by toggle handler 
classes to do the
@@ -1429,7 +1536,7 @@ public class KerberosHelper {
       //  2) remove keytab files
       //  3) update configurations
       //  3) restart services
-      return -1;
+      return requestStageContainer == null ? -1 : 
requestStageContainer.getLastStageId();
     }
   }
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/1dd3ad21/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostComponentResourceProvider.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostComponentResourceProvider.java
 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostComponentResourceProvider.java
index 7c7e280..b1e05cc 100644
--- 
a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostComponentResourceProvider.java
+++ 
b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/HostComponentResourceProvider.java
@@ -34,6 +34,7 @@ import com.google.inject.Injector;
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.configuration.ComponentSSLConfiguration;
 import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.KerberosHelper;
 import org.apache.ambari.server.controller.MaintenanceStateHelper;
 import org.apache.ambari.server.controller.RequestStatusResponse;
 import org.apache.ambari.server.controller.ServiceComponentHostRequest;
@@ -59,6 +60,7 @@ import com.google.inject.assistedinject.AssistedInject;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
 import org.apache.ambari.server.state.MaintenanceState;
+import org.apache.ambari.server.state.SecurityType;
 import org.apache.ambari.server.state.ServiceComponent;
 import org.apache.ambari.server.state.ServiceComponentHost;
 import org.apache.ambari.server.state.ServiceComponentHostEvent;
@@ -122,6 +124,12 @@ public class HostComponentResourceProvider extends 
AbstractControllerResourcePro
   @Inject
   private MaintenanceStateHelper maintenanceStateHelper;
 
+  /**
+   * kerberos helper
+   */
+  @Inject
+  private KerberosHelper kerberosHelper;
+
 
   // ----- Constructors ----------------------------------------------------
 
@@ -406,6 +414,9 @@ public class HostComponentResourceProvider extends 
AbstractControllerResourcePro
     if (clusterName != null && !clusterName.isEmpty()) {
       clusterNames.add(clusterName);
     }
+
+    boolean addKerberosStages = false;
+
     for (ServiceComponentHostRequest request : requests) {
       validateServiceComponentHostRequest(request);
 
@@ -463,6 +474,11 @@ public class HostComponentResourceProvider extends 
AbstractControllerResourcePro
       if (request.getDesiredState() != null) {
         // set desired state on host component
         newState = State.valueOf(request.getDesiredState());
+
+        // determine if this state transition will require that kerberos 
stages are added to request.
+        // once set to true will stay true
+        addKerberosStages = addKerberosStages || 
requiresKerberosStageAddition(oldState, newState, cluster);
+
         // throw exception if desired state isn't a valid desired state 
(static check)
         if (!newState.isValidDesiredState()) {
           throw new IllegalArgumentException("Invalid arguments, invalid"
@@ -547,8 +563,16 @@ public class HostComponentResourceProvider extends 
AbstractControllerResourcePro
     // just getting the first cluster
     Cluster cluster = clusters.getCluster(clusterNames.iterator().next());
 
-    return getManagementController().addStages(stages, cluster, 
requestProperties, null, null, null,
+    RequestStageContainer requestStages = getManagementController().addStages(
+        stages, cluster, requestProperties, null, null, null,
         changedScHosts, ignoredScHosts, runSmokeTest, false);
+
+    if (addKerberosStages) {
+      // adds the necessary kerberos related stages to the request
+      kerberosHelper.toggleKerberos(cluster, SecurityType.KERBEROS, null, 
requestStages);
+    }
+
+    return requestStages;
   }
 
   @Override
@@ -607,6 +631,11 @@ public class HostComponentResourceProvider extends 
AbstractControllerResourcePro
     Set<Resource> matchingResources = getResources(queryRequest, predicate);
 
     for (Resource queryResource : matchingResources) {
+      //todo: this was removed for BUG-28737 and the removal of this breaks
+      //todo: the new "add hosts" api.  BUG-4818 is the root cause and needs
+      //todo: to be addressed and then this predicate evaluation should be
+      //todo: uncommented to fix "add hosts".
+//    if (predicate.evaluate(queryResource)) {
       Map<String, Object> updateRequestProperties = new HashMap<String, 
Object>();
 
       // add props from query resource
@@ -618,6 +647,7 @@ public class HostComponentResourceProvider extends 
AbstractControllerResourcePro
         
updateRequestProperties.putAll(request.getProperties().iterator().next());
       }
       requests.add(getRequest(updateRequestProperties));
+//    }
     }
 
     RequestStageContainer requestStages = modifyResources(new 
Command<RequestStageContainer>() {
@@ -799,6 +829,21 @@ public class HostComponentResourceProvider extends 
AbstractControllerResourcePro
     }
   }
 
+  /**
+   * Determine if kerberos stages need to be added to the request as a result 
of a
+   * host component state change.
+   *
+   * @param current  current host component state
+   * @param target   target host component state
+   * @param cluster  associated cluster
+   * @return whether kerberos stages should be added to the request
+   */
+  public boolean requiresKerberosStageAddition(State current, State target, 
Cluster cluster) {
+    return current == State.INIT &&
+        target  == State.INSTALLED &&
+        kerberosHelper.isClusterKerberosEnabled(cluster);
+  }
+
 
   // ----- inner classes ---------------------------------------------------
 

http://git-wip-us.apache.org/repos/asf/ambari/blob/1dd3ad21/ambari-server/src/test/java/org/apache/ambari/server/controller/KerberosHelperTest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/controller/KerberosHelperTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/controller/KerberosHelperTest.java
index 758e741..e976d81 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/controller/KerberosHelperTest.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/controller/KerberosHelperTest.java
@@ -29,7 +29,13 @@ import org.apache.ambari.server.actionmanager.RequestFactory;
 import org.apache.ambari.server.actionmanager.Stage;
 import org.apache.ambari.server.actionmanager.StageFactory;
 import org.apache.ambari.server.api.services.AmbariMetaInfo;
+import org.apache.ambari.server.controller.internal.ArtifactResourceProvider;
 import org.apache.ambari.server.controller.internal.RequestStageContainer;
+import org.apache.ambari.server.controller.spi.ClusterController;
+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.metadata.RoleCommandOrder;
 import org.apache.ambari.server.orm.DBAccessor;
 import org.apache.ambari.server.security.SecurityHelper;
@@ -62,14 +68,19 @@ import 
org.apache.ambari.server.state.kerberos.KerberosPrincipalDescriptor;
 import org.apache.ambari.server.state.kerberos.KerberosPrincipalType;
 import org.apache.ambari.server.state.kerberos.KerberosServiceDescriptor;
 import org.apache.ambari.server.state.stack.OsFamily;
-import org.easymock.EasyMockSupport;
+import org.easymock.Capture;
 import org.easymock.IAnswer;
 import org.junit.After;
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.powermock.core.classloader.annotations.PowerMockIgnore;
+import org.powermock.core.classloader.annotations.PrepareForTest;
+import org.powermock.modules.junit4.PowerMockRunner;
 
 import javax.persistence.EntityManager;
 
+import java.lang.reflect.Field;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
@@ -77,15 +88,40 @@ import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-
-import static org.easymock.EasyMock.*;
-
-public class KerberosHelperTest extends EasyMockSupport {
+import java.util.Set;
+
+import static org.easymock.EasyMock.anyLong;
+import static org.easymock.EasyMock.anyObject;
+import static org.easymock.EasyMock.capture;
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.powermock.api.easymock.PowerMock.createMock;
+import static org.powermock.api.easymock.PowerMock.createNiceMock;
+import static org.powermock.api.easymock.PowerMock.createStrictMock;
+import static org.powermock.api.easymock.PowerMock.expectLastCall;
+import static org.powermock.api.easymock.PowerMock.mockStatic;
+import static org.powermock.api.easymock.PowerMock.replay;
+import static org.powermock.api.easymock.PowerMock.replayAll;
+import static org.powermock.api.easymock.PowerMock.reset;
+import static org.powermock.api.easymock.PowerMock.verify;
+import static org.powermock.api.easymock.PowerMock.verifyAll;
+
+@RunWith(PowerMockRunner.class)
+@PrepareForTest(KerberosDescriptor.class)
+@PowerMockIgnore({"javax.crypto.*" })
+@SuppressWarnings("unchecked")
+public class KerberosHelperTest {
 
   private static Injector injector;
+  private final ClusterController clusterController = 
createStrictMock(ClusterController.class);
+  private final AmbariMetaInfo metaInfo = createNiceMock(AmbariMetaInfo.class);
 
   @Before
   public void setUp() throws Exception {
+    reset(clusterController);
+    reset(metaInfo);
+
     final KerberosOperationHandlerFactory kerberosOperationHandlerFactory = 
createNiceMock(KerberosOperationHandlerFactory.class);
 
     
expect(kerberosOperationHandlerFactory.getKerberosOperationHandler(KDCType.MIT_KDC))
@@ -137,15 +173,19 @@ public class KerberosHelperTest extends EasyMockSupport {
         
bind(AmbariCustomCommandExecutionHelper.class).toInstance(createNiceMock(AmbariCustomCommandExecutionHelper.class));
         
bind(MaintenanceStateHelper.class).toInstance(createNiceMock(MaintenanceStateHelper.class));
         
bind(AmbariManagementController.class).toInstance(createNiceMock(AmbariManagementController.class));
-        
bind(AmbariMetaInfo.class).toInstance(createNiceMock(AmbariMetaInfo.class));
+        bind(AmbariMetaInfo.class).toInstance(metaInfo);
         
bind(ActionManager.class).toInstance(createNiceMock(ActionManager.class));
         
bind(RequestFactory.class).toInstance(createNiceMock(RequestFactory.class));
         
bind(StageFactory.class).toInstance(createNiceMock(StageFactory.class));
         bind(Clusters.class).toInstance(createNiceMock(ClustersImpl.class));
         
bind(ConfigHelper.class).toInstance(createNiceMock(ConfigHelper.class));
         
bind(KerberosOperationHandlerFactory.class).toInstance(kerberosOperationHandlerFactory);
+        bind(ClusterController.class).toInstance(clusterController);
       }
     });
+
+    //todo: currently don't bind ClusterController due to circular references 
so can't use @Inject
+    setClusterController();
   }
 
   @After
@@ -211,13 +251,13 @@ public class KerberosHelperTest extends EasyMockSupport {
 
   @Test
   public void testEnableKerberos() throws Exception {
-    testEnableKerberos(new KerberosCredential("principal", "password", 
"keytab"));
+    testEnableKerberos(new KerberosCredential("principal", "password", 
"keytab"), false, false);
   }
 
   @Test(expected = IllegalArgumentException.class)
   public void testEnableKerberosMissingCredentials() throws Exception {
     try {
-      testEnableKerberos(null);
+      testEnableKerberos(null, false, false);
     } catch (IllegalArgumentException e) {
       Assert.assertTrue(e.getMessage().startsWith("Missing KDC administrator 
credentials"));
       throw e;
@@ -227,7 +267,7 @@ public class KerberosHelperTest extends EasyMockSupport {
   @Test(expected = IllegalArgumentException.class)
   public void testEnableKerberosInvalidCredentials() throws Exception {
     try {
-      testEnableKerberos(new KerberosCredential("invalid_principal", 
"password", "keytab"));
+      testEnableKerberos(new KerberosCredential("invalid_principal", 
"password", "keytab"), false, false);
     } catch (IllegalArgumentException e) {
       Assert.assertTrue(e.getMessage().startsWith("Invalid KDC administrator 
credentials"));
       throw e;
@@ -235,6 +275,16 @@ public class KerberosHelperTest extends EasyMockSupport {
   }
 
   @Test
+  public void testEnableKerberos_GetKerberosDescriptorFromCluster() throws 
Exception {
+    testEnableKerberos(new KerberosCredential("principal", "password", 
"keytab"), true, false);
+  }
+
+  @Test
+  public void testEnableKerberos_GetKerberosDescriptorFromStack() throws 
Exception {
+    testEnableKerberos(new KerberosCredential("principal", "password", 
"keytab"), false, true);
+  }
+
+  @Test
   public void testEnsureIdentities() throws Exception {
     testEnsureIdentities(new KerberosCredential("principal", "password", 
"keytab"));
   }
@@ -259,7 +309,10 @@ public class KerberosHelperTest extends EasyMockSupport {
     }
   }
 
-  private void testEnableKerberos(final KerberosCredential kerberosCredential) 
throws Exception {
+  private void testEnableKerberos(final KerberosCredential kerberosCredential,
+                                  boolean getClusterDescriptor,
+                                  boolean getStackDescriptor) throws Exception 
{
+
     KerberosHelper kerberosHelper = injector.getInstance(KerberosHelper.class);
 
     final ServiceComponentHost sch1 = 
createNiceMock(ServiceComponentHost.class);
@@ -430,6 +483,13 @@ public class KerberosHelperTest extends EasyMockSupport {
     
expect(kerberosDescriptor.getService("SERVICE1")).andReturn(serviceDescriptor1).once();
     
expect(kerberosDescriptor.getService("SERVICE2")).andReturn(serviceDescriptor2).once();
 
+    //todo: extract method?
+    if (getClusterDescriptor) {
+      // needed to mock the static method fromJson()
+      setupGetDescriptorFromCluster(kerberosDescriptor);
+    } else if (getStackDescriptor) {
+      setupGetDescriptorFromStack(kerberosDescriptor);
+    }
     final StageFactory stageFactory = injector.getInstance(StageFactory.class);
     expect(stageFactory.createNew(anyLong(), anyObject(String.class), 
anyObject(String.class),
         anyLong(), anyObject(String.class), anyObject(String.class), 
anyObject(String.class),
@@ -480,13 +540,64 @@ public class KerberosHelperTest extends EasyMockSupport {
     replayAll();
 
     // Needed by infrastructure
-    injector.getInstance(AmbariMetaInfo.class).init();
+    metaInfo.init();
 
-    kerberosHelper.toggleKerberos(cluster, SecurityType.KERBEROS, 
kerberosDescriptor, requestStageContainer);
+    kerberosHelper.toggleKerberos(cluster, SecurityType.KERBEROS, 
!(getClusterDescriptor || getStackDescriptor) ?
+        kerberosDescriptor : null, requestStageContainer);
 
     verifyAll();
   }
 
+  private void setupGetDescriptorFromCluster(KerberosDescriptor 
kerberosDescriptor) throws Exception {
+    mockStatic(KerberosDescriptor.class);
+    ResourceProvider resourceProvider = 
createStrictMock(ResourceProvider.class);
+    
expect(clusterController.ensureResourceProvider(Resource.Type.Artifact)).andReturn(resourceProvider).once();
+
+    Resource resource = createStrictMock(Resource.class);
+    Set<Resource> result = Collections.singleton(resource);
+
+    Capture<Predicate> predicateCapture = new Capture<Predicate>();
+    Capture<Request> requestCapture = new Capture<Request>();
+
+    //todo: validate captures
+
+//      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();
+
+    expect(resourceProvider.getResources(capture(requestCapture),
+        capture(predicateCapture))).andReturn(result).once();
+
+    String artifactData = "kerberos descriptor json";
+    
expect(resource.getPropertyValue(ArtifactResourceProvider.ARTIFACT_DATA_PROPERTY)).
+        andReturn(artifactData).once();
+
+    
expect(KerberosDescriptor.fromJSON(artifactData)).andReturn(kerberosDescriptor).once();
+  }
+
+  private void setupGetDescriptorFromStack(KerberosDescriptor 
kerberosDescriptor) throws Exception {
+    mockStatic(KerberosDescriptor.class);
+    ResourceProvider resourceProvider = 
createStrictMock(ResourceProvider.class);
+    
expect(clusterController.ensureResourceProvider(Resource.Type.Artifact)).andReturn(resourceProvider).once();
+
+    Capture<Predicate> predicateCapture = new Capture<Predicate>();
+    Capture<Request> requestCapture = new Capture<Request>();
+
+    //todo: validate captures
+
+//      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();
+
+    expect(resourceProvider.getResources(capture(requestCapture),
+        capture(predicateCapture))).andReturn(null).once();
+
+    // cluster.getCurrentStackVersion expectation is already specified in main 
test method
+    expect(metaInfo.getKerberosDescriptor("HDP", 
"2.2")).andReturn(kerberosDescriptor).once();
+  }
+
   private void testEnsureIdentities(final KerberosCredential 
kerberosCredential) throws Exception {
     KerberosHelper kerberosHelper = injector.getInstance(KerberosHelper.class);
 
@@ -726,4 +837,38 @@ public class KerberosHelperTest extends EasyMockSupport {
 
     verifyAll();
   }
+
+  @Test
+  public void testIsClusterKerberosEnabled_false() throws Exception {
+    KerberosHelper kerberosHelper = injector.getInstance(KerberosHelper.class);
+    Cluster cluster = createStrictMock(Cluster.class);
+
+    expect(cluster.getSecurityType()).andReturn(SecurityType.NONE);
+
+    replay(cluster);
+    assertFalse(kerberosHelper.isClusterKerberosEnabled(cluster));
+    verify(cluster);
+  }
+
+  @Test
+  public void testIsClusterKerberosEnabled_true() throws Exception {
+    KerberosHelper kerberosHelper = injector.getInstance(KerberosHelper.class);
+    Cluster cluster = createStrictMock(Cluster.class);
+
+    expect(cluster.getSecurityType()).andReturn(SecurityType.KERBEROS);
+
+    replay(cluster);
+    assertTrue(kerberosHelper.isClusterKerberosEnabled(cluster));
+    verify(cluster);
+  }
+
+  private void setClusterController() throws Exception {
+    KerberosHelper kerberosHelper = injector.getInstance(KerberosHelper.class);
+
+    Class<?> c = kerberosHelper.getClass();
+
+    Field f = c.getDeclaredField("clusterController");
+    f.setAccessible(true);
+    f.set(kerberosHelper, clusterController);
+  }
 }

http://git-wip-us.apache.org/repos/asf/ambari/blob/1dd3ad21/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/HostComponentResourceProviderTest.java
----------------------------------------------------------------------
diff --git 
a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/HostComponentResourceProviderTest.java
 
b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/HostComponentResourceProviderTest.java
index c6a89ed..337cc74 100644
--- 
a/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/HostComponentResourceProviderTest.java
+++ 
b/ambari-server/src/test/java/org/apache/ambari/server/controller/internal/HostComponentResourceProviderTest.java
@@ -21,6 +21,7 @@ package org.apache.ambari.server.controller.internal;
 import com.google.inject.Injector;
 import org.apache.ambari.server.AmbariException;
 import org.apache.ambari.server.controller.AmbariManagementController;
+import org.apache.ambari.server.controller.KerberosHelper;
 import org.apache.ambari.server.controller.MaintenanceStateHelper;
 import org.apache.ambari.server.controller.RequestStatusResponse;
 import org.apache.ambari.server.controller.ResourceProviderFactory;
@@ -35,6 +36,7 @@ import 
org.apache.ambari.server.controller.utilities.PredicateBuilder;
 import org.apache.ambari.server.controller.utilities.PropertyHelper;
 import org.apache.ambari.server.state.Cluster;
 import org.apache.ambari.server.state.Clusters;
+import org.apache.ambari.server.state.SecurityType;
 import org.apache.ambari.server.state.Service;
 import org.apache.ambari.server.state.ServiceComponent;
 import org.apache.ambari.server.state.ServiceComponentHost;
@@ -59,6 +61,7 @@ import java.util.Set;
 import static org.easymock.EasyMock.anyObject;
 import static org.easymock.EasyMock.createMock;
 import static org.easymock.EasyMock.createNiceMock;
+import static org.easymock.EasyMock.createStrictMock;
 import static org.easymock.EasyMock.eq;
 import static org.easymock.EasyMock.expect;
 import static org.easymock.EasyMock.replay;
@@ -302,7 +305,7 @@ public class HostComponentResourceProviderTest {
     HostComponentResourceProvider provider =
         new 
TestHostComponentResourceProvider(PropertyHelper.getPropertyIds(type),
             PropertyHelper.getKeyPropertyIds(type),
-            managementController, injector, maintenanceStateHelper);
+            managementController, injector, maintenanceStateHelper, null);
 
     
expect(resourceProviderFactory.getHostComponentResourceProvider(anyObject(Set.class),
         anyObject(Map.class),
@@ -351,6 +354,8 @@ public class HostComponentResourceProviderTest {
     ServiceComponentHost componentHost = 
createNiceMock(ServiceComponentHost.class);
     RequestStageContainer stageContainer = 
createNiceMock(RequestStageContainer.class);
     MaintenanceStateHelper maintenanceStateHelper = 
createNiceMock(MaintenanceStateHelper.class);
+    // INIT->INSTALLED state transition causes check for kerverized cluster
+    KerberosHelper kerberosHelper = createStrictMock(KerberosHelper.class);
 
     Collection<String> hosts = new HashSet<String>();
     hosts.add("Host100");
@@ -379,7 +384,7 @@ public class HostComponentResourceProviderTest {
     expect(componentHost.getHostName()).andReturn("Host100").anyTimes();
     
expect(componentHost.getServiceComponentName()).andReturn("Component100").anyTimes();
     expect(response.getMessage()).andReturn("response msg").anyTimes();
-    //expect(response.getRequestId()).andReturn(1000L);
+
 
     //Cluster is default type.  Maintenance mode is not being tested here so 
the default is returned.
     expect(maintenanceStateHelper.isOperationAllowed(Resource.Type.Cluster, 
componentHost)).andReturn(true).anyTimes();
@@ -413,16 +418,18 @@ public class HostComponentResourceProviderTest {
     HostComponentResourceProvider provider =
         new 
TestHostComponentResourceProvider(PropertyHelper.getPropertyIds(type),
             PropertyHelper.getKeyPropertyIds(type),
-            managementController, injector, maintenanceStateHelper);
+            managementController, injector, maintenanceStateHelper, 
kerberosHelper);
 
     
expect(resourceProviderFactory.getHostComponentResourceProvider(anyObject(Set.class),
         anyObject(Map.class),
         eq(managementController))).
         andReturn(provider).anyTimes();
 
+    
expect(kerberosHelper.isClusterKerberosEnabled(cluster)).andReturn(false).once();
+
     // replay
     replay(managementController, response, resourceProviderFactory, clusters, 
cluster, service,
-        component, componentHost, stageContainer, maintenanceStateHelper);
+        component, componentHost, stageContainer, maintenanceStateHelper, 
kerberosHelper);
 
     Map<String, Object> properties = new LinkedHashMap<String, Object>();
     
properties.put(HostComponentResourceProvider.HOST_COMPONENT_STATE_PROPERTY_ID, 
"STARTED");
@@ -431,7 +438,108 @@ public class HostComponentResourceProviderTest {
 
     assertSame(response, requestResponse);
     // verify
-    verify(managementController, response, resourceProviderFactory, 
stageContainer);
+    verify(managementController, response, resourceProviderFactory, 
stageContainer, kerberosHelper);
+  }
+
+  @Test
+  public void testInstallAndStart_kerberizedCluster() throws Exception {
+    Resource.Type type = Resource.Type.HostComponent;
+
+    AmbariManagementController managementController = 
createMock(AmbariManagementController.class);
+    RequestStatusResponse response = 
createNiceMock(RequestStatusResponse.class);
+    ResourceProviderFactory resourceProviderFactory = 
createNiceMock(ResourceProviderFactory.class);
+    Injector injector = createNiceMock(Injector.class);
+    Clusters clusters = createNiceMock(Clusters.class);
+    Cluster cluster = createNiceMock(Cluster.class);
+    Service service = createNiceMock(Service.class);
+    ServiceComponent component = createNiceMock(ServiceComponent.class);
+    ServiceComponentHost componentHost = 
createNiceMock(ServiceComponentHost.class);
+    RequestStageContainer stageContainer = 
createNiceMock(RequestStageContainer.class);
+    MaintenanceStateHelper maintenanceStateHelper = 
createNiceMock(MaintenanceStateHelper.class);
+    KerberosHelper kerberosHelper = createStrictMock(KerberosHelper.class);
+
+    Collection<String> hosts = new HashSet<String>();
+    hosts.add("Host100");
+
+    Map<String, String> mapRequestProps = new HashMap<String, String>();
+    mapRequestProps.put("context", "Install and start components on added 
hosts");
+
+    Set<ServiceComponentHostResponse> nameResponse = new 
HashSet<ServiceComponentHostResponse>();
+    nameResponse.add(new ServiceComponentHostResponse(
+        "Cluster102", "Service100", "Component100", "Host100", "INIT", "", 
"INIT", "", null));
+    Set<ServiceComponentHostResponse> nameResponse2 = new 
HashSet<ServiceComponentHostResponse>();
+    nameResponse2.add(new ServiceComponentHostResponse(
+        "Cluster102", "Service100", "Component100", "Host100", "INIT", "", 
"INSTALLED", "", null));
+
+
+    // set expectations
+    expect(managementController.getClusters()).andReturn(clusters).anyTimes();
+    expect(managementController.findServiceName(cluster, 
"Component100")).andReturn("Service100").anyTimes();
+    expect(clusters.getCluster("Cluster102")).andReturn(cluster).anyTimes();
+    expect(cluster.getService("Service100")).andReturn(service).anyTimes();
+    
expect(service.getServiceComponent("Component100")).andReturn(component).anyTimes();
+    
expect(component.getServiceComponentHost("Host100")).andReturn(componentHost).anyTimes();
+    expect(component.getName()).andReturn("Component100").anyTimes();
+    // actual state is always INIT until stages actually execute
+    expect(componentHost.getState()).andReturn(State.INIT).anyTimes();
+    expect(componentHost.getHostName()).andReturn("Host100").anyTimes();
+    
expect(componentHost.getServiceComponentName()).andReturn("Component100").anyTimes();
+    expect(response.getMessage()).andReturn("response msg").anyTimes();
+
+    //Cluster is default type.  Maintenance mode is not being tested here so 
the default is returned.
+    expect(maintenanceStateHelper.isOperationAllowed(Resource.Type.Cluster, 
componentHost)).andReturn(true).anyTimes();
+
+    expect(managementController.getHostComponents(
+        
EasyMock.<Set<ServiceComponentHostRequest>>anyObject())).andReturn(nameResponse);
+    expect(managementController.getHostComponents(
+        
EasyMock.<Set<ServiceComponentHostRequest>>anyObject())).andReturn(nameResponse2);
+
+    Map<String, Map<State, List<ServiceComponentHost>>> changedHosts =
+        new HashMap<String, Map<State, List<ServiceComponentHost>>>();
+    List<ServiceComponentHost> changedComponentHosts = 
Collections.singletonList(componentHost);
+    changedHosts.put("Component100", Collections.singletonMap(State.INSTALLED, 
changedComponentHosts));
+
+    Map<String, Map<State, List<ServiceComponentHost>>> changedHosts2 =
+        new HashMap<String, Map<State, List<ServiceComponentHost>>>();
+    List<ServiceComponentHost> changedComponentHosts2 = 
Collections.singletonList(componentHost);
+    changedHosts2.put("Component100", Collections.singletonMap(State.STARTED, 
changedComponentHosts2));
+
+    expect(managementController.addStages(null, cluster, mapRequestProps, 
null, null, null, changedHosts,
+        Collections.<ServiceComponentHost>emptyList(), false, 
false)).andReturn(stageContainer).once();
+
+    expect(managementController.addStages(stageContainer, cluster, 
mapRequestProps, null, null, null, changedHosts2,
+        Collections.<ServiceComponentHost>emptyList(), false, 
false)).andReturn(stageContainer).once();
+
+    stageContainer.persist();
+    expect(stageContainer.getProjectedState("Host100", 
"Component100")).andReturn(State.INSTALLED).once();
+    
expect(stageContainer.getRequestStatusResponse()).andReturn(response).once();
+
+    HostComponentResourceProvider provider =
+        new 
TestHostComponentResourceProvider(PropertyHelper.getPropertyIds(type),
+            PropertyHelper.getKeyPropertyIds(type),
+            managementController, injector, maintenanceStateHelper, 
kerberosHelper);
+
+    
expect(resourceProviderFactory.getHostComponentResourceProvider(anyObject(Set.class),
+        anyObject(Map.class),
+        eq(managementController))).
+        andReturn(provider).anyTimes();
+
+    
expect(kerberosHelper.isClusterKerberosEnabled(cluster)).andReturn(true).once();
+    expect(kerberosHelper.toggleKerberos(cluster, SecurityType.KERBEROS, null, 
stageContainer)).
+        andReturn(stageContainer).once();
+
+    // replay
+    replay(managementController, response, resourceProviderFactory, clusters, 
cluster, service,
+        component, componentHost, stageContainer, maintenanceStateHelper, 
kerberosHelper);
+
+    Map<String, Object> properties = new LinkedHashMap<String, Object>();
+    
properties.put(HostComponentResourceProvider.HOST_COMPONENT_STATE_PROPERTY_ID, 
"STARTED");
+
+    RequestStatusResponse requestResponse = 
provider.installAndStart("Cluster102", hosts);
+
+    assertSame(response, requestResponse);
+    // verify
+    verify(managementController, response, resourceProviderFactory, 
stageContainer, kerberosHelper);
   }
 
   @Test
@@ -533,7 +641,8 @@ public class HostComponentResourceProviderTest {
     HostComponentResourceProvider provider =
         new 
TestHostComponentResourceProvider(PropertyHelper.getPropertyIds(type),
             PropertyHelper.getKeyPropertyIds(type),
-            controller, injector, 
injector.getInstance(MaintenanceStateHelper.class));
+            controller, injector, 
injector.getInstance(MaintenanceStateHelper.class),
+            injector.getInstance(KerberosHelper.class));
     RequestStageContainer requestStages = provider.updateHostComponents(null, 
requests, requestProperties, runSmokeTest);
     requestStages.persist();
     return requestStages.getRequestStatusResponse();
@@ -550,14 +659,20 @@ public class HostComponentResourceProviderTest {
      */
     public TestHostComponentResourceProvider(Set<String> propertyIds, 
Map<Resource.Type, String> keyPropertyIds,
                                              AmbariManagementController 
managementController, Injector injector,
-                                             MaintenanceStateHelper 
maintenanceStateHelper) throws Exception {
+                                             MaintenanceStateHelper 
maintenanceStateHelper,
+                                             KerberosHelper kerberosHelper) 
throws Exception {
 
       super(propertyIds, keyPropertyIds, managementController, injector);
 
       Class<?> c = getClass().getSuperclass();
+
       Field f = c.getDeclaredField("maintenanceStateHelper");
       f.setAccessible(true);
       f.set(this, maintenanceStateHelper);
+
+      f = c.getDeclaredField("kerberosHelper");
+      f.setAccessible(true);
+      f.set(this, kerberosHelper);
     }
   }
 }

Reply via email to