aurora-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kevi...@apache.org
Subject incubator-aurora git commit: Break out API servlet configuration into its own module.
Date Thu, 05 Mar 2015 22:45:45 GMT
Repository: incubator-aurora
Updated Branches:
  refs/heads/master f64b3f85c -> 70494a174


Break out API servlet configuration into its own module.

This is necessary to make a follow-up patch introducing HTTP Basic auth testable.

Reviewed at https://reviews.apache.org/r/31754/


Project: http://git-wip-us.apache.org/repos/asf/incubator-aurora/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-aurora/commit/70494a17
Tree: http://git-wip-us.apache.org/repos/asf/incubator-aurora/tree/70494a17
Diff: http://git-wip-us.apache.org/repos/asf/incubator-aurora/diff/70494a17

Branch: refs/heads/master
Commit: 70494a1741419bab5d94fe3883ff8875f08b8cd4
Parents: f64b3f8
Author: Kevin Sweeney <kevints@apache.org>
Authored: Thu Mar 5 14:45:23 2015 -0800
Committer: Kevin Sweeney <kevints@apache.org>
Committed: Thu Mar 5 14:45:23 2015 -0800

----------------------------------------------------------------------
 .../scheduler/http/JettyServerModule.java       | 208 +++++++++----------
 .../scheduler/http/SchedulerAPIServlet.java     |  31 ---
 .../aurora/scheduler/http/api/ApiBeta.java      |   3 +-
 .../aurora/scheduler/http/api/ApiModule.java    |  86 ++++++++
 .../scheduler/mesos/ExecutorSettings.java       |   1 -
 .../thrift/SchedulerThriftInterface.java        |   1 -
 .../scheduler/http/JettyServerModuleTest.java   |  37 ++--
 .../scheduler/http/ServletFilterTest.java       |   5 -
 .../aurora/scheduler/http/api/ApiBetaTest.java  |  24 +++
 .../apache/aurora/scheduler/http/api/ApiIT.java |  65 ++++++
 10 files changed, 305 insertions(+), 156 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/70494a17/src/main/java/org/apache/aurora/scheduler/http/JettyServerModule.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/http/JettyServerModule.java b/src/main/java/org/apache/aurora/scheduler/http/JettyServerModule.java
index 8a59d89..9fad055 100644
--- a/src/main/java/org/apache/aurora/scheduler/http/JettyServerModule.java
+++ b/src/main/java/org/apache/aurora/scheduler/http/JettyServerModule.java
@@ -21,15 +21,16 @@ import java.util.logging.Logger;
 import javax.annotation.Nonnegative;
 import javax.inject.Inject;
 import javax.inject.Singleton;
+import javax.servlet.ServletContextListener;
 import javax.servlet.http.HttpServlet;
-import javax.ws.rs.HttpMethod;
 
-import com.google.common.base.Joiner;
+import com.google.common.annotations.VisibleForTesting;
 import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
 import com.google.common.util.concurrent.AbstractIdleService;
 import com.google.inject.AbstractModule;
 import com.google.inject.Injector;
+import com.google.inject.Module;
+import com.google.inject.Provides;
 import com.google.inject.TypeLiteral;
 import com.google.inject.name.Names;
 import com.google.inject.servlet.GuiceFilter;
@@ -57,7 +58,7 @@ import com.twitter.common.net.http.handlers.VarsJsonHandler;
 import com.twitter.common.net.pool.DynamicHostSet.MonitorException;
 
 import org.apache.aurora.scheduler.SchedulerServicesModule;
-import org.apache.aurora.scheduler.http.api.ApiBeta;
+import org.apache.aurora.scheduler.http.api.ApiModule;
 import org.eclipse.jetty.rewrite.handler.RewriteHandler;
 import org.eclipse.jetty.rewrite.handler.RewriteRegexRule;
 import org.eclipse.jetty.server.Connector;
@@ -97,27 +98,27 @@ public class JettyServerModule extends AbstractModule {
       help = "The port to start an HTTP server on.  Default value will choose a random port.")
   protected static final Arg<Integer> HTTP_PORT = Arg.create(0);
 
-  @CmdLine(name = "enable_cors_support", help = "Enable CORS support for thrift end points.")
-  private static final Arg<Boolean> ENABLE_CORS_SUPPORT = Arg.create(false);
-
-  // More info on CORS can be found at http://enable-cors.org/index.html
-  @CmdLine(name = "enable_cors_for",
-      help = "List of domains for which CORS support should be enabled.")
-  private static final Arg<String> ENABLE_CORS_FOR = Arg.create("*");
-
-  private static final Map<String, String> CONTAINER_PARAMS = ImmutableMap.of(
+  public static final Map<String, String> GUICE_CONTAINER_PARAMS = ImmutableMap.of(
       FEATURE_POJO_MAPPING, Boolean.TRUE.toString(),
       PROPERTY_CONTAINER_REQUEST_FILTERS, GZIPContentEncodingFilter.class.getName(),
       PROPERTY_CONTAINER_RESPONSE_FILTERS, GZIPContentEncodingFilter.class.getName());
 
-  private static final String API_CLIENT_ROOT = Resource
-      .newClassPathResource("org/apache/aurora/scheduler/gen/client")
-      .toString();
   private static final String STATIC_ASSETS_ROOT = Resource
       .newClassPathResource("scheduler/assets/index.html")
       .toString()
       .replace("assets/index.html", "");
 
+  private final boolean production;
+
+  public JettyServerModule() {
+    this(true);
+  }
+
+  @VisibleForTesting
+  JettyServerModule(boolean production) {
+    this.production = production;
+  }
+
   @Override
   protected void configure() {
     bind(Runnable.class)
@@ -137,6 +138,88 @@ public class JettyServerModule extends AbstractModule {
 
     bind(LeaderRedirect.class).in(Singleton.class);
     SchedulerServicesModule.addAppStartupServiceBinding(binder()).to(RedirectMonitor.class);
+
+    if (production) {
+      install(PRODUCTION_SERVLET_CONTEXT_LISTENER);
+    }
+  }
+
+  private static final Module PRODUCTION_SERVLET_CONTEXT_LISTENER = new AbstractModule()
{
+    @Override
+    protected void configure() {
+      // Provider binding only.
+    }
+
+    @Provides
+    @Singleton
+    ServletContextListener provideServletContextListener(Injector parentInjector) {
+      return makeServletContextListener(parentInjector, new ApiModule());
+    };
+  };
+
+  // TODO(ksweeney): Factor individual servlet configurations to their own ServletModules.
+  @VisibleForTesting
+  static ServletContextListener makeServletContextListener(
+      final Injector parentInjector,
+      final Module childModule) {
+
+    return new GuiceServletContextListener() {
+      @Override
+      protected Injector getInjector() {
+        return parentInjector.createChildInjector(
+            childModule,
+            new JerseyServletModule() {
+              private void registerJerseyEndpoint(String indexPath, Class<?> servlet)
{
+                filter(indexPath + "*").through(LeaderRedirectFilter.class);
+                filter(indexPath + "*").through(GuiceContainer.class, GUICE_CONTAINER_PARAMS);
+                bind(servlet);
+              }
+
+              private void registerServlet(String pathSpec, Class<? extends HttpServlet>
servlet) {
+                bind(servlet).in(Singleton.class);
+                serve(pathSpec).with(servlet);
+              }
+
+              @Override
+              protected void configureServlets() {
+                bind(HttpStatsFilter.class).in(Singleton.class);
+                filter("*").through(HttpStatsFilter.class);
+                bind(LeaderRedirectFilter.class).in(Singleton.class);
+
+                filterRegex("/assets/.*").through(new GzipFilter());
+                filterRegex("/assets/scheduler(?:/.*)?").through(LeaderRedirectFilter.class);
+
+                serve("/assets", "/assets/*")
+                    .with(new DefaultServlet(), ImmutableMap.of(
+                        "resourceBase", STATIC_ASSETS_ROOT,
+                        "dirAllowed", "false"));
+
+                bind(GuiceContainer.class).in(Singleton.class);
+                registerJerseyEndpoint("/cron", Cron.class);
+                registerJerseyEndpoint("/locks", Locks.class);
+                registerJerseyEndpoint("/maintenance", Maintenance.class);
+                registerJerseyEndpoint("/mname", Mname.class);
+                registerJerseyEndpoint("/offers", Offers.class);
+                registerJerseyEndpoint("/pendingtasks", PendingTasks.class);
+                registerJerseyEndpoint("/quotas", Quotas.class);
+                registerJerseyEndpoint("/services", Services.class);
+                registerJerseyEndpoint("/slaves", Slaves.class);
+                registerJerseyEndpoint("/structdump", StructDump.class);
+                registerJerseyEndpoint("/utilization", Utilization.class);
+
+                registerServlet("/abortabortabort", AbortHandler.class);
+                registerServlet("/contention", ContentionPrinter.class);
+                registerServlet("/health", HealthHandler.class);
+                registerServlet("/logconfig", LogConfig.class);
+                registerServlet("/quitquitquit", QuitHandler.class);
+                registerServlet("/threads", ThreadStackPrinter.class);
+                registerServlet("/graphdata/", TimeSeriesDataSource.class);
+                registerServlet("/vars", VarsHandler.class);
+                registerServlet("/vars.json", VarsJsonHandler.class);
+              }
+            });
+      }
+    };
   }
 
   static class RedirectMonitor extends AbstractIdleService {
@@ -160,11 +243,11 @@ public class JettyServerModule extends AbstractModule {
 
   // TODO(wfarner): Use guava's Service to enforce the lifecycle of this.
   public static final class HttpServerLauncher implements LifecycleModule.ServiceRunner {
-    private final Injector parentInjector;
+    private final ServletContextListener servletContextListener;
 
     @Inject
-    HttpServerLauncher(Injector parentInjector) {
-      this.parentInjector = requireNonNull(parentInjector);
+    HttpServerLauncher(ServletContextListener servletContextListener) {
+      this.servletContextListener = requireNonNull(servletContextListener);
     }
 
     private static final Map<String, String> REGEX_REWRITE_RULES =
@@ -193,11 +276,6 @@ public class JettyServerModule extends AbstractModule {
       return rewrites;
     }
 
-    @Singleton
-    static class ApiClientServlet extends DefaultServlet {
-      // Subclass to allow extra instance of DefaultServlet.
-    }
-
     @Override
     public LocalService launch() throws LaunchException {
       // N.B. we explicitly disable the resource cache here due to a bug serving content
out of the
@@ -210,6 +288,7 @@ public class JettyServerModule extends AbstractModule {
 
       servletHandler.addServlet(DefaultServlet.class, "/");
       servletHandler.addFilter(GuiceFilter.class,  "/*", EnumSet.allOf(DispatcherType.class));
+      servletHandler.addEventListener(servletContextListener);
 
       HandlerCollection rootHandler = new HandlerCollection();
 
@@ -219,87 +298,6 @@ public class JettyServerModule extends AbstractModule {
       rootHandler.addHandler(logHandler);
       rootHandler.addHandler(servletHandler);
 
-      servletHandler.addEventListener(new GuiceServletContextListener() {
-        @Override
-        protected Injector getInjector() {
-          return parentInjector.createChildInjector(new JerseyServletModule() {
-            private void registerJerseyEndpoint(String indexPath, Class<?> servlet)
{
-              filter(indexPath + "*").through(LeaderRedirectFilter.class);
-              filter(indexPath + "*").through(GuiceContainer.class, CONTAINER_PARAMS);
-              bind(servlet);
-            }
-
-            private void registerServlet(String pathSpec, Class<? extends HttpServlet>
servlet) {
-              bind(servlet).in(Singleton.class);
-              serve(pathSpec).with(servlet);
-            }
-
-            @Override
-            protected void configureServlets() {
-              bind(HttpStatsFilter.class).in(Singleton.class);
-              filter("*").through(HttpStatsFilter.class);
-              bind(LeaderRedirectFilter.class).in(Singleton.class);
-              filterRegex("/assets/scheduler(?:/.*)?").through(LeaderRedirectFilter.class);
-
-              // Add CORS support for all /api endpoints.
-              if (ENABLE_CORS_SUPPORT.get()) {
-                bind(CorsFilter.class).toInstance(new CorsFilter(ENABLE_CORS_FOR.get()));
-                filter("/api*").through(CorsFilter.class);
-              }
-
-              // NOTE: GzipFilter is applied only to /api instead of globally because the
-              // Jersey-managed servlets have a conflicting filter applied to them.
-              bind(GzipFilter.class).in(Singleton.class);
-              filterRegex("/api(?:/.*)?").through(GzipFilter.class, ImmutableMap.of(
-                  "methods", Joiner.on(',').join(ImmutableSet.of(
-                      HttpMethod.GET,
-                      HttpMethod.POST))));
-              filterRegex("/assets/.*").through(
-                  GzipFilter.class,
-                  ImmutableMap.of("methods", HttpMethod.GET));
-
-              bind(DefaultServlet.class).in(Singleton.class);
-              serve("/assets", "/assets/*")
-                  .with(DefaultServlet.class, ImmutableMap.of(
-                      "resourceBase", STATIC_ASSETS_ROOT,
-                      "dirAllowed", "false"));
-
-              serve("/apiclient", "/apiclient/*")
-                  .with(ApiClientServlet.class, ImmutableMap.<String, String>builder()
-                      .put("resourceBase", API_CLIENT_ROOT)
-                      .put("pathInfoOnly", "true")
-                      .put("dirAllowed", "false")
-                      .build());
-
-              bind(GuiceContainer.class).in(Singleton.class);
-              registerJerseyEndpoint("/apibeta", ApiBeta.class);
-              registerJerseyEndpoint("/cron", Cron.class);
-              registerJerseyEndpoint("/locks", Locks.class);
-              registerJerseyEndpoint("/maintenance", Maintenance.class);
-              registerJerseyEndpoint("/mname", Mname.class);
-              registerJerseyEndpoint("/offers", Offers.class);
-              registerJerseyEndpoint("/pendingtasks", PendingTasks.class);
-              registerJerseyEndpoint("/quotas", Quotas.class);
-              registerJerseyEndpoint("/services", Services.class);
-              registerJerseyEndpoint("/slaves", Slaves.class);
-              registerJerseyEndpoint("/structdump", StructDump.class);
-              registerJerseyEndpoint("/utilization", Utilization.class);
-
-              registerServlet("/abortabortabort", AbortHandler.class);
-              registerServlet("/contention", ContentionPrinter.class);
-              registerServlet("/health", HealthHandler.class);
-              registerServlet("/logconfig", LogConfig.class);
-              registerServlet("/quitquitquit", QuitHandler.class);
-              registerServlet("/api", SchedulerAPIServlet.class);
-              registerServlet("/threads", ThreadStackPrinter.class);
-              registerServlet("/graphdata/", TimeSeriesDataSource.class);
-              registerServlet("/vars", VarsHandler.class);
-              registerServlet("/vars.json", VarsJsonHandler.class);
-            }
-          });
-        }
-      });
-
       Connector connector = new SelectChannelConnector();
       connector.setPort(HTTP_PORT.get());
       server.addConnector(connector);

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/70494a17/src/main/java/org/apache/aurora/scheduler/http/SchedulerAPIServlet.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/http/SchedulerAPIServlet.java b/src/main/java/org/apache/aurora/scheduler/http/SchedulerAPIServlet.java
deleted file mode 100644
index 33ad43b..0000000
--- a/src/main/java/org/apache/aurora/scheduler/http/SchedulerAPIServlet.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/**
- * 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 org.apache.aurora.scheduler.http;
-
-import javax.inject.Inject;
-
-import org.apache.aurora.gen.AuroraAdmin;
-import org.apache.thrift.protocol.TJSONProtocol;
-import org.apache.thrift.server.TServlet;
-
-/**
- * A servlet that exposes the scheduler Thrift API over HTTP/JSON.
- */
-class SchedulerAPIServlet extends TServlet {
-
-  @Inject
-  SchedulerAPIServlet(AuroraAdmin.Iface schedulerThriftInterface) {
-    super(new AuroraAdmin.Processor<>(schedulerThriftInterface), new TJSONProtocol.Factory());
-  }
-}

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/70494a17/src/main/java/org/apache/aurora/scheduler/http/api/ApiBeta.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/http/api/ApiBeta.java b/src/main/java/org/apache/aurora/scheduler/http/api/ApiBeta.java
index d1ab9b1..827e85b 100644
--- a/src/main/java/org/apache/aurora/scheduler/http/api/ApiBeta.java
+++ b/src/main/java/org/apache/aurora/scheduler/http/api/ApiBeta.java
@@ -57,8 +57,9 @@ import static org.apache.aurora.scheduler.http.api.GsonMessageBodyHandler.GSON;
  * A scheduler interface that allows interaction with the thrift API via traditional JSON,
  * rather than thrift's preferred means which uses field IDs.
  */
-@Path("/apibeta")
+@Path(ApiBeta.PATH)
 public class ApiBeta {
+  static final String PATH = "/apibeta";
 
   private static final Logger LOG = Logger.getLogger(ApiBeta.class.getName());
 

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/70494a17/src/main/java/org/apache/aurora/scheduler/http/api/ApiModule.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/http/api/ApiModule.java b/src/main/java/org/apache/aurora/scheduler/http/api/ApiModule.java
new file mode 100644
index 0000000..fe2ccda
--- /dev/null
+++ b/src/main/java/org/apache/aurora/scheduler/http/api/ApiModule.java
@@ -0,0 +1,86 @@
+/**
+ * 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 org.apache.aurora.scheduler.http.api;
+
+import javax.inject.Singleton;
+import javax.ws.rs.HttpMethod;
+
+import com.google.common.base.Joiner;
+import com.google.common.collect.ImmutableMap;
+import com.google.inject.Provides;
+import com.google.inject.servlet.ServletModule;
+import com.sun.jersey.guice.spi.container.servlet.GuiceContainer;
+import com.twitter.common.args.Arg;
+import com.twitter.common.args.CmdLine;
+
+import org.apache.aurora.gen.AuroraAdmin;
+import org.apache.aurora.scheduler.http.CorsFilter;
+import org.apache.aurora.scheduler.http.JettyServerModule;
+import org.apache.aurora.scheduler.http.LeaderRedirectFilter;
+import org.apache.thrift.protocol.TJSONProtocol;
+import org.apache.thrift.server.TServlet;
+import org.eclipse.jetty.servlet.DefaultServlet;
+import org.eclipse.jetty.servlets.GzipFilter;
+import org.eclipse.jetty.util.resource.Resource;
+
+public class ApiModule extends ServletModule {
+  static final String API_PATH = "/api";
+  @CmdLine(name = "enable_cors_support", help = "Enable CORS support for thrift end points.")
+  private static final Arg<Boolean> ENABLE_CORS_SUPPORT = Arg.create(false);
+
+  /**
+   * Set the {@code Access-Control-Allow-Origin} header for API requests. See
+   * http://www.w3.org/TR/cors/
+   */
+  @CmdLine(name = "enable_cors_for",
+      help = "List of domains for which CORS support should be enabled.")
+  private static final Arg<String> ENABLE_CORS_FOR = Arg.create("*");
+
+  private static final String API_CLIENT_ROOT = Resource
+      .newClassPathResource("org/apache/aurora/scheduler/gen/client")
+      .toString();
+
+  @Override
+  protected void configureServlets() {
+    if (ENABLE_CORS_SUPPORT.get()) {
+      filter(API_PATH).through(new CorsFilter(ENABLE_CORS_FOR.get()));
+    }
+    // NOTE: GzipFilter is applied only to /api instead of globally because the
+    // Jersey-managed servlets have a conflicting filter applied to them.
+    filter(API_PATH)
+        .through(
+            new GzipFilter(),
+            ImmutableMap.of("methods", Joiner.on(',').join(HttpMethod.GET, HttpMethod.POST)));
+    serve(API_PATH).with(TServlet.class);
+
+    filter(ApiBeta.PATH, ApiBeta.PATH + "/*").through(LeaderRedirectFilter.class);
+    filter(ApiBeta.PATH, ApiBeta.PATH + "/*")
+        .through(GuiceContainer.class, JettyServerModule.GUICE_CONTAINER_PARAMS);
+    bind(ApiBeta.class);
+
+    serve("/apiclient", "/apiclient/*")
+        .with(new DefaultServlet(), ImmutableMap.<String, String>builder()
+            .put("resourceBase", API_CLIENT_ROOT)
+            .put("pathInfoOnly", "true")
+            .put("dirAllowed", "false")
+            .build());
+  }
+
+  @Provides
+  @Singleton
+  TServlet provideApiThriftServlet(AuroraAdmin.Iface schedulerThriftInterface) {
+    return new TServlet(
+        new AuroraAdmin.Processor<>(schedulerThriftInterface), new TJSONProtocol.Factory());
+  }
+}

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/70494a17/src/main/java/org/apache/aurora/scheduler/mesos/ExecutorSettings.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/mesos/ExecutorSettings.java b/src/main/java/org/apache/aurora/scheduler/mesos/ExecutorSettings.java
index 9804bf5..325f556 100644
--- a/src/main/java/org/apache/aurora/scheduler/mesos/ExecutorSettings.java
+++ b/src/main/java/org/apache/aurora/scheduler/mesos/ExecutorSettings.java
@@ -16,7 +16,6 @@ package org.apache.aurora.scheduler.mesos;
 import java.util.List;
 
 import com.google.common.base.Optional;
-
 import com.google.common.collect.ImmutableList;
 
 import org.apache.aurora.gen.Volume;

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/70494a17/src/main/java/org/apache/aurora/scheduler/thrift/SchedulerThriftInterface.java
----------------------------------------------------------------------
diff --git a/src/main/java/org/apache/aurora/scheduler/thrift/SchedulerThriftInterface.java
b/src/main/java/org/apache/aurora/scheduler/thrift/SchedulerThriftInterface.java
index 8ec5f9a..dbb5c19 100644
--- a/src/main/java/org/apache/aurora/scheduler/thrift/SchedulerThriftInterface.java
+++ b/src/main/java/org/apache/aurora/scheduler/thrift/SchedulerThriftInterface.java
@@ -39,7 +39,6 @@ import com.google.common.collect.Maps;
 import com.google.common.collect.Multimap;
 import com.google.common.collect.Multimaps;
 import com.google.common.collect.Range;
-
 import com.twitter.common.args.Arg;
 import com.twitter.common.args.CmdLine;
 import com.twitter.common.args.constraints.Positive;

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/70494a17/src/test/java/org/apache/aurora/scheduler/http/JettyServerModuleTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/http/JettyServerModuleTest.java b/src/test/java/org/apache/aurora/scheduler/http/JettyServerModuleTest.java
index 80beb25..c3e40d8 100644
--- a/src/test/java/org/apache/aurora/scheduler/http/JettyServerModuleTest.java
+++ b/src/test/java/org/apache/aurora/scheduler/http/JettyServerModuleTest.java
@@ -15,6 +15,7 @@ package org.apache.aurora.scheduler.http;
 
 import java.net.InetSocketAddress;
 
+import javax.servlet.ServletContextListener;
 import javax.ws.rs.core.MediaType;
 
 import com.google.common.base.Optional;
@@ -24,7 +25,10 @@ import com.google.common.util.concurrent.RateLimiter;
 import com.google.inject.AbstractModule;
 import com.google.inject.Guice;
 import com.google.inject.Injector;
+import com.google.inject.Module;
+import com.google.inject.Provider;
 import com.google.inject.TypeLiteral;
+import com.google.inject.util.Modules;
 import com.sun.jersey.api.client.Client;
 import com.sun.jersey.api.client.WebResource;
 import com.sun.jersey.api.client.config.ClientConfig;
@@ -44,7 +48,6 @@ import com.twitter.common.testing.easymock.EasyMockTest;
 import com.twitter.common.util.BackoffStrategy;
 import com.twitter.thrift.ServiceInstance;
 
-import org.apache.aurora.gen.AuroraAdmin;
 import org.apache.aurora.gen.ServerInfo;
 import org.apache.aurora.scheduler.SchedulerServicesModule;
 import org.apache.aurora.scheduler.app.LocalServiceRegistryWithOverrides;
@@ -54,7 +57,6 @@ import org.apache.aurora.scheduler.async.TaskGroups.TaskGroupsSettings;
 import org.apache.aurora.scheduler.async.TaskScheduler;
 import org.apache.aurora.scheduler.cron.CronJobManager;
 import org.apache.aurora.scheduler.http.api.GsonMessageBodyHandler;
-import org.apache.aurora.scheduler.quota.QuotaManager;
 import org.apache.aurora.scheduler.state.LockManager;
 import org.apache.aurora.scheduler.storage.Storage;
 import org.apache.aurora.scheduler.storage.entities.IServerInfo;
@@ -62,6 +64,7 @@ import org.apache.aurora.scheduler.storage.testing.StorageTestUtil;
 import org.easymock.Capture;
 import org.junit.Before;
 
+import static org.apache.aurora.scheduler.http.JettyServerModule.makeServletContextListener;
 import static org.easymock.EasyMock.capture;
 import static org.easymock.EasyMock.expect;
 import static org.junit.Assert.assertNotNull;
@@ -73,22 +76,27 @@ import static org.junit.Assert.assertNotNull;
  *
  */
 public abstract class JettyServerModuleTest extends EasyMockTest {
-
   private Injector injector;
   protected StorageTestUtil storage;
   protected InetSocketAddress httpServer;
   protected Capture<HostChangeMonitor<ServiceInstance>> schedulerWatcher;
-  protected AuroraAdmin.Iface thrift;
+
+  /**
+   * Subclasses should override with a module that configures the servlets they are testing.
+   *
+   * @return A module used in the creation of the servlet container's child injector.
+   */
+  protected Module getChildServletModule() {
+    return Modules.EMPTY_MODULE;
+  }
 
   @Before
-  public void setUp() throws Exception {
+  public void setUpBase() throws Exception {
     storage = new StorageTestUtil(this);
     final DynamicHostSet<ServiceInstance> schedulers =
-        createMock(new Clazz<DynamicHostSet<ServiceInstance>>() {
-        });
+        createMock(new Clazz<DynamicHostSet<ServiceInstance>>() { });
 
     injector = Guice.createInjector(
-        new JettyServerModule(),
         new StatsModule(),
         new LifecycleModule(),
         new SchedulerServicesModule(),
@@ -114,17 +122,22 @@ public abstract class JettyServerModuleTest extends EasyMockTest {
             bind(LocalServiceRegistryWithOverrides.Settings.class).toInstance(
                 new LocalServiceRegistryWithOverrides.Settings(Optional.<String>absent()));
             bind(new TypeLiteral<DynamicHostSet<ServiceInstance>>() { }).toInstance(schedulers);
-            thrift = bindMock(AuroraAdmin.Iface.class);
             bindMock(CronJobManager.class);
             bindMock(LockManager.class);
             bindMock(OfferManager.class);
-            bindMock(QuotaManager.class);
             bindMock(RescheduleCalculator.class);
             bindMock(TaskScheduler.class);
             bindMock(Thread.UncaughtExceptionHandler.class);
-          }
-        });
 
+            bind(ServletContextListener.class).toProvider(new Provider<ServletContextListener>()
{
+              @Override
+              public ServletContextListener get() {
+                return makeServletContextListener(injector, getChildServletModule());
+              }
+            });
+          }
+        },
+        new JettyServerModule(false));
     schedulerWatcher = createCapture();
     expect(schedulers.watch(capture(schedulerWatcher))).andReturn(createMock(Command.class));
   }

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/70494a17/src/test/java/org/apache/aurora/scheduler/http/ServletFilterTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/http/ServletFilterTest.java b/src/test/java/org/apache/aurora/scheduler/http/ServletFilterTest.java
index 47d54e3..c5c5f78 100644
--- a/src/test/java/org/apache/aurora/scheduler/http/ServletFilterTest.java
+++ b/src/test/java/org/apache/aurora/scheduler/http/ServletFilterTest.java
@@ -24,10 +24,8 @@ import com.sun.jersey.api.client.ClientResponse.Status;
 import com.twitter.thrift.Endpoint;
 import com.twitter.thrift.ServiceInstance;
 
-import org.apache.aurora.gen.Response;
 import org.junit.Test;
 
-import static org.easymock.EasyMock.expect;
 import static org.junit.Assert.assertEquals;
 
 public class ServletFilterTest extends JettyServerModuleTest {
@@ -59,7 +57,6 @@ public class ServletFilterTest extends JettyServerModuleTest {
 
   @Test
   public void testGzipEncoding() throws Exception {
-    expect(thrift.getJobSummary("www-data")).andReturn(new Response()).times(2);
     replayAndStart();
 
     assertGzipEncodedGet("/");
@@ -76,8 +73,6 @@ public class ServletFilterTest extends JettyServerModuleTest {
 
     assertGzipEncodedGet("/assets/bower_components/angular/angular.js");
 
-    assertGzipEncodedPost("/api", "[1,\"getJobSummary\",1,0,{\"1\":{\"str\":\"www-data\"}}]");
-    assertGzipEncodedPost("/apibeta/getJobSummary", "{\"role\":\"www-data\"}");
   }
 
   private void assertResponseStatus(String path, Status expectedStatus) {

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/70494a17/src/test/java/org/apache/aurora/scheduler/http/api/ApiBetaTest.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/http/api/ApiBetaTest.java b/src/test/java/org/apache/aurora/scheduler/http/api/ApiBetaTest.java
index 5019094..cafd10f 100644
--- a/src/test/java/org/apache/aurora/scheduler/http/api/ApiBetaTest.java
+++ b/src/test/java/org/apache/aurora/scheduler/http/api/ApiBetaTest.java
@@ -21,12 +21,16 @@ import javax.ws.rs.core.Response.Status;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
+import com.google.inject.AbstractModule;
+import com.google.inject.Module;
+import com.google.inject.util.Modules;
 import com.sun.jersey.api.client.Client;
 import com.sun.jersey.api.client.ClientResponse;
 import com.sun.jersey.api.client.config.ClientConfig;
 import com.sun.jersey.api.client.config.DefaultClientConfig;
 
 import org.apache.aurora.gen.AssignedTask;
+import org.apache.aurora.gen.AuroraAdmin;
 import org.apache.aurora.gen.Constraint;
 import org.apache.aurora.gen.CronCollisionPolicy;
 import org.apache.aurora.gen.ExecutorConfig;
@@ -51,6 +55,7 @@ import org.apache.aurora.gen.TaskQuery;
 import org.apache.aurora.scheduler.http.JettyServerModuleTest;
 import org.apache.aurora.scheduler.storage.entities.IJobConfiguration;
 import org.apache.aurora.scheduler.storage.entities.ITaskConfig;
+import org.junit.Before;
 import org.junit.Test;
 
 import static org.apache.aurora.gen.ResponseCode.OK;
@@ -59,6 +64,25 @@ import static org.easymock.EasyMock.expect;
 import static org.junit.Assert.assertEquals;
 
 public class ApiBetaTest extends JettyServerModuleTest {
+  private AuroraAdmin.Iface thrift;
+
+  @Before
+  public void setUp() {
+    thrift = createMock(AuroraAdmin.Iface.class);
+  }
+
+  @Override
+  protected Module getChildServletModule() {
+    return Modules.combine(
+        new ApiModule(),
+        new AbstractModule() {
+          @Override
+          protected void configure() {
+            bind(AuroraAdmin.Iface.class).toInstance(thrift);
+          }
+        }
+    );
+  }
 
   private static final ITaskConfig TASK_CONFIG = ITaskConfig.build(
       new TaskConfig()

http://git-wip-us.apache.org/repos/asf/incubator-aurora/blob/70494a17/src/test/java/org/apache/aurora/scheduler/http/api/ApiIT.java
----------------------------------------------------------------------
diff --git a/src/test/java/org/apache/aurora/scheduler/http/api/ApiIT.java b/src/test/java/org/apache/aurora/scheduler/http/api/ApiIT.java
new file mode 100644
index 0000000..ed284f4
--- /dev/null
+++ b/src/test/java/org/apache/aurora/scheduler/http/api/ApiIT.java
@@ -0,0 +1,65 @@
+/**
+ * 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 org.apache.aurora.scheduler.http.api;
+
+import javax.ws.rs.core.HttpHeaders;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Module;
+import com.google.inject.util.Modules;
+import com.sun.jersey.api.client.ClientResponse;
+
+import org.apache.aurora.gen.AuroraAdmin;
+import org.apache.aurora.gen.Response;
+import org.apache.aurora.scheduler.http.JettyServerModuleTest;
+import org.junit.Before;
+import org.junit.Test;
+
+import static org.easymock.EasyMock.expect;
+import static org.junit.Assert.assertEquals;
+
+public class ApiIT extends JettyServerModuleTest {
+  private AuroraAdmin.Iface thrift;
+
+  @Before
+  public void setUp() {
+    thrift = createMock(AuroraAdmin.Iface.class);
+  }
+
+  @Override
+  protected Module getChildServletModule() {
+    return Modules.combine(
+        new ApiModule(),
+        new AbstractModule() {
+          @Override
+          protected void configure() {
+            bind(AuroraAdmin.Iface.class).toInstance(thrift);
+          }
+        });
+  }
+
+  @Test
+  public void testGzipFilterApplied() throws Exception {
+    expect(thrift.getRoleSummary()).andReturn(new Response());
+
+    replayAndStart();
+
+    ClientResponse response = getRequestBuilder(ApiModule.API_PATH)
+        .header(HttpHeaders.ACCEPT_ENCODING, "gzip")
+        .type("application/x-thrift")
+        .post(ClientResponse.class, "[1,\"getRoleSummary\",1,0,{}]");
+
+    assertEquals("gzip", response.getHeaders().getFirst(HttpHeaders.CONTENT_ENCODING));
+  }
+}


Mime
View raw message