Repository: ambari Updated Branches: refs/heads/branch-2.2 fc469d3b9 -> 6b9909aef
AMBARI-15961. Kerberos wizard stuck trying to schedule service check operation (rlevas) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/6b9909ae Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/6b9909ae Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/6b9909ae Branch: refs/heads/branch-2.2 Commit: 6b9909aef21cd64033dfa29a94cd351e16b4c0fd Parents: fc469d3 Author: Robert Levas <[email protected]> Authored: Tue Apr 19 14:28:52 2016 -0400 Committer: Robert Levas <[email protected]> Committed: Tue Apr 19 14:28:52 2016 -0400 ---------------------------------------------------------------------- .../server/controller/KerberosHelperImpl.java | 308 ++++++++----------- .../kerberos/ADKerberosOperationHandler.java | 9 +- .../kerberos/CreatePrincipalsServerAction.java | 149 +++++---- .../kerberos/DestroyPrincipalsServerAction.java | 60 ++-- ...erberosMissingAdminCredentialsException.java | 32 +- .../kerberos/KerberosOperationHandler.java | 2 + ...KerberosPrincipalAlreadyExistsException.java | 45 +++ .../KerberosPrincipalDoesNotExistException.java | 45 +++ .../kerberos/MITKerberosOperationHandler.java | 34 +- .../AMBARI_METRICS/0.1.0/kerberos.json | 3 + .../server/controller/KerberosHelperTest.java | 67 +--- 11 files changed, 415 insertions(+), 339 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/6b9909ae/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 737b0aa..dc4829d 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 @@ -1235,6 +1235,7 @@ public class KerberosHelperImpl implements KerberosHelper { false, kerberosEnvProperties, kerberosOperationHandler, + false, null); if (result == null) { @@ -1288,16 +1289,7 @@ public class KerberosHelperImpl implements KerberosHelper { if (kerberosDetails.manageIdentities()) { PrincipalKeyCredential credentials = getKDCAdministratorCredentials(cluster.getClusterName()); if (credentials == null) { - throw new KerberosMissingAdminCredentialsException( - "Missing KDC administrator credentials.\n" + - "The KDC administrator credentials must be set as a persisted or temporary credential resource." + - "This may be done by issuing a POST to the /api/v1/clusters/:clusterName/credentials/kdc.admin.credential API entry point with the following payload:\n" + - "{\n" + - " \"Credential\" : {\n" + - " \"principal\" : \"(PRINCIPAL)\", \"key\" : \"(PASSWORD)\", \"type\" : \"(persisted|temporary)\"}\n" + - " }\n" + - "}" - ); + throw new KerberosMissingAdminCredentialsException(); } else { KerberosOperationHandler operationHandler = kerberosOperationHandlerFactory.getKerberosOperationHandler(kerberosDetails.getKdcType()); @@ -1346,16 +1338,7 @@ public class KerberosHelperImpl implements KerberosHelper { // need to throw this outside of the try/catch so it isn't caught if (missingCredentials) { - throw new KerberosMissingAdminCredentialsException( - "Invalid KDC administrator credentials.\n" + - "The KDC administrator credentials must be set as a persisted or temporary credential resource." + - "This may be done by issuing a POST to the /api/v1/clusters/:clusterName/credentials/kdc.admin.credential API entry point with the following payload:\n" + - "{\n" + - " \"Credential\" : {\n" + - " \"principal\" : \"(PRINCIPAL)\", \"key\" : \"(PASSWORD)\", \"type\" : \"(persisted|temporary)\"}\n" + - " }\n" + - "}" - ); + throw new KerberosMissingAdminCredentialsException(); } } } @@ -1548,188 +1531,138 @@ public class KerberosHelperImpl implements KerberosHelper { throw new AmbariException("The properties map must not be null. It is needed to store data related to the service check identity"); } - Map<String, Service> services = cluster.getServices(); + List<ServiceComponentHost> serviceComponentHostsToProcess = new ArrayList<ServiceComponentHost>(); + KerberosDescriptor kerberosDescriptor = getKerberosDescriptor(cluster); + KerberosIdentityDataFileWriter kerberosIdentityDataFileWriter = null; - if ((services != null) && !services.isEmpty()) { - String clusterName = cluster.getClusterName(); - Map<String, Host> hosts = clusters.getHostsForCluster(clusterName); - - if ((hosts != null) && !hosts.isEmpty()) { - List<ServiceComponentHost> serviceComponentHostsToProcess = new ArrayList<ServiceComponentHost>(); - KerberosDescriptor kerberosDescriptor = getKerberosDescriptor(cluster); - KerberosIdentityDataFileWriter kerberosIdentityDataFileWriter = null; - Map<String, String> kerberosDescriptorProperties = kerberosDescriptor.getProperties(); - - // This is needed to help determine which hosts to perform actions for and create tasks for. - Set<String> hostsWithValidKerberosClient = getHostsWithValidKerberosClient(cluster); - - // Create a temporary directory to store metadata needed to complete this task. Information - // such as which principals and keytabs files to create as well as what configurations need - // to be update are stored in data files in this directory. Any keytab files are stored in - // this directory until they are distributed to their appropriate hosts. - File dataDirectory = createTemporaryDirectory(); - - // Create the file used to store details about principals and keytabs to create - File identityDataFile = new File(dataDirectory, KerberosIdentityDataFileWriter.DATA_FILE_NAME); - - // Create a special identity for the test user - KerberosIdentityDescriptor identity = new KerberosIdentityDescriptor(new HashMap<String, Object>() { - { - put("principal", - new HashMap<String, Object>() { - { - put("value", "${kerberos-env/service_check_principal_name}@${realm}"); - put("type", "user"); - } - }); - put("keytab", - new HashMap<String, Object>() { - { - put("file", "${keytab_dir}/kerberos.service_check.${short_date}.keytab"); - - put("owner", new HashMap<String, Object>() {{ - put("name", "${cluster-env/smokeuser}"); - put("access", "rw"); - }}); - - put("group", new HashMap<String, Object>() {{ - put("name", "${cluster-env/user_group}"); - put("access", "r"); - }}); - - put("cachable", "false"); - } - }); - } - }); + Map<String, String> kerberosDescriptorProperties = kerberosDescriptor.getProperties(); - try { - // Iterate over the hosts in the cluster to find the components installed in each. For each - // component (aka service component host - sch) determine the configuration updates and - // and the principals an keytabs to create. - for (Host host : hosts.values()) { - String hostname = host.getHostName(); - - // Get a list of components on the current host - List<ServiceComponentHost> serviceComponentHosts = cluster.getServiceComponentHosts(hostname); - - if ((serviceComponentHosts != null) && !serviceComponentHosts.isEmpty()) { - // Calculate the current host-specific configurations. These will be used to replace - // variables within the Kerberos descriptor data - Map<String, Map<String, String>> configurations = calculateConfigurations(cluster, hostname, kerberosDescriptorProperties); - - // Add a short date value - configurations.get("").put("short_date", new SimpleDateFormat("MMddyy").format(new Date())); - - // Iterate over the components installed on the current host to get the service and - // component-level Kerberos descriptors in order to determine which principals, - // keytab files, and configurations need to be created or updated. - for (ServiceComponentHost sch : serviceComponentHosts) { - String serviceName = sch.getServiceName(); - String componentName = sch.getServiceComponentName(); - - // If the current ServiceComponentHost represents the KERBEROS/KERBEROS_CLIENT and - // indicates that the KERBEROS_CLIENT component is in the INSTALLED state, add the - // current host to the set of hosts that should be handled... - if (Service.Type.KERBEROS.name().equals(serviceName) && - Role.KERBEROS_CLIENT.name().equals(componentName) && - (sch.getState() == State.INSTALLED)) { - hostsWithValidKerberosClient.add(hostname); - - int identitiesAdded = 0; - - // Lazily create the KerberosIdentityDataFileWriter instance... - if (kerberosIdentityDataFileWriter == null) { - kerberosIdentityDataFileWriter = kerberosIdentityDataFileWriterFactory.createKerberosIdentityDataFileWriter(identityDataFile); - } + // This is needed to help determine which hosts to perform actions for and create tasks for. + Set<String> hostsWithValidKerberosClient = getHostsWithValidKerberosClient(cluster); - // Add service-level principals (and keytabs) - identitiesAdded += addIdentities(kerberosIdentityDataFileWriter, Collections.singleton(identity), - null, hostname, serviceName, componentName, null, configurations); + // Create a temporary directory to store metadata needed to complete this task. Information + // such as which principals and keytabs files to create as well as what configurations need + // to be update are stored in data files in this directory. Any keytab files are stored in + // this directory until they are distributed to their appropriate hosts. + File dataDirectory = createTemporaryDirectory(); - if (identitiesAdded > 0) { - // Add the relevant principal name and keytab file data to the command params state - if (!commandParameters.containsKey("principal_name") || !commandParameters.containsKey("keytab_file")) { - commandParameters.put("principal_name", - variableReplacementHelper.replaceVariables(identity.getPrincipalDescriptor().getValue(), configurations)); - commandParameters.put("keytab_file", - variableReplacementHelper.replaceVariables(identity.getKeytabDescriptor().getFile(), configurations)); - } + // Create the file used to store details about principals and keytabs to create + File identityDataFile = new File(dataDirectory, KerberosIdentityDataFileWriter.DATA_FILE_NAME); - serviceComponentHostsToProcess.add(sch); - } - } - } - } - } - } catch (IOException e) { - String message = String.format("Failed to write index file - %s", identityDataFile.getAbsolutePath()); - LOG.error(message); - throw new AmbariException(message, e); - } finally { - if (kerberosIdentityDataFileWriter != null) { - // Make sure the data file is closed - try { - kerberosIdentityDataFileWriter.close(); - } catch (IOException e) { - LOG.warn("Failed to close the index file writer", e); - } - } - } + // Calculate the current non-host-specific configurations. These will be used to replace + // variables within the Kerberos descriptor data + Map<String, Map<String, String>> configurations = calculateConfigurations(cluster, null, kerberosDescriptorProperties); - // If there are ServiceComponentHosts to process, make sure the administrator credential - // are available - if (!serviceComponentHostsToProcess.isEmpty()) { - try { - validateKDCCredentials(kerberosDetails, cluster); - } catch (KerberosOperationException e) { - try { - FileUtils.deleteDirectory(dataDirectory); - } catch (Throwable t) { - LOG.warn(String.format("The data directory (%s) was not deleted due to an error condition - {%s}", - dataDirectory.getAbsolutePath(), t.getMessage()), t); - } + String principal = variableReplacementHelper.replaceVariables("${kerberos-env/service_check_principal_name}@${realm}", configurations); + String principalType = "user"; - throw e; + String keytabFilePath = variableReplacementHelper.replaceVariables("${keytab_dir}/kerberos.service_check.${short_date}.keytab", configurations); + String keytabFileOwnerName = variableReplacementHelper.replaceVariables("${cluster-env/smokeuser}", configurations); + String keytabFileOwnerAccess = "rw"; + String keytabFileGroupName = variableReplacementHelper.replaceVariables("${cluster-env/user_group}", configurations); + String keytabFileGroupAccess = "r"; + + // Add the relevant principal name and keytab file data to the command params state + commandParameters.put("principal_name", principal); + commandParameters.put("keytab_file", keytabFilePath); + + try { + List<ServiceComponentHost> serviceComponentHosts = cluster.getServiceComponentHosts(Service.Type.KERBEROS.name(), Role.KERBEROS_CLIENT.name()); + + if ((serviceComponentHosts != null) && !serviceComponentHosts.isEmpty()) { + kerberosIdentityDataFileWriter = kerberosIdentityDataFileWriterFactory.createKerberosIdentityDataFileWriter(identityDataFile); + + // Iterate over the KERBEROS_CLIENT service component hosts to get the service and + // component-level Kerberos descriptors in order to determine which principals, + // keytab files needed to be created or updated. + for (ServiceComponentHost sch : serviceComponentHosts) { + if (sch.getState() == State.INSTALLED) { + String hostname = sch.getHostName(); + + kerberosIdentityDataFileWriter.writeRecord( + hostname, + Service.Type.KERBEROS.name(), + Role.KERBEROS_CLIENT.name(), + principal, + principalType, + keytabFilePath, + keytabFileOwnerName, + keytabFileOwnerAccess, + keytabFileGroupName, + keytabFileGroupAccess, + "false"); + + hostsWithValidKerberosClient.add(hostname); + serviceComponentHostsToProcess.add(sch); } } + } + } catch (IOException e) { + String message = String.format("Failed to write index file - %s", identityDataFile.getAbsolutePath()); + LOG.error(message); + throw new AmbariException(message, e); + } finally { + if (kerberosIdentityDataFileWriter != null) { + // Make sure the data file is closed + try { + kerberosIdentityDataFileWriter.close(); + } catch (IOException e) { + LOG.warn("Failed to close the index file writer", e); + } + } + } - // Always set up the necessary stages to perform the tasks needed to complete the operation. - // Some stages may be no-ops, this is expected. - // Gather data needed to create stages and tasks... - Map<String, Set<String>> clusterHostInfo = StageUtils.getClusterHostInfo(cluster); - String clusterHostInfoJson = StageUtils.getGson().toJson(clusterHostInfo); - Map<String, String> hostParams = customCommandExecutionHelper.createDefaultHostParams(cluster); - String hostParamsJson = StageUtils.getGson().toJson(hostParams); - String ambariServerHostname = StageUtils.getHostName(); - ServiceComponentHostServerActionEvent event = new ServiceComponentHostServerActionEvent( - "AMBARI_SERVER", - ambariServerHostname, // TODO: Choose a random hostname from the cluster. All tasks for the AMBARI_SERVER service will be executed on this Ambari server - System.currentTimeMillis()); - RoleCommandOrder roleCommandOrder = ambariManagementController.getRoleCommandOrder(cluster); - - // If a RequestStageContainer does not already exist, create a new one... - if (requestStageContainer == null) { - requestStageContainer = new RequestStageContainer( - actionManager.getNextRequestId(), - null, - requestFactory, - actionManager); + // If there are ServiceComponentHosts to process, make sure the administrator credential + // are available + if (!serviceComponentHostsToProcess.isEmpty()) { + try { + validateKDCCredentials(kerberosDetails, cluster); + } catch (KerberosOperationException e) { + try { + FileUtils.deleteDirectory(dataDirectory); + } catch (Throwable t) { + LOG.warn(String.format("The data directory (%s) was not deleted due to an error condition - {%s}", + dataDirectory.getAbsolutePath(), t.getMessage()), t); } - // Use the handler implementation to setup the relevant stages. - // Set the service/component filter to an empty map since the service/component processing - // was done above. - handler.createStages(cluster, - clusterHostInfoJson, hostParamsJson, event, roleCommandOrder, kerberosDetails, - dataDirectory, requestStageContainer, serviceComponentHostsToProcess, - Collections.<String, Collection<String>>emptyMap(), null, null, hostsWithValidKerberosClient); + throw e; + } + } + // Always set up the necessary stages to perform the tasks needed to complete the operation. + // Some stages may be no-ops, this is expected. + // Gather data needed to create stages and tasks... + Map<String, Set<String>> clusterHostInfo = StageUtils.getClusterHostInfo(cluster); + String clusterHostInfoJson = StageUtils.getGson().toJson(clusterHostInfo); + Map<String, String> hostParams = customCommandExecutionHelper.createDefaultHostParams(cluster); + String hostParamsJson = StageUtils.getGson().toJson(hostParams); + String ambariServerHostname = StageUtils.getHostName(); + ServiceComponentHostServerActionEvent event = new ServiceComponentHostServerActionEvent( + "AMBARI_SERVER", + ambariServerHostname, // TODO: Choose a random hostname from the cluster. All tasks for the AMBARI_SERVER service will be executed on this Ambari server + System.currentTimeMillis()); + RoleCommandOrder roleCommandOrder = ambariManagementController.getRoleCommandOrder(cluster); - handler.addFinalizeOperationStage(cluster, clusterHostInfoJson, hostParamsJson, event, - dataDirectory, roleCommandOrder, requestStageContainer); - } + // If a RequestStageContainer does not already exist, create a new one... + if (requestStageContainer == null) { + requestStageContainer = new RequestStageContainer( + actionManager.getNextRequestId(), + null, + requestFactory, + actionManager); } + + // Use the handler implementation to setup the relevant stages. + // Set the service/component filter to an empty map since the service/component processing + // was done above. + handler.createStages(cluster, + clusterHostInfoJson, hostParamsJson, event, roleCommandOrder, kerberosDetails, + dataDirectory, requestStageContainer, serviceComponentHostsToProcess, + Collections.<String, Collection<String>>emptyMap(), null, null, hostsWithValidKerberosClient); + + + handler.addFinalizeOperationStage(cluster, clusterHostInfoJson, hostParamsJson, event, + dataDirectory, roleCommandOrder, requestStageContainer); } return requestStageContainer; @@ -2277,6 +2210,7 @@ public class KerberosHelperImpl implements KerberosHelper { // Add the current cluster's name generalProperties.put("cluster_name", cluster.getClusterName()); + generalProperties.put("short_date", new SimpleDateFormat("MMddyy").format(new Date())); // add clusterHostInfo config if (configurations.get("clusterHostInfo") == null) { http://git-wip-us.apache.org/repos/asf/ambari/blob/6b9909ae/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/ADKerberosOperationHandler.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/ADKerberosOperationHandler.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/ADKerberosOperationHandler.java index a1e1544..c236a27 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/ADKerberosOperationHandler.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/ADKerberosOperationHandler.java @@ -235,6 +235,7 @@ public class ADKerberosOperationHandler extends KerberosOperationHandler { * @param password a String containing the password to use when creating the principal * @param service a boolean value indicating whether the principal is to be created as a service principal or not * @return an Integer declaring the generated key number + * @throws KerberosPrincipalAlreadyExistsException if the principal already exists * @throws KerberosOperationException */ @Override @@ -243,13 +244,15 @@ public class ADKerberosOperationHandler extends KerberosOperationHandler { if (!isOpen()) { throw new KerberosOperationException("This operation handler has not been opened"); } - if (principal == null) { throw new KerberosOperationException("principal is null"); } if (password == null) { throw new KerberosOperationException("principal password is null"); } + if (principalExists(principal)) { + throw new KerberosPrincipalAlreadyExistsException(principal); + } DeconstructedPrincipal deconstructedPrincipal = createDeconstructPrincipal(principal); @@ -333,6 +336,7 @@ public class ADKerberosOperationHandler extends KerberosOperationHandler { * @param principal a String containing the principal to update * @param password a String containing the password to set * @return an Integer declaring the new key number + * @throws KerberosPrincipalDoesNotExistException if the principal does not exist * @throws KerberosOperationException */ @Override @@ -346,6 +350,9 @@ public class ADKerberosOperationHandler extends KerberosOperationHandler { if (password == null) { throw new KerberosOperationException("principal password is null"); } + if(!principalExists(principal)) { + throw new KerberosPrincipalDoesNotExistException(principal); + } DeconstructedPrincipal deconstructPrincipal = createDeconstructPrincipal(principal); http://git-wip-us.apache.org/repos/asf/ambari/blob/6b9909ae/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CreatePrincipalsServerAction.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CreatePrincipalsServerAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CreatePrincipalsServerAction.java index 55e046e..99487c9 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CreatePrincipalsServerAction.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/CreatePrincipalsServerAction.java @@ -31,7 +31,9 @@ import org.apache.commons.lang.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentMap; /** @@ -64,6 +66,12 @@ public class CreatePrincipalsServerAction extends KerberosServerAction { private SecurePasswordHelper securePasswordHelper; /** + * A set of visited principal names used to prevent unnecessary processing on already processed + * principal names + */ + private Set<String> seenPrincipals = new HashSet<String>(); + + /** * Called to execute this action. Upon invocation, calls * {@link org.apache.ambari.server.serveraction.kerberos.KerberosServerAction#processIdentities(java.util.Map)} * to iterate through the Kerberos identity metadata and call @@ -113,43 +121,49 @@ public class CreatePrincipalsServerAction extends KerberosServerAction { throws AmbariException { CommandReport commandReport = null; - boolean processPrincipal; - boolean regenerateKeytabs = "true".equalsIgnoreCase(getCommandParameterValue(getCommandParameters(), REGENERATE_ALL)); + // Only process this principal name if we haven't already processed it + if (!seenPrincipals.contains(evaluatedPrincipal)) { + seenPrincipals.add(evaluatedPrincipal); - if (regenerateKeytabs) { - processPrincipal = true; - } else { - KerberosPrincipalEntity kerberosPrincipalEntity = kerberosPrincipalDAO.find(evaluatedPrincipal); + boolean processPrincipal; + boolean regenerateKeytabs = "true".equalsIgnoreCase(getCommandParameterValue(getCommandParameters(), REGENERATE_ALL)); - if (kerberosPrincipalEntity == null) { - // This principal has not been processed before, process it. + if (regenerateKeytabs) { processPrincipal = true; - } else if (!StringUtils.isEmpty(kerberosPrincipalEntity.getCachedKeytabPath())) { - // This principal has been processed and a keytab file has been cached for it... do not process it. - processPrincipal = false; - } else if (kerberosPrincipalHostDAO.exists(evaluatedPrincipal)) { - // This principal has been processed and a keytab file has been distributed... do not process it. - processPrincipal = false; } else { - // This principal has been processed but a keytab file for it has been distributed... process it. - processPrincipal = true; + KerberosPrincipalEntity kerberosPrincipalEntity = kerberosPrincipalDAO.find(evaluatedPrincipal); + + if (kerberosPrincipalEntity == null) { + // This principal has not been processed before, process it. + processPrincipal = true; + } else if (!StringUtils.isEmpty(kerberosPrincipalEntity.getCachedKeytabPath())) { + // This principal has been processed and a keytab file has been cached for it... do not process it. + processPrincipal = false; + } else if (kerberosPrincipalHostDAO.exists(evaluatedPrincipal)) { + // This principal has been processed and a keytab file has been distributed... do not process it. + processPrincipal = false; + } else { + // This principal has been processed but a keytab file for it has been distributed... process it. + processPrincipal = true; + } } - } Map<String, String> principalPasswordMap = getPrincipalPasswordMap(requestSharedDataContext); Map<String, Integer> principalKeyNumberMap = getPrincipalKeyNumberMap(requestSharedDataContext); - if (processPrincipal) { - String password = principalPasswordMap.get(evaluatedPrincipal); + if (processPrincipal) { + String password = principalPasswordMap.get(evaluatedPrincipal); - if (password == null) { - boolean servicePrincipal = "service".equalsIgnoreCase(identityRecord.get(KerberosIdentityDataFileReader.PRINCIPAL_TYPE)); - CreatePrincipalResult result = createPrincipal(evaluatedPrincipal, servicePrincipal, kerberosConfiguration, operationHandler, actionLog); + if (password == null) { + boolean servicePrincipal = "service".equalsIgnoreCase(identityRecord.get(KerberosIdentityDataFileReader.PRINCIPAL_TYPE)); - if (result == null) { - commandReport = createCommandReport(1, HostRoleStatus.FAILED, "{}", actionLog.getStdOut(), actionLog.getStdErr()); - } else { - principalPasswordMap.put(evaluatedPrincipal, result.getPassword()); - principalKeyNumberMap.put(evaluatedPrincipal, result.getKeyNumber()); + CreatePrincipalResult result = createPrincipal(evaluatedPrincipal, servicePrincipal, kerberosConfiguration, operationHandler, regenerateKeytabs, actionLog); + + if (result == null) { + commandReport = createCommandReport(1, HostRoleStatus.FAILED, "{}", actionLog.getStdOut(), actionLog.getStdErr()); + } else { + principalPasswordMap.put(evaluatedPrincipal, result.getPassword()); + principalKeyNumberMap.put(evaluatedPrincipal, result.getKeyNumber()); + } } } } @@ -165,16 +179,16 @@ public class CreatePrincipalsServerAction extends KerberosServerAction { * principal is a user principal * @param kerberosConfiguration the kerberos-env configuration properties * @param kerberosOperationHandler the KerberosOperationHandler for the relevant KDC - * @param actionLog the logger (may be null if no logging is desired) - * @return a CreatePrincipalResult containing the generated password and key number value + * @param regenerateKeytabs true if this was triggered in response to regenerating keytab files; false otherwize + * @param actionLog the logger (may be null if no logging is desired) @return a CreatePrincipalResult containing the generated password and key number value */ public CreatePrincipalResult createPrincipal(String principal, boolean isServicePrincipal, Map<String, String> kerberosConfiguration, KerberosOperationHandler kerberosOperationHandler, - ActionLog actionLog) { + boolean regenerateKeytabs, ActionLog actionLog) { CreatePrincipalResult result = null; - String message = String.format("Creating principal, %s", principal); + String message = String.format("Processing principal, %s", principal); LOG.info(message); if (actionLog != null) { actionLog.writeStdOut(message); @@ -203,48 +217,61 @@ public class CreatePrincipalsServerAction extends KerberosServerAction { minWhitespace = toInt(kerberosConfiguration.get("password_min_whitespace")); } + // Create a new password since we need to know what it is. String password = securePasswordHelper.createSecurePassword(length, minLowercaseLetters, minUppercaseLetters, minDigits, minPunctuation, minWhitespace); try { + boolean created; + Integer keyNumber; + + if (regenerateKeytabs) { + try { + keyNumber = kerberosOperationHandler.setPrincipalPassword(principal, password); + created = false; + } catch (KerberosPrincipalDoesNotExistException e) { + message = String.format("Principal, %s, does not exist, creating new principal", principal); + LOG.warn(message); + if (actionLog != null) { + actionLog.writeStdOut(message); + } - if (kerberosOperationHandler.principalExists(principal)) { - // Create a new password since we need to know what it is. - // A new password/key would have been generated after exporting the keytab anyways. - message = String.format("Principal, %s, already exists, setting new password", principal); - LOG.warn(message); - if (actionLog != null) { - actionLog.writeStdOut(message); + keyNumber = kerberosOperationHandler.createPrincipal(principal, password, isServicePrincipal); + created = true; } - - Integer keyNumber = kerberosOperationHandler.setPrincipalPassword(principal, password); - - if (keyNumber != null) { - result = new CreatePrincipalResult(principal, password, keyNumber); - message = String.format("Successfully set password for %s", principal); - LOG.debug(message); - } else { - message = String.format("Failed to set password for %s - unknown reason", principal); - LOG.error(message); + } else { + try { + keyNumber = kerberosOperationHandler.createPrincipal(principal, password, isServicePrincipal); + created = true; + } catch (KerberosPrincipalAlreadyExistsException e) { + message = String.format("Principal, %s, already exists, setting new password", principal); + LOG.warn(message); if (actionLog != null) { - actionLog.writeStdErr(message); + actionLog.writeStdOut(message); } + + keyNumber = kerberosOperationHandler.setPrincipalPassword(principal, password); + created = false; } - } else { - message = String.format("Creating new principal, %s", principal); - LOG.debug(message); + } - Integer keyNumber = kerberosOperationHandler.createPrincipal(principal, password, isServicePrincipal); + if (keyNumber != null) { + result = new CreatePrincipalResult(principal, password, keyNumber); - if (keyNumber != null) { - result = new CreatePrincipalResult(principal, password, keyNumber); + if (created) { message = String.format("Successfully created new principal, %s", principal); - LOG.debug(message); } else { + message = String.format("Successfully set password for %s", principal); + } + LOG.debug(message); + } else { + if (created) { message = String.format("Failed to create principal, %s - unknown reason", principal); - LOG.error(message); - if (actionLog != null) { - actionLog.writeStdErr(message); - } + } else { + message = String.format("Failed to set password for %s - unknown reason", principal); + } + LOG.error(message); + if (actionLog != null) { + actionLog.writeStdErr(message); } } @@ -253,7 +280,7 @@ public class CreatePrincipalsServerAction extends KerberosServerAction { } } catch (KerberosOperationException e) { - message = String.format("Failed to create principal, %s - %s", principal, e.getMessage()); + message = String.format("Failed to create or update principal, %s - %s", principal, e.getMessage()); LOG.error(message, e); if (actionLog != null) { actionLog.writeStdErr(message); http://git-wip-us.apache.org/repos/asf/ambari/blob/6b9909ae/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/DestroyPrincipalsServerAction.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/DestroyPrincipalsServerAction.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/DestroyPrincipalsServerAction.java index 93daae8..cc635c4 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/DestroyPrincipalsServerAction.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/DestroyPrincipalsServerAction.java @@ -27,7 +27,9 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import java.util.concurrent.ConcurrentMap; /** @@ -46,6 +48,12 @@ public class DestroyPrincipalsServerAction extends KerberosServerAction { private KerberosPrincipalDAO kerberosPrincipalDAO; /** + * A set of visited principal names used to prevent unnecessary processing on already processed + * principal names + */ + private Set<String> seenPrincipals = new HashSet<String>(); + + /** * Called to execute this action. Upon invocation, calls * {@link KerberosServerAction#processIdentities(java.util.Map)} * to iterate through the Kerberos identity metadata and call @@ -86,39 +94,43 @@ public class DestroyPrincipalsServerAction extends KerberosServerAction { Map<String, Object> requestSharedDataContext) throws AmbariException { - String message = String.format("Destroying identity, %s", evaluatedPrincipal); - LOG.info(message); - actionLog.writeStdOut(message); + // Only process this principal if we haven't already processed it + if(!seenPrincipals.contains(evaluatedPrincipal)) { + seenPrincipals.add(evaluatedPrincipal); - try { - operationHandler.removePrincipal(evaluatedPrincipal); - } catch (KerberosOperationException e) { - message = String.format("Failed to remove identity for %s from the KDC - %s", evaluatedPrincipal, e.getMessage()); - LOG.warn(message); - actionLog.writeStdErr(message); - } + String message = String.format("Destroying identity, %s", evaluatedPrincipal); + LOG.info(message); + actionLog.writeStdOut(message); - try { - KerberosPrincipalEntity principalEntity = kerberosPrincipalDAO.find(evaluatedPrincipal); + try { + operationHandler.removePrincipal(evaluatedPrincipal); + } catch (KerberosOperationException e) { + message = String.format("Failed to remove identity for %s from the KDC - %s", evaluatedPrincipal, e.getMessage()); + LOG.warn(message); + actionLog.writeStdErr(message); + } + + try { + KerberosPrincipalEntity principalEntity = kerberosPrincipalDAO.find(evaluatedPrincipal); - if(principalEntity != null) { - String cachedKeytabPath = principalEntity.getCachedKeytabPath(); + if (principalEntity != null) { + String cachedKeytabPath = principalEntity.getCachedKeytabPath(); - kerberosPrincipalDAO.remove(principalEntity); + kerberosPrincipalDAO.remove(principalEntity); - // If a cached keytabs file exists for this principal, delete it. - if (cachedKeytabPath != null) { - if (!new File(cachedKeytabPath).delete()) { - LOG.debug(String.format("Failed to remove cached keytab for %s", evaluatedPrincipal)); + // If a cached keytabs file exists for this principal, delete it. + if (cachedKeytabPath != null) { + if (!new File(cachedKeytabPath).delete()) { + LOG.debug(String.format("Failed to remove cached keytab for %s", evaluatedPrincipal)); + } } } + } catch (Throwable t) { + message = String.format("Failed to remove identity for %s from the Ambari database - %s", evaluatedPrincipal, t.getMessage()); + LOG.warn(message); + actionLog.writeStdErr(message); } } - catch (Throwable t) { - message = String.format("Failed to remove identity for %s from the Ambari database - %s", evaluatedPrincipal, t.getMessage()); - LOG.warn(message); - actionLog.writeStdErr(message); - } // There is no reason to fail this task if an identity was not removed. The cluster will work // just fine if this cleanup process fails. http://git-wip-us.apache.org/repos/asf/ambari/blob/6b9909ae/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosMissingAdminCredentialsException.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosMissingAdminCredentialsException.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosMissingAdminCredentialsException.java index ddb2769..323af59 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosMissingAdminCredentialsException.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosMissingAdminCredentialsException.java @@ -23,6 +23,25 @@ package org.apache.ambari.server.serveraction.kerberos; */ public class KerberosMissingAdminCredentialsException extends KerberosOperationException { /** + * The default error message to use when handling this exception + */ + private static final String DEFAULT_MESSAGE = "Missing KDC administrator credentials.\n" + + "The KDC administrator credentials must be set as a persisted or temporary credential resource." + + "This may be done by issuing a POST to the /api/v1/clusters/:clusterName/credentials/kdc.admin.credential API entry point with the following payload:\n" + + "{\n" + + " \"Credential\" : {\n" + + " \"principal\" : \"(PRINCIPAL)\", \"key\" : \"(PASSWORD)\", \"type\" : \"(persisted|temporary)\"}\n" + + " }\n" + + "}"; + + /** + * Constructor using the default missing credentials message. + */ + public KerberosMissingAdminCredentialsException() { + this(DEFAULT_MESSAGE); + } + + /** * Constructor. * * @param message error message @@ -32,10 +51,19 @@ public class KerberosMissingAdminCredentialsException extends KerberosOperationE } /** + * Constructor using the default message. + * + * @param cause root cause + */ + public KerberosMissingAdminCredentialsException(Throwable cause) { + this(DEFAULT_MESSAGE, cause); + } + + /** * Constructor. * - * @param message error message - * @param cause root cause + * @param message error message + * @param cause root cause */ public KerberosMissingAdminCredentialsException(String message, Throwable cause) { super(message, cause); http://git-wip-us.apache.org/repos/asf/ambari/blob/6b9909ae/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandler.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandler.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandler.java index e3d31de..1a50ce5 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandler.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosOperationHandler.java @@ -246,6 +246,7 @@ public abstract class KerberosOperationHandler { * @param service a boolean value indicating whether the principal is to be created as a service principal or not * @return an Integer declaring the generated key number * @throws KerberosOperationException + * @throws KerberosPrincipalAlreadyExistsException if the principal already exists */ public abstract Integer createPrincipal(String principal, String password, boolean service) throws KerberosOperationException; @@ -259,6 +260,7 @@ public abstract class KerberosOperationHandler { * @param password a String containing the password to set * @return an Integer declaring the new key number * @throws KerberosOperationException + * @throws KerberosPrincipalDoesNotExistException if the principal does not exist */ public abstract Integer setPrincipalPassword(String principal, String password) throws KerberosOperationException; http://git-wip-us.apache.org/repos/asf/ambari/blob/6b9909ae/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosPrincipalAlreadyExistsException.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosPrincipalAlreadyExistsException.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosPrincipalAlreadyExistsException.java new file mode 100644 index 0000000..3419c0b --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosPrincipalAlreadyExistsException.java @@ -0,0 +1,45 @@ +/* + * 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.serveraction.kerberos; + +/** + * KerberosPrincipalAlreadyExistsException is a KerberosOperationException thrown in the event a + * request to create a new princials was made but the princial already exists in the KDC. + */ +public class KerberosPrincipalAlreadyExistsException extends KerberosOperationException { + + /** + * Creates a new KerberosPrincipalAlreadyExistsException with a message + * + * @param message a String containing the message indicating the reason for this exception + */ + public KerberosPrincipalAlreadyExistsException(String message) { + super(message); + } + + /** + * Creates a new KerberosPrincipalAlreadyExistsException with a message and a cause + * + * @param message a String containing the message indicating the reason for this exception + * @param cause a Throwable declaring the previously thrown Throwable that led to this exception + */ + public KerberosPrincipalAlreadyExistsException(String message, Throwable cause) { + super(message, cause); + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/6b9909ae/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosPrincipalDoesNotExistException.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosPrincipalDoesNotExistException.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosPrincipalDoesNotExistException.java new file mode 100644 index 0000000..5618547 --- /dev/null +++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/KerberosPrincipalDoesNotExistException.java @@ -0,0 +1,45 @@ +/* + * 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.serveraction.kerberos; + +/** + * KerberosPrincipalDoesNotExistException is a KerberosOperationException thrown in the event a + * request to modify an existing princial was made but the princial does not exist in the KDC. + */ +public class KerberosPrincipalDoesNotExistException extends KerberosOperationException { + + /** + * Creates a new KerberosPrincipalDoesNotExistException with a message + * + * @param message a String containing the message indicating the reason for this exception + */ + public KerberosPrincipalDoesNotExistException(String message) { + super(message); + } + + /** + * Creates a new KerberosPrincipalDoesNotExistException with a message and a cause + * + * @param message a String containing the message indicating the reason for this exception + * @param cause a Throwable declaring the previously thrown Throwable that led to this exception + */ + public KerberosPrincipalDoesNotExistException(String message, Throwable cause) { + super(message, cause); + } +} http://git-wip-us.apache.org/repos/asf/ambari/blob/6b9909ae/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandler.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandler.java b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandler.java index 90858fb..f48052f 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandler.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/serveraction/kerberos/MITKerberosOperationHandler.java @@ -165,10 +165,11 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler { * @param password a String containing the password to use when creating the principal * @param service a boolean value indicating whether the principal is to be created as a service principal or not * @return an Integer declaring the generated key number - * @throws KerberosKDCConnectionException if a connection to the KDC cannot be made - * @throws KerberosAdminAuthenticationException if the administrator credentials fail to authenticate - * @throws KerberosRealmException if the realm does not map to a KDC - * @throws KerberosOperationException if an unexpected error occurred + * @throws KerberosKDCConnectionException if a connection to the KDC cannot be made + * @throws KerberosAdminAuthenticationException if the administrator credentials fail to authenticate + * @throws KerberosRealmException if the realm does not map to a KDC + * @throws KerberosPrincipalAlreadyExistsException if the principal already exists + * @throws KerberosOperationException if an unexpected error occurred */ @Override public Integer createPrincipal(String principal, String password, boolean service) @@ -193,6 +194,8 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler { String stdOut = result.getStdout(); if ((stdOut != null) && stdOut.contains(String.format("Principal \"%s\" created", principal))) { return getKeyNumber(principal); + } else if ((stdOut != null) && stdOut.contains(String.format("Principal or policy already exists while creating \"%s\"", principal))) { + throw new KerberosPrincipalAlreadyExistsException(principal); } else { LOG.error("Failed to execute kadmin query: add_principal -pw \"********\" {} {}\nSTDOUT: {}\nSTDERR: {}", (createAttributes == null) ? "" : createAttributes, principal, stdOut, result.getStderr()); @@ -211,10 +214,11 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler { * @param principal a String containing the principal to update * @param password a String containing the password to set * @return an Integer declaring the new key number - * @throws KerberosKDCConnectionException if a connection to the KDC cannot be made - * @throws KerberosAdminAuthenticationException if the administrator credentials fail to authenticate - * @throws KerberosRealmException if the realm does not map to a KDC - * @throws KerberosOperationException if an unexpected error occurred + * @throws KerberosKDCConnectionException if a connection to the KDC cannot be made + * @throws KerberosAdminAuthenticationException if the administrator credentials fail to authenticate + * @throws KerberosRealmException if the realm does not map to a KDC + * @throws KerberosPrincipalDoesNotExistException if the principal does not exist + * @throws KerberosOperationException if an unexpected error occurred */ @Override public Integer setPrincipalPassword(String principal, String password) throws KerberosOperationException { @@ -228,9 +232,19 @@ public class MITKerberosOperationHandler extends KerberosOperationHandler { throw new KerberosOperationException("Failed to set password - no password specified"); } else { // Create the kdamin query: change_password <-randkey|-pw <password>> <principal> - invokeKAdmin(String.format("change_password -pw \"%s\" %s", password, principal)); + ShellCommandUtil.Result result = invokeKAdmin(String.format("change_password -pw \"%s\" %s", password, principal)); - return getKeyNumber(principal); + String stdOut = result.getStdout(); + if ((stdOut != null) && stdOut.contains(String.format("Password for \"%s\" changed", principal))) { + return getKeyNumber(principal); + } else if ((stdOut != null) && stdOut.contains("Principal does not exist")) { + throw new KerberosPrincipalDoesNotExistException(principal); + } else { + LOG.error("Failed to execute kadmin query: change_password -pw \"********\" {} \nSTDOUT: {}\nSTDERR: {}", + principal, stdOut, result.getStderr()); + throw new KerberosOperationException(String.format("Failed to update password for %s\nSTDOUT: %s\nSTDERR: %s", + principal, stdOut, result.getStderr())); + } } } http://git-wip-us.apache.org/repos/asf/ambari/blob/6b9909ae/ambari-server/src/main/resources/common-services/AMBARI_METRICS/0.1.0/kerberos.json ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/resources/common-services/AMBARI_METRICS/0.1.0/kerberos.json b/ambari-server/src/main/resources/common-services/AMBARI_METRICS/0.1.0/kerberos.json index 34de6a8..d84ed02 100644 --- a/ambari-server/src/main/resources/common-services/AMBARI_METRICS/0.1.0/kerberos.json +++ b/ambari-server/src/main/resources/common-services/AMBARI_METRICS/0.1.0/kerberos.json @@ -12,6 +12,9 @@ "name": "METRICS_COLLECTOR", "identities": [ { + "name": "/HDFS/NAMENODE/hdfs" + }, + { "name": "ams_hbase_master_hbase", "principal": { "value": "amshbase/_HOST@${realm}", http://git-wip-us.apache.org/repos/asf/ambari/blob/6b9909ae/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 eefaf04..feb11a1 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 @@ -2594,7 +2594,7 @@ public class KerberosHelperTest extends EasyMockSupport { Capture<? extends String> capturePrincipalForKeytab = newCapture(CaptureType.ALL); CreatePrincipalsServerAction createPrincipalsServerAction = injector.getInstance(CreatePrincipalsServerAction.class); - expect(createPrincipalsServerAction.createPrincipal(capture(capturePrincipal), eq(false), anyObject(Map.class), anyObject(KerberosOperationHandler.class), isNull(ActionLog.class))) + expect(createPrincipalsServerAction.createPrincipal(capture(capturePrincipal), eq(false), anyObject(Map.class), anyObject(KerberosOperationHandler.class), eq(false), isNull(ActionLog.class))) .andReturn(new CreatePrincipalsServerAction.CreatePrincipalResult("anything", "password", 1)) .times(3); @@ -3205,20 +3205,19 @@ public class KerberosHelperTest extends EasyMockSupport { KerberosHelper kerberosHelper = injector.getInstance(KerberosHelper.class); boolean managingIdentities = !Boolean.FALSE.equals(manageIdentities); - final Map<String, String> kerberosEnvProperties = createMock(Map.class); - expect(kerberosEnvProperties.get("kdc_type")).andReturn("mit-kdc").anyTimes(); - expect(kerberosEnvProperties.get("realm")).andReturn("FOOBAR.COM").anyTimes(); - - expect(kerberosEnvProperties.get("manage_identities")) - .andReturn((manageIdentities == null) + final Map<String, String> kerberosEnvProperties = new HashMap<String,String>(); + kerberosEnvProperties.put("kdc_type","mit-kdc"); + kerberosEnvProperties.put("realm","FOOBAR.COM"); + kerberosEnvProperties.put("manage_identities","FOOBAR.COM"); + kerberosEnvProperties.put("manage_identities", + (manageIdentities == null) ? null - : ((manageIdentities) ? "true" : "false")) - .anyTimes(); + : ((manageIdentities) ? "true" : "false")); final Config kerberosEnvConfig = createMock(Config.class); expect(kerberosEnvConfig.getProperties()).andReturn(kerberosEnvProperties).anyTimes(); - final Map<String, String> krb5ConfProperties = createMock(Map.class); + final Map<String, String> krb5ConfProperties = new HashMap<String, String>(); final Config krb5ConfConfig = createMock(Config.class); expect(krb5ConfConfig.getProperties()).andReturn(krb5ConfProperties).anyTimes(); @@ -3243,20 +3242,6 @@ public class KerberosHelperTest extends EasyMockSupport { expect(schKerberosClient.getHostName()).andReturn("host1").anyTimes(); expect(schKerberosClient.getState()).andReturn(State.INSTALLED).anyTimes(); - final ServiceComponentHost sch1 = createMock(ServiceComponentHost.class); - expect(sch1.getServiceName()).andReturn("SERVICE1").anyTimes(); - expect(sch1.getServiceComponentName()).andReturn("COMPONENT1").anyTimes(); - expect(sch1.getHostName()).andReturn("host1").anyTimes(); - - final ServiceComponentHost sch2 = createStrictMock(ServiceComponentHost.class); - expect(sch2.getServiceName()).andReturn("SERVICE2").anyTimes(); - expect(sch2.getServiceComponentName()).andReturn("COMPONENT3").anyTimes(); - - final ServiceComponentHost sch3 = createStrictMock(ServiceComponentHost.class); - expect(sch3.getServiceName()).andReturn("SERVICE3").anyTimes(); - expect(sch3.getServiceComponentName()).andReturn("COMPONENT3").anyTimes(); - expect(sch3.getHostName()).andReturn("host1").anyTimes(); - final ServiceComponent serviceComponentKerberosClient = createNiceMock(ServiceComponent.class); expect(serviceComponentKerberosClient.getName()).andReturn(Role.KERBEROS_CLIENT.name()).anyTimes(); expect(serviceComponentKerberosClient.getServiceComponentHosts()).andReturn(Collections.singletonMap("host1", schKerberosClient)).anyTimes(); @@ -3290,16 +3275,13 @@ public class KerberosHelperTest extends EasyMockSupport { } }) .anyTimes(); - expect(cluster.getServiceComponentHosts("host1")) + expect(cluster.getServiceComponentHosts(Service.Type.KERBEROS.name(), Role.KERBEROS_CLIENT.name())) .andReturn(new ArrayList<ServiceComponentHost>() { { - add(sch1); - add(sch2); - add(sch3); add(schKerberosClient); } }) - .once(); + .anyTimes(); expect(cluster.getCurrentStackVersion()) .andReturn(new StackId("HDP", "2.2")) .anyTimes(); @@ -3316,21 +3298,11 @@ public class KerberosHelperTest extends EasyMockSupport { }).anyTimes(); final Clusters clusters = injector.getInstance(Clusters.class); - expect(clusters.getHostsForCluster("c1")) - .andReturn(new HashMap<String, Host>() { - { - put("host1", host); - } - }) - .once(); expect(clusters.getHost("host1")) .andReturn(host) .once(); final AmbariManagementController ambariManagementController = injector.getInstance(AmbariManagementController.class); - expect(ambariManagementController.findConfigurationTagsWithOverrides(cluster, "host1")) - .andReturn(Collections.<String, Map<String, String>>emptyMap()) - .once(); expect(ambariManagementController.findConfigurationTagsWithOverrides(cluster, null)) .andReturn(Collections.<String, Map<String, String>>emptyMap()) .once(); @@ -3496,37 +3468,24 @@ public class KerberosHelperTest extends EasyMockSupport { } }) .anyTimes(); - expect(cluster.getServiceComponentHosts("host1")) + expect(cluster.getServiceComponentHosts(Service.Type.KERBEROS.name(), Role.KERBEROS_CLIENT.name())) .andReturn(new ArrayList<ServiceComponentHost>() { { - add(sch1); - add(sch2); - add(sch3); add(schKerberosClient); } }) - .once(); + .anyTimes(); expect(cluster.getCurrentStackVersion()) .andReturn(new StackId("HDP", "2.2")) .anyTimes(); expect(cluster.getSessionAttributes()).andReturn(new HashMap<String, Object>()).anyTimes(); final Clusters clusters = injector.getInstance(Clusters.class); - expect(clusters.getHostsForCluster("c1")) - .andReturn(new HashMap<String, Host>() { - { - put("host1", host); - } - }) - .once(); expect(clusters.getHost("host1")) .andReturn(host) .once(); final AmbariManagementController ambariManagementController = injector.getInstance(AmbariManagementController.class); - expect(ambariManagementController.findConfigurationTagsWithOverrides(cluster, "host1")) - .andReturn(Collections.<String, Map<String, String>>emptyMap()) - .once(); expect(ambariManagementController.findConfigurationTagsWithOverrides(cluster, null)) .andReturn(Collections.<String, Map<String, String>>emptyMap()) .once();
