org.apache.hadoop.gateway.GatewayPortMappingFuncTest.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.hadoop.gateway.GatewayPortMappingFuncTest.java

Source

package org.apache.hadoop.gateway;

/**
 * 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
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * 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.
 */

import com.mycila.xmltool.XMLDoc;
import com.mycila.xmltool.XMLTag;
import org.apache.hadoop.test.TestUtils;
import org.apache.hadoop.test.category.ReleaseTest;
import org.apache.hadoop.test.mock.MockServer;
import org.apache.http.HttpStatus;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.experimental.categories.Category;

import java.io.IOException;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import static com.jayway.restassured.RestAssured.given;
import static org.apache.hadoop.test.TestUtils.LOG_ENTER;
import static org.apache.hadoop.test.TestUtils.LOG_EXIT;
import static org.hamcrest.CoreMatchers.is;

/**
 * Test the Gateway Topology Port Mapping functionality
 *
 */
@Category(ReleaseTest.class)
public class GatewayPortMappingFuncTest {

    // Specifies if the test requests should go through the gateway or directly to the services.
    // This is frequently used to verify the behavior of the test both with and without the gateway.
    private static final boolean USE_GATEWAY = true;

    // Specifies if the test requests should be sent to mock services or the real services.
    // This is frequently used to verify the behavior of the test both with and without mock services.
    private static final boolean USE_MOCK_SERVICES = true;

    private static GatewayFuncTestDriver driver = new GatewayFuncTestDriver();

    private static MockServer masterServer;

    private int eeriePort;

    public GatewayPortMappingFuncTest() {
        super();
    }

    /**
     * Creates a deployment of a gateway instance that all test methods will share.  This method also creates a
     * registry of sorts for all of the services that will be used by the test methods.
     * The createTopology method is used to create the topology file that would normally be read from disk.
     * The driver.setupGateway invocation is where the creation of GATEWAY_HOME occurs.
     * <p/>
     * This would normally be done once for this suite but the failure tests start affecting each other depending
     * on the state the last 'active' url
     *
     * @throws Exception Thrown if any failure occurs.
     */
    @Before
    public void setup() throws Exception {
        LOG_ENTER();

        eeriePort = getAvailablePort(1240, 49151);

        ConcurrentHashMap<String, Integer> topologyPortMapping = new ConcurrentHashMap<String, Integer>();
        topologyPortMapping.put("eerie", eeriePort);

        masterServer = new MockServer("master", true);
        GatewayTestConfig config = new GatewayTestConfig();
        config.setGatewayPath("gateway");
        config.setTopologyPortMapping(topologyPortMapping);

        driver.setResourceBase(WebHdfsHaFuncTest.class);
        driver.setupLdap(0);

        driver.setupService("WEBHDFS", "http://vm.local:50070/webhdfs", "/eerie/webhdfs", USE_MOCK_SERVICES);

        driver.setupGateway(config, "eerie", createTopology("WEBHDFS"), USE_GATEWAY);

        LOG_EXIT();
    }

    @After
    public void cleanup() throws Exception {
        LOG_ENTER();
        driver.cleanup();
        driver.reset();
        masterServer.reset();
        LOG_EXIT();
    }

    /**
     * Test the standard case:
     * http://localhost:{gatewayPort}/gateway/eerie/webhdfs/v1
     *
     * @throws IOException
     */
    @Test(timeout = TestUtils.MEDIUM_TIMEOUT)
    public void testBasicListOperation() throws IOException {
        LOG_ENTER();
        test("http://localhost:" + driver.getGatewayPort() + "/gateway/eerie" + "/webhdfs");
        LOG_EXIT();
    }

    /**
     * Test the multi port scenario.
     *
     * http://localhost:{eeriePort}/webhdfs/v1
     *
     * @throws IOException
     */
    @Test(timeout = TestUtils.MEDIUM_TIMEOUT)
    public void testMultiPortOperation() throws IOException {
        LOG_ENTER();
        test("http://localhost:" + eeriePort + "/webhdfs");
        LOG_EXIT();
    }

    /**
     * Test the multi port scenario when gateway path is included.
     *
     * http://localhost:{eeriePort}/gateway/eerie/webhdfs/v1
     *
     * @throws IOException
     */
    @Test(timeout = TestUtils.MEDIUM_TIMEOUT)
    public void testMultiPortWithGatewayPath() throws IOException {
        LOG_ENTER();
        test("http://localhost:" + eeriePort + "/gateway/eerie" + "/webhdfs");
        LOG_EXIT();
    }

    /**
     * Fail when trying to use this feature on the standard port.
     *
     * http://localhost:{gatewayPort}/webhdfs/v1
     *
     * @throws IOException
     */
    @Test(timeout = TestUtils.MEDIUM_TIMEOUT)
    public void testMultiPortOperationFail() throws IOException {
        LOG_ENTER();
        final String url = "http://localhost:" + driver.getGatewayPort() + "/webhdfs";

        String password = "hdfs-password";
        String username = "hdfs";

        masterServer.expect().method("GET").pathInfo("/webhdfs/v1/").queryParam("op", "LISTSTATUS")
                .queryParam("user.name", username).respond().status(HttpStatus.SC_OK)
                .content(driver.getResourceBytes("webhdfs-liststatus-success.json"))
                .contentType("application/json");

        given().auth().preemptive().basic(username, password).header("X-XSRF-Header", "jksdhfkhdsf")
                .queryParam("op", "LISTSTATUS").expect()
                //.log().ifError()
                .statusCode(HttpStatus.SC_NOT_FOUND)
                //.content("FileStatuses.FileStatus[0].pathSuffix", is("app-logs"))
                .when().get(url + "/v1/");
        masterServer.isEmpty();

        LOG_EXIT();
    }

    private void test(final String url) throws IOException {
        String password = "hdfs-password";
        String username = "hdfs";

        masterServer.expect().method("GET").pathInfo("/webhdfs/v1/").queryParam("op", "LISTSTATUS")
                .queryParam("user.name", username).respond().status(HttpStatus.SC_OK)
                .content(driver.getResourceBytes("webhdfs-liststatus-success.json"))
                .contentType("application/json");

        given().auth().preemptive().basic(username, password).header("X-XSRF-Header", "jksdhfkhdsf")
                .queryParam("op", "LISTSTATUS").expect().log().ifError().statusCode(HttpStatus.SC_OK)
                .content("FileStatuses.FileStatus[0].pathSuffix", is("app-logs")).when().get(url + "/v1/");
        masterServer.isEmpty();
    }

    /**
     * Creates a topology that is deployed to the gateway instance for the test suite.
     * Note that this topology is shared by all of the test methods in this suite.
     *
     * @return A populated XML structure for a topology file.
     */
    private static XMLTag createTopology(final String role) {
        XMLTag xml = XMLDoc.newDocument(true).addRoot("topology").addTag("gateway").addTag("provider")
                .addTag("role").addText("webappsec").addTag("name").addText("WebAppSec").addTag("enabled")
                .addText("true").addTag("param").addTag("name").addText("csrf.enabled").addTag("value")
                .addText("true").gotoParent().gotoParent().addTag("provider").addTag("role")
                .addText("authentication").addTag("name").addText("ShiroProvider").addTag("enabled").addText("true")
                .addTag("param").addTag("name").addText("main.ldapRealm").addTag("value")
                .addText("org.apache.hadoop.gateway.shirorealm.KnoxLdapRealm").gotoParent().addTag("param")
                .addTag("name").addText("main.ldapRealm.userDnTemplate").addTag("value")
                .addText("uid={0},ou=people,dc=hadoop,dc=apache,dc=org").gotoParent().addTag("param").addTag("name")
                .addText("main.ldapRealm.contextFactory.url").addTag("value").addText(driver.getLdapUrl())
                .gotoParent().addTag("param").addTag("name")
                .addText("main.ldapRealm.contextFactory.authenticationMechanism").addTag("value").addText("simple")
                .gotoParent().addTag("param").addTag("name").addText("urls./**").addTag("value")
                .addText("authcBasic").gotoParent().gotoParent().addTag("provider").addTag("role")
                .addText("identity-assertion").addTag("enabled").addText("true").addTag("name").addText("Default")
                .gotoParent().addTag("provider").addTag("role").addText("authorization").addTag("enabled")
                .addText("true").addTag("name").addText("AclsAuthz").gotoParent().addTag("param").addTag("name")
                .addText("webhdfs-acl").addTag("value").addText("hdfs;*;*").gotoParent().addTag("provider")
                .addTag("role").addText("ha").addTag("enabled").addText("true").addTag("name").addText("HaProvider")
                .addTag("param").addTag("name").addText("WEBHDFS").addTag("value")
                .addText("maxFailoverAttempts=3;failoverSleep=15;maxRetryAttempts=3;retrySleep=10;enabled=true")
                .gotoParent().gotoRoot().addTag("service").addTag("role").addText(role).addTag("url")
                .addText("http://localhost:" + masterServer.getPort() + "/webhdfs").gotoRoot();
        return xml;
    }

    /**
     * This utility method will return the next available port
     * that can be used.
     *
     * @return Port that is available.
     */
    public static int getAvailablePort(final int min, final int max) {

        for (int i = min; i <= max; i++) {

            if (!GatewayServer.isPortInUse(i)) {
                return i;
            }
        }
        // too bad
        return -1;
    }

}