commit 8276759656e234eb41ee426ecd42191730a87733 Author: Eric Yang Date: Fri Sep 14 19:27:41 2018 -0400 YARN-8777. Added ability to run interactive docker exec in container-executor. Contributed by Eric Yang diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/docker-util.c b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/docker-util.c index 3884abf..70549f0 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/docker-util.c +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/docker-util.c @@ -432,6 +432,8 @@ int get_docker_command(const char *command_file, const struct configuration *con ret = get_docker_volume_command(command_file, conf, args); } else if (strcmp(DOCKER_START_COMMAND, command) == 0) { ret = get_docker_start_command(command_file, conf, args); + } else if (strcmp(DOCKER_EXEC_COMMAND, command) == 0) { + ret = get_docker_exec_command(command_file, conf, args); } else { ret = UNKNOWN_DOCKER_COMMAND; } @@ -819,6 +821,57 @@ free_and_exit: return ret; } +int get_docker_exec_command(const char *command_file, const struct configuration *conf, args *args) { + int ret = 0, i = 0; + char *container_name = NULL; + char **launch_command = NULL; + struct configuration command_config = {0, NULL}; + ret = read_and_verify_command_file(command_file, DOCKER_EXEC_COMMAND, &command_config); + if (ret != 0) { + goto free_and_exit; + } + + container_name = get_configuration_value("name", DOCKER_COMMAND_FILE_SECTION, &command_config); + if (container_name == NULL || validate_container_name(container_name) != 0) { + ret = INVALID_DOCKER_CONTAINER_NAME; + goto free_and_exit; + } + + ret = add_to_args(args, DOCKER_EXEC_COMMAND); + if (ret != 0) { + goto free_and_exit; + } + + ret = add_to_args(args, "-it"); + if (ret != 0) { + goto free_and_exit; + } + + ret = add_to_args(args, container_name); + if (ret != 0) { + goto free_and_exit; + } + + launch_command = get_configuration_values_delimiter("launch-command", DOCKER_COMMAND_FILE_SECTION, &command_config, + ","); + if (launch_command != NULL) { + for (i = 0; launch_command[i] != NULL; ++i) { + ret = add_to_args(args, launch_command[i]); + if (ret != 0) { + ret = BUFFER_TOO_SMALL; + goto free_and_exit; + } + } + } else { + ret = INVALID_COMMAND_FILE; + } +free_and_exit: + free(container_name); + free_configuration(&command_config); + free_values(launch_command); + return ret; +} + static int detach_container(const struct configuration *command_config, args *args) { return add_param_to_command(command_config, "detach", "-d", 0, args); } diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/docker-util.h b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/docker-util.h index 278dc53..62d58ef 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/docker-util.h +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/docker-util.h @@ -34,6 +34,7 @@ #define DOCKER_KILL_COMMAND "kill" #define DOCKER_VOLUME_COMMAND "volume" #define DOCKER_START_COMMAND "start" +#define DOCKER_EXEC_COMMAND "exec" #define DOCKER_ARG_MAX 1024 #define ARGS_INITIAL_VALUE { 0 }; @@ -186,6 +187,15 @@ int get_docker_volume_command(const char *command_file, const struct configurati int get_docker_start_command(const char* command_file, const struct configuration* conf, args *args); /** + * Get the Docker exec command line string. The function will verify that the params file is meant for the exec command. + * @param command_file File containing the params for the Docker start command + * @param conf Configuration struct containing the container-executor.cfg details + * @param args Buffer to construct argv + * @return Return code with 0 indicating success and non-zero codes indicating error + */ +int get_docker_exec_command(const char* command_file, const struct configuration* conf, args *args); + +/** * Give an error message for the supplied error code * @param error_code the error code * @return const string containing the error message diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/test/utils/test_docker_util.cc b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/test/utils/test_docker_util.cc index b289857..e74cf12 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/test/utils/test_docker_util.cc +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/test/utils/test_docker_util.cc @@ -1762,4 +1762,32 @@ namespace ContainerExecutor { free_configuration(&container_executor_cfg); } } + + TEST_F(TestDockerUtil, test_docker_exec) { + std::string container_executor_contents = "[docker]\n" + " docker.allowed.devices=/dev/test\n docker.trusted.registries=hadoop\n"; + write_file(container_executor_cfg_file, container_executor_contents); + int ret = read_config(container_executor_cfg_file.c_str(), &container_executor_cfg); + if (ret != 0) { + FAIL(); + } + ret = create_ce_file(); + if (ret != 0) { + std::cerr << "Could not create ce file, skipping test" << std::endl; + return; + } + + std::vector > file_cmd_vec; + file_cmd_vec.push_back(std::make_pair( + "[docker-command-execution]\n" + " docker-command=exec\n name=container_e1_12312_11111_02_000001\n launch-command=bash", + "exec -it container_e1_12312_11111_02_000001 bash")); + + std::vector > bad_file_cmd_vec; + + bad_file_cmd_vec.push_back(std::make_pair( + "[docker-command-execution]\n docker-command=exec\n image=hadoop/docker-image\n user=nobody", + static_cast(INVALID_DOCKER_CONTAINER_NAME))); + run_docker_command_test(file_cmd_vec, bad_file_cmd_vec, get_docker_exec_command); + } }