/* * Copyright © 2014-2015 Cask Data, Inc. * * Licensed 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 co.cask.cdap.gateway.router; import co.cask.cdap.common.conf.CConfiguration; import co.cask.cdap.common.conf.Constants; import co.cask.cdap.common.conf.SConfiguration; import co.cask.cdap.common.guice.ConfigModule; import co.cask.cdap.common.guice.DiscoveryRuntimeModule; import co.cask.cdap.common.guice.IOModule; import co.cask.cdap.common.utils.Networks; import co.cask.cdap.security.auth.AccessTokenTransformer; import co.cask.cdap.security.guice.SecurityModules; import co.cask.http.AbstractHttpHandler; import co.cask.http.HttpResponder; import com.google.common.base.Charsets; import com.google.common.io.ByteStreams; import com.google.common.net.InetAddresses; import com.google.inject.Guice; import com.google.inject.Injector; import org.apache.twill.discovery.DiscoveryService; import org.apache.twill.discovery.DiscoveryServiceClient; import org.jboss.netty.handler.codec.http.HttpRequest; import org.jboss.netty.handler.codec.http.HttpResponseStatus; import org.junit.AfterClass; import org.junit.Assert; import org.junit.BeforeClass; import org.junit.Test; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import javax.ws.rs.DELETE; import javax.ws.rs.GET; import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.PathParam; /** * TODO: Eventually this can be removed, since we do not have any proxy rules anymore for datasets. */ public class RoutingToDataSetsTest { private static NettyRouter nettyRouter; private static MockHttpService mockService; private static int port; @BeforeClass public static void before() throws Exception { Injector injector = Guice.createInjector(new ConfigModule(), new IOModule(), new SecurityModules().getInMemoryModules(), new DiscoveryRuntimeModule().getInMemoryModules()); // Starting router DiscoveryServiceClient discoveryServiceClient = injector.getInstance(DiscoveryServiceClient.class); AccessTokenTransformer accessTokenTransformer = injector.getInstance(AccessTokenTransformer.class); CConfiguration cConf = CConfiguration.create(); SConfiguration sConf = SConfiguration.create(); cConf.set(Constants.Router.ADDRESS, "localhost"); port = Networks.getRandomPort(); cConf.setInt(Constants.Router.ROUTER_PORT, port); nettyRouter = new NettyRouter(cConf, sConf, InetAddresses.forString("127.0.0.1"), new RouterServiceLookup(discoveryServiceClient, new RouterPathLookup()), new SuccessTokenValidator(), accessTokenTransformer, discoveryServiceClient); nettyRouter.startAndWait(); // Starting mock DataSet service DiscoveryService discoveryService = injector.getInstance(DiscoveryService.class); mockService = new MockHttpService(discoveryService, Constants.Service.DATASET_MANAGER, new MockDatasetTypeHandler(), new MockDatasetInstanceHandler()); mockService.startAndWait(); } @AfterClass public static void after() { try { nettyRouter.stopAndWait(); } finally { mockService.stopAndWait(); } } @Test public void testTypeHandlerRequests() throws Exception { Assert.assertEquals("listModules", doRequest("/namespaces/myspace/data/modules", "GET")); Assert.assertEquals("post:myModule", doRequest("/namespaces/myspace/data/modules/myModule", "POST")); Assert.assertEquals("delete:myModule", doRequest("/namespaces/myspace/data/modules/myModule", "DELETE")); Assert.assertEquals("get:myModule", doRequest("/namespaces/myspace/data/modules/myModule", "GET")); Assert.assertEquals("listTypes", doRequest("/namespaces/myspace/data/types", "GET")); Assert.assertEquals("getType:myType", doRequest("/namespaces/myspace/data/types/myType", "GET")); } @Test public void testInstanceHandlerRequests() throws Exception { Assert.assertEquals("list", doRequest("/namespaces/myspace/data/datasets", "GET")); Assert.assertEquals("post:myInstance", doRequest("/namespaces/myspace/data/datasets/myInstance", "POST")); Assert.assertEquals("delete:myInstance", doRequest("/namespaces/myspace/data/datasets/myInstance", "DELETE")); Assert.assertEquals("get:myInstance", doRequest("/namespaces/myspace/data/datasets/myInstance", "GET")); } @Path(Constants.Gateway.API_VERSION_3 + "/namespaces/{namespace-id}") public static final class MockDatasetTypeHandler extends AbstractHttpHandler { @GET @Path("/data/modules") public void listModules(HttpRequest request, final HttpResponder responder) { responder.sendString(HttpResponseStatus.OK, "listModules"); } @POST @Path("/data/modules/{name}") public void addModule(HttpRequest request, final HttpResponder responder, @PathParam("name") String name) throws IOException { responder.sendString(HttpResponseStatus.OK, "post:" + name); } @DELETE @Path("/data/modules/{name}") public void deleteModule(HttpRequest request, final HttpResponder responder, @PathParam("name") String name) { responder.sendString(HttpResponseStatus.OK, "delete:" + name); } @GET @Path("/data/modules/{name}") public void getModuleInfo(HttpRequest request, final HttpResponder responder, @PathParam("name") String name) { responder.sendString(HttpResponseStatus.OK, "get:" + name); } @GET @Path("/data/types") public void listTypes(HttpRequest request, final HttpResponder responder) { responder.sendString(HttpResponseStatus.OK, "listTypes"); } @GET @Path("/data/types/{name}") public void getTypeInfo(HttpRequest request, final HttpResponder responder, @PathParam("name") String name) { responder.sendString(HttpResponseStatus.OK, "getType:" + name); } } @Path(Constants.Gateway.API_VERSION_3 + "/namespaces/{namespace-id}") public static final class MockDatasetInstanceHandler extends AbstractHttpHandler { @GET @Path("/data/datasets/") public void list(HttpRequest request, final HttpResponder responder) { responder.sendString(HttpResponseStatus.OK, "list"); } @GET @Path("/data/datasets/{instance-name}") public void getInfo(HttpRequest request, final HttpResponder responder, @PathParam("instance-name") String name) { responder.sendString(HttpResponseStatus.OK, "get:" + name); } @POST @Path("/data/datasets/{instance-name}") public void add(HttpRequest request, final HttpResponder responder, @PathParam("instance-name") String name) { responder.sendString(HttpResponseStatus.OK, "post:" + name); } @DELETE @Path("/data/datasets/{instance-name}") public void drop(HttpRequest request, final HttpResponder responder, @PathParam("instance-name") String instanceName) { responder.sendString(HttpResponseStatus.OK, "delete:" + instanceName); } } private String doRequest(String resource, String requestMethod) throws Exception { resource = String.format("http://localhost:%d%s" + resource, port, Constants.Gateway.API_VERSION_3); URL url = new URL(resource); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod(requestMethod); conn.setDoInput(true); conn.connect(); try { byte[] responseBody = null; if (HttpURLConnection.HTTP_OK == conn.getResponseCode() && conn.getDoInput()) { InputStream is = conn.getInputStream(); try { responseBody = ByteStreams.toByteArray(is); } finally { is.close(); } } return new String(responseBody, Charsets.UTF_8); } finally { conn.disconnect(); } } }