diff --git a/hadoop-yarn-project/CHANGES.txt b/hadoop-yarn-project/CHANGES.txt index f8798cad159..6276b5e61b8 100644 --- a/hadoop-yarn-project/CHANGES.txt +++ b/hadoop-yarn-project/CHANGES.txt @@ -461,6 +461,9 @@ Release 2.4.0 - UNRELEASED ATTEMPT_FINISHED event at ACCEPTED state that can happen after RM restarts. (Jian He via vinodkv) + YARN-1789. ApplicationSummary does not escape newlines in the app name + (Tsuyoshi OZAWA via jlowe) + Release 2.3.1 - UNRELEASED INCOMPATIBLE CHANGES diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMAppManager.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMAppManager.java index e4bcd4fb230..51024cfcb85 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMAppManager.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/main/java/org/apache/hadoop/yarn/server/resourcemanager/RMAppManager.java @@ -116,8 +116,10 @@ public class RMAppManager implements EventHandler, } SummaryBuilder add(String key, T value) { - return _add(key, StringUtils.escapeString(String.valueOf(value), - StringUtils.ESCAPE_CHAR, charsToEscape)); + String escapedString = StringUtils.escapeString(String.valueOf(value), + StringUtils.ESCAPE_CHAR, charsToEscape).replaceAll("\n", "\\\\n") + .replaceAll("\r", "\\\\r"); + return _add(key, escapedString); } SummaryBuilder add(SummaryBuilder summary) { diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestAppManager.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestAppManager.java index 19031f91356..7ce3fe66a34 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestAppManager.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-resourcemanager/src/test/java/org/apache/hadoop/yarn/server/resourcemanager/TestAppManager.java @@ -19,6 +19,9 @@ package org.apache.hadoop.yarn.server.resourcemanager; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.apache.hadoop.yarn.server.resourcemanager.rmapp.RMAppImpl; import static org.mockito.Matchers.isA; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; @@ -74,6 +77,7 @@ import com.google.common.collect.Maps; */ public class TestAppManager{ + private Log LOG = LogFactory.getLog(TestAppManager.class); private static RMAppEventType appEventType = RMAppEventType.KILL; public synchronized RMAppEventType getAppEventType() { @@ -548,6 +552,29 @@ public class TestAppManager{ } } + @Test (timeout = 30000) + public void testEscapeApplicationSummary() { + RMApp app = mock(RMAppImpl.class); + when(app.getApplicationId()).thenReturn( + ApplicationId.newInstance(100L, 1)); + when(app.getName()).thenReturn("Multiline\n\n\r\rAppName"); + when(app.getUser()).thenReturn("Multiline\n\n\r\rUserName"); + when(app.getQueue()).thenReturn("Multiline\n\n\r\rQueueName"); + when(app.getState()).thenReturn(RMAppState.RUNNING); + + RMAppManager.ApplicationSummary.SummaryBuilder summary = + new RMAppManager.ApplicationSummary().createAppSummary(app); + String msg = summary.toString(); + LOG.info("summary: " + msg); + Assert.assertFalse(msg.contains("\n")); + Assert.assertFalse(msg.contains("\r")); + + String escaped = "\\n\\n\\r\\r"; + Assert.assertTrue(msg.contains("Multiline" + escaped +"AppName")); + Assert.assertTrue(msg.contains("Multiline" + escaped +"UserName")); + Assert.assertTrue(msg.contains("Multiline" + escaped +"QueueName")); + } + private static ResourceScheduler mockResourceScheduler() { ResourceScheduler scheduler = mock(ResourceScheduler.class); when(scheduler.getMinimumResourceCapability()).thenReturn(