SLIDER-768 refactoring tests to work even when back door is closed (i.e. 0.70 branch)
Project: http://git-wip-us.apache.org/repos/asf/incubator-slider/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-slider/commit/680d64dc Tree: http://git-wip-us.apache.org/repos/asf/incubator-slider/tree/680d64dc Diff: http://git-wip-us.apache.org/repos/asf/incubator-slider/diff/680d64dc Branch: refs/heads/develop Commit: 680d64dced565c68de398705072c192a6bb84c2e Parents: 181c5e9 Author: Steve Loughran <ste...@apache.org> Authored: Fri Jan 30 17:54:52 2015 +0000 Committer: Steve Loughran <ste...@apache.org> Committed: Fri Jan 30 17:54:52 2015 +0000 ---------------------------------------------------------------------- .../common/SliderXMLConfKeysForTesting.java | 1 + .../apache/slider/common/SliderXmlConfKeys.java | 16 +- .../server/appmaster/SliderAppMaster.java | 13 +- .../agent/rest/AbstractRestTestDelegate.groovy | 46 +++ .../agent/rest/JerseyTestDelegates.groovy | 16 +- .../agent/rest/LowLevelRestTestDelegates.groovy | 324 +++++++++++++++++++ .../rest/RestAPIClientTestDelegates.groovy | 248 ++++++++++++++ .../slider/agent/rest/RestTestDelegates.groovy | 322 ------------------ .../rest/SliderRestClientTestDelegates.groovy | 250 -------------- .../slider/agent/rest/TestStandaloneREST.groovy | 50 +-- .../funtest/lifecycle/AgentWebPagesIT.groovy | 66 ++-- 11 files changed, 707 insertions(+), 645 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/680d64dc/slider-core/src/main/java/org/apache/slider/common/SliderXMLConfKeysForTesting.java ---------------------------------------------------------------------- diff --git a/slider-core/src/main/java/org/apache/slider/common/SliderXMLConfKeysForTesting.java b/slider-core/src/main/java/org/apache/slider/common/SliderXMLConfKeysForTesting.java index 0a7f292..1e3cf64 100644 --- a/slider-core/src/main/java/org/apache/slider/common/SliderXMLConfKeysForTesting.java +++ b/slider-core/src/main/java/org/apache/slider/common/SliderXMLConfKeysForTesting.java @@ -73,4 +73,5 @@ public interface SliderXMLConfKeysForTesting { * Local path to AM keytab: {@value} */ String KEY_TEST_AM_KEYTAB = "slider.test.am.keytab.local"; + } http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/680d64dc/slider-core/src/main/java/org/apache/slider/common/SliderXmlConfKeys.java ---------------------------------------------------------------------- diff --git a/slider-core/src/main/java/org/apache/slider/common/SliderXmlConfKeys.java b/slider-core/src/main/java/org/apache/slider/common/SliderXmlConfKeys.java index 0d1121d..712b821 100644 --- a/slider-core/src/main/java/org/apache/slider/common/SliderXmlConfKeys.java +++ b/slider-core/src/main/java/org/apache/slider/common/SliderXmlConfKeys.java @@ -145,5 +145,19 @@ public interface SliderXmlConfKeys { /** * Flag to enable the insecure AM filter: {@value} */ - String X_DEV_INSECURE_WS = "slider.dev.ws.insecure"; + String X_DEV_INSECURE_WS = "slider.feature.ws.insecure"; + + /** + * Flag to indicate the insecure AM filter is enabled by default: {@value}. + */ + boolean X_DEV_INSECURE_DEFAULT = true; + + + /** + * Flag to indicate the insecure AM filter is required: {@value}. + * When Slider switches to being Hadoop 2.7+ only, this flag + * can be set to false + */ + boolean X_DEV_INSECURE_REQUIRED = true; + } http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/680d64dc/slider-core/src/main/java/org/apache/slider/server/appmaster/SliderAppMaster.java ---------------------------------------------------------------------- diff --git a/slider-core/src/main/java/org/apache/slider/server/appmaster/SliderAppMaster.java b/slider-core/src/main/java/org/apache/slider/server/appmaster/SliderAppMaster.java index 2629a4d..9f0a357 100644 --- a/slider-core/src/main/java/org/apache/slider/server/appmaster/SliderAppMaster.java +++ b/slider-core/src/main/java/org/apache/slider/server/appmaster/SliderAppMaster.java @@ -83,7 +83,7 @@ import org.apache.slider.api.proto.Messages; import org.apache.slider.api.proto.SliderClusterAPI; import org.apache.slider.common.SliderExitCodes; import org.apache.slider.common.SliderKeys; -import org.apache.slider.common.SliderXmlConfKeys; +import static org.apache.slider.common.SliderXmlConfKeys.*; import org.apache.slider.common.params.AbstractActionArgs; import org.apache.slider.common.params.SliderAMArgs; import org.apache.slider.common.params.SliderAMCreateAction; @@ -692,9 +692,9 @@ public class SliderAppMaster extends AbstractSliderLaunchedService if (securityEnabled) { // fix up the ACLs if they are not set - String acls = getConfig().get(SliderXmlConfKeys.KEY_PROTOCOL_ACL); + String acls = getConfig().get(KEY_PROTOCOL_ACL); if (acls == null) { - getConfig().set(SliderXmlConfKeys.KEY_PROTOCOL_ACL, "*"); + getConfig().set(KEY_PROTOCOL_ACL, "*"); } } //bring up the Slider RPC service @@ -1138,7 +1138,8 @@ public class SliderAppMaster extends AbstractSliderLaunchedService // This is here until YARN supports proxy & redirect operations // on verbs other than GET, and is only supported for testing - if (serviceConf.getBoolean(SliderXmlConfKeys.X_DEV_INSECURE_WS, false)) { + if (X_DEV_INSECURE_REQUIRED && serviceConf.getBoolean(X_DEV_INSECURE_WS, + X_DEV_INSECURE_DEFAULT)) { log.warn("Insecure filter enabled: REST operations are unauthenticated"); amFilterName = InsecureAmFilterInitializer.NAME; } @@ -1500,11 +1501,11 @@ public class SliderAppMaster extends AbstractSliderLaunchedService boolean authorization = getConfig().getBoolean( CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHORIZATION, false); - String acls = getConfig().get(SliderXmlConfKeys.KEY_PROTOCOL_ACL); + String acls = getConfig().get(KEY_PROTOCOL_ACL); if (authorization && SliderUtils.isUnset(acls)) { throw new BadConfigException("Application has IPC authorization enabled in " + CommonConfigurationKeysPublic.HADOOP_SECURITY_AUTHORIZATION + - " but no ACLs in " + SliderXmlConfKeys.KEY_PROTOCOL_ACL); + " but no ACLs in " + KEY_PROTOCOL_ACL); } } http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/680d64dc/slider-core/src/test/groovy/org/apache/slider/agent/rest/AbstractRestTestDelegate.groovy ---------------------------------------------------------------------- diff --git a/slider-core/src/test/groovy/org/apache/slider/agent/rest/AbstractRestTestDelegate.groovy b/slider-core/src/test/groovy/org/apache/slider/agent/rest/AbstractRestTestDelegate.groovy new file mode 100644 index 0000000..15026e4 --- /dev/null +++ b/slider-core/src/test/groovy/org/apache/slider/agent/rest/AbstractRestTestDelegate.groovy @@ -0,0 +1,46 @@ +/* + * 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.slider.agent.rest + +import org.apache.slider.test.SliderTestUtils + +/** + * Base class for anything we want common to all + */ +abstract class AbstractRestTestDelegate extends SliderTestUtils { + public static final String TEST_GLOBAL_OPTION = "test.global.option" + public static final String TEST_GLOBAL_OPTION_PRESENT = "present" + public final boolean enableComplexVerbs + + AbstractRestTestDelegate(boolean enableComplexVerbs) { + this.enableComplexVerbs = enableComplexVerbs + } + + + public abstract void testSuiteGetOperations() + + public abstract void testSuiteComplexVerbs() + + public void testSuiteAll() { + testSuiteGetOperations() + if (enableComplexVerbs) { + testSuiteComplexVerbs() + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/680d64dc/slider-core/src/test/groovy/org/apache/slider/agent/rest/JerseyTestDelegates.groovy ---------------------------------------------------------------------- diff --git a/slider-core/src/test/groovy/org/apache/slider/agent/rest/JerseyTestDelegates.groovy b/slider-core/src/test/groovy/org/apache/slider/agent/rest/JerseyTestDelegates.groovy index 1ff7eae..4a4fa7f 100644 --- a/slider-core/src/test/groovy/org/apache/slider/agent/rest/JerseyTestDelegates.groovy +++ b/slider-core/src/test/groovy/org/apache/slider/agent/rest/JerseyTestDelegates.groovy @@ -36,7 +36,6 @@ import org.apache.slider.core.conf.ConfTreeOperations import org.apache.slider.core.restclient.HttpVerb import org.apache.slider.server.appmaster.web.rest.application.ApplicationResource import org.apache.slider.api.types.PingResource -import org.apache.slider.test.SliderTestUtils import javax.ws.rs.core.MediaType @@ -48,15 +47,15 @@ import static org.apache.slider.server.appmaster.web.rest.RestPaths.* /** * This class contains parts of tests that can be run * against a deployed AM: local or remote. - * It uses Jersey ... and must be passed a client that is either secure - * or not + * It uses Jersey WebResource... and must be passed a client + * that is either secure or not + * {@link WebResource} + * * */ @CompileStatic @Slf4j -class JerseyTestDelegates extends SliderTestUtils { - public static final String TEST_GLOBAL_OPTION = "test.global.option" - public static final String TEST_GLOBAL_OPTION_PRESENT = "present" +class JerseyTestDelegates extends AbstractRestTestDelegate { final String appmaster; final String application; @@ -65,7 +64,9 @@ class JerseyTestDelegates extends SliderTestUtils { final WebResource appResource - JerseyTestDelegates(String appmaster, Client jersey) { + JerseyTestDelegates(String appmaster, Client jersey, + boolean enableComplexVerbs = true) { + super(enableComplexVerbs) this.jersey = jersey this.appmaster = appmaster application = appendToURL(appmaster, SLIDER_PATH_APPLICATION) @@ -473,4 +474,5 @@ class JerseyTestDelegates extends SliderTestUtils { public void testSuiteComplexVerbs() { testPing(); } + } http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/680d64dc/slider-core/src/test/groovy/org/apache/slider/agent/rest/LowLevelRestTestDelegates.groovy ---------------------------------------------------------------------- diff --git a/slider-core/src/test/groovy/org/apache/slider/agent/rest/LowLevelRestTestDelegates.groovy b/slider-core/src/test/groovy/org/apache/slider/agent/rest/LowLevelRestTestDelegates.groovy new file mode 100644 index 0000000..be3de8c --- /dev/null +++ b/slider-core/src/test/groovy/org/apache/slider/agent/rest/LowLevelRestTestDelegates.groovy @@ -0,0 +1,324 @@ +/* + * 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.slider.agent.rest + +import groovy.transform.CompileStatic +import groovy.util.logging.Slf4j +import org.apache.hadoop.yarn.webapp.NotFoundException +import org.apache.slider.api.StateValues +import org.apache.slider.api.types.ComponentInformation +import org.apache.slider.api.types.ContainerInformation +import org.apache.slider.core.conf.AggregateConf +import org.apache.slider.core.conf.ConfTree +import org.apache.slider.core.conf.ConfTreeOperations +import org.apache.slider.core.restclient.HttpOperationResponse +import org.apache.slider.core.restclient.HttpVerb +import org.apache.slider.core.restclient.UrlConnectionOperations +import org.apache.slider.server.appmaster.web.rest.application.ApplicationResource +import org.apache.slider.api.types.PingResource +import org.apache.slider.test.Outcome + +import javax.ws.rs.core.MediaType + +import static org.apache.slider.api.ResourceKeys.COMPONENT_INSTANCES +import static org.apache.slider.api.StatusKeys.* +import static org.apache.slider.common.SliderKeys.COMPONENT_AM +import static org.apache.slider.server.appmaster.web.rest.RestPaths.* + +/** + * Low-level operations + */ +@CompileStatic +@Slf4j +class LowLevelRestTestDelegates extends AbstractRestTestDelegate { + + private final String appmaster; + private final String application; + // flag to indicate complex verbs are enabled + + LowLevelRestTestDelegates(String appmaster, boolean enableComplexVerbs = true) { + super(enableComplexVerbs) + this.appmaster = appmaster + application = appendToURL(appmaster, SLIDER_PATH_APPLICATION) + } + + + public void testCodahaleOperations() throws Throwable { + describe "Codahale operations" + getWebPage(appmaster) + getWebPage(appmaster, SYSTEM_THREADS) + getWebPage(appmaster, SYSTEM_HEALTHCHECK) + getWebPage(appmaster, SYSTEM_PING) + getWebPage(appmaster, SYSTEM_METRICS_JSON) + } + + public void logCodahaleMetrics() { + // query Coda Hale metrics + log.info getWebPage(appmaster, SYSTEM_HEALTHCHECK) + log.info getWebPage(appmaster, SYSTEM_METRICS) + } + + + public void testMimeTypes() throws Throwable { + describe "Mime Types" + HttpOperationResponse response= executeGet( + appendToURL(appmaster, + SLIDER_PATH_APPLICATION, LIVE_RESOURCES)) + response.headers.each { key, val -> log.info("$key $val")} + log.info "Content type: ${response.contentType}" + assert response.contentType.contains(MediaType.APPLICATION_JSON_TYPE.toString()) + } + + + public void testLiveResources() throws Throwable { + describe "Live Resources" + ConfTreeOperations tree = fetchConfigTree(appmaster, LIVE_RESOURCES) + + log.info tree.toString() + def liveAM = tree.getComponent(COMPONENT_AM) + def desiredInstances = liveAM.getMandatoryOptionInt(COMPONENT_INSTANCES); + assert desiredInstances == + liveAM.getMandatoryOptionInt(COMPONENT_INSTANCES_ACTUAL) + + assert 1 == liveAM.getMandatoryOptionInt(COMPONENT_INSTANCES_STARTED) + assert 0 == liveAM.getMandatoryOptionInt(COMPONENT_INSTANCES_REQUESTING) + assert 0 == liveAM.getMandatoryOptionInt(COMPONENT_INSTANCES_FAILED) + assert 0 == liveAM.getMandatoryOptionInt(COMPONENT_INSTANCES_COMPLETED) + assert 0 == liveAM.getMandatoryOptionInt(COMPONENT_INSTANCES_RELEASING) + } + + public void testLiveContainers() throws Throwable { + describe "Application REST ${LIVE_CONTAINERS}" + + Map<String, ContainerInformation> containers = + fetchType(HashMap, appmaster, LIVE_CONTAINERS) + assert containers.size() == 1 + log.info "${containers}" + ContainerInformation amContainerInfo = + (ContainerInformation) containers.values()[0] + assert amContainerInfo.containerId + + def amContainerId = amContainerInfo.containerId + assert containers[amContainerId] + + assert amContainerInfo.component == COMPONENT_AM + assert amContainerInfo.createTime > 0 + assert amContainerInfo.exitCode == null + assert amContainerInfo.output == null + assert amContainerInfo.released == null + assert amContainerInfo.state == StateValues.STATE_LIVE + + describe "containers" + + ContainerInformation retrievedContainerInfo = + fetchType(ContainerInformation, appmaster, + LIVE_CONTAINERS + "/${amContainerId}") + assert retrievedContainerInfo.containerId == amContainerId + + // fetch missing + try { + def result = fetchType(ContainerInformation, appmaster, + LIVE_CONTAINERS + "/unknown") + fail("expected an error, got $result") + } catch (NotFoundException e) { + // expected + } + + + describe "components" + + Map<String, ComponentInformation> components = + fetchType(HashMap, appmaster, LIVE_COMPONENTS) + // two components + assert components.size() >= 1 + log.info "${components}" + + ComponentInformation amComponentInfo = + (ComponentInformation) components[COMPONENT_AM] + + ComponentInformation amFullInfo = fetchType( + ComponentInformation, + appmaster, + LIVE_COMPONENTS + "/${COMPONENT_AM}") + + assert amFullInfo.containers.size() == 1 + assert amFullInfo.containers[0] == amContainerId + + } + + /** + * Test the rest model. For this to work the cluster has to be configured + * with the global option + * @param appmaster + */ + public void testRESTModel() { + describe "model" + + assertPathServesList(appmaster, + MODEL, + ApplicationResource.MODEL_ENTRIES) + + def unresolvedConf = fetchType(AggregateConf, appmaster, MODEL_DESIRED) +// log.info "Unresolved \n$unresolvedConf" + def unresolvedAppConf = unresolvedConf.appConfOperations + + def sam = "slider-appmaster" + assert unresolvedAppConf.getComponentOpt(sam, + TEST_GLOBAL_OPTION, "") == "" + def resolvedConf = fetchType(AggregateConf, appmaster, MODEL_RESOLVED) +// log.info "Resolved \n$resolvedConf" + assert resolvedConf.appConfOperations.getComponentOpt( + sam, TEST_GLOBAL_OPTION, "") == TEST_GLOBAL_OPTION_PRESENT + + def unresolved = fetchTypeList(ConfTree, appmaster, + [MODEL_DESIRED_APPCONF, MODEL_DESIRED_RESOURCES]) + assert unresolved[MODEL_DESIRED_APPCONF].components[sam] + [TEST_GLOBAL_OPTION] == null + + + def resolved = fetchTypeList(ConfTree, appmaster, + [MODEL_RESOLVED_APPCONF, MODEL_RESOLVED_RESOURCES]) + assert resolved[MODEL_RESOLVED_APPCONF].components[sam] + [TEST_GLOBAL_OPTION] == + TEST_GLOBAL_OPTION_PRESENT + } + + /** + * Test the various ping operations + */ + public void testPing() { + // GET + String ping = appendToURL(appmaster, SLIDER_PATH_APPLICATION, ACTION_PING) + describe "ping to AM URL $appmaster, ping URL $ping" + def pinged = fetchType(PingResource, appmaster, ACTION_PING + "?body=hello") + log.info "Ping GET: $pinged" + + URL pingUrl = new URL(ping) + def message = "hello" + + // HEAD + pingAction(HttpVerb.HEAD, pingUrl, message) + + // Other verbs + pingAction(HttpVerb.POST, pingUrl, message) + pingAction(HttpVerb.PUT, pingUrl, message) + pingAction(HttpVerb.DELETE, pingUrl, message) + + } + + + private HttpOperationResponse pingAction( + HttpVerb verb, + URL pingUrl, + String payload) { + return pingAction(connectionOperations, verb, pingUrl, payload) + } + + private HttpOperationResponse pingAction( + UrlConnectionOperations ops, HttpVerb verb, URL pingUrl, String payload) { + def pinged + def outcome = ops.execHttpOperation( + verb, + pingUrl, + payload.bytes, + MediaType.TEXT_PLAIN) + byte[] bytes = outcome.data + if (verb.hasResponseBody()) { + assert bytes.length > 0, "0 bytes from ping $verb.verb" + pinged = deser(PingResource, bytes) + log.info "Ping $verb.verb: $pinged" + assert verb.verb == pinged.verb + } else { + assert bytes.length == + 0, "${bytes.length} bytes of data from ping $verb.verb" + } + return outcome + } + + /** + * Test the stop command. + * Important: once executed, the AM is no longer there. + * This must be the last test in the sequence. + */ + public void testStop() { + String target = appendToURL(appmaster, SLIDER_PATH_APPLICATION, ACTION_STOP) + describe "Stop URL $target" + URL targetUrl = new URL(target) + def outcome = connectionOperations.execHttpOperation( + HttpVerb.POST, + targetUrl, + new byte[0], + MediaType.TEXT_PLAIN) + log.info "Stopped: $outcome" + + // await the shutdown + sleep(1000) + + // now a ping is expected to fail + String ping = appendToURL(appmaster, SLIDER_PATH_APPLICATION, ACTION_PING) + URL pingUrl = new URL(ping) + + repeatUntilSuccess("probe for missing registry entry", + this.&probePingFailing, 30000, 500, + [url: ping], + true, + "AM failed to shut down") { + def pinged = fetchType( + PingResource, + appmaster, + ACTION_PING + "?body=hello") + fail("AM didn't shut down; Ping GET= $pinged") + } + + } + + /** + * Probe that spins until the url specified by "url") refuses + * connections + * @param args argument map + * @return the outcome + */ + Outcome probePingFailing(Map args) { + String ping = args["url"] + URL pingUrl = new URL(ping) + try { + def response = pingAction(HttpVerb.HEAD, pingUrl, "should not be running") + return Outcome.Retry + } catch (IOException e) { + // expected + return Outcome.Success + } + } + + + @Override + public void testSuiteGetOperations() { + + testCodahaleOperations() + testMimeTypes() + testLiveResources() + testLiveContainers(); + testRESTModel() + } + + @Override + public void testSuiteComplexVerbs() { + testPing(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/680d64dc/slider-core/src/test/groovy/org/apache/slider/agent/rest/RestAPIClientTestDelegates.groovy ---------------------------------------------------------------------- diff --git a/slider-core/src/test/groovy/org/apache/slider/agent/rest/RestAPIClientTestDelegates.groovy b/slider-core/src/test/groovy/org/apache/slider/agent/rest/RestAPIClientTestDelegates.groovy new file mode 100644 index 0000000..de89b8e --- /dev/null +++ b/slider-core/src/test/groovy/org/apache/slider/agent/rest/RestAPIClientTestDelegates.groovy @@ -0,0 +1,248 @@ +/* + * 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.slider.agent.rest + +import com.sun.jersey.api.client.Client +import com.sun.jersey.api.client.WebResource +import groovy.transform.CompileStatic +import groovy.util.logging.Slf4j +import org.apache.slider.api.StateValues +import org.apache.slider.api.types.ComponentInformation +import org.apache.slider.api.types.ContainerInformation +import org.apache.slider.client.rest.SliderApplicationAPI +import org.apache.slider.core.conf.ConfTree +import org.apache.slider.core.conf.ConfTreeOperations +import org.apache.slider.server.appmaster.web.rest.application.ApplicationResource + +import javax.ws.rs.core.MediaType + +import static org.apache.slider.api.ResourceKeys.COMPONENT_INSTANCES +import static org.apache.slider.api.StatusKeys.* +import static org.apache.slider.common.SliderKeys.COMPONENT_AM +import static org.apache.slider.server.appmaster.web.rest.RestPaths.* + +/** + * Uses the Slider Application API for the tests. + * {@link SliderApplicationAPI} + */ +@CompileStatic +@Slf4j +class RestAPIClientTestDelegates extends AbstractRestTestDelegate { + public static final String TEST_GLOBAL_OPTION = "test.global.option" + public static final String TEST_GLOBAL_OPTION_PRESENT = "present" + + final String appmaster; + final String application; + final Client jersey; + final SliderApplicationAPI appAPI; + + + RestAPIClientTestDelegates(String appmaster, Client jersey, + boolean enableComplexVerbs = true) { + super(enableComplexVerbs) + this.jersey = jersey + this.appmaster = appmaster + application = appendToURL(appmaster, SLIDER_PATH_APPLICATION) + WebResource amResource = jersey.resource(appmaster) + amResource.type(MediaType.APPLICATION_JSON) + appAPI = new SliderApplicationAPI(jersey, amResource) + } + + + public void testGetDesiredModel() throws Throwable { + appAPI.getDesiredModel() + appAPI.getDesiredAppconf() + appAPI.getDesiredYarnResources() + } + + public void testGetResolvedModel() throws Throwable { + appAPI.getResolvedModel() + appAPI.getResolvedAppconf() + appAPI.getResolvedYarnResources() + } + + + public void testLiveResources() throws Throwable { + describe "Live Resources" + + ConfTreeOperations tree = appAPI.getLiveYarnResources() + + log.info tree.toString() + def liveAM = tree.getComponent(COMPONENT_AM) + def desiredInstances = liveAM.getMandatoryOptionInt(COMPONENT_INSTANCES); + assert desiredInstances == + liveAM.getMandatoryOptionInt(COMPONENT_INSTANCES_ACTUAL) + + assert 1 == liveAM.getMandatoryOptionInt(COMPONENT_INSTANCES_STARTED) + assert 0 == liveAM.getMandatoryOptionInt(COMPONENT_INSTANCES_REQUESTING) + assert 0 == liveAM.getMandatoryOptionInt(COMPONENT_INSTANCES_FAILED) + assert 0 == liveAM.getMandatoryOptionInt(COMPONENT_INSTANCES_COMPLETED) + assert 0 == liveAM.getMandatoryOptionInt(COMPONENT_INSTANCES_RELEASING) + } + + public void testLiveContainers() throws Throwable { + describe "Application REST ${LIVE_CONTAINERS}" + + Map<String, ContainerInformation> containers = appAPI.enumContainers() + assert containers.size() == 1 + log.info "${containers}" + ContainerInformation amContainerInfo = + (ContainerInformation) containers.values()[0] + assert amContainerInfo.containerId + + def amContainerId = amContainerInfo.containerId + assert containers[amContainerId] + + assert amContainerInfo.component == COMPONENT_AM + assert amContainerInfo.createTime > 0 + assert amContainerInfo.exitCode == null + assert amContainerInfo.output == null + assert amContainerInfo.released == null + assert amContainerInfo.state == StateValues.STATE_LIVE + + describe "containers" + + ContainerInformation amContainerInfo2 = + appAPI.getContainer(amContainerId) + assert amContainerInfo2.containerId == amContainerId + + // fetch missing + try { + def result = appAPI.getContainer("unknown") + fail("expected an error, got $result") + } catch (FileNotFoundException e) { + // expected + } + + + describe "components" + + Map<String, ComponentInformation> components = + appAPI.enumComponents() + + // two components + assert components.size() >= 1 + log.info "${components}" + + ComponentInformation amComponentInfo = + (ComponentInformation) components[COMPONENT_AM] + + ComponentInformation amFullInfo = appAPI.getComponent(COMPONENT_AM) + + assert amFullInfo.containers.size() == 1 + assert amFullInfo.containers[0] == amContainerId + + } + + + /** + * Test the rest model. For this to work the cluster has to be configured + * with the global option + * @param appmaster + */ + public void testRESTModel() { + describe "model" + + assertPathServesList(appmaster, + MODEL, + ApplicationResource.MODEL_ENTRIES) + + def unresolvedConf = appAPI.getDesiredModel() +// log.info "Unresolved \n$unresolvedConf" + def unresolvedAppConf = unresolvedConf.appConfOperations + + def sam = "slider-appmaster" + assert unresolvedAppConf.getComponentOpt(sam, + TEST_GLOBAL_OPTION, "") == "" + def resolvedConf = appAPI.getResolvedModel() + assert resolvedConf.appConfOperations.getComponentOpt( + sam, TEST_GLOBAL_OPTION, "") == TEST_GLOBAL_OPTION_PRESENT + + def unresolved = fetchTypeList(ConfTree, appmaster, + [MODEL_DESIRED_APPCONF, MODEL_DESIRED_RESOURCES]) + assert unresolved[MODEL_DESIRED_APPCONF].components[sam] + [TEST_GLOBAL_OPTION] == null + + + + def resolvedAppconf = appAPI.getResolvedAppconf() + assert resolvedAppconf. + components[sam][TEST_GLOBAL_OPTION] == TEST_GLOBAL_OPTION_PRESENT + } + + public void testPing() { + // GET + describe "pinging" + + appAPI.ping("hello") + } + + + /** + * Test the stop command. + * Important: once executed, the AM is no longer there. + * This must be the last test in the sequence. + */ +/* + + public void testStop() { + String target = appendToURL(appmaster, SLIDER_PATH_APPLICATION, ACTION_STOP) + describe "Stop URL $target" + URL targetUrl = new URL(target) + def outcome = connectionOperations.execHttpOperation( + HttpVerb.POST, + targetUrl, + new byte[0], + MediaType.TEXT_PLAIN) + log.info "Stopped: $outcome" + + // await the shutdown + sleep(1000) + + // now a ping is expected to fail + String ping = appendToURL(appmaster, SLIDER_PATH_APPLICATION, ACTION_PING) + URL pingUrl = new URL(ping) + + repeatUntilSuccess("probe for missing registry entry", + this.&probePingFailing, 30000, 500, + [url: ping], + true, + "AM failed to shut down") { + def pinged = jFetchType(ACTION_PING + "?body=hello", + PingResource + ) + fail("AM didn't shut down; Ping GET= $pinged") + } + + } +*/ + + public void testSuiteGetOperations() { + + testGetDesiredModel() + testGetResolvedModel() + testLiveResources() + testLiveContainers(); + testRESTModel() + } + + public void testSuiteComplexVerbs() { + testPing(); + } +} http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/680d64dc/slider-core/src/test/groovy/org/apache/slider/agent/rest/RestTestDelegates.groovy ---------------------------------------------------------------------- diff --git a/slider-core/src/test/groovy/org/apache/slider/agent/rest/RestTestDelegates.groovy b/slider-core/src/test/groovy/org/apache/slider/agent/rest/RestTestDelegates.groovy deleted file mode 100644 index be0b3d8..0000000 --- a/slider-core/src/test/groovy/org/apache/slider/agent/rest/RestTestDelegates.groovy +++ /dev/null @@ -1,322 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.slider.agent.rest - -import groovy.transform.CompileStatic -import groovy.util.logging.Slf4j -import org.apache.hadoop.yarn.webapp.NotFoundException -import org.apache.slider.api.StateValues -import org.apache.slider.api.types.ComponentInformation -import org.apache.slider.api.types.ContainerInformation -import org.apache.slider.core.conf.AggregateConf -import org.apache.slider.core.conf.ConfTree -import org.apache.slider.core.conf.ConfTreeOperations -import org.apache.slider.core.restclient.HttpOperationResponse -import org.apache.slider.core.restclient.HttpVerb -import org.apache.slider.core.restclient.UrlConnectionOperations -import org.apache.slider.server.appmaster.web.rest.RestPaths -import org.apache.slider.server.appmaster.web.rest.application.ApplicationResource -import org.apache.slider.api.types.PingResource -import org.apache.slider.test.Outcome -import org.apache.slider.test.SliderTestUtils - -import javax.ws.rs.core.MediaType - -import static org.apache.slider.api.ResourceKeys.COMPONENT_INSTANCES -import static org.apache.slider.api.StatusKeys.* -import static org.apache.slider.common.SliderKeys.COMPONENT_AM -import static org.apache.slider.server.appmaster.web.rest.RestPaths.* - -/** - * This class contains parts of tests that can be run - * against a deployed AM: local or remote - */ -@CompileStatic -@Slf4j -class RestTestDelegates extends SliderTestUtils { - public static final String TEST_GLOBAL_OPTION = "test.global.option" - public static final String TEST_GLOBAL_OPTION_PRESENT = "present" - - final String appmaster; - final String application; - - RestTestDelegates(String appmaster) { - this.appmaster = appmaster - application = appendToURL(appmaster, RestPaths.SLIDER_PATH_APPLICATION) - } - - - public void testCodahaleOperations() throws Throwable { - describe "Codahale operations" - getWebPage(appmaster) - getWebPage(appmaster, SYSTEM_THREADS) - getWebPage(appmaster, SYSTEM_HEALTHCHECK) - getWebPage(appmaster, SYSTEM_PING) - getWebPage(appmaster, SYSTEM_METRICS_JSON) - } - - public void logCodahaleMetrics() { - // query Coda Hale metrics - log.info getWebPage(appmaster, SYSTEM_HEALTHCHECK) - log.info getWebPage(appmaster, SYSTEM_METRICS) - } - - - public void testMimeTypes() throws Throwable { - describe "Mime Types" - HttpOperationResponse response= executeGet( - appendToURL(appmaster, - SLIDER_PATH_APPLICATION, LIVE_RESOURCES)) - response.headers.each { key, val -> log.info("$key $val")} - log.info "Content type: ${response.contentType}" - assert response.contentType.contains(MediaType.APPLICATION_JSON_TYPE.toString()) - } - - - public void testLiveResources() throws Throwable { - describe "Live Resources" - ConfTreeOperations tree = fetchConfigTree(appmaster, LIVE_RESOURCES) - - log.info tree.toString() - def liveAM = tree.getComponent(COMPONENT_AM) - def desiredInstances = liveAM.getMandatoryOptionInt(COMPONENT_INSTANCES); - assert desiredInstances == - liveAM.getMandatoryOptionInt(COMPONENT_INSTANCES_ACTUAL) - - assert 1 == liveAM.getMandatoryOptionInt(COMPONENT_INSTANCES_STARTED) - assert 0 == liveAM.getMandatoryOptionInt(COMPONENT_INSTANCES_REQUESTING) - assert 0 == liveAM.getMandatoryOptionInt(COMPONENT_INSTANCES_FAILED) - assert 0 == liveAM.getMandatoryOptionInt(COMPONENT_INSTANCES_COMPLETED) - assert 0 == liveAM.getMandatoryOptionInt(COMPONENT_INSTANCES_RELEASING) - } - - public void testLiveContainers() throws Throwable { - describe "Application REST ${LIVE_CONTAINERS}" - - Map<String, ContainerInformation> containers = - fetchType(HashMap, appmaster, LIVE_CONTAINERS) - assert containers.size() == 1 - log.info "${containers}" - ContainerInformation amContainerInfo = - (ContainerInformation) containers.values()[0] - assert amContainerInfo.containerId - - def amContainerId = amContainerInfo.containerId - assert containers[amContainerId] - - assert amContainerInfo.component == COMPONENT_AM - assert amContainerInfo.createTime > 0 - assert amContainerInfo.exitCode == null - assert amContainerInfo.output == null - assert amContainerInfo.released == null - assert amContainerInfo.state == StateValues.STATE_LIVE - - describe "containers" - - ContainerInformation retrievedContainerInfo = - fetchType(ContainerInformation, appmaster, - LIVE_CONTAINERS + "/${amContainerId}") - assert retrievedContainerInfo.containerId == amContainerId - - // fetch missing - try { - def result = fetchType(ContainerInformation, appmaster, - LIVE_CONTAINERS + "/unknown") - fail("expected an error, got $result") - } catch (NotFoundException e) { - // expected - } - - - describe "components" - - Map<String, ComponentInformation> components = - fetchType(HashMap, appmaster, LIVE_COMPONENTS) - // two components - assert components.size() >= 1 - log.info "${components}" - - ComponentInformation amComponentInfo = - (ComponentInformation) components[COMPONENT_AM] - - ComponentInformation amFullInfo = fetchType( - ComponentInformation, - appmaster, - LIVE_COMPONENTS + "/${COMPONENT_AM}") - - assert amFullInfo.containers.size() == 1 - assert amFullInfo.containers[0] == amContainerId - - } - - /** - * Test the rest model. For this to work the cluster has to be configured - * with the global option - * @param appmaster - */ - public void testRESTModel() { - describe "model" - - assertPathServesList(appmaster, - MODEL, - ApplicationResource.MODEL_ENTRIES) - - def unresolvedConf = fetchType(AggregateConf, appmaster, MODEL_DESIRED) -// log.info "Unresolved \n$unresolvedConf" - def unresolvedAppConf = unresolvedConf.appConfOperations - - def sam = "slider-appmaster" - assert unresolvedAppConf.getComponentOpt(sam, - TEST_GLOBAL_OPTION, "") == "" - def resolvedConf = fetchType(AggregateConf, appmaster, MODEL_RESOLVED) -// log.info "Resolved \n$resolvedConf" - assert resolvedConf.appConfOperations.getComponentOpt( - sam, TEST_GLOBAL_OPTION, "") == TEST_GLOBAL_OPTION_PRESENT - - def unresolved = fetchTypeList(ConfTree, appmaster, - [MODEL_DESIRED_APPCONF, MODEL_DESIRED_RESOURCES]) - assert unresolved[MODEL_DESIRED_APPCONF].components[sam] - [TEST_GLOBAL_OPTION] == null - - - def resolved = fetchTypeList(ConfTree, appmaster, - [MODEL_RESOLVED_APPCONF, MODEL_RESOLVED_RESOURCES]) - assert resolved[MODEL_RESOLVED_APPCONF].components[sam] - [TEST_GLOBAL_OPTION] == - TEST_GLOBAL_OPTION_PRESENT - } - - public void testPing() { - // GET - String ping = appendToURL(appmaster, SLIDER_PATH_APPLICATION, ACTION_PING) - describe "ping to AM URL $appmaster, ping URL $ping" - def pinged = fetchType(PingResource, appmaster, ACTION_PING + "?body=hello") - log.info "Ping GET: $pinged" - - URL pingUrl = new URL(ping) - def message = "hello" - - // HEAD - pingAction(HttpVerb.HEAD, pingUrl, message) - - // Other verbs - pingAction(HttpVerb.POST, pingUrl, message) - pingAction(HttpVerb.PUT, pingUrl, message) - pingAction(HttpVerb.DELETE, pingUrl, message) - - } - - - private HttpOperationResponse pingAction( - HttpVerb verb, - URL pingUrl, - String payload) { - return pingAction(connectionOperations, verb, pingUrl, payload) - } - - private HttpOperationResponse pingAction( - UrlConnectionOperations ops, HttpVerb verb, URL pingUrl, String payload) { - def pinged - def outcome = ops.execHttpOperation( - verb, - pingUrl, - payload.bytes, - MediaType.TEXT_PLAIN) - byte[] bytes = outcome.data - if (verb.hasResponseBody()) { - assert bytes.length > 0, "0 bytes from ping $verb.verb" - pinged = deser(PingResource, bytes) - log.info "Ping $verb.verb: $pinged" - assert verb.verb == pinged.verb - } else { - assert bytes.length == - 0, "${bytes.length} bytes of data from ping $verb.verb" - } - return outcome - } - - /** - * Test the stop command. - * Important: once executed, the AM is no longer there. - * This must be the last test in the sequence. - */ - public void testStop() { - String target = appendToURL(appmaster, SLIDER_PATH_APPLICATION, ACTION_STOP) - describe "Stop URL $target" - URL targetUrl = new URL(target) - def outcome = connectionOperations.execHttpOperation( - HttpVerb.POST, - targetUrl, - new byte[0], - MediaType.TEXT_PLAIN) - log.info "Stopped: $outcome" - - // await the shutdown - sleep(1000) - - // now a ping is expected to fail - String ping = appendToURL(appmaster, SLIDER_PATH_APPLICATION, ACTION_PING) - URL pingUrl = new URL(ping) - - repeatUntilSuccess("probe for missing registry entry", - this.&probePingFailing, 30000, 500, - [url: ping], - true, - "AM failed to shut down") { - def pinged = fetchType( - PingResource, - appmaster, - ACTION_PING + "?body=hello") - fail("AM didn't shut down; Ping GET= $pinged") - } - - } - - /** - * Probe that spins until the url specified by "url") refuses - * connections - * @param args argument map - * @return the outcome - */ - Outcome probePingFailing(Map args) { - String ping = args["url"] - URL pingUrl = new URL(ping) - try { - def response = pingAction(HttpVerb.HEAD, pingUrl, "should not be running") - return Outcome.Retry - } catch (IOException e) { - // expected - return Outcome.Success - } - } - - - public void testSuiteGetOperations() { - - testCodahaleOperations() - testMimeTypes() - testLiveResources() - testLiveContainers(); - testRESTModel() - } - - public void testSuiteComplexVerbs() { - testPing(); - } -} http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/680d64dc/slider-core/src/test/groovy/org/apache/slider/agent/rest/SliderRestClientTestDelegates.groovy ---------------------------------------------------------------------- diff --git a/slider-core/src/test/groovy/org/apache/slider/agent/rest/SliderRestClientTestDelegates.groovy b/slider-core/src/test/groovy/org/apache/slider/agent/rest/SliderRestClientTestDelegates.groovy deleted file mode 100644 index 95943f4..0000000 --- a/slider-core/src/test/groovy/org/apache/slider/agent/rest/SliderRestClientTestDelegates.groovy +++ /dev/null @@ -1,250 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.slider.agent.rest - -import com.sun.jersey.api.client.Client -import com.sun.jersey.api.client.WebResource -import groovy.transform.CompileStatic -import groovy.util.logging.Slf4j -import org.apache.slider.api.StateValues -import org.apache.slider.api.types.ComponentInformation -import org.apache.slider.api.types.ContainerInformation -import org.apache.slider.client.rest.SliderApplicationAPI -import org.apache.slider.core.conf.ConfTree -import org.apache.slider.core.conf.ConfTreeOperations -import org.apache.slider.server.appmaster.web.rest.application.ApplicationResource -import org.apache.slider.test.SliderTestUtils - -import javax.ws.rs.core.MediaType - -import static org.apache.slider.api.ResourceKeys.COMPONENT_INSTANCES -import static org.apache.slider.api.StatusKeys.* -import static org.apache.slider.common.SliderKeys.COMPONENT_AM -import static org.apache.slider.server.appmaster.web.rest.RestPaths.* - -/** - * This class contains parts of tests that can be run - * against a deployed AM: local or remote. - * It uses Jersey ... and must be passed a client that is either secure - * or not - * - */ -@CompileStatic -@Slf4j -class SliderRestClientTestDelegates extends SliderTestUtils { - public static final String TEST_GLOBAL_OPTION = "test.global.option" - public static final String TEST_GLOBAL_OPTION_PRESENT = "present" - - final String appmaster; - final String application; - final Client jersey; - final SliderApplicationAPI appAPI; - - - SliderRestClientTestDelegates(String appmaster, Client jersey) { - this.jersey = jersey - this.appmaster = appmaster - application = appendToURL(appmaster, SLIDER_PATH_APPLICATION) - WebResource amResource = jersey.resource(appmaster) - amResource.type(MediaType.APPLICATION_JSON) - appAPI = new SliderApplicationAPI(jersey, amResource) - } - - - public void testGetDesiredModel() throws Throwable { - appAPI.getDesiredModel() - appAPI.getDesiredAppconf() - appAPI.getDesiredYarnResources() - } - - public void testGetResolvedModel() throws Throwable { - appAPI.getResolvedModel() - appAPI.getResolvedAppconf() - appAPI.getResolvedYarnResources() - } - - - public void testLiveResources() throws Throwable { - describe "Live Resources" - - ConfTreeOperations tree = appAPI.getLiveYarnResources() - - log.info tree.toString() - def liveAM = tree.getComponent(COMPONENT_AM) - def desiredInstances = liveAM.getMandatoryOptionInt(COMPONENT_INSTANCES); - assert desiredInstances == - liveAM.getMandatoryOptionInt(COMPONENT_INSTANCES_ACTUAL) - - assert 1 == liveAM.getMandatoryOptionInt(COMPONENT_INSTANCES_STARTED) - assert 0 == liveAM.getMandatoryOptionInt(COMPONENT_INSTANCES_REQUESTING) - assert 0 == liveAM.getMandatoryOptionInt(COMPONENT_INSTANCES_FAILED) - assert 0 == liveAM.getMandatoryOptionInt(COMPONENT_INSTANCES_COMPLETED) - assert 0 == liveAM.getMandatoryOptionInt(COMPONENT_INSTANCES_RELEASING) - } - - public void testLiveContainers() throws Throwable { - describe "Application REST ${LIVE_CONTAINERS}" - - Map<String, ContainerInformation> containers = appAPI.enumContainers() - assert containers.size() == 1 - log.info "${containers}" - ContainerInformation amContainerInfo = - (ContainerInformation) containers.values()[0] - assert amContainerInfo.containerId - - def amContainerId = amContainerInfo.containerId - assert containers[amContainerId] - - assert amContainerInfo.component == COMPONENT_AM - assert amContainerInfo.createTime > 0 - assert amContainerInfo.exitCode == null - assert amContainerInfo.output == null - assert amContainerInfo.released == null - assert amContainerInfo.state == StateValues.STATE_LIVE - - describe "containers" - - ContainerInformation amContainerInfo2 = - appAPI.getContainer(amContainerId) - assert amContainerInfo2.containerId == amContainerId - - // fetch missing - try { - def result = appAPI.getContainer("unknown") - fail("expected an error, got $result") - } catch (FileNotFoundException e) { - // expected - } - - - describe "components" - - Map<String, ComponentInformation> components = - appAPI.enumComponents() - - // two components - assert components.size() >= 1 - log.info "${components}" - - ComponentInformation amComponentInfo = - (ComponentInformation) components[COMPONENT_AM] - - ComponentInformation amFullInfo = appAPI.getComponent(COMPONENT_AM) - - assert amFullInfo.containers.size() == 1 - assert amFullInfo.containers[0] == amContainerId - - } - - - /** - * Test the rest model. For this to work the cluster has to be configured - * with the global option - * @param appmaster - */ - public void testRESTModel() { - describe "model" - - assertPathServesList(appmaster, - MODEL, - ApplicationResource.MODEL_ENTRIES) - - def unresolvedConf = appAPI.getDesiredModel() -// log.info "Unresolved \n$unresolvedConf" - def unresolvedAppConf = unresolvedConf.appConfOperations - - def sam = "slider-appmaster" - assert unresolvedAppConf.getComponentOpt(sam, - TEST_GLOBAL_OPTION, "") == "" - def resolvedConf = appAPI.getResolvedModel() - assert resolvedConf.appConfOperations.getComponentOpt( - sam, TEST_GLOBAL_OPTION, "") == TEST_GLOBAL_OPTION_PRESENT - - def unresolved = fetchTypeList(ConfTree, appmaster, - [MODEL_DESIRED_APPCONF, MODEL_DESIRED_RESOURCES]) - assert unresolved[MODEL_DESIRED_APPCONF].components[sam] - [TEST_GLOBAL_OPTION] == null - - - - def resolvedAppconf = appAPI.getResolvedAppconf() - assert resolvedAppconf. - components[sam][TEST_GLOBAL_OPTION] == TEST_GLOBAL_OPTION_PRESENT - } - - public void testPing() { - // GET - describe "pinging" - - appAPI.ping("hello") - } - - - /** - * Test the stop command. - * Important: once executed, the AM is no longer there. - * This must be the last test in the sequence. - */ -/* - - public void testStop() { - String target = appendToURL(appmaster, SLIDER_PATH_APPLICATION, ACTION_STOP) - describe "Stop URL $target" - URL targetUrl = new URL(target) - def outcome = connectionOperations.execHttpOperation( - HttpVerb.POST, - targetUrl, - new byte[0], - MediaType.TEXT_PLAIN) - log.info "Stopped: $outcome" - - // await the shutdown - sleep(1000) - - // now a ping is expected to fail - String ping = appendToURL(appmaster, SLIDER_PATH_APPLICATION, ACTION_PING) - URL pingUrl = new URL(ping) - - repeatUntilSuccess("probe for missing registry entry", - this.&probePingFailing, 30000, 500, - [url: ping], - true, - "AM failed to shut down") { - def pinged = jFetchType(ACTION_PING + "?body=hello", - PingResource - ) - fail("AM didn't shut down; Ping GET= $pinged") - } - - } -*/ - - public void testSuiteGetOperations() { - - testGetDesiredModel() - testGetResolvedModel() - testLiveResources() - testLiveContainers(); - testRESTModel() - } - - public void testSuiteComplexVerbs() { - testPing(); - } -} http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/680d64dc/slider-core/src/test/groovy/org/apache/slider/agent/rest/TestStandaloneREST.groovy ---------------------------------------------------------------------- diff --git a/slider-core/src/test/groovy/org/apache/slider/agent/rest/TestStandaloneREST.groovy b/slider-core/src/test/groovy/org/apache/slider/agent/rest/TestStandaloneREST.groovy index 3c3dd52..ab5f156 100644 --- a/slider-core/src/test/groovy/org/apache/slider/agent/rest/TestStandaloneREST.groovy +++ b/slider-core/src/test/groovy/org/apache/slider/agent/rest/TestStandaloneREST.groovy @@ -33,12 +33,10 @@ import org.apache.hadoop.yarn.api.records.ApplicationReport import org.apache.slider.agent.AgentMiniClusterTestBase import org.apache.slider.client.SliderClient import org.apache.slider.client.rest.RestClientFactory -import org.apache.slider.client.rest.SliderApplicationAPI import org.apache.slider.common.SliderKeys import org.apache.slider.common.SliderXmlConfKeys import org.apache.slider.common.params.Arguments import org.apache.slider.core.main.ServiceLauncher -import org.apache.slider.core.registry.info.CustomRegistryConstants import org.apache.slider.core.restclient.HttpOperationResponse import org.junit.Test @@ -65,8 +63,8 @@ class TestStandaloneREST extends AgentMiniClusterTestBase { ServiceLauncher<SliderClient> launcher = createStandaloneAMWithArgs(clustername, [Arguments.ARG_OPTION, - RestTestDelegates.TEST_GLOBAL_OPTION, - RestTestDelegates.TEST_GLOBAL_OPTION_PRESENT], + AbstractRestTestDelegate.TEST_GLOBAL_OPTION, + AbstractRestTestDelegate.TEST_GLOBAL_OPTION_PRESENT], true, false) SliderClient client = launcher.service addToTeardown(client); @@ -96,9 +94,18 @@ class TestStandaloneREST extends AgentMiniClusterTestBase { log.info GET(proxyAM, SYSTEM_HEALTHCHECK) log.info GET(proxyAM, SYSTEM_METRICS_JSON) - def wsBackDoorRequired = conf.getBoolean( + /* + Is the back door required? If so, don't test complex verbs via the proxy + */ + def proxyComplexVerbs = !SliderXmlConfKeys.X_DEV_INSECURE_REQUIRED + + /* + * Only do direct complex verbs if the no back door is needed, or if + * it is enabled + */ + def directComplexVerbs = proxyComplexVerbs || SLIDER_CONFIG.getBoolean( SliderXmlConfKeys.X_DEV_INSECURE_WS, - true) + SliderXmlConfKeys.X_DEV_INSECURE_DEFAULT) describe "Direct response headers from AM Web resources" def liveResUrl = appendToURL(directAM, @@ -117,44 +124,37 @@ class TestStandaloneREST extends AgentMiniClusterTestBase { def ugiClient = createUGIJerseyClient(); describe "Proxy SliderRestClient Tests" - SliderRestClientTestDelegates proxySliderRestClient = - new SliderRestClientTestDelegates(proxyAM, ugiClient) + RestAPIClientTestDelegates proxySliderRestClient = + new RestAPIClientTestDelegates(proxyAM, ugiClient, proxyComplexVerbs) proxySliderRestClient.testSuiteGetOperations() describe "Direct SliderRestClient Tests" - SliderRestClientTestDelegates directSliderRestClient = - new SliderRestClientTestDelegates(directAM, ugiClient) - directSliderRestClient.testSuiteGetOperations() - directSliderRestClient.testSuiteComplexVerbs() - + RestAPIClientTestDelegates directSliderRestClient = + new RestAPIClientTestDelegates(directAM, ugiClient, directComplexVerbs) + directSliderRestClient.testSuiteAll() describe "Proxy Jersey Tests" JerseyTestDelegates proxyJerseyTests = - new JerseyTestDelegates(proxyAM, ugiClient) + new JerseyTestDelegates(proxyAM, ugiClient, proxyComplexVerbs) proxyJerseyTests.testSuiteGetOperations() describe "Direct Jersey Tests" JerseyTestDelegates directJerseyTests = new JerseyTestDelegates(directAM, ugiClient) - directJerseyTests.testSuiteGetOperations() - directJerseyTests.testSuiteComplexVerbs() + directJerseyTests.testSuiteAll() describe "Direct Tests" - RestTestDelegates direct = new RestTestDelegates(directAM) - direct.testSuiteGetOperations() - direct.testSuiteComplexVerbs() + LowLevelRestTestDelegates direct = + new LowLevelRestTestDelegates(directAM, directComplexVerbs) + direct.testSuiteAll() describe "Proxy Tests" - RestTestDelegates proxied = new RestTestDelegates(proxyAM) - proxied.testSuiteGetOperations() - if (!wsBackDoorRequired) { - // and via the proxy - proxied.testSuiteComplexVerbs() - } + LowLevelRestTestDelegates proxied = new LowLevelRestTestDelegates(proxyAM, proxyComplexVerbs) + proxied.testSuiteAll() // create the Rest client via the registry http://git-wip-us.apache.org/repos/asf/incubator-slider/blob/680d64dc/slider-funtest/src/test/groovy/org/apache/slider/funtest/lifecycle/AgentWebPagesIT.groovy ---------------------------------------------------------------------- diff --git a/slider-funtest/src/test/groovy/org/apache/slider/funtest/lifecycle/AgentWebPagesIT.groovy b/slider-funtest/src/test/groovy/org/apache/slider/funtest/lifecycle/AgentWebPagesIT.groovy index e6b8bc4..2cd13dd 100644 --- a/slider-funtest/src/test/groovy/org/apache/slider/funtest/lifecycle/AgentWebPagesIT.groovy +++ b/slider-funtest/src/test/groovy/org/apache/slider/funtest/lifecycle/AgentWebPagesIT.groovy @@ -25,8 +25,9 @@ import org.apache.hadoop.registry.client.api.RegistryOperations import org.apache.hadoop.security.UserGroupInformation import org.apache.hadoop.yarn.webapp.ForbiddenException import org.apache.slider.agent.rest.JerseyTestDelegates -import org.apache.slider.agent.rest.RestTestDelegates -import org.apache.slider.agent.rest.SliderRestClientTestDelegates +import org.apache.slider.agent.rest.AbstractRestTestDelegate +import org.apache.slider.agent.rest.LowLevelRestTestDelegates +import org.apache.slider.agent.rest.RestAPIClientTestDelegates import org.apache.slider.client.SliderClient import org.apache.slider.client.rest.RestClientFactory import org.apache.slider.common.SliderExitCodes @@ -69,21 +70,26 @@ public class AgentWebPagesIT extends AgentCommandTestBase // verify the ws/ path is open for all HTTP verbs def sliderConfiguration = ConfigHelper.loadSliderConfiguration(); - def wsBackDoorRequired = SLIDER_CONFIG.getBoolean( + /* + Is the back door required? If so, don't test complex verbs via the proxy + */ + def proxyComplexVerbs = !SliderXmlConfKeys.X_DEV_INSECURE_REQUIRED + + /* + * Only do direct complex verbs if the no back door is needed, or if + * it is enabled + */ + def directComplexVerbs = proxyComplexVerbs || SLIDER_CONFIG.getBoolean( SliderXmlConfKeys.X_DEV_INSECURE_WS, - true) - assert wsBackDoorRequired == - sliderConfiguration.getBoolean( - SliderXmlConfKeys.X_DEV_INSECURE_WS, - false) + SliderXmlConfKeys.X_DEV_INSECURE_DEFAULT) def clusterpath = buildClusterPath(CLUSTER) File launchReportFile = createTempJsonFile(); SliderShell shell = createTemplatedSliderApplication(CLUSTER, APP_TEMPLATE, APP_RESOURCE2, [ARG_OPTION, - RestTestDelegates.TEST_GLOBAL_OPTION, - RestTestDelegates.TEST_GLOBAL_OPTION_PRESENT], + AbstractRestTestDelegate.TEST_GLOBAL_OPTION, + AbstractRestTestDelegate.TEST_GLOBAL_OPTION_PRESENT], launchReportFile) logShell(shell) @@ -108,46 +114,38 @@ public class AgentWebPagesIT extends AgentCommandTestBase def directAM = report.origTrackingUrl; // now attempt direct-to-AM pings - RestTestDelegates direct = new RestTestDelegates(directAM) + LowLevelRestTestDelegates direct = new LowLevelRestTestDelegates(directAM, + proxyComplexVerbs) - direct.testSuiteGetOperations() - direct.testSuiteComplexVerbs() + direct.testSuiteAll() // and via the proxy - RestTestDelegates proxied = new RestTestDelegates(proxyAM) - proxied.testSuiteGetOperations() - if (!wsBackDoorRequired) { - proxied.testSuiteComplexVerbs() - } + LowLevelRestTestDelegates proxied = new LowLevelRestTestDelegates(proxyAM, + directComplexVerbs) + proxied.testSuiteAll() proxied.logCodahaleMetrics(); describe "Proxy Jersey Tests" Client ugiClient = createUGIJerseyClient() JerseyTestDelegates proxyJerseyTests = - new JerseyTestDelegates(proxyAM, ugiClient) + new JerseyTestDelegates(proxyAM, ugiClient, proxyComplexVerbs) proxyJerseyTests.testSuiteGetOperations() describe "Direct Jersey Tests" JerseyTestDelegates directJerseyTests = - new JerseyTestDelegates(directAM, ugiClient) - directJerseyTests.testSuiteGetOperations() - directJerseyTests.testSuiteComplexVerbs() + new JerseyTestDelegates(directAM, ugiClient, directComplexVerbs) + directJerseyTests.testSuiteAll() describe "Proxy SliderRestClient Tests" - SliderRestClientTestDelegates proxySliderRestClient = - new SliderRestClientTestDelegates(proxyAM, ugiClient) - proxySliderRestClient.testSuiteGetOperations() - if (!wsBackDoorRequired) { - proxySliderRestClient.testSuiteComplexVerbs() - } - describe "Direct SliderRestClient Tests" - SliderRestClientTestDelegates directSliderRestClient = - new SliderRestClientTestDelegates(directAM, ugiClient) - directSliderRestClient.testSuiteGetOperations() - directSliderRestClient.testSuiteComplexVerbs() - + RestAPIClientTestDelegates proxySliderRestClient = + new RestAPIClientTestDelegates(proxyAM, ugiClient, proxyComplexVerbs) + proxySliderRestClient.testSuiteAll() + describe "Direct SliderRestClient Tests" + RestAPIClientTestDelegates directSliderRestClient = + new RestAPIClientTestDelegates(directAM, ugiClient, directComplexVerbs) + directSliderRestClient.testSuiteAll() if (UserGroupInformation.securityEnabled) { describe "Insecure Proxy Tests against a secure cluster"