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/DockerLinuxContainerRuntime.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/DockerLinuxContainerRuntime.java index b70a4e1..a860ff5 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/DockerLinuxContainerRuntime.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/DockerLinuxContainerRuntime.java @@ -145,6 +145,10 @@ @InterfaceAudience.Private public static final String ENV_DOCKER_CONTAINER_LOCAL_RESOURCE_MOUNTS = "YARN_CONTAINER_RUNTIME_DOCKER_LOCAL_RESOURCE_MOUNTS"; + @InterfaceAudience.Private + public static final String ENV_DOCKER_CONTAINER_ENVIRONMENT_VARIABLES = + "YARN_CONTAINER_RUNTIME_DOCKER_ENVIRONMENT_VARIABLES"; + static final String CGROUPS_ROOT_DIRECTORY = "/sys/fs/cgroup"; @@ -481,6 +485,15 @@ public void launchContainer(ContainerRuntimeContext ctx) } } + if (environment.containsKey(ENV_DOCKER_CONTAINER_ENVIRONMENT_VARIABLES)) { + String envs = environment.get(ENV_DOCKER_CONTAINER_ENVIRONMENT_VARIABLES); + if (!envs.isEmpty()) { + for (String env : StringUtils.split(envs)) { + runCommand.setEnv(env); + } + } + } + if (allowPrivilegedContainerExecution(container)) { runCommand.setPrivileged(); } 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/DockerRunCommand.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/DockerRunCommand.java index f79f4ed..1aab940 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/DockerRunCommand.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/DockerRunCommand.java @@ -114,6 +114,11 @@ public DockerRunCommand setOverrideCommandWithArgs( return this; } + public DockerRunCommand setEnv(String env) { + super.addCommandArguments("-e " + env); + return this; + } + @Override public String getCommandWithArguments() { List argList = new ArrayList<>(); 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/TestDockerContainerRuntime.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/TestDockerContainerRuntime.java index 3253394..52e3d10 100644 --- 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/TestDockerContainerRuntime.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/TestDockerContainerRuntime.java @@ -881,6 +881,97 @@ public void testDockerStopOnQuitSignal() Charset.forName("UTF-8")); } + @Test + public void testDockerContainerLaunchWithEnvironmentVariable() + throws ContainerExecutionException, PrivilegedOperationException, + IOException { + DockerLinuxContainerRuntime runtime = new DockerLinuxContainerRuntime( + mockExecutor, mockCGroupsHandler); + runtime.initialize(conf); + + env.put("YARN_CONTAINER_RUNTIME_DOCKER_ENVIRONMENT_VARIABLES", + "HADOOP_CONF_DIR=/test/hadoop/conf"); + runtime.launchContainer(builder.build()); + + PrivilegedOperation op = capturePrivilegedOperationAndVerifyArgs(); + List args = op.getArguments(); + String dockerCommandFile = args.get(11); + + //This is the expected docker invocation for this case + StringBuffer expectedCommandTemplate = new StringBuffer("run --name=%1$s ") + .append("--user=%2$s -d ") + .append("--workdir=%3$s ") + .append("--net=host ") + .append(getExpectedTestCapabilitiesArgumentString()) + .append("-v %4$s:%4$s ") + .append("-v %5$s:%5$s ") + .append("-v %6$s:%6$s ") + .append("-v %7$s:%7$s ") + .append("-v %8$s:%8$s ") + .append("-e %9$s ") + .append("%10$s ") + .append("bash %11$s/launch_container.sh"); + + String expectedCommand = String + .format(expectedCommandTemplate.toString(), containerId, runAsUser, + containerWorkDir, containerLocalDirs.get(0), filecacheDirs.get(0), + containerWorkDir, containerLogDirs.get(0), userLocalDirs.get(0), + "HADOOP_CONF_DIR=/test/hadoop/conf", + image, containerWorkDir); + + List dockerCommands = Files.readAllLines(Paths.get + (dockerCommandFile), Charset.forName("UTF-8")); + + Assert.assertEquals(1, dockerCommands.size()); + Assert.assertEquals(expectedCommand, dockerCommands.get(0)); + } + + @Test + public void testDockerContainerLaunchWithEnvironmentVariables() + throws ContainerExecutionException, PrivilegedOperationException, + IOException { + DockerLinuxContainerRuntime runtime = new DockerLinuxContainerRuntime( + mockExecutor, mockCGroupsHandler); + runtime.initialize(conf); + + env.put("YARN_CONTAINER_RUNTIME_DOCKER_ENVIRONMENT_VARIABLES", + "HADOOP_CONF_DIR=/test/hadoop/conf,MYVAR=foo"); + runtime.launchContainer(builder.build()); + + PrivilegedOperation op = capturePrivilegedOperationAndVerifyArgs(); + List args = op.getArguments(); + String dockerCommandFile = args.get(11); + + //This is the expected docker invocation for this case + StringBuffer expectedCommandTemplate = new StringBuffer("run --name=%1$s ") + .append("--user=%2$s -d ") + .append("--workdir=%3$s ") + .append("--net=host ") + .append(getExpectedTestCapabilitiesArgumentString()) + .append("-v %4$s:%4$s ") + .append("-v %5$s:%5$s ") + .append("-v %6$s:%6$s ") + .append("-v %7$s:%7$s ") + .append("-v %8$s:%8$s ") + .append("-e %9$s ") + .append("-e %10$s ") + .append("%11$s ") + .append("bash %12$s/launch_container.sh"); + + String expectedCommand = String + .format(expectedCommandTemplate.toString(), containerId, runAsUser, + containerWorkDir, containerLocalDirs.get(0), filecacheDirs.get(0), + containerWorkDir, containerLogDirs.get(0), userLocalDirs.get(0), + "HADOOP_CONF_DIR=/test/hadoop/conf", "MYVAR=foo", + image, containerWorkDir); + + List dockerCommands = Files.readAllLines(Paths.get + (dockerCommandFile), Charset.forName("UTF-8")); + + Assert.assertEquals(1, dockerCommands.size()); + Assert.assertEquals(expectedCommand, dockerCommands.get(0)); + } + private Configuration getConfigurationWithMockContainerExecutor() { File f = new File("./src/test/resources/mock-container-executor"); if(!FileUtil.canExecute(f)) {