Selaa lähdekoodia

MAPREDUCE-2999. Fix YARN webapp framework to properly filter servlet paths. Contributed by Thomas Graves.

git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1176469 13f79535-47bb-0310-9956-ffa450edef68
Vinod Kumar Vavilapalli 13 vuotta sitten
vanhempi
commit
87b969c835

+ 3 - 0
hadoop-mapreduce-project/CHANGES.txt

@@ -1444,6 +1444,9 @@ Release 0.23.0 - Unreleased
     MAPREDUCE-3067. Ensure exit-code is set correctly for containers. (Hitesh
     Shah via acmurthy)
 
+    MAPREDUCE-2999. Fix YARN webapp framework to properly filter servlet
+    paths. (Thomas Graves via vinodkv)
+
 Release 0.22.0 - Unreleased
 
   INCOMPATIBLE CHANGES

+ 9 - 0
hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/Dispatcher.java

@@ -84,6 +84,15 @@ public class Dispatcher extends HttpServlet {
       prepareToExit();
       return;
     }
+    // if they provide a redirectPath go there instead of going to
+    // "/" so that filters can differentiate the webapps.
+    if (uri.equals("/")) {
+      String redirectPath = webApp.getRedirectPath();
+      if (redirectPath != null && !redirectPath.isEmpty()) {
+        res.sendRedirect(redirectPath);
+        return;
+      }
+    }
     String method = req.getMethod();
     if (method.equals("OPTIONS")) {
       doOptions(req, res);

+ 24 - 1
hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/WebApp.java

@@ -26,6 +26,7 @@ import com.google.inject.Provides;
 import com.google.inject.servlet.GuiceFilter;
 import com.google.inject.servlet.ServletModule;
 
+import java.util.ArrayList;
 import java.util.List;
 
 import org.apache.hadoop.conf.Configuration;
@@ -44,6 +45,9 @@ public abstract class WebApp extends ServletModule {
   public enum HTTP { GET, POST, HEAD, PUT, DELETE };
 
   private volatile String name;
+  private volatile List<String> servePathSpecs = new ArrayList<String>(); 
+  // path to redirect to if user goes to "/"
+  private volatile String redirectPath;
   private volatile Configuration conf;
   private volatile HttpServer httpServer;
   private volatile GuiceFilter guiceFilter;
@@ -98,6 +102,22 @@ public abstract class WebApp extends ServletModule {
 
   public String name() { return this.name; }
 
+  void addServePathSpec(String path) { this.servePathSpecs.add(path); }
+
+  public String[] getServePathSpecs() { 
+    return this.servePathSpecs.toArray(new String[this.servePathSpecs.size()]);
+  }
+
+  /**
+   * Set a path to redirect the user to if they just go to "/". For 
+   * instance "/" goes to "/yarn/apps". This allows the filters to 
+   * more easily differentiate the different webapps.
+   * @param path  the path to redirect to
+   */
+  void setRedirectPath(String path) { this.redirectPath = path; }
+
+  public String getRedirectPath() { return this.redirectPath; }
+
   void setHostClass(Class<?> cls) {
     router.setHostClass(cls);
   }
@@ -109,7 +129,10 @@ public abstract class WebApp extends ServletModule {
   @Override
   public void configureServlets() {
     setup();
-    serve("/", "/__stop", StringHelper.join('/', name, '*')).with(Dispatcher.class);
+    serve("/", "/__stop").with(Dispatcher.class);
+    for (String path : this.servePathSpecs) {
+      serve(path).with(Dispatcher.class);
+    }
   }
 
   /**

+ 10 - 1
hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/main/java/org/apache/hadoop/yarn/webapp/WebApps.java

@@ -113,6 +113,14 @@ public class WebApps {
         };
       }
       webapp.setName(name);
+      String basePath = "/" + name;
+      webapp.setRedirectPath(basePath);
+      if (basePath.equals("/")) { 
+        webapp.addServePathSpec("/*");
+      }  else {
+        webapp.addServePathSpec(basePath);
+        webapp.addServePathSpec(basePath + "/*");
+      }
       if (conf == null) {
         conf = new Configuration();
       }
@@ -142,7 +150,8 @@ public class WebApps {
           }
         }
         HttpServer server =
-            new HttpServer(name, bindAddress, port, findPort, conf);
+            new HttpServer(name, bindAddress, port, findPort, conf, 
+            webapp.getServePathSpecs());
         server.addGlobalFilter("guice", GuiceFilter.class.getName(), null);
         webapp.setConf(conf);
         webapp.setHttpServer(server);

+ 27 - 0
hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-common/src/test/java/org/apache/hadoop/yarn/webapp/TestWebApp.java

@@ -18,6 +18,7 @@
 
 package org.apache.hadoop.yarn.webapp;
 
+import org.apache.commons.lang.ArrayUtils;
 import org.apache.hadoop.yarn.MockApps;
 import org.apache.hadoop.yarn.webapp.Controller;
 import org.apache.hadoop.yarn.webapp.WebApp;
@@ -148,6 +149,32 @@ public class TestWebApp {
     app.stop();
   }
 
+  @Test public void testServePaths() {
+    WebApp app = WebApps.$for("test", this).start();
+    assertEquals("/test", app.getRedirectPath());
+    String[] expectedPaths = { "/test", "/test/*" };
+    String[] pathSpecs = app.getServePathSpecs();
+     
+    assertEquals(2, pathSpecs.length);
+    for(int i = 0; i < expectedPaths.length; i++) {
+      assertTrue(ArrayUtils.contains(pathSpecs, expectedPaths[i]));
+    }
+    app.stop();
+  }
+
+  @Test public void testServePathsNoName() {
+    WebApp app = WebApps.$for("", this).start();
+    assertEquals("/", app.getRedirectPath());
+    String[] expectedPaths = { "/*" };
+    String[] pathSpecs = app.getServePathSpecs();
+     
+    assertEquals(1, pathSpecs.length);
+    for(int i = 0; i < expectedPaths.length; i++) {
+      assertTrue(ArrayUtils.contains(pathSpecs, expectedPaths[i]));
+    }
+    app.stop();
+  }
+
   @Test public void testDefaultRoutes() throws Exception {
     WebApp app = WebApps.$for("test", this).start();
     String baseUrl = baseUrl(app);

+ 1 - 1
hadoop-mapreduce-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/rmnode/RMNodeImpl.java

@@ -144,7 +144,7 @@ public class RMNodeImpl implements RMNode, EventHandler<RMNodeEvent> {
     this.httpPort = httpPort;
     this.totalCapability = capability; 
     this.nodeAddress = hostName + ":" + cmPort;
-    this.httpAddress = hostName + ":" + httpPort;;
+    this.httpAddress = hostName + ":" + httpPort;
     this.node = node;
     this.nodeHealthStatus.setIsNodeHealthy(true);
     this.nodeHealthStatus.setHealthReport("Healthy");