diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/docker/DockerClient.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/docker/DockerClient.java index 77c53a86970..18b5816c19d 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/docker/DockerClient.java +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/docker/DockerClient.java @@ -81,13 +81,13 @@ public String writeCommandToTempFile(DockerCommand cmd, String filePrefix) "'=' found in entry for docker command file, key = " + entry .getKey() + "; value = " + entry.getValue()); } - if (entry.getValue().contains("\n")) { + String value = StringUtils.join(",", entry.getValue()); + if (value.contains("\n")) { throw new ContainerExecutionException( "'\\n' found in entry for docker command file, key = " + entry - .getKey() + "; value = " + entry.getValue()); + .getKey() + "; value = " + value); } - printWriter.println(" " + entry.getKey() + "=" + StringUtils - .join(",", entry.getValue())); + printWriter.println(" " + entry.getKey() + "=" + value); } printWriter.close(); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/docker/TestDockerClient.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/docker/TestDockerClient.java new file mode 100644 index 00000000000..3ebccb5fb70 --- /dev/null +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/docker/TestDockerClient.java @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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.hadoop.yarn.server.nodemanager.containermanager.linux.runtime.docker; + +import org.apache.hadoop.conf.Configuration; +import org.apache.hadoop.fs.FileUtil; +import org.apache.hadoop.test.GenericTestUtils; +import org.apache.hadoop.yarn.api.records.ApplicationAttemptId; +import org.apache.hadoop.yarn.api.records.ApplicationId; +import org.apache.hadoop.yarn.api.records.ContainerId; +import org.apache.hadoop.yarn.server.nodemanager.containermanager.runtime.ContainerExecutionException; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; +import java.util.Arrays; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +/** Unit tests for DockerClient. */ +public class TestDockerClient { + private static final File TEST_ROOT_DIR = GenericTestUtils.getTestDir( + TestDockerClient.class.getName()); + + @Before + public void setup() { + TEST_ROOT_DIR.mkdirs(); + } + + @After + public void cleanup() { + FileUtil.fullyDelete(TEST_ROOT_DIR); + } + + @Test + public void testCommandValidation() throws Exception { + String absRoot = TEST_ROOT_DIR.getAbsolutePath(); + ApplicationId appId = ApplicationId.newInstance(1, 1); + ApplicationAttemptId attemptId = ApplicationAttemptId.newInstance(appId, 1); + ContainerId cid = ContainerId.newContainerId(attemptId, 1); + Configuration conf = new Configuration(); + conf.set("hadoop.tmp.dir", absRoot); + + DockerClient dockerClient = new DockerClient(conf); + try { + DockerRunCommand dockerCmd = new DockerRunCommand(cid.toString(), "user", + "image"); + dockerCmd.addCommandArguments("prop=bad", "val"); + dockerClient.writeCommandToTempFile(dockerCmd, cid.toString()); + fail("Expected exception writing command file"); + } catch (ContainerExecutionException e) { + assertTrue("Expected key validation error", e.getMessage() + .contains("'=' found in entry for docker command file")); + } + + try { + DockerRunCommand dockerCmd = new DockerRunCommand(cid.toString(), "user", + "image"); + dockerCmd.setOverrideCommandWithArgs(Arrays.asList("sleep","1000\n")); + dockerClient.writeCommandToTempFile(dockerCmd, cid.toString()); + fail("Expected exception writing command file"); + } catch (ContainerExecutionException e) { + assertTrue("Expected value validation error", e.getMessage() + .contains("'\\n' found in entry for docker command file")); + } + } +}