Repository: ambari Updated Branches: refs/heads/trunk 7bf3a098c -> af6aba67b
AMBARI-19105. Ambari LogSearch REST Layer should use a configurable timeout for HTTP connections to LogSearch Server. (rnettleton) Project: http://git-wip-us.apache.org/repos/asf/ambari/repo Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/af6aba67 Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/af6aba67 Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/af6aba67 Branch: refs/heads/trunk Commit: af6aba67bbb26d4116532d45f3ea0117aa3cb6a8 Parents: 7bf3a09 Author: Bob Nettleton <rnettle...@hortonworks.com> Authored: Thu Dec 15 15:26:41 2016 -0500 Committer: Bob Nettleton <rnettle...@hortonworks.com> Committed: Thu Dec 15 15:26:41 2016 -0500 ---------------------------------------------------------------------- ambari-server/docs/configuration/index.md | 15 ++-- .../server/api/services/ClusterService.java | 2 +- .../server/api/services/LoggingService.java | 19 +++-- .../server/configuration/Configuration.java | 34 ++++++++ .../controller/AmbariManagementController.java | 12 +++ .../AmbariManagementControllerImpl.java | 8 ++ .../internal/LoggingResourceProvider.java | 24 ------ .../logging/LogSearchDataRetrievalService.java | 32 +++++++- .../LoggingRequestHelperFactoryImpl.java | 27 ++++++- .../logging/LoggingRequestHelperImpl.java | 35 ++++++-- .../logging/LoggingSearchPropertyProvider.java | 14 ++-- .../ambari/server/controller/logging/Utils.java | 2 +- .../server/api/services/LoggingServiceTest.java | 3 +- .../LogSearchDataRetrievalServiceTest.java | 17 ++++ .../LoggingRequestHelperFactoryImplTest.java | 66 ++++++++++++++- .../logging/LoggingRequestHelperImplTest.java | 84 ++++++++++++++++++++ .../server/controller/logging/UtilsTest.java | 2 +- 17 files changed, 340 insertions(+), 56 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/af6aba67/ambari-server/docs/configuration/index.md ---------------------------------------------------------------------- diff --git a/ambari-server/docs/configuration/index.md b/ambari-server/docs/configuration/index.md index 6ff263c..50864f2 100644 --- a/ambari-server/docs/configuration/index.md +++ b/ambari-server/docs/configuration/index.md @@ -132,6 +132,7 @@ The following are the properties which can be used to configure Ambari. | default.kdcserver.port | The port used to communicate with the Kerberos Key Distribution Center. |`88` | | extensions.path | The location on the Ambari Server where stack extensions exist.<br/><br/>The following are examples of valid values:<ul><li>`/var/lib/ambari-server/resources/extensions`</ul> | | | http.cache-control | The value that will be used to set the `Cache-Control` HTTP response header. |`no-store` | +| http.charset | The value that will be used to set the Character encoding to HTTP response header. |`utf-8` | | http.pragma | The value that will be used to set the `PRAGMA` HTTP response header. |`no-cache` | | http.strict-transport-security | When using SSL, this will be used to set the `Strict-Transport-Security` response header. |`max-age=31536000` | | http.x-content-type-options | The value that will be used to set the `X-CONTENT-TYPE` HTTP response header. |`nosniff` | @@ -147,6 +148,8 @@ The following are the properties which can be used to configure Ambari. | kerberos.operation.retry.timeout | The time to wait (in seconds) between failed kerberos operations retries. |`10` | | ldap.sync.username.collision.behavior | Determines how to handle username collision while updating from LDAP.<br/><br/>The following are examples of valid values:<ul><li>`skip`<li>`convert`</ul> |`convert` | | log4j.monitor.delay | Indicates the delay, in milliseconds, for the log4j monitor to check for changes |`300000` | +| logsearch.portal.connect.timeout | The time, in milliseconds, that the Ambari Server will wait while attempting to connect to the LogSearch Portal service. |`5000` | +| logsearch.portal.read.timeout | The time, in milliseconds, that the Ambari Server will wait while attempting to read a response from the LogSearch Portal service. |`5000` | | metadata.path | The location on the Ambari Server where the stack resources exist.<br/><br/>The following are examples of valid values:<ul><li>`/var/lib/ambari-server/resources/stacks`</ul> | | | metrics.retrieval-service.cache.timeout | The amount of time, in minutes, that JMX and REST metrics retrieved directly can remain in the cache. |`30` | | metrics.retrieval-service.request.ttl | The number of seconds to wait between issuing JMX or REST metric requests to the same endpoint. This property is used to throttle requests to the same URL being made too close together<br/><br/> This property is related to `metrics.retrieval-service.request.ttl.enabled`. |`5` | @@ -231,16 +234,16 @@ The following are the properties which can be used to configure Ambari. | server.jdbc.user.passwd | The password for the user when logging into the database. |`bigdata` | | server.locks.profiling | Enable the profiling of internal locks. |`false` | | server.metrics.retrieval-service.thread.priority | The priority of threads used by the service which retrieves JMX and REST metrics directly from their respective endpoints. |`5` | -| server.metrics.retrieval-service.threadpool.size.core | The core number of threads used to retrieve JMX and REST metrics directly from their respective endpoints. |`8` | -| server.metrics.retrieval-service.threadpool.size.max | The maximum number of threads used to retrieve JMX and REST metrics directly from their respective endpoints. |`16` | -| server.metrics.retrieval-service.threadpool.worker.size | The number of queued requests allowed for JMX and REST metrics before discarding old requests which have not been fullfilled. |`160` | +| server.metrics.retrieval-service.threadpool.size.core | The core number of threads used to retrieve JMX and REST metrics directly from their respective endpoints. |`16` | +| server.metrics.retrieval-service.threadpool.size.max | The maximum number of threads used to retrieve JMX and REST metrics directly from their respective endpoints. |`32` | +| server.metrics.retrieval-service.threadpool.worker.size | The number of queued requests allowed for JMX and REST metrics before discarding old requests which have not been fullfilled. |`320` | | server.operations.retry-attempts | The number of retry attempts for failed API and blueprint operations. |`0` | | server.os_family | The operating system family for all hosts in the cluster. This is used when bootstrapping agents and when enabling Kerberos.<br/><br/>The following are examples of valid values:<ul><li>`redhat`<li>`ubuntu`</ul> | | | server.os_type | The operating system version for all hosts in the cluster. This is used when bootstrapping agents and when enabling Kerberos.<br/><br/>The following are examples of valid values:<ul><li>`6`<li>`7`</ul> | | | server.persistence.type | The type of database connection being used. Unless using an embedded PostgresSQL server, then this should be `remote`.<br/><br/>The following are examples of valid values:<ul><li>`local`<li>`remote`</ul> |`local` | | server.property-provider.threadpool.completion.timeout | The maximum time, in milliseconds, that federated requests for data can execute before being terminated. Increasing this value could result in degraded performanc from the REST APIs. |`5000` | -| server.property-provider.threadpool.size.core | The core number of threads that will be used to retrieve data from federated datasources, such as remote JMX endpoints. |`8` | -| server.property-provider.threadpool.size.max | The maximum number of threads that will be used to retrieve data from federated datasources, such as remote JMX endpoints. |`16` | +| server.property-provider.threadpool.size.core | The core number of threads that will be used to retrieve data from federated datasources, such as remote JMX endpoints. |`16` | +| server.property-provider.threadpool.size.max | The maximum number of threads that will be used to retrieve data from federated datasources, such as remote JMX endpoints. |`32` | | server.property-provider.threadpool.worker.size | The maximum size of pending federated datasource requests, such as those to JMX endpoints, which can be queued before rejecting new requests. |`2147483647` | | server.requestlogs.namepattern | The pattern of request log file name |`ambari-access-yyyy_mm_dd.log` | | server.requestlogs.path | The location on the Ambari Server where request logs can be created. | | @@ -276,6 +279,7 @@ The following are the properties which can be used to configure Ambari. | task.query.parameterlist.size | The maximum number of tasks which can be queried by ID from the database. |`999` | | topology.task.creation.parallel | Indicates whether parallel topology task creation is enabled |`false` | | topology.task.creation.parallel.threads | The number of threads to use for parallel topology task creation if enabled |`10` | +| view.extract-after-cluster-config | Drives view extraction in case of blueprint deployments; non-system views are deployed when cluster configuration is successful |`false` | | view.extraction.threadpool.size.core | The number of threads used to extract Ambari Views when Ambari Server is starting up. |`10` | | view.extraction.threadpool.size.max | The maximum number of threads used to extract Ambari Views when Ambari Server is starting up. |`20` | | view.extraction.threadpool.timeout | The time, in milliseconds, that non-core threads will live when extraction views on Ambari Server startup. |`100000` | @@ -285,6 +289,7 @@ The following are the properties which can be used to configure Ambari. | views.ambari.request.read.timeout.millis | The amount of time, in milliseconds, that a view will wait before terminating an HTTP(S) read request to the Ambari REST API. |`45000` | | views.dir | The directory on the Ambari Server file system used for expanding Views and storing webapp work. |`/var/lib/ambari-server/resources/views` | | views.http.cache-control | The value that will be used to set the `Cache-Control` HTTP response header for Ambari View requests. |`no-store` | +| views.http.charset | The value that will be used to set the Character encoding to HTTP response header for Ambari View requests. |`utf-8` | | views.http.pragma | The value that will be used to set the `PRAGMA` HTTP response header for Ambari View requests. |`no-cache` | | views.http.strict-transport-security | The value that will be used to set the `Strict-Transport-Security` HTTP response header for Ambari View requests. |`max-age=31536000` | | views.http.x-content-type-options | The value that will be used to set the `X-CONTENT-TYPE` HTTP response header for Ambari View requests. |`nosniff` | http://git-wip-us.apache.org/repos/asf/ambari/blob/af6aba67/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java index 072c4a2..9f6feaa 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/ClusterService.java @@ -662,7 +662,7 @@ public class ClusterService extends BaseService { @Path("{clusterName}/logging") public LoggingService getLogging(@Context javax.ws.rs.core.Request request, @PathParam("clusterName") String clusterName) { - return new LoggingService(clusterName); + return AmbariServer.getController().getLoggingService(clusterName); } // ----- helper methods ---------------------------------------------------- http://git-wip-us.apache.org/repos/asf/ambari/blob/af6aba67/ambari-server/src/main/java/org/apache/ambari/server/api/services/LoggingService.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/api/services/LoggingService.java b/ambari-server/src/main/java/org/apache/ambari/server/api/services/LoggingService.java index ea4960f..d83aa25 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/api/services/LoggingService.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/api/services/LoggingService.java @@ -42,7 +42,6 @@ import org.apache.ambari.server.controller.internal.ResourceImpl; import org.apache.ambari.server.controller.logging.LogQueryResponse; import org.apache.ambari.server.controller.logging.LoggingRequestHelper; import org.apache.ambari.server.controller.logging.LoggingRequestHelperFactory; -import org.apache.ambari.server.controller.logging.LoggingRequestHelperFactoryImpl; import org.apache.ambari.server.controller.spi.Resource; import org.apache.ambari.server.security.authorization.AuthorizationException; import org.apache.ambari.server.security.authorization.AuthorizationHelper; @@ -52,6 +51,8 @@ import org.apache.ambari.server.state.Cluster; import org.apache.ambari.server.utils.RetryHelper; import org.apache.commons.lang.StringUtils; +import com.google.inject.Inject; + /** * This Service provides access to the LogSearch query services, including: * - Access to all service log files in a given cluster @@ -68,19 +69,19 @@ public class LoggingService extends BaseService { private final ControllerFactory controllerFactory; - private final LoggingRequestHelperFactory helperFactory; + @Inject + private LoggingRequestHelperFactory helperFactory; private final String clusterName; public LoggingService(String clusterName) { - this(clusterName, new DefaultControllerFactory(), new LoggingRequestHelperFactoryImpl()); + this(clusterName, new DefaultControllerFactory()); } - public LoggingService(String clusterName, ControllerFactory controllerFactory, LoggingRequestHelperFactory helperFactory) { + public LoggingService(String clusterName, ControllerFactory controllerFactory) { this.clusterName = clusterName; this.controllerFactory = controllerFactory; - this.helperFactory = helperFactory; } @GET @@ -207,6 +208,14 @@ public class LoggingService extends BaseService { return responseBuilder.build(); } + /** + * Package-level setter that facilitates simpler unit testing + * + * @param helperFactory + */ + void setLoggingRequestHelperFactory(LoggingRequestHelperFactory helperFactory) { + this.helperFactory = helperFactory; + } /** * Internal interface that defines an access factory for the http://git-wip-us.apache.org/repos/asf/ambari/blob/af6aba67/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java index f9b6878..22d8168 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/configuration/Configuration.java @@ -2561,6 +2561,22 @@ public class Configuration { public static final ConfigurationProperty<Integer> SRVR_API_ACCEPTOR_THREAD_COUNT = new ConfigurationProperty<>( "client.api.acceptor.count", null); + /** + * The time, in milliseconds, that the Ambari Server will wait while attempting to connect to the + * LogSearch Portal service. + */ + @Markdown(description = "The time, in milliseconds, that the Ambari Server will wait while attempting to connect to the LogSearch Portal service.") + public static final ConfigurationProperty<Integer> LOGSEARCH_PORTAL_CONNECT_TIMEOUT = new ConfigurationProperty<>( + "logsearch.portal.connect.timeout", 5000); + + /** + * The time, in milliseconds, that the Ambari Server will wait while attempting to read a response from the + * LogSearch Portal service. + */ + @Markdown(description = "The time, in milliseconds, that the Ambari Server will wait while attempting to read a response from the LogSearch Portal service.") + public static final ConfigurationProperty<Integer> LOGSEARCH_PORTAL_READ_TIMEOUT = new ConfigurationProperty<>( + "logsearch.portal.read.timeout", 5000); + private static final Logger LOG = LoggerFactory.getLogger( Configuration.class); @@ -5315,6 +5331,24 @@ public class Configuration { } /** + * Get the connect timeout used for connecting to the LogSearch Portal Service + * + * @return + */ + public int getLogSearchPortalConnectTimeout() { + return NumberUtils.toInt(getProperty(LOGSEARCH_PORTAL_CONNECT_TIMEOUT)); + } + + /** + * Get the read timeout used for connecting to the LogSearch Portal Service + * + * @return + */ + public int getLogSearchPortalReadTimeout() { + return NumberUtils.toInt(getProperty(LOGSEARCH_PORTAL_READ_TIMEOUT)); + } + + /** * Generates a markdown table which includes: * <ul> * <li>Property key name</li> http://git-wip-us.apache.org/repos/asf/ambari/blob/af6aba67/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java index 389f973..cc20324 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementController.java @@ -28,6 +28,7 @@ import org.apache.ambari.server.RoleCommand; import org.apache.ambari.server.actionmanager.ActionManager; import org.apache.ambari.server.agent.ExecutionCommand; import org.apache.ambari.server.api.services.AmbariMetaInfo; +import org.apache.ambari.server.api.services.LoggingService; import org.apache.ambari.server.controller.internal.DeleteStatusMetaData; import org.apache.ambari.server.controller.internal.RequestStageContainer; import org.apache.ambari.server.controller.logging.LoggingSearchPropertyProvider; @@ -872,6 +873,17 @@ public interface AmbariManagementController { */ LoggingSearchPropertyProvider getLoggingSearchPropertyProvider(); + + /** + * Gets the LoggingService instance from the dependency injection framework. + * + * @param clusterName the cluster name associated with this LoggingService instance + * + * @return an instance of LoggingService associated with the specified cluster. + */ + LoggingService getLoggingService(String clusterName); + + /** * Returns KerberosHelper instance * @return http://git-wip-us.apache.org/repos/asf/ambari/blob/af6aba67/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java index 6b5731c..5fe7585 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/AmbariManagementControllerImpl.java @@ -87,6 +87,7 @@ import org.apache.ambari.server.actionmanager.StageFactory; import org.apache.ambari.server.agent.ExecutionCommand; import org.apache.ambari.server.agent.ExecutionCommand.KeyNames; import org.apache.ambari.server.api.services.AmbariMetaInfo; +import org.apache.ambari.server.api.services.LoggingService; import org.apache.ambari.server.configuration.Configuration; import org.apache.ambari.server.configuration.Configuration.DatabaseType; import org.apache.ambari.server.controller.internal.DeleteStatusMetaData; @@ -5081,6 +5082,13 @@ public class AmbariManagementControllerImpl implements AmbariManagementControlle return injector.getInstance(LoggingSearchPropertyProvider.class); } + @Override + public LoggingService getLoggingService(String clusterName) { + LoggingService loggingService = new LoggingService(clusterName); + injector.injectMembers(loggingService); + return loggingService; + } + /** * {@inheritDoc} */ http://git-wip-us.apache.org/repos/asf/ambari/blob/af6aba67/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/LoggingResourceProvider.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/LoggingResourceProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/LoggingResourceProvider.java index 2eb1a63..b46399c 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/LoggingResourceProvider.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/internal/LoggingResourceProvider.java @@ -22,8 +22,6 @@ package org.apache.ambari.server.controller.internal; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.LinkedList; -import java.util.List; import java.util.Map; import java.util.Set; @@ -113,28 +111,6 @@ public class LoggingResourceProvider extends AbstractControllerResourceProvider return Collections.singleton(resource); } - private static List<Map<String, String>> createTestData(Resource resource) { - // just create some test data for verifying basic resource code, not an actual result - Map<String, String> levelCounts = new HashMap<String, String>(); - levelCounts.put("INFO", "100"); - levelCounts.put("WARN", "250"); - levelCounts.put("DEBUG", "300"); - - resource.setProperty("logLevels", levelCounts); - - List<Map <String, String>> listOfResults = new LinkedList<Map<String, String>>(); - Map<String, String> resultOne = new HashMap<String, String>(); - resultOne.put("data", "This is a test sentence."); - resultOne.put("score", "100"); - resultOne.put("level", "INFO"); - resultOne.put("type", "hdfs_namenode"); - resultOne.put("host", "c6401.ambari.apache.org"); - resultOne.put("LoggerName", "NameNodeLogger"); - - listOfResults.add(resultOne); - return listOfResults; - } - @Override public Set<String> checkPropertyIds(Set<String> propertyIds) { Set<String> unSupportedProperties = http://git-wip-us.apache.org/repos/asf/ambari/blob/af6aba67/ambari-server/src/main/java/org/apache/ambari/server/controller/logging/LogSearchDataRetrievalService.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/logging/LogSearchDataRetrievalService.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/logging/LogSearchDataRetrievalService.java index e65cd59..ce6094c 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/logging/LogSearchDataRetrievalService.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/logging/LogSearchDataRetrievalService.java @@ -29,11 +29,14 @@ import org.apache.commons.collections.CollectionUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; + import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; import com.google.common.collect.Sets; import com.google.common.util.concurrent.AbstractService; import com.google.inject.Inject; +import com.google.inject.Injector; + /** * The {@link LogSearchDataRetrievalService} is an Ambari Service that @@ -64,9 +67,16 @@ public class LogSearchDataRetrievalService extends AbstractService { private static Logger LOG = LoggerFactory.getLogger(LogSearchDataRetrievalService.class); + /** + * Factory instance used to handle URL string generation requests on the + * main request thread. + */ @Inject private LoggingRequestHelperFactory loggingRequestHelperFactory; + @Inject + private Injector injector; + /** * A Cache of host+component names to a set of log files associated with * that Host/Component combination. This data is retrieved from the @@ -201,6 +211,15 @@ public class LogSearchDataRetrievalService extends AbstractService { } /** + * Package-level setter to facilitate simpler unit testing + * + * @param injector + */ + void setInjector(Injector injector) { + this.injector = injector; + } + + /** * This protected method provides a way for unit-tests to insert a * mock executor for simpler unit-testing. * @@ -220,7 +239,14 @@ public class LogSearchDataRetrievalService extends AbstractService { } private void startLogSearchFileNameRequest(String host, String component, String cluster) { - executor.execute(new LogSearchFileNameRequestRunnable(host, component, cluster, logFileNameCache, currentRequests)); + // Create a separate instance of LoggingRequestHelperFactory for + // each task launched, since these tasks will occur on a separate thread + // TODO: In a future patch, this should be refactored, to either remove the need + // TODO: for the separate factory instance at the level of this class, or to make + // TODO: the LoggingRequestHelperFactory implementation thread-safe, so that + // TODO: a single factory instance can be shared across multiple threads safely + executor.execute(new LogSearchFileNameRequestRunnable(host, component, cluster, logFileNameCache, currentRequests, + injector.getInstance(LoggingRequestHelperFactory.class))); } private AmbariManagementController getController() { @@ -258,8 +284,8 @@ public class LogSearchDataRetrievalService extends AbstractService { private AmbariManagementController controller; - LogSearchFileNameRequestRunnable(String host, String component, String cluster, Cache<String, Set<String>> logFileNameCache, Set<String> currentRequests) { - this(host, component, cluster, logFileNameCache, currentRequests, new LoggingRequestHelperFactoryImpl(), AmbariServer.getController()); + LogSearchFileNameRequestRunnable(String host, String component, String cluster, Cache<String, Set<String>> logFileNameCache, Set<String> currentRequests, LoggingRequestHelperFactory loggingRequestHelperFactory) { + this(host, component, cluster, logFileNameCache, currentRequests, loggingRequestHelperFactory, AmbariServer.getController()); } LogSearchFileNameRequestRunnable(String host, String component, String cluster, Cache<String, Set<String>> logFileNameCache, Set<String> currentRequests, http://git-wip-us.apache.org/repos/asf/ambari/blob/af6aba67/ambari-server/src/main/java/org/apache/ambari/server/controller/logging/LoggingRequestHelperFactoryImpl.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/logging/LoggingRequestHelperFactoryImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/logging/LoggingRequestHelperFactoryImpl.java index afe1757..2f4f8d7 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/logging/LoggingRequestHelperFactoryImpl.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/logging/LoggingRequestHelperFactoryImpl.java @@ -19,7 +19,10 @@ package org.apache.ambari.server.controller.logging; import java.util.List; +import javax.inject.Inject; + import org.apache.ambari.server.AmbariException; +import org.apache.ambari.server.configuration.Configuration; import org.apache.ambari.server.controller.AmbariManagementController; import org.apache.ambari.server.state.Cluster; import org.apache.ambari.server.state.Clusters; @@ -28,6 +31,7 @@ import org.apache.ambari.server.state.ServiceComponentHost; import org.apache.ambari.server.state.State; import org.apache.log4j.Logger; + public class LoggingRequestHelperFactoryImpl implements LoggingRequestHelperFactory { private static final Logger LOG = Logger.getLogger(LoggingRequestHelperFactoryImpl.class); @@ -42,9 +46,17 @@ public class LoggingRequestHelperFactoryImpl implements LoggingRequestHelperFact private static final String LOGSEARCH_UI_PROTOCOL = "logsearch_ui_protocol"; + @Inject + private Configuration ambariServerConfiguration; @Override public LoggingRequestHelper getHelper(AmbariManagementController ambariManagementController, String clusterName) { + + if (ambariServerConfiguration == null) { + LOG.error("Ambari Server configuration object not available, cannot create request helper"); + return null; + } + Clusters clusters = ambariManagementController.getClusters(); @@ -90,7 +102,11 @@ public class LoggingRequestHelperFactoryImpl implements LoggingRequestHelperFact final String logSearchProtocol = logSearchEnvConfig.getProperties().get(LOGSEARCH_UI_PROTOCOL); - return new LoggingRequestHelperImpl(logSearchHostName, logSearchPortNumber, logSearchProtocol, ambariManagementController.getCredentialStoreService(), cluster); + final LoggingRequestHelperImpl loggingRequestHelper = new LoggingRequestHelperImpl(logSearchHostName, logSearchPortNumber, logSearchProtocol, ambariManagementController.getCredentialStoreService(), cluster); + // set configured timeouts for the Ambari connection to the LogSearch Portal service + loggingRequestHelper.setLogSearchConnectTimeoutInMilliseconds(ambariServerConfiguration.getLogSearchPortalConnectTimeout()); + loggingRequestHelper.setLogSearchReadTimeoutInMilliseconds(ambariServerConfiguration.getLogSearchPortalReadTimeout()); + return loggingRequestHelper; } } catch (AmbariException ambariException) { LOG.error("Error occurred while trying to obtain the cluster, cluster name = " + clusterName, ambariException); @@ -99,4 +115,13 @@ public class LoggingRequestHelperFactoryImpl implements LoggingRequestHelperFact return null; } + + /** + * Package-level setter to facilitate simpler unit testing + * + * @param ambariServerConfiguration the Ambari Server configuration properties + */ + void setAmbariServerConfiguration(Configuration ambariServerConfiguration) { + this.ambariServerConfiguration = ambariServerConfiguration; + } } http://git-wip-us.apache.org/repos/asf/ambari/blob/af6aba67/ambari-server/src/main/java/org/apache/ambari/server/controller/logging/LoggingRequestHelperImpl.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/logging/LoggingRequestHelperImpl.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/logging/LoggingRequestHelperImpl.java index 88996d7..e915538 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/logging/LoggingRequestHelperImpl.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/logging/LoggingRequestHelperImpl.java @@ -55,12 +55,14 @@ import org.apache.ambari.server.state.Config; import org.apache.commons.codec.binary.Base64; import org.apache.commons.lang.StringUtils; import org.apache.http.client.utils.URIBuilder; -import org.apache.log4j.Logger; import org.codehaus.jackson.map.AnnotationIntrospector; import org.codehaus.jackson.map.ObjectMapper; import org.codehaus.jackson.map.ObjectReader; import org.codehaus.jackson.map.annotate.JsonSerialize; import org.codehaus.jackson.map.introspect.JacksonAnnotationIntrospector; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + /** * Convenience class to handle the connection details of a LogSearch query request. @@ -68,7 +70,7 @@ import org.codehaus.jackson.map.introspect.JacksonAnnotationIntrospector; */ public class LoggingRequestHelperImpl implements LoggingRequestHelper { - private static Logger LOG = Logger.getLogger(LoggingRequestHelperImpl.class); + private static Logger LOG = LoggerFactory.getLogger(LoggingRequestHelperImpl.class); private static final String LOGSEARCH_ADMIN_JSON_CONFIG_TYPE_NAME = "logsearch-admin-json"; @@ -114,6 +116,11 @@ public class LoggingRequestHelperImpl implements LoggingRequestHelper { private SSLSocketFactory sslSocketFactory; + private int logSearchConnectTimeoutInMilliseconds = DEFAULT_LOGSEARCH_CONNECT_TIMEOUT_IN_MILLISECONDS; + + private int logSearchReadTimeoutInMilliseconds = DEFAULT_LOGSEARCH_READ_TIMEOUT_IN_MILLISECONDS; + + public LoggingRequestHelperImpl(String hostName, String portNumber, String protocol, CredentialStoreService credentialStoreService, Cluster cluster) { this(hostName, portNumber, protocol, credentialStoreService, cluster, new DefaultNetworkConnection()); } @@ -127,6 +134,22 @@ public class LoggingRequestHelperImpl implements LoggingRequestHelper { this.networkConnection = networkConnection; } + public int getLogSearchConnectTimeoutInMilliseconds() { + return this.logSearchConnectTimeoutInMilliseconds; + } + + public void setLogSearchConnectTimeoutInMilliseconds(int logSearchConnectTimeoutInMilliseconds) { + this.logSearchConnectTimeoutInMilliseconds = logSearchConnectTimeoutInMilliseconds; + } + + public int getLogSearchReadTimeoutInMilliseconds() { + return this.logSearchReadTimeoutInMilliseconds; + } + + public void setLogSearchReadTimeoutInMilliseconds(int logSearchReadTimeoutInMilliseconds) { + this.logSearchReadTimeoutInMilliseconds = logSearchReadTimeoutInMilliseconds; + } + public LogQueryResponse sendQueryRequest(Map<String, String> queryParameters) { try { // use the Apache builder to create the correct URI @@ -135,10 +158,12 @@ public class LoggingRequestHelperImpl implements LoggingRequestHelper { HttpURLConnection httpURLConnection = (HttpURLConnection) logSearchURI.toURL().openConnection(); secure(httpURLConnection, protocol); httpURLConnection.setRequestMethod("GET"); - httpURLConnection.setConnectTimeout(DEFAULT_LOGSEARCH_CONNECT_TIMEOUT_IN_MILLISECONDS); - httpURLConnection.setReadTimeout(DEFAULT_LOGSEARCH_READ_TIMEOUT_IN_MILLISECONDS); + httpURLConnection.setConnectTimeout(logSearchConnectTimeoutInMilliseconds); + httpURLConnection.setReadTimeout(logSearchReadTimeoutInMilliseconds); addCookiesFromCookieStore(httpURLConnection); + LOG.debug("Attempting request to LogSearch Portal Server, with connect timeout = {} milliseconds and read timeout = {} milliseconds", + logSearchConnectTimeoutInMilliseconds, logSearchReadTimeoutInMilliseconds); setupCredentials(httpURLConnection); @@ -282,7 +307,7 @@ public class LoggingRequestHelperImpl implements LoggingRequestHelper { queryParameters.put("pageSize", "1"); LogQueryResponse response = sendQueryRequest(queryParameters); - if ((response != null) && (!response.getListOfResults().isEmpty())) { + if ((response != null) && (response.getListOfResults() != null) && (!response.getListOfResults().isEmpty())) { LogLineResult lineOne = response.getListOfResults().get(0); // this assumes that each component has only one associated log file, // which may not always hold true http://git-wip-us.apache.org/repos/asf/ambari/blob/af6aba67/ambari-server/src/main/java/org/apache/ambari/server/controller/logging/LoggingSearchPropertyProvider.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/logging/LoggingSearchPropertyProvider.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/logging/LoggingSearchPropertyProvider.java index 6ffcdf9..36c485a 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/logging/LoggingSearchPropertyProvider.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/logging/LoggingSearchPropertyProvider.java @@ -43,13 +43,14 @@ import org.apache.ambari.server.state.ComponentInfo; import org.apache.ambari.server.state.LogDefinition; import org.apache.ambari.server.state.StackId; import org.apache.commons.lang.StringUtils; -import org.apache.log4j.Logger; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import com.google.inject.Inject; public class LoggingSearchPropertyProvider implements PropertyProvider { - private static final Logger LOG = Logger.getLogger(LoggingSearchPropertyProvider.class); + private static final Logger LOG = LoggerFactory.getLogger(LoggingSearchPropertyProvider.class); private static final String CLUSTERS_PATH = "/api/v1/clusters"; @@ -68,12 +69,9 @@ public class LoggingSearchPropertyProvider implements PropertyProvider { @Inject private LogSearchDataRetrievalService logSearchDataRetrievalService; + @Inject private LoggingRequestHelperFactory loggingRequestHelperFactory; - public LoggingSearchPropertyProvider() { - loggingRequestHelperFactory = new LoggingRequestHelperFactoryImpl(); - } - @Override public Set<Resource> populateResources(Set<Resource> resources, Request request, Predicate predicate) throws SystemException { Map<String, Boolean> isLogSearchRunning = new HashMap<>(); @@ -223,11 +221,11 @@ public class LoggingSearchPropertyProvider implements PropertyProvider { this.ambariManagementController = ambariManagementController; } - protected void setLogSearchDataRetrievalService(LogSearchDataRetrievalService logSearchDataRetrievalService) { + void setLogSearchDataRetrievalService(LogSearchDataRetrievalService logSearchDataRetrievalService) { this.logSearchDataRetrievalService = logSearchDataRetrievalService; } - protected void setLoggingRequestHelperFactory(LoggingRequestHelperFactory loggingRequestHelperFactory) { + void setLoggingRequestHelperFactory(LoggingRequestHelperFactory loggingRequestHelperFactory) { this.loggingRequestHelperFactory = loggingRequestHelperFactory; } http://git-wip-us.apache.org/repos/asf/ambari/blob/af6aba67/ambari-server/src/main/java/org/apache/ambari/server/controller/logging/Utils.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/main/java/org/apache/ambari/server/controller/logging/Utils.java b/ambari-server/src/main/java/org/apache/ambari/server/controller/logging/Utils.java index fdc9267..969d442 100644 --- a/ambari-server/src/main/java/org/apache/ambari/server/controller/logging/Utils.java +++ b/ambari-server/src/main/java/org/apache/ambari/server/controller/logging/Utils.java @@ -19,7 +19,7 @@ package org.apache.ambari.server.controller.logging; import java.util.concurrent.atomic.AtomicInteger; -import org.apache.log4j.Logger; +import org.slf4j.Logger; /** * Utility class to hold static convenience methods for http://git-wip-us.apache.org/repos/asf/ambari/blob/af6aba67/ambari-server/src/test/java/org/apache/ambari/server/api/services/LoggingServiceTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/api/services/LoggingServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/api/services/LoggingServiceTest.java index 64fff1e..800aca2 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/api/services/LoggingServiceTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/api/services/LoggingServiceTest.java @@ -125,7 +125,8 @@ public class LoggingServiceTest { SecurityContextHolder.getContext().setAuthentication(authentication); LoggingService loggingService = - new LoggingService(expectedClusterName, controllerFactoryMock, helperFactoryMock); + new LoggingService(expectedClusterName, controllerFactoryMock); + loggingService.setLoggingRequestHelperFactory(helperFactoryMock); Response resource = loggingService.getSearchEngine("", null, uriInfoMock); http://git-wip-us.apache.org/repos/asf/ambari/blob/af6aba67/ambari-server/src/test/java/org/apache/ambari/server/controller/logging/LogSearchDataRetrievalServiceTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/logging/LogSearchDataRetrievalServiceTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/logging/LogSearchDataRetrievalServiceTest.java index 0bd681b..59aa9c8 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/controller/logging/LogSearchDataRetrievalServiceTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/logging/LogSearchDataRetrievalServiceTest.java @@ -28,6 +28,16 @@ import java.util.Collections; import java.util.Set; import java.util.concurrent.Executor; + +import org.apache.ambari.server.controller.AmbariManagementController; +import org.easymock.EasyMockSupport; +import org.junit.Test; + +import com.google.common.cache.Cache; +import com.google.inject.Injector; + + + import org.apache.ambari.server.controller.AmbariManagementController; import org.easymock.EasyMockSupport; import org.junit.Test; @@ -117,15 +127,21 @@ public class LogSearchDataRetrievalServiceTest { Executor executorMock = mockSupport.createMock(Executor.class); + Injector injectorMock = + mockSupport.createMock(Injector.class); + // expect the executor to be called to execute the LogSearch request executorMock.execute(isA(LogSearchDataRetrievalService.LogSearchFileNameRequestRunnable.class)); // executor should only be called once expectLastCall().once(); + expect(injectorMock.getInstance(LoggingRequestHelperFactory.class)).andReturn(helperFactoryMock); + mockSupport.replayAll(); LogSearchDataRetrievalService retrievalService = new LogSearchDataRetrievalService(); retrievalService.setLoggingRequestHelperFactory(helperFactoryMock); + retrievalService.setInjector(injectorMock); // call the initialization routine called by the Google framework retrievalService.doStart(); retrievalService.setExecutor(executorMock); @@ -137,6 +153,7 @@ public class LogSearchDataRetrievalServiceTest { assertNull("Inital query on the retrieval service should be null, since cache is empty by default", resultSet); assertEquals("Incorrect number of entries in the current request set", 1, retrievalService.getCurrentRequests().size()); + assertTrue("Incorrect HostComponent set on request set", retrievalService.getCurrentRequests().contains(expectedComponentName + "+" + expectedHostName)); http://git-wip-us.apache.org/repos/asf/ambari/blob/af6aba67/ambari-server/src/test/java/org/apache/ambari/server/controller/logging/LoggingRequestHelperFactoryImplTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/logging/LoggingRequestHelperFactoryImplTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/logging/LoggingRequestHelperFactoryImplTest.java index 7c8405d..71a2d49 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/controller/logging/LoggingRequestHelperFactoryImplTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/logging/LoggingRequestHelperFactoryImplTest.java @@ -19,6 +19,7 @@ package org.apache.ambari.server.controller.logging; import static org.easymock.EasyMock.expect; +import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -27,6 +28,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.Map; +import org.apache.ambari.server.configuration.Configuration; import org.apache.ambari.server.controller.AmbariManagementController; import org.apache.ambari.server.security.encryption.CredentialStoreService; import org.apache.ambari.server.state.Cluster; @@ -38,6 +40,8 @@ import org.apache.ambari.server.state.State; import org.easymock.EasyMockSupport; import org.junit.Test; + + public class LoggingRequestHelperFactoryImplTest { @Test @@ -45,6 +49,8 @@ public class LoggingRequestHelperFactoryImplTest { final String expectedClusterName = "testclusterone"; final String expectedHostName = "c6410.ambari.apache.org"; final String expectedPortNumber = "61889"; + final int expectedConnectTimeout = 3000; + final int expectedReadTimeout = 3000; EasyMockSupport mockSupport = new EasyMockSupport(); @@ -66,6 +72,9 @@ public class LoggingRequestHelperFactoryImplTest { CredentialStoreService credentialStoreServiceMock = mockSupport.createMock(CredentialStoreService.class); + Configuration serverConfigMock = + mockSupport.createMock(Configuration.class); + Map<String, String> testProperties = new HashMap<String, String>(); testProperties.put("logsearch_ui_port", expectedPortNumber); @@ -79,13 +88,17 @@ public class LoggingRequestHelperFactoryImplTest { expect(logSearchEnvConfig.getProperties()).andReturn(testProperties).atLeastOnce(); expect(serviceComponentHostMock.getHostName()).andReturn(expectedHostName).atLeastOnce(); expect(serviceComponentHostMock.getState()).andReturn(State.STARTED).atLeastOnce(); - + expect(serverConfigMock.getLogSearchPortalConnectTimeout()).andReturn(expectedConnectTimeout); + expect(serverConfigMock.getLogSearchPortalReadTimeout()).andReturn(expectedReadTimeout); mockSupport.replayAll(); LoggingRequestHelperFactory helperFactory = new LoggingRequestHelperFactoryImpl(); + // set the configuration mock using the concrete type + ((LoggingRequestHelperFactoryImpl)helperFactory).setAmbariServerConfiguration(serverConfigMock); + LoggingRequestHelper helper = helperFactory.getHelper(controllerMock, expectedClusterName); @@ -95,6 +108,12 @@ public class LoggingRequestHelperFactoryImplTest { assertTrue("Helper created was not of the expected type", helper instanceof LoggingRequestHelperImpl); + assertEquals("Helper factory did not set the expected connect timeout on the helper instance", + expectedConnectTimeout, ((LoggingRequestHelperImpl)helper).getLogSearchConnectTimeoutInMilliseconds()); + + assertEquals("Helper factory did not set the expected read timeout on the helper instance", + expectedReadTimeout, ((LoggingRequestHelperImpl)helper).getLogSearchReadTimeoutInMilliseconds()); + mockSupport.verifyAll(); } @@ -121,6 +140,9 @@ public class LoggingRequestHelperFactoryImplTest { ServiceComponentHost serviceComponentHostMock = mockSupport.createMock(ServiceComponentHost.class); + Configuration serverConfigMock = + mockSupport.createMock(Configuration.class); + Map<String, String> testProperties = new HashMap<String, String>(); testProperties.put("logsearch_ui_port", expectedPortNumber); @@ -141,6 +163,9 @@ public class LoggingRequestHelperFactoryImplTest { LoggingRequestHelperFactory helperFactory = new LoggingRequestHelperFactoryImpl(); + // set the configuration mock using the concrete type + ((LoggingRequestHelperFactoryImpl)helperFactory).setAmbariServerConfiguration(serverConfigMock); + LoggingRequestHelper helper = helperFactory.getHelper(controllerMock, expectedClusterName); @@ -168,6 +193,9 @@ public class LoggingRequestHelperFactoryImplTest { Config logSearchEnvConfig = mockSupport.createMock(Config.class); + Configuration serverConfigMock = + mockSupport.createMock(Configuration.class); + expect(controllerMock.getClusters()).andReturn(clustersMock).atLeastOnce(); expect(clustersMock.getCluster(expectedClusterName)).andReturn(clusterMock).atLeastOnce(); expect(clusterMock.getDesiredConfigByType("logsearch-env")).andReturn(logSearchEnvConfig).atLeastOnce(); @@ -179,6 +207,9 @@ public class LoggingRequestHelperFactoryImplTest { LoggingRequestHelperFactory helperFactory = new LoggingRequestHelperFactoryImpl(); + // set the configuration mock using the concrete type + ((LoggingRequestHelperFactoryImpl)helperFactory).setAmbariServerConfiguration(serverConfigMock); + LoggingRequestHelper helper = helperFactory.getHelper(controllerMock, expectedClusterName); @@ -203,6 +234,9 @@ public class LoggingRequestHelperFactoryImplTest { Cluster clusterMock = mockSupport.createMock(Cluster.class); + Configuration serverConfigMock = + mockSupport.createMock(Configuration.class); + expect(controllerMock.getClusters()).andReturn(clustersMock).atLeastOnce(); expect(clustersMock.getCluster(expectedClusterName)).andReturn(clusterMock).atLeastOnce(); // do not include LOGSEARCH in this map, to simulate the case when LogSearch is not deployed @@ -213,6 +247,36 @@ public class LoggingRequestHelperFactoryImplTest { LoggingRequestHelperFactory helperFactory = new LoggingRequestHelperFactoryImpl(); + // set the configuration mock using the concrete type + ((LoggingRequestHelperFactoryImpl)helperFactory).setAmbariServerConfiguration(serverConfigMock); + + LoggingRequestHelper helper = + helperFactory.getHelper(controllerMock, expectedClusterName); + + assertNull("LoggingRequestHelper object returned by the factory should have been null", + helper); + + mockSupport.verifyAll(); + } + + @Test + public void testHelperCreationWithNoAmbariServerConfiguration() throws Exception { + final String expectedClusterName = "testclusterone"; + + EasyMockSupport mockSupport = new EasyMockSupport(); + + AmbariManagementController controllerMock = + mockSupport.createMock(AmbariManagementController.class); + + mockSupport.replayAll(); + + LoggingRequestHelperFactory helperFactory = + new LoggingRequestHelperFactoryImpl(); + + // set the configuration mock using the concrete type + // set the configuration object to null, to simulate an error in dependency injection + ((LoggingRequestHelperFactoryImpl)helperFactory).setAmbariServerConfiguration(null); + LoggingRequestHelper helper = helperFactory.getHelper(controllerMock, expectedClusterName); http://git-wip-us.apache.org/repos/asf/ambari/blob/af6aba67/ambari-server/src/test/java/org/apache/ambari/server/controller/logging/LoggingRequestHelperImplTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/logging/LoggingRequestHelperImplTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/logging/LoggingRequestHelperImplTest.java index 3129f6e..654c02d 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/controller/logging/LoggingRequestHelperImplTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/logging/LoggingRequestHelperImplTest.java @@ -105,6 +105,9 @@ public class LoggingRequestHelperImplTest { "{\"name\":\"WARN\",\"value\":\"41\"},{\"name\":\"INFO\",\"value\":\"186\"},{\"name\":\"DEBUG\",\"value\":\"0\"}," + "{\"name\":\"TRACE\",\"value\":\"0\"}]}"; + private static final String TEST_JSON_INPUT_NULL_LOG_LIST = + "{\"startIndex\":0,\"pageSize\":0,\"totalCount\":0,\"resultSize\":0,\"sortType\":null,\"sortBy\":null,\"queryTimeMS\":1479850014987,\"logList\":null,\"listSize\":0}"; + private final String EXPECTED_HOST_NAME = "c6401.ambari.apache.org"; @@ -471,6 +474,87 @@ public class LoggingRequestHelperImplTest { assertEquals("Response did not include the expected file name", "/var/log/hadoop/hdfs/hadoop-hdfs-namenode-c6401.ambari.apache.org.log", result.iterator().next()); + + mockSupport.verifyAll(); + } + + @Test + public void testLogFileNameRequestWithNullLogList() throws Exception { + final String expectedComponentName = "hdfs_namenode"; + + EasyMockSupport mockSupport = + new EasyMockSupport(); + + CredentialStoreService credentialStoreServiceMock = + mockSupport.createMock(CredentialStoreService.class); + + Cluster clusterMock = + mockSupport.createMock(Cluster.class); + + LoggingRequestHelperImpl.NetworkConnection networkConnectionMock = + mockSupport.createMock(LoggingRequestHelperImpl.NetworkConnection.class); + + Config adminPropertiesConfigMock = + mockSupport.createMock(Config.class); + + Map<String, String> testConfigProperties = + new HashMap<String, String>(); + testConfigProperties.put("logsearch_admin_username", "admin-user"); + testConfigProperties.put("logsearch_admin_password", "admin-pwd"); + testConfigProperties = Collections.unmodifiableMap(testConfigProperties); + + Capture<HttpURLConnection> captureURLConnection = new Capture<HttpURLConnection>(); + Capture<HttpURLConnection> captureURLConnectionForAuthentication = new Capture<HttpURLConnection>(); + + expect(clusterMock.getDesiredConfigByType("logsearch-admin-json")).andReturn(adminPropertiesConfigMock).atLeastOnce(); + expect(adminPropertiesConfigMock.getProperties()).andReturn(testConfigProperties).atLeastOnce(); + expect(networkConnectionMock.readQueryResponseFromServer(capture(captureURLConnection))).andReturn(new StringBuffer(TEST_JSON_INPUT_NULL_LOG_LIST)).atLeastOnce(); + + // expect that basic authentication is setup, with the expected encoded credentials + networkConnectionMock.setupBasicAuthentication(capture(captureURLConnectionForAuthentication), eq(EXPECTED_ENCODED_CREDENTIALS)); + + mockSupport.replayAll(); + + LoggingRequestHelper helper = + new LoggingRequestHelperImpl(EXPECTED_HOST_NAME, EXPECTED_PORT_NUMBER, EXPECTED_PROTOCOL, credentialStoreServiceMock, clusterMock, networkConnectionMock); + + // invoke query request + Set<String> result = + helper.sendGetLogFileNamesRequest(expectedComponentName, EXPECTED_HOST_NAME); + + // verify that the HttpURLConnection was created with the propert values + HttpURLConnection httpURLConnection = + captureURLConnection.getValue(); + + assertEquals("URLConnection did not have the correct hostname information", + EXPECTED_HOST_NAME, httpURLConnection.getURL().getHost()); + assertEquals("URLConnection did not have the correct port information", + EXPECTED_PORT_NUMBER, httpURLConnection.getURL().getPort() + ""); + assertEquals("URLConnection did not have the expected http protocol scheme", + "http", httpURLConnection.getURL().getProtocol()); + assertEquals("URLConnection did not have the expected method set", + "GET", httpURLConnection.getRequestMethod()); + + assertSame("HttpUrlConnection instances passed into NetworkConnection mock should have been the same instance", + httpURLConnection, captureURLConnectionForAuthentication.getValue()); + + final String resultQuery = + httpURLConnection.getURL().getQuery(); + + // verify that the query contains the three required parameters + assertTrue("host_name parameter was not included in query", + resultQuery.contains("host_name=c6401.ambari.apache.org")); + assertTrue("component_name parameter was not included in the query", + resultQuery.contains("component_name=" + expectedComponentName)); + assertTrue("pageSize parameter was not included in query", + resultQuery.contains("pageSize=1")); + + assertNotNull("Response object should not be null", + result); + assertEquals("Response Set was not of the expected size, expected an empty set", + 0, result.size()); + + mockSupport.verifyAll(); } /** http://git-wip-us.apache.org/repos/asf/ambari/blob/af6aba67/ambari-server/src/test/java/org/apache/ambari/server/controller/logging/UtilsTest.java ---------------------------------------------------------------------- diff --git a/ambari-server/src/test/java/org/apache/ambari/server/controller/logging/UtilsTest.java b/ambari-server/src/test/java/org/apache/ambari/server/controller/logging/UtilsTest.java index 63b46ac..60f4725 100644 --- a/ambari-server/src/test/java/org/apache/ambari/server/controller/logging/UtilsTest.java +++ b/ambari-server/src/test/java/org/apache/ambari/server/controller/logging/UtilsTest.java @@ -24,10 +24,10 @@ import static org.junit.Assert.assertSame; import java.util.concurrent.atomic.AtomicInteger; -import org.apache.log4j.Logger; import org.easymock.Capture; import org.easymock.EasyMockSupport; import org.junit.Test; +import org.slf4j.Logger; public class UtilsTest {