diff --git hadoop-common-project/hadoop-common/pom.xml hadoop-common-project/hadoop-common/pom.xml index 3ae78f4..442ddaa 100644 --- hadoop-common-project/hadoop-common/pom.xml +++ hadoop-common-project/hadoop-common/pom.xml @@ -147,6 +147,11 @@ test + org.jsoup + jsoup + 1.7.3 + + commons-lang commons-lang compile diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RmView.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RmView.java index 769c4da..0c58c28 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RmView.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/RmView.java @@ -20,6 +20,8 @@ import org.apache.hadoop.yarn.webapp.SubView; import org.apache.hadoop.yarn.webapp.view.TwoColumnLayout; +import org.jsoup.Jsoup; +import org.jsoup.safety.Whitelist; import static org.apache.hadoop.yarn.util.StringHelper.sjoin; import static org.apache.hadoop.yarn.webapp.YarnWebParams.APP_STATE; @@ -37,11 +39,15 @@ protected void preHead(Page.HTML<_> html) { set(DATATABLES_ID, "apps"); set(initID(DATATABLES, "apps"), appsTableInit()); setTableStyles(html, "apps", ".queue {width:6em}", ".ui {width:8em}"); - // Set the correct title. String reqState = $(APP_STATE); reqState = (reqState == null || reqState.isEmpty() ? "All" : reqState); setTitle(sjoin(reqState, "Applications")); + + String refreshInterval = request().getParameter("refresh"); + if (refreshInterval != null) + //sanitize input against SQL injection / XSS attacks + html.meta_http("refresh", Jsoup.clean(refreshInterval, Whitelist.none())); } protected void commonPreHead(Page.HTML<_> html) { diff --git hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebApp.java hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebApp.java index fb1e61d..c55e02d 100644 --- hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebApp.java +++ hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/webapp/TestRMWebApp.java @@ -24,10 +24,14 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import java.io.File; +import java.io.FileNotFoundException; import java.io.IOException; +import java.io.PrintWriter; import java.util.List; import java.util.concurrent.ConcurrentMap; +import org.apache.commons.io.FileUtils; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.yarn.api.records.ApplicationId; import org.apache.hadoop.yarn.api.records.NodeId; @@ -80,6 +84,7 @@ public void configure(Binder binder) { assertEquals("Applications", c.get(TITLE, "unknown")); } + @Test public void testView() { Injector injector = WebAppTests.createMockInjector(RMContext.class, mockRMContext(15, 1, 2, 8*GiB), @@ -141,6 +146,45 @@ public void configure(Binder binder) { } + @Test + public void testAutoRefresh() { + final RMContext rmContext = mockRMContext(3, 2, 12, 8 * GiB); + Injector injector = WebAppTests.createMockInjector(RMContext.class, + rmContext, + new Module() { + @Override + public void configure(Binder binder) { + try { + binder.bind(ResourceManager.class).toInstance(mockRm(rmContext)); + } catch (IOException e) { + throw new IllegalStateException(e); + } + } + }); + RmView instance = injector.getInstance(RmView.class); + when(instance.request().getParameter("refresh")).thenReturn("30"); + + //test that refresh header written out to HttpServletResponse + PrintWriter writer; + try { + File f = File.createTempFile("yarn-rm", ""); + writer = new PrintWriter(f.getAbsolutePath()); + when(instance.response().getWriter()).thenReturn(writer); + instance.render(); + writer.flush(); + assert(FileUtils.readFileToString(new File(f.getAbsolutePath()), "UTF-8") + .contains("\"refresh\" content=\"30\"")); + } catch (FileNotFoundException e) { + e.printStackTrace(); + assert(false); + } catch (IOException e) { + e.printStackTrace(); + assert(false); + } finally { + WebAppTests.flushOutput(injector); + } + } + public static RMContext mockRMContext(int numApps, int racks, int numNodes, int mbsPerNode) { final List apps = MockAsm.newApplications(numApps);