SLIDER-724 don't serve web content until AM is fully configured: tests to iterate until happy or timed out. Includes creation of better exceptions on failures
Project: http://git-wip-us.apache.org/repos/asf/incubator-slider/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-slider/commit/e654a0f2 Tree: http://git-wip-us.apache.org/repos/asf/incubator-slider/tree/e654a0f2 Diff: http://git-wip-us.apache.org/repos/asf/incubator-slider/diff/e654a0f2 Branch: refs/heads/feature/SLIDER-151_REST_API Commit: e654a0f27e1a53ed713745305f4dd446b8ef2cf8 Parents: bfc20d7 Author: Steve Loughran <[email protected]> Authored: Tue Dec 16 20:24:29 2014 +0000 Committer: Steve Loughran <[email protected]> Committed: Tue Dec 16 20:25:40 2014 +0000 ---------------------------------------------------------------------- .../standalone/TestStandaloneAgentWeb.groovy | 31 ++++--- .../apache/slider/test/SliderTestUtils.groovy | 89 ++++++++++++++++---- 2 files changed, 92 insertions(+), 28 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/e654a0f2/slider-core/src/test/groovy/org/apache/slider/agent/standalone/TestStandaloneAgentWeb.groovy ---------------------------------------------------------------------- diff --git a/slider-core/src/test/groovy/org/apache/slider/agent/standalone/TestStandaloneAgentWeb.groovy b/slider-core/src/test/groovy/org/apache/slider/agent/standalone/TestStandaloneAgentWeb.groovy index b2d29f3..577ad73 100644 --- a/slider-core/src/test/groovy/org/apache/slider/agent/standalone/TestStandaloneAgentWeb.groovy +++ b/slider-core/src/test/groovy/org/apache/slider/agent/standalone/TestStandaloneAgentWeb.groovy @@ -25,6 +25,7 @@ import org.apache.slider.agent.AgentMiniClusterTestBase import org.apache.slider.client.SliderClient import org.apache.slider.core.main.ServiceLauncher import org.apache.slider.server.appmaster.web.rest.RestPaths +import static org.apache.slider.server.appmaster.web.rest.RestPaths.*; import org.junit.Test import static org.apache.slider.server.appmaster.management.MetricsKeys.* @@ -52,8 +53,10 @@ class TestStandaloneAgentWeb extends AgentMiniClusterTestBase { ApplicationReport report = waitForClusterLive(client) def realappmaster = report.originalTrackingUrl - GET(realappmaster) - def metrics = GET(realappmaster, RestPaths.SYSTEM_METRICS) + execHttpRequest(30000) { + GET(realappmaster) + } + def metrics = GET(realappmaster, SYSTEM_METRICS) log.info metrics sleep(5000) @@ -61,21 +64,27 @@ class TestStandaloneAgentWeb extends AgentMiniClusterTestBase { GET(appmaster) - log.info GET(appmaster, RestPaths.SYSTEM_PING) - log.info GET(appmaster, RestPaths.SYSTEM_THREADS) - log.info GET(appmaster, RestPaths.SYSTEM_HEALTHCHECK) - log.info GET(appmaster, RestPaths.SYSTEM_METRICS_JSON) + log.info GET(appmaster, SYSTEM_PING) + log.info GET(appmaster, SYSTEM_THREADS) + log.info GET(appmaster, SYSTEM_HEALTHCHECK) + log.info GET(appmaster, SYSTEM_METRICS_JSON) - describe "Hadoop HTTP operations" + describe "Codahale operations" // now switch to the Hadoop URL connection, with SPNEGO escalation getWebPage(conf, appmaster) - getWebPage(conf, appmaster, RestPaths.SYSTEM_THREADS) - getWebPage(conf, appmaster, RestPaths.SYSTEM_HEALTHCHECK) - getWebPage(conf, appmaster, RestPaths.SYSTEM_METRICS_JSON) + getWebPage(conf, appmaster, SYSTEM_THREADS) + getWebPage(conf, appmaster, SYSTEM_HEALTHCHECK) + getWebPage(conf, appmaster, SYSTEM_METRICS_JSON) - log.info getWebPage(conf, realappmaster, RestPaths.SYSTEM_METRICS_JSON) + log.info getWebPage(conf, realappmaster, SYSTEM_METRICS_JSON) + // now some REST gets + describe "Application REST GETs" + + getWebPage(conf, appmaster, SLIDER_PATH_APPLICATION + LIVE_RESOURCES) + + } http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/e654a0f2/slider-core/src/test/groovy/org/apache/slider/test/SliderTestUtils.groovy ---------------------------------------------------------------------- diff --git a/slider-core/src/test/groovy/org/apache/slider/test/SliderTestUtils.groovy b/slider-core/src/test/groovy/org/apache/slider/test/SliderTestUtils.groovy index e612aa3..d3cbae0 100644 --- a/slider-core/src/test/groovy/org/apache/slider/test/SliderTestUtils.groovy +++ b/slider-core/src/test/groovy/org/apache/slider/test/SliderTestUtils.groovy @@ -23,18 +23,21 @@ import groovy.transform.CompileStatic import groovy.util.logging.Slf4j import org.apache.commons.httpclient.HttpClient import org.apache.commons.httpclient.MultiThreadedHttpConnectionManager +import org.apache.commons.httpclient.URI import org.apache.commons.httpclient.methods.GetMethod import org.apache.hadoop.conf.Configuration import org.apache.hadoop.fs.FileStatus import org.apache.hadoop.fs.FileSystem as HadoopFS import org.apache.hadoop.fs.Path import org.apache.hadoop.hdfs.web.URLConnectionFactory -import org.apache.hadoop.io.IOUtils +import org.apache.hadoop.net.NetUtils import org.apache.hadoop.service.ServiceStateException import org.apache.hadoop.util.Shell import org.apache.hadoop.yarn.api.records.ApplicationReport import org.apache.hadoop.yarn.conf.YarnConfiguration import org.apache.hadoop.registry.client.types.ServiceRecord +import org.apache.hadoop.yarn.webapp.ForbiddenException +import org.apache.hadoop.yarn.webapp.NotFoundException import org.apache.slider.api.ClusterDescription import org.apache.slider.api.ClusterNode import org.apache.slider.api.RoleKeys @@ -480,17 +483,44 @@ class SliderTestUtils extends Assert { def client = new HttpClient(new MultiThreadedHttpConnectionManager()); client.httpConnectionManager.params.connectionTimeout = 10000; GetMethod get = new GetMethod(url); + URI destURI = get.getURI() + assert destURI.port != 0 + assert destURI.host + get.followRedirects = true; - int resultCode = client.executeMethod(get); + int resultCode + try { + resultCode = client.executeMethod(get); + } catch (IOException e) { + throw NetUtils.wrapException(url, 0, null, 0, e) + } def body = get.responseBodyAsString + + uprateFaults(url, resultCode, body) + return body; + } + + /** + * uprate some faults + * @param url + * @param resultCode + * @param body + */ + public static void uprateFaults(String url, int resultCode, String body) { + + if (resultCode == 404) { + throw new NotFoundException(url) + } + if (resultCode == 401) { + throw new ForbiddenException(url) + } if (!(resultCode >= 200 && resultCode < 400)) { def message = "Request to $url failed with exit code $resultCode, body length ${body?.length()}:\n$body" log.error(message) - fail(message) + throw new IOException(message) } - return body; } /** @@ -508,7 +538,30 @@ class SliderTestUtils extends Assert { return getWebPage(conf, s) } - /** + /** + * Execute any of the http requests, swallowing exceptions until + * eventually they time out + * @param timeout + * @param operation + * @return + */ + public static String execHttpRequest(int timeout, Closure operation) { + Duration duration = new Duration(timeout).start() + Exception ex = new IOException("limit exceeded before starting"); + while (!duration.limitExceeded) { + try { + String result = operation(); + return result; + } catch (Exception e) { + ex = e; + sleep(1000) + } + } + // timeout + throw ex; + } + + /** * Fetches a web page asserting that the response code is between 200 and 400. * Will error on 400 and 500 series response codes and let 200 and 300 through. * @@ -523,32 +576,34 @@ class SliderTestUtils extends Assert { URLConnectionFactory connectionFactory = URLConnectionFactory .newDefaultURLConnectionFactory(conf); URL url = new URL(page) - HttpURLConnection conn = - (HttpURLConnection) connectionFactory.openConnection(url); + assert url.port != 0 + HttpURLConnection conn = null; + int resultCode = 0 + def body = "" try { + conn = (HttpURLConnection) connectionFactory.openConnection(url); conn.instanceFollowRedirects = true; conn.connect() - int resultCode = conn.responseCode + resultCode = conn.responseCode InputStream stream = conn.errorStream; if (stream == null) { stream = conn.inputStream; } - def body = stream ? stream.text : "(no body)" - if (!(resultCode >= 200 && resultCode < 400)) { - def message = "Request to $url failed with ${conn.responseMessage}, body length ${body?.length()}:\n$body" - log.error(message) - fail(message) - } - return body; + body = stream ? stream.text : "(no body)" + } catch (IOException e) { + throw NetUtils.wrapException(url.toString(), 0, null, 0, e) } finally { conn?.disconnect() - } + uprateFaults(page, resultCode, body) + return body; } + + - /** +/** * Assert that a service operation succeeded * @param service service */
