commit 07a45df3c5d1899f9b8aa8dec0a9687a17490848 Author: Eric Yang Date: Wed Apr 25 21:24:09 2018 -0400 YARN-8207. Use execvp for docker container launch. 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/container-executor.c b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.c index d9ed070..d62bb68 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.c +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.c @@ -20,6 +20,7 @@ #include "container-executor.h" #include "utils/docker-util.h" #include "utils/path-utils.h" +#include "utils/string-utils.h" #include "util.h" #include "config.h" @@ -67,6 +68,7 @@ #endif static const int DEFAULT_MIN_USERID = 1000; +static const int MAX_RETRIES = 10; static const char* DEFAULT_BANNED_USERS[] = {"yarn", "mapred", "hdfs", "bin", 0}; @@ -93,6 +95,8 @@ static gid_t nm_gid = -1; struct configuration CFG = {.size=0, .sections=NULL}; struct section executor_cfg = {.size=0, .kv_pairs=NULL}; +static char *chosen_container_log_dir = NULL; + char *concatenate(char *concat_pattern, char *return_path_name, int numArgs, ...); @@ -737,7 +741,6 @@ static int create_container_directories(const char* user, const char *app_id, result = OUT_OF_MEMORY; } else { sprintf(combined_name, "%s/%s", app_id, container_id); - char* const* log_dir_ptr; for(log_dir_ptr = log_dir; *log_dir_ptr != NULL; ++log_dir_ptr) { char *container_log_dir = get_app_log_directory(*log_dir_ptr, combined_name); @@ -756,7 +759,7 @@ static int create_container_directories(const char* user, const char *app_id, free(container_log_dir); } else { result = 0; - free(container_log_dir); + chosen_container_log_dir = container_log_dir; } } free(combined_name); @@ -1094,7 +1097,6 @@ int initialize_user(const char *user, char* const* local_dirs) { } int create_log_dirs(const char *app_id, char * const * log_dirs) { - char* const* log_root; char *any_one_app_log_dir = NULL; for(log_root=log_dirs; *log_root != NULL; ++log_root) { @@ -1130,6 +1132,31 @@ char* get_container_log_directory(const char *log_root, const char* app_id, container_id); } +char *init_log_path(const char *container_log_dir, const char *logfile) { + char *tmp_buffer = NULL; + tmp_buffer = make_string("%s/%s", container_log_dir, logfile); + + mode_t permissions = S_IRUSR | S_IWUSR | S_IRGRP; + int fd = open(tmp_buffer, O_CREAT | O_WRONLY, permissions); + if (fd >= 0) { + close(fd); + if (change_owner(tmp_buffer, user_detail->pw_uid, user_detail->pw_gid) != 0) { + fprintf(ERRORFILE, "Failed to chown %s to %d:%d: %s\n", tmp_buffer, user_detail->pw_uid, user_detail->pw_gid, + strerror(errno)); + tmp_buffer = NULL; + } else if (chmod(tmp_buffer, permissions) != 0) { + fprintf(ERRORFILE, "Can't chmod %s - %s\n", + tmp_buffer, strerror(errno)); + tmp_buffer = NULL; + } + } else { + fprintf(ERRORFILE, "Failed to create file %s - %s\n", tmp_buffer, + strerror(errno)); + tmp_buffer = NULL; + } + return tmp_buffer; +} + int create_container_log_dirs(const char *container_id, const char *app_id, char * const * log_dirs) { char* const* log_root; @@ -1275,11 +1302,10 @@ int initialize_app(const char *user, const char *app_id, return -1; } -char *construct_docker_command(const char *command_file) { +char **construct_docker_command(const char *command_file) { int ret = 0; - size_t command_size = MIN(sysconf(_SC_ARG_MAX), 128*1024); - char *buffer = alloc_and_clear_memory(command_size, sizeof(char)); - + struct argv buffer; + reset(&buffer); uid_t user = geteuid(); gid_t group = getegid(); if (change_effective_user(nm_uid, nm_gid) != 0) { @@ -1287,8 +1313,7 @@ char *construct_docker_command(const char *command_file) { fflush(ERRORFILE); exit(SETUID_OPER_FAILED); } - - ret = get_docker_command(command_file, &CFG, buffer, command_size); + ret = get_docker_command(command_file, &CFG, &buffer); if (ret != 0) { fprintf(ERRORFILE, "Error constructing docker command, docker error code=%d, error message='%s'\n", ret, get_docker_error_message(ret)); @@ -1302,19 +1327,12 @@ char *construct_docker_command(const char *command_file) { exit(SETUID_OPER_FAILED); } - return buffer; + return buffer.out; } int run_docker(const char *command_file) { - char* docker_command = construct_docker_command(command_file); + char **args = construct_docker_command(command_file); char* docker_binary = get_docker_binary(&CFG); - size_t command_size = MIN(sysconf(_SC_ARG_MAX), 128*1024); - - char* docker_command_with_binary = alloc_and_clear_memory(command_size, sizeof(char)); - snprintf(docker_command_with_binary, command_size, "%s %s", docker_binary, docker_command); - fprintf(LOGFILE, "Invoking '%s'\n", docker_command_with_binary); - char **args = split_delimiter(docker_command_with_binary, " "); - int exit_code = -1; if (execvp(docker_binary, args) != 0) { fprintf(ERRORFILE, "Couldn't execute the container launch with args %s - %s", @@ -1323,8 +1341,6 @@ int run_docker(const char *command_file) { fflush(ERRORFILE); free(docker_binary); free(args); - free(docker_command_with_binary); - free(docker_command); exit_code = DOCKER_RUN_FAILED; } else { exit_code = 0; @@ -1422,9 +1438,9 @@ int create_local_dirs(const char * user, const char *app_id, goto cleanup; } - // Copy script file with permissions 700 + // Copy script file with permissions 751 if (copy_file(container_file_source, script_name, script_file_dest,S_IRWXU) != 0) { - fprintf(ERRORFILE, "Could not create copy file %d %s\n", container_file_source, script_file_dest); + fprintf(ERRORFILE, "Could not create copy file %s %s (%d)\n", script_name, script_file_dest, container_file_source); fflush(ERRORFILE); exit_code = COULD_NOT_CREATE_SCRIPT_COPY; goto cleanup; @@ -1485,25 +1501,15 @@ int launch_docker_container_as_user(const char * user, const char *app_id, char *cred_file_dest = NULL; char *exit_code_file = NULL; char *docker_command_with_binary = NULL; - char *docker_wait_command = NULL; char *docker_inspect_command = NULL; - char *docker_rm_command = NULL; char *docker_inspect_exitcode_command = NULL; int container_file_source =-1; int cred_file_source = -1; - size_t command_size = MIN(sysconf(_SC_ARG_MAX), 128*1024); - - docker_command_with_binary = (char *) alloc_and_clear_memory(command_size, sizeof(char)); - docker_wait_command = (char *) alloc_and_clear_memory(command_size, sizeof(char)); - docker_inspect_command = (char *) alloc_and_clear_memory(command_size, sizeof(char)); - docker_rm_command = (char *) alloc_and_clear_memory(command_size, sizeof(char)); - docker_inspect_exitcode_command = (char *) alloc_and_clear_memory(command_size, sizeof(char)); - gid_t user_gid = getegid(); uid_t prev_uid = geteuid(); - char *docker_command = NULL; + char **docker_command = NULL; char *docker_binary = NULL; fprintf(LOGFILE, "Creating script paths...\n"); @@ -1553,37 +1559,81 @@ int launch_docker_container_as_user(const char * user, const char *app_id, goto cleanup; } - snprintf(docker_command_with_binary, command_size, "%s %s", docker_binary, docker_command); + char *so = init_log_path(chosen_container_log_dir, "stdout.txt"); + if (so == NULL) { + exit_code = UNABLE_TO_EXECUTE_CONTAINER_SCRIPT; + goto cleanup; + } + char *se = init_log_path(chosen_container_log_dir, "stderr.txt"); + if (se == NULL) { + exit_code = UNABLE_TO_EXECUTE_CONTAINER_SCRIPT; + goto cleanup; + } + + docker_command_with_binary = flatten(docker_command); - fprintf(LOGFILE, "Launching docker container...\n"); - fprintf(LOGFILE, "Docker run command: %s\n", docker_command_with_binary); - FILE* start_docker = popen(docker_command_with_binary, "r"); - if (WEXITSTATUS(pclose (start_docker)) != 0) - { + // Launch container + pid_t child_pid = fork(); + if (child_pid == -1) { fprintf (ERRORFILE, - "Could not invoke docker %s.\n", docker_command_with_binary); + "Could not invoke docker %s.\n", docker_command_with_binary); fflush(ERRORFILE); exit_code = UNABLE_TO_EXECUTE_CONTAINER_SCRIPT; goto cleanup; } - snprintf(docker_inspect_command, command_size, + if (child_pid == 0) { + FILE* so_fd = fopen(so, "a+"); + if (so_fd == NULL) { + fprintf(ERRORFILE, "Could not append to %s\n", so); + exit_code = UNABLE_TO_EXECUTE_CONTAINER_SCRIPT; + goto cleanup; + } + FILE* se_fd = fopen(se, "a+"); + if (se_fd == NULL) { + fprintf(ERRORFILE, "Could not append to %s\n", se); + exit_code = UNABLE_TO_EXECUTE_CONTAINER_SCRIPT; + fclose(so_fd); + goto cleanup; + } + fprintf(so_fd, "Launching docker container...\n"); + fprintf(so_fd, "Docker run command: %s\n", docker_command_with_binary); + fclose(so_fd); + fclose(se_fd); + execvp(docker_binary, docker_command); + fprintf(LOGFILE, "failed to execute docker command! error: %s\n", strerror(errno)); + return UNABLE_TO_EXECUTE_CONTAINER_SCRIPT; + } + free(so); + free(se); + + int pid = 0; + int res = 0; + int count = 0; + docker_inspect_command = make_string( "%s inspect --format {{.State.Pid}} %s", docker_binary, container_id); - fprintf(LOGFILE, "Inspecting docker container...\n"); - fprintf(LOGFILE, "Docker inspect command: %s\n", docker_inspect_command); - FILE* inspect_docker = popen(docker_inspect_command, "r"); - int pid = 0; - int res = fscanf (inspect_docker, "%d", &pid); - fprintf(LOGFILE, "pid from docker inspect: %d\n", pid); - if (pclose (inspect_docker) != 0 || res <= 0) - { - fprintf (ERRORFILE, - "Could not inspect docker to get pid %s.\n", docker_inspect_command); - fflush(ERRORFILE); - exit_code = UNABLE_TO_EXECUTE_CONTAINER_SCRIPT; - goto cleanup; + // check for docker container pid + while (count < MAX_RETRIES) { + fprintf(LOGFILE, "Inspecting docker container...\n"); + fprintf(LOGFILE, "Docker inspect command: %s\n", docker_inspect_command); + fflush(LOGFILE); + FILE* inspect_docker = popen(docker_inspect_command, "r"); + res = fscanf (inspect_docker, "%d", &pid); + fprintf(LOGFILE, "pid from docker inspect: %d\n", pid); + if (pclose (inspect_docker) != 0 || res <= 0) { + fprintf (ERRORFILE, + "Could not inspect docker to get pid %s.\n", docker_inspect_command); + fflush(ERRORFILE); + exit_code = UNABLE_TO_EXECUTE_CONTAINER_SCRIPT; + } else { + if (pid != 0) { + break; + } + } + sleep(3); + count++; } if (pid != 0) { @@ -1615,10 +1665,10 @@ int launch_docker_container_as_user(const char * user, const char *app_id, } fprintf(LOGFILE, "Waiting for docker container to finish.\n"); + + // wait for pid to finish #ifdef __linux - size_t command_size = MIN(sysconf(_SC_ARG_MAX), 128*1024); - char* proc_pid_path = alloc_and_clear_memory(command_size, sizeof(char)); - snprintf(proc_pid_path, command_size, "%s/%d", PROC_PATH, pid); + char* proc_pid_path = make_string("%s/%d", PROC_PATH, pid); while (dir_exists(proc_pid_path) == 0) { sleep(1); } @@ -1633,7 +1683,8 @@ int launch_docker_container_as_user(const char * user, const char *app_id, #endif } - sprintf(docker_inspect_exitcode_command, + // discover container exit code + docker_inspect_exitcode_command = make_string( "%s inspect --format {{.State.ExitCode}} %s", docker_binary, container_id); fprintf(LOGFILE, "Obtaining the exit code...\n"); @@ -1685,9 +1736,8 @@ cleanup: free(script_file_dest); free(cred_file_dest); free(docker_command_with_binary); - free(docker_wait_command); free(docker_inspect_command); - free(docker_rm_command); + free(chosen_container_log_dir); return exit_code; } @@ -2376,3 +2426,31 @@ int traffic_control_read_stats(char *command_file) { struct configuration* get_cfg() { return &CFG; } + +/** + * Flatten docker launch command + */ +char* flatten(char **args) { + size_t string_len = 0; + size_t current_len = 0; + size_t total = 1; + for (int i = 0; args[i] != NULL; i++) { + total = total + strlen(args[i]) + 1; + } + char *buffer = (char *) malloc(total * sizeof(char)); + for (int i = 0; args[i] != NULL; i++) { + string_len = strlen(args[i]); + if (string_len != 0) { + strncpy(buffer + current_len, args[i], string_len); + current_len = current_len + string_len; + if (args[i +1] != NULL) { + strncpy(buffer + current_len, " ", 1); + current_len++; + } + } + } + buffer[current_len] = '\0'; + return buffer; +} + + diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.h b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.h index 7c3ed77..970aff6 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.h +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/container-executor.h @@ -276,3 +276,8 @@ int execute_regex_match(const char *regex_str, const char *input); int validate_docker_image_name(const char *image_name); struct configuration* get_cfg(); + +/** + * Flatten docker launch command + */ +char* flatten(char **args); diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/util.c b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/util.c index eea3e10..4a727d3 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/util.c +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/util.c @@ -193,3 +193,4 @@ void quote_and_append_arg(char **str, size_t *size, const char* param, const cha sprintf(cur_ptr, append_format, param, tmp); free(tmp); } + 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 6795bd8..b9a53f7 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 @@ -31,6 +31,7 @@ #include #include #include +#include static int read_and_verify_command_file(const char *command_file, const char *docker_command, struct configuration *command_config) { @@ -47,29 +48,43 @@ static int read_and_verify_command_file(const char *command_file, const char *do return ret; } -static int add_to_buffer(char *buff, const size_t bufflen, const char *string) { - size_t current_len = strlen(buff); - size_t string_len = strlen(string); - if (current_len + string_len < bufflen - 1) { - strncpy(buff + current_len, string, string_len); - buff[current_len + string_len] = '\0'; +static int add_to_buffer(struct argv *argv, const char *string) { + if (!string[0]) { return 0; } - return -1; + if (argv->index > DOCKER_ARG_MAX) { + return -1; + } + char *clone = strdup(string); + if (clone == NULL) { + return -1; + } + if (argv->out != NULL) { + argv->out[argv->index] = clone; + } + argv->index++; + return 0; +} + +void free_buffer(struct argv *argv) { + if (argv != NULL) { + for (int i = 0; i < argv->index; i++) { + free(argv->out[i]); + } + } } static int add_param_to_command(const struct configuration *command_config, const char *key, const char *param, - const int with_argument, char *out, const size_t outlen) { - size_t tmp_buffer_size = 4096; + const int with_argument, struct argv *argv) { int ret = 0; - char *tmp_buffer = (char *) alloc_and_clear_memory(tmp_buffer_size, sizeof(char)); + char *tmp_buffer = NULL; char *value = get_configuration_value(key, DOCKER_COMMAND_FILE_SECTION, command_config); if (value != NULL) { if (with_argument) { - quote_and_append_arg(&tmp_buffer, &tmp_buffer_size, param, value); - ret = add_to_buffer(out, outlen, tmp_buffer); + tmp_buffer = make_string("%s%s", param, value); + ret = add_to_buffer(argv, tmp_buffer); } else if (strcmp(value, "true") == 0) { - ret = add_to_buffer(out, outlen, param); + ret = add_to_buffer(argv, param); } free(value); if (ret != 0) { @@ -141,7 +156,8 @@ static int add_param_to_command_if_allowed(const struct configuration *command_c const struct configuration *executor_cfg, const char *key, const char *allowed_key, const char *param, const int multiple_values, const char prefix, - char *out, const size_t outlen) { + struct argv *argv) { + int previous = argv->index; size_t tmp_buffer_size = 4096; char *tmp_buffer = (char *) alloc_and_clear_memory(tmp_buffer_size, sizeof(char)); char *tmp_ptr = NULL; @@ -174,7 +190,6 @@ static int add_param_to_command_if_allowed(const struct configuration *command_c if (permitted_values != NULL) { // Values are user requested. for (i = 0; values[i] != NULL; ++i) { - memset(tmp_buffer, 0, tmp_buffer_size); permitted = 0; if(prefix != 0) { tmp_ptr = strchr(values[i], prefix); @@ -214,8 +229,8 @@ static int add_param_to_command_if_allowed(const struct configuration *command_c } } if (permitted == 1) { - quote_and_append_arg(&tmp_buffer, &tmp_buffer_size, param, values[i]); - ret = add_to_buffer(out, outlen, tmp_buffer); + tmp_buffer = make_string("%s%s", param, values[i]); + ret = add_to_buffer(argv, tmp_buffer); if (ret != 0) { fprintf(ERRORFILE, "Output buffer too small\n"); ret = BUFFER_TOO_SMALL; @@ -240,13 +255,13 @@ static int add_param_to_command_if_allowed(const struct configuration *command_c free_values(permitted_values); free(tmp_buffer); if (ret != 0) { - memset(out, 0, outlen); + argv->index=previous; } return ret; } -static int add_docker_config_param(const struct configuration *command_config, char *out, const size_t outlen) { - return add_param_to_command(command_config, "docker-config", "--config=", 1, out, outlen); +static int add_docker_config_param(const struct configuration *command_config, struct argv *argv) { + return add_param_to_command(command_config, "docker-config", "--config=", 1, argv); } static int validate_volume_name(const char *volume_name) { @@ -338,7 +353,7 @@ int docker_module_enabled(const struct configuration *conf) { return 0; } -int get_docker_command(const char *command_file, const struct configuration *conf, char *out, const size_t outlen) { +int get_docker_command(const char *command_file, const struct configuration *conf, struct argv *argv) { int ret = 0; struct configuration command_config = {0, NULL}; @@ -349,23 +364,23 @@ int get_docker_command(const char *command_file, const struct configuration *con char *command = get_configuration_value("docker-command", DOCKER_COMMAND_FILE_SECTION, &command_config); if (strcmp(DOCKER_INSPECT_COMMAND, command) == 0) { - return get_docker_inspect_command(command_file, conf, out, outlen); + return get_docker_inspect_command(command_file, conf, argv); } else if (strcmp(DOCKER_KILL_COMMAND, command) == 0) { - return get_docker_kill_command(command_file, conf, out, outlen); + return get_docker_kill_command(command_file, conf, argv); } else if (strcmp(DOCKER_LOAD_COMMAND, command) == 0) { - return get_docker_load_command(command_file, conf, out, outlen); + return get_docker_load_command(command_file, conf, argv); } else if (strcmp(DOCKER_PULL_COMMAND, command) == 0) { - return get_docker_pull_command(command_file, conf, out, outlen); + return get_docker_pull_command(command_file, conf, argv); } else if (strcmp(DOCKER_RM_COMMAND, command) == 0) { - return get_docker_rm_command(command_file, conf, out, outlen); + return get_docker_rm_command(command_file, conf, argv); } else if (strcmp(DOCKER_RUN_COMMAND, command) == 0) { - return get_docker_run_command(command_file, conf, out, outlen); + return get_docker_run_command(command_file, conf, argv); } else if (strcmp(DOCKER_STOP_COMMAND, command) == 0) { - return get_docker_stop_command(command_file, conf, out, outlen); + return get_docker_stop_command(command_file, conf, argv); } else if (strcmp(DOCKER_VOLUME_COMMAND, command) == 0) { - return get_docker_volume_command(command_file, conf, out, outlen); + return get_docker_volume_command(command_file, conf, argv); } else if (strcmp(DOCKER_START_COMMAND, command) == 0) { - return get_docker_start_command(command_file, conf, out, outlen); + return get_docker_start_command(command_file, conf, argv); } else { return UNKNOWN_DOCKER_COMMAND; } @@ -397,10 +412,10 @@ static int value_permitted(const struct configuration* executor_cfg, return found; } -int get_docker_volume_command(const char *command_file, const struct configuration *conf, char *out, - const size_t outlen) { +int get_docker_volume_command(const char *command_file, const struct configuration *conf, struct argv *argv) { + argv->index = 0; int ret = 0; - char *driver = NULL, *volume_name = NULL, *sub_command = NULL, *format = NULL; + char *driver = NULL, *volume_name = NULL, *sub_command = NULL, *format = NULL, *docker = NULL; struct configuration command_config = {0, NULL}; ret = read_and_verify_command_file(command_file, DOCKER_VOLUME_COMMAND, &command_config); if (ret != 0) { @@ -416,15 +431,20 @@ int get_docker_volume_command(const char *command_file, const struct configurati goto cleanup; } - memset(out, 0, outlen); + docker = get_docker_binary(conf); + ret = add_to_buffer(argv, docker); + if (ret != 0) { + ret = BUFFER_TOO_SMALL; + goto cleanup; + } - ret = add_docker_config_param(&command_config, out, outlen); + ret = add_docker_config_param(&command_config, argv); if (ret != 0) { ret = BUFFER_TOO_SMALL; goto cleanup; } - ret = add_to_buffer(out, outlen, DOCKER_VOLUME_COMMAND); + ret = add_to_buffer(argv, DOCKER_VOLUME_COMMAND); if (ret != 0) { goto cleanup; } @@ -443,17 +463,14 @@ int get_docker_volume_command(const char *command_file, const struct configurati goto cleanup; } - ret = add_to_buffer(out, outlen, " create"); - if (ret != 0) { - goto cleanup; - } - - ret = add_to_buffer(out, outlen, " --name="); + ret = add_to_buffer(argv, "create"); if (ret != 0) { goto cleanup; } - ret = add_to_buffer(out, outlen, volume_name); + char *name_buffer = make_string("--name=%s", volume_name); + ret = add_to_buffer(argv, name_buffer); + free(name_buffer); if (ret != 0) { goto cleanup; } @@ -465,29 +482,23 @@ int get_docker_volume_command(const char *command_file, const struct configurati goto cleanup; } - ret = add_to_buffer(out, outlen, " --driver="); - if (ret != 0) { - goto cleanup; - } - - ret = add_to_buffer(out, outlen, driver); + char *driver_buffer = make_string("--driver=%s", driver); + ret = add_to_buffer(argv, driver_buffer); + free(driver_buffer); if (ret != 0) { goto cleanup; } } else if (0 == strcmp(sub_command, "ls")) { format = get_configuration_value("format", DOCKER_COMMAND_FILE_SECTION, &command_config); - ret = add_to_buffer(out, outlen, " ls"); + ret = add_to_buffer(argv, "ls"); if (ret != 0) { goto cleanup; } - if (format) { - ret = add_to_buffer(out, outlen, " --format="); - if (ret != 0) { - goto cleanup; - } - ret = add_to_buffer(out, outlen, format); + char *tmp_buffer = make_string("--format=%s", format); + ret = add_to_buffer(argv, tmp_buffer); + free(tmp_buffer); if (ret != 0) { goto cleanup; } @@ -502,17 +513,17 @@ cleanup: // clean up out buffer if (ret != 0) { - out[0] = 0; + free_buffer(argv); } return ret; } -int get_docker_inspect_command(const char *command_file, const struct configuration *conf, char *out, - const size_t outlen) { +int get_docker_inspect_command(const char *command_file, const struct configuration *conf, struct argv *argv) { const char *valid_format_strings[] = { "{{.State.Status}}", "{{range(.NetworkSettings.Networks)}}{{.IPAddress}},{{end}}{{.Config.Hostname}}" }; int ret = 0, i = 0, valid_format = 0; - char *format = NULL, *container_name = NULL; + argv->index = 0; + char *format = NULL, *container_name = NULL, *tmp_buffer = NULL; struct configuration command_config = {0, NULL}; ret = read_and_verify_command_file(command_file, DOCKER_INSPECT_COMMAND, &command_config); if (ret != 0) { @@ -542,32 +553,30 @@ int get_docker_inspect_command(const char *command_file, const struct configurat return INVALID_DOCKER_INSPECT_FORMAT; } - memset(out, 0, outlen); + char *docker = get_docker_binary(conf); + ret = add_to_buffer(argv, docker); + if (ret != 0) { + goto free_and_exit; + } - ret = add_docker_config_param(&command_config, out, outlen); + ret = add_docker_config_param(&command_config, argv); if (ret != 0) { free(container_name); free(format); return BUFFER_TOO_SMALL; } - ret = add_to_buffer(out, outlen, DOCKER_INSPECT_COMMAND); - if (ret != 0) { - goto free_and_exit; - } - ret = add_to_buffer(out, outlen, " --format="); - if (ret != 0) { - goto free_and_exit; - } - ret = add_to_buffer(out, outlen, format); + ret = add_to_buffer(argv, DOCKER_INSPECT_COMMAND); if (ret != 0) { goto free_and_exit; } - ret = add_to_buffer(out, outlen, " "); + tmp_buffer = make_string("--format=%s", format); + ret = add_to_buffer(argv, tmp_buffer); if (ret != 0) { goto free_and_exit; } - ret = add_to_buffer(out, outlen, container_name); + free(tmp_buffer); + ret = add_to_buffer(argv, container_name); if (ret != 0) { goto free_and_exit; } @@ -578,14 +587,13 @@ int get_docker_inspect_command(const char *command_file, const struct configurat free_and_exit: free(format); free(container_name); + free(docker); return BUFFER_TOO_SMALL; } -int get_docker_load_command(const char *command_file, const struct configuration *conf, char *out, const size_t outlen) { +int get_docker_load_command(const char *command_file, const struct configuration *conf, struct argv *argv) { int ret = 0; char *image_name = NULL; - size_t tmp_buffer_size = 1024; - char *tmp_buffer = NULL; struct configuration command_config = {0, NULL}; ret = read_and_verify_command_file(command_file, DOCKER_LOAD_COMMAND, &command_config); if (ret != 0) { @@ -597,19 +605,24 @@ int get_docker_load_command(const char *command_file, const struct configuration return INVALID_DOCKER_IMAGE_NAME; } - memset(out, 0, outlen); + char *docker = get_docker_binary(conf); + ret = add_to_buffer(argv, docker); + if (ret != 0) { + free(docker); + return BUFFER_TOO_SMALL; + } + free(docker); - ret = add_docker_config_param(&command_config, out, outlen); + ret = add_docker_config_param(&command_config, argv); if (ret != 0) { free(image_name); return BUFFER_TOO_SMALL; } - ret = add_to_buffer(out, outlen, DOCKER_LOAD_COMMAND); + ret = add_to_buffer(argv, DOCKER_LOAD_COMMAND); if (ret == 0) { - tmp_buffer = (char *) alloc_and_clear_memory(tmp_buffer_size, sizeof(char)); - quote_and_append_arg(&tmp_buffer, &tmp_buffer_size, " --i=", image_name); - ret = add_to_buffer(out, outlen, tmp_buffer); + char *tmp_buffer = make_string("--i=%s", image_name); + ret = add_to_buffer(argv, tmp_buffer); free(tmp_buffer); free(image_name); if (ret != 0) { @@ -626,11 +639,9 @@ static int validate_docker_image_name(const char *image_name) { return execute_regex_match(regex_str, image_name); } -int get_docker_pull_command(const char *command_file, const struct configuration *conf, char *out, const size_t outlen) { +int get_docker_pull_command(const char *command_file, const struct configuration *conf, struct argv *argv) { int ret = 0; char *image_name = NULL; - size_t tmp_buffer_size = 1024; - char *tmp_buffer = NULL; struct configuration command_config = {0, NULL}; ret = read_and_verify_command_file(command_file, DOCKER_PULL_COMMAND, &command_config); if (ret != 0) { @@ -642,30 +653,33 @@ int get_docker_pull_command(const char *command_file, const struct configuration return INVALID_DOCKER_IMAGE_NAME; } - memset(out, 0, outlen); + char *docker = get_docker_binary(conf); + ret = add_to_buffer(argv, docker); + if (ret != 0) { + goto free_pull; + } - ret = add_docker_config_param(&command_config, out, outlen); + ret = add_docker_config_param(&command_config, argv); if (ret != 0) { - return BUFFER_TOO_SMALL; + goto free_pull; } - ret = add_to_buffer(out, outlen, DOCKER_PULL_COMMAND); + ret = add_to_buffer(argv, DOCKER_PULL_COMMAND); if (ret == 0) { - tmp_buffer = (char *) alloc_and_clear_memory(tmp_buffer_size, sizeof(char)); - quote_and_append_arg(&tmp_buffer, &tmp_buffer_size, " ", image_name); - ret = add_to_buffer(out, outlen, tmp_buffer); - free(tmp_buffer); + ret = add_to_buffer(argv, image_name); free(image_name); if (ret != 0) { - return BUFFER_TOO_SMALL; + goto free_pull; } return 0; } + free_pull: free(image_name); + free(docker); return BUFFER_TOO_SMALL; } -int get_docker_rm_command(const char *command_file, const struct configuration *conf, char *out, const size_t outlen) { +int get_docker_rm_command(const char *command_file, const struct configuration *conf, struct argv *argv) { int ret = 0; char *container_name = NULL; struct configuration command_config = {0, NULL}; @@ -679,19 +693,22 @@ int get_docker_rm_command(const char *command_file, const struct configuration * return INVALID_DOCKER_CONTAINER_NAME; } - memset(out, 0, outlen); + char *docker = get_docker_binary(conf); + ret = add_to_buffer(argv, docker); + if (ret != 0) { + free(docker); + return BUFFER_TOO_SMALL; + } + free(docker); - ret = add_docker_config_param(&command_config, out, outlen); + ret = add_docker_config_param(&command_config, argv); if (ret != 0) { return BUFFER_TOO_SMALL; } - ret = add_to_buffer(out, outlen, DOCKER_RM_COMMAND); + ret = add_to_buffer(argv, DOCKER_RM_COMMAND); if (ret == 0) { - ret = add_to_buffer(out, outlen, " "); - if (ret == 0) { - ret = add_to_buffer(out, outlen, container_name); - } + ret = add_to_buffer(argv, container_name); free(container_name); if (ret != 0) { return BUFFER_TOO_SMALL; @@ -703,7 +720,7 @@ int get_docker_rm_command(const char *command_file, const struct configuration * } int get_docker_stop_command(const char *command_file, const struct configuration *conf, - char *out, const size_t outlen) { + struct argv *argv) { int ret = 0; size_t len = 0, i = 0; char *value = NULL; @@ -719,14 +736,20 @@ int get_docker_stop_command(const char *command_file, const struct configuration return INVALID_DOCKER_CONTAINER_NAME; } - memset(out, 0, outlen); + char *docker = get_docker_binary(conf); + ret = add_to_buffer(argv, docker); + if (ret != 0) { + free(docker); + return BUFFER_TOO_SMALL; + } + free(docker); - ret = add_docker_config_param(&command_config, out, outlen); + ret = add_docker_config_param(&command_config, argv); if (ret != 0) { return BUFFER_TOO_SMALL; } - ret = add_to_buffer(out, outlen, DOCKER_STOP_COMMAND); + ret = add_to_buffer(argv, DOCKER_STOP_COMMAND); if (ret == 0) { value = get_configuration_value("time", DOCKER_COMMAND_FILE_SECTION, &command_config); if (value != NULL) { @@ -735,23 +758,19 @@ int get_docker_stop_command(const char *command_file, const struct configuration if (isdigit(value[i]) == 0) { fprintf(ERRORFILE, "Value for time is not a number '%s'\n", value); free(container_name); - memset(out, 0, outlen); + free_buffer(argv); return INVALID_DOCKER_STOP_COMMAND; } } - ret = add_to_buffer(out, outlen, " --time="); - if (ret == 0) { - ret = add_to_buffer(out, outlen, value); - } + char *time_buffer = make_string("--time=%s", value); + ret = add_to_buffer(argv, time_buffer); if (ret != 0) { + free(time_buffer); free(container_name); return BUFFER_TOO_SMALL; } } - ret = add_to_buffer(out, outlen, " "); - if (ret == 0) { - ret = add_to_buffer(out, outlen, container_name); - } + ret = add_to_buffer(argv, container_name); free(container_name); if (ret != 0) { return BUFFER_TOO_SMALL; @@ -763,8 +782,9 @@ int get_docker_stop_command(const char *command_file, const struct configuration } int get_docker_kill_command(const char *command_file, const struct configuration *conf, - char *out, const size_t outlen) { + struct argv *argv) { int ret = 0; + int tmp_buffer_size = 40; size_t len = 0, i = 0; char *value = NULL; char *container_name = NULL; @@ -779,14 +799,20 @@ int get_docker_kill_command(const char *command_file, const struct configuration return INVALID_DOCKER_CONTAINER_NAME; } - memset(out, 0, outlen); + char *docker = get_docker_binary(conf); + ret = add_to_buffer(argv, docker); + if (ret != 0) { + free(docker); + return BUFFER_TOO_SMALL; + } + free(docker); - ret = add_docker_config_param(&command_config, out, outlen); + ret = add_docker_config_param(&command_config, argv); if (ret != 0) { return BUFFER_TOO_SMALL; } - ret = add_to_buffer(out, outlen, DOCKER_KILL_COMMAND); + ret = add_to_buffer(argv, DOCKER_KILL_COMMAND); if (ret == 0) { value = get_configuration_value("signal", DOCKER_COMMAND_FILE_SECTION, &command_config); if (value != NULL) { @@ -795,23 +821,21 @@ int get_docker_kill_command(const char *command_file, const struct configuration if (isupper(value[i]) == 0) { fprintf(ERRORFILE, "Value for signal contains non-uppercase characters '%s'\n", value); free(container_name); - memset(out, 0, outlen); + free_buffer(argv); return INVALID_DOCKER_KILL_COMMAND; } } - ret = add_to_buffer(out, outlen, " --signal="); - if (ret == 0) { - ret = add_to_buffer(out, outlen, value); - } + + char *signal_buffer = (char *) alloc_and_clear_memory(tmp_buffer_size, sizeof(char)); + signal_buffer = make_string("--signal=%s", value); + ret = add_to_buffer(argv, signal_buffer); + free(signal_buffer); if (ret != 0) { free(container_name); return BUFFER_TOO_SMALL; } } - ret = add_to_buffer(out, outlen, " "); - if (ret == 0) { - ret = add_to_buffer(out, outlen, container_name); - } + ret = add_to_buffer(argv, container_name); free(container_name); if (ret != 0) { return BUFFER_TOO_SMALL; @@ -822,7 +846,7 @@ int get_docker_kill_command(const char *command_file, const struct configuration return BUFFER_TOO_SMALL; } -int get_docker_start_command(const char *command_file, const struct configuration *conf, char *out, const size_t outlen) { +int get_docker_start_command(const char *command_file, const struct configuration *conf, struct argv *argv) { int ret = 0; char *container_name = NULL; struct configuration command_config = {0, NULL}; @@ -836,22 +860,16 @@ int get_docker_start_command(const char *command_file, const struct configuratio return INVALID_DOCKER_CONTAINER_NAME; } - memset(out, 0, outlen); - - ret = add_docker_config_param(&command_config, out, outlen); + ret = add_docker_config_param(&command_config, argv); if (ret != 0) { return BUFFER_TOO_SMALL; } - ret = add_to_buffer(out, outlen, DOCKER_START_COMMAND); + ret = add_to_buffer(argv, DOCKER_START_COMMAND); if (ret != 0) { goto free_and_exit; } - ret = add_to_buffer(out, outlen, " "); - if (ret != 0) { - goto free_and_exit; - } - ret = add_to_buffer(out, outlen, container_name); + ret = add_to_buffer(argv, container_name); if (ret != 0) { goto free_and_exit; } @@ -860,31 +878,29 @@ free_and_exit: return ret; } -static int detach_container(const struct configuration *command_config, char *out, const size_t outlen) { - return add_param_to_command(command_config, "detach", "-d ", 0, out, outlen); +static int detach_container(const struct configuration *command_config, struct argv *argv) { + return add_param_to_command(command_config, "detach", "-d", 0, argv); } -static int rm_container_on_exit(const struct configuration *command_config, char *out, const size_t outlen) { - return add_param_to_command(command_config, "rm", "--rm ", 0, out, outlen); +static int rm_container_on_exit(const struct configuration *command_config, struct argv *argv) { + return add_param_to_command(command_config, "rm", "--rm", 0, argv); } -static int set_container_workdir(const struct configuration *command_config, char *out, const size_t outlen) { - return add_param_to_command(command_config, "workdir", "--workdir=", 1, out, outlen); +static int set_container_workdir(const struct configuration *command_config, struct argv *argv) { + return add_param_to_command(command_config, "workdir", "--workdir=", 1, argv); } -static int set_cgroup_parent(const struct configuration *command_config, char *out, const size_t outlen) { - return add_param_to_command(command_config, "cgroup-parent", "--cgroup-parent=", 1, out, outlen); +static int set_cgroup_parent(const struct configuration *command_config, struct argv *argv) { + return add_param_to_command(command_config, "cgroup-parent", "--cgroup-parent=", 1, argv); } -static int set_hostname(const struct configuration *command_config, char *out, const size_t outlen) { - return add_param_to_command(command_config, "hostname", "--hostname=", 1, out, outlen); +static int set_hostname(const struct configuration *command_config, struct argv *argv) { + return add_param_to_command(command_config, "hostname", "--hostname=", 1, argv); } -static int set_group_add(const struct configuration *command_config, char *out, const size_t outlen) { +static int set_group_add(const struct configuration *command_config, struct argv *argv) { int i = 0, ret = 0; char **group_add = get_configuration_values_delimiter("group-add", DOCKER_COMMAND_FILE_SECTION, command_config, ","); - size_t tmp_buffer_size = 4096; - char *tmp_buffer = NULL; char *privileged = NULL; privileged = get_configuration_value("privileged", DOCKER_COMMAND_FILE_SECTION, command_config); @@ -896,9 +912,11 @@ static int set_group_add(const struct configuration *command_config, char *out, if (group_add != NULL) { for (i = 0; group_add[i] != NULL; ++i) { - tmp_buffer = (char *) alloc_and_clear_memory(tmp_buffer_size, sizeof(char)); - quote_and_append_arg(&tmp_buffer, &tmp_buffer_size, "--group-add ", group_add[i]); - ret = add_to_buffer(out, outlen, tmp_buffer); + ret = add_to_buffer(argv, "--group-add"); + if (ret != 0) { + return BUFFER_TOO_SMALL; + } + ret = add_to_buffer(argv, group_add[i]); if (ret != 0) { return BUFFER_TOO_SMALL; } @@ -908,25 +926,22 @@ static int set_group_add(const struct configuration *command_config, char *out, } static int set_network(const struct configuration *command_config, - const struct configuration *conf, char *out, - const size_t outlen) { + const struct configuration *conf, struct argv *argv) { int ret = 0; ret = add_param_to_command_if_allowed(command_config, conf, "net", "docker.allowed.networks", "--net=", - 0, 0, out, outlen); + 0, 0, argv); if (ret != 0) { fprintf(ERRORFILE, "Could not find requested network in allowed networks\n"); ret = INVALID_DOCKER_NETWORK; - memset(out, 0, outlen); } return ret; } static int set_pid_namespace(const struct configuration *command_config, - const struct configuration *conf, char *out, - const size_t outlen) { + const struct configuration *conf, struct argv *argv) { size_t tmp_buffer_size = 1024; char *tmp_buffer = (char *) alloc_and_clear_memory(tmp_buffer_size, sizeof(char)); char *value = get_configuration_value("pid", DOCKER_COMMAND_FILE_SECTION, @@ -940,7 +955,7 @@ static int set_pid_namespace(const struct configuration *command_config, if (pid_host_enabled != NULL) { if (strcmp(pid_host_enabled, "1") == 0 || strcasecmp(pid_host_enabled, "True") == 0) { - ret = add_to_buffer(out, outlen, "--pid='host' "); + ret = add_to_buffer(argv, "--pid='host'"); if (ret != 0) { ret = BUFFER_TOO_SMALL; } @@ -964,19 +979,14 @@ static int set_pid_namespace(const struct configuration *command_config, free(tmp_buffer); free(value); free(pid_host_enabled); - if (ret != 0) { - memset(out, 0, outlen); - } return ret; } static int set_capabilities(const struct configuration *command_config, - const struct configuration *conf, char *out, - const size_t outlen) { - + const struct configuration *conf, struct argv *argv) { int ret = 0; - ret = add_to_buffer(out, outlen, "--cap-drop='ALL' "); + ret = add_to_buffer(argv, "--cap-drop=ALL"); if (ret != 0) { return BUFFER_TOO_SMALL; } @@ -984,7 +994,7 @@ static int set_capabilities(const struct configuration *command_config, ret = add_param_to_command_if_allowed(command_config, conf, "cap-add", "docker.allowed.capabilities", "--cap-add=", 1, 0, - out, outlen); + argv); switch (ret) { case 0: break; @@ -995,21 +1005,18 @@ static int set_capabilities(const struct configuration *command_config, default: fprintf(ERRORFILE, "Invalid docker capability requested\n"); ret = INVALID_DOCKER_CAPABILITY; - memset(out, 0, outlen); } return ret; } -static int set_devices(const struct configuration *command_config, const struct configuration *conf, char *out, - const size_t outlen) { +static int set_devices(const struct configuration *command_config, const struct configuration *conf, struct argv *argv) { int ret = 0; ret = add_param_to_command_if_allowed(command_config, conf, "devices", "docker.allowed.devices", "--device=", 1, ':', - out, outlen); + argv); if (ret != 0) { fprintf(ERRORFILE, "Invalid docker device requested\n"); ret = INVALID_DOCKER_DEVICE; - memset(out, 0, outlen); } return ret; @@ -1046,7 +1053,6 @@ static char* normalize_mount(const char* mount, int isRegexAllowed) { } } fprintf(ERRORFILE, "Could not determine real path of mount '%s'\n", mount); - free(real_mount); return NULL; } ret = stat(real_mount, &buff); @@ -1054,6 +1060,7 @@ static char* normalize_mount(const char* mount, int isRegexAllowed) { if (S_ISDIR(buff.st_mode)) { size_t len = strlen(real_mount); if (len <= 0) { + free(real_mount); return NULL; } if (real_mount[len - 1] != '/') { @@ -1097,6 +1104,7 @@ static int check_mount_permitted(const char **permitted_mounts, const char *requ size_t permitted_mount_len = 0; char *normalized_path = normalize_mount(requested, 0); if (permitted_mounts == NULL) { + free(normalized_path); return 0; } if (normalized_path == NULL) { @@ -1124,40 +1132,36 @@ static int check_mount_permitted(const char **permitted_mounts, const char *requ break; } } - } free(normalized_path); return ret; } static char* get_mount_source(const char *mount) { - char *src_mount = NULL; - const char *tmp = NULL; - tmp = strchr(mount, ':'); + const char *tmp = strchr(mount, ':'); if (tmp == NULL) { fprintf(ERRORFILE, "Invalid docker mount '%s'\n", mount); return NULL; } - src_mount = strndup(mount, tmp - mount); + size_t len = tmp - mount; + char *src_mount; + src_mount = strndup(mount, len); return src_mount; } static int add_mounts(const struct configuration *command_config, const struct configuration *conf, const char *key, - const int ro, char *out, const size_t outlen) { - size_t tmp_buffer_size = 1024; - const char *ro_suffix = ""; + const int ro, struct argv *argv) { + char *ro_suffix = (char*) ""; const char *tmp_path_buffer[2] = {NULL, NULL}; - char *tmp_buffer = (char *) alloc_and_clear_memory(tmp_buffer_size, sizeof(char)); char **permitted_ro_mounts = get_configuration_values_delimiter("docker.allowed.ro-mounts", CONTAINER_EXECUTOR_CFG_DOCKER_SECTION, conf, ","); char **permitted_rw_mounts = get_configuration_values_delimiter("docker.allowed.rw-mounts", CONTAINER_EXECUTOR_CFG_DOCKER_SECTION, conf, ","); char **values = get_configuration_values_delimiter(key, DOCKER_COMMAND_FILE_SECTION, command_config, ","); - char *tmp_buffer_2 = NULL, *mount_src = NULL; const char *container_executor_cfg_path = normalize_mount(get_config_path(""), 0); int i = 0, permitted_rw = 0, permitted_ro = 0, ret = 0; if (ro != 0) { - ro_suffix = ":ro"; + ro_suffix = (char*) ":ro"; } if (values != NULL) { @@ -1180,8 +1184,8 @@ static int add_mounts(const struct configuration *command_config, const struct c ret = MOUNT_ACCESS_ERROR; goto free_and_exit; } - for (i = 0; values[i] != NULL; ++i) { - mount_src = get_mount_source(values[i]); + for (i = 0; values[i] != NULL; i++) { + char *mount_src = get_mount_source(values[i]); if (mount_src == NULL) { fprintf(ERRORFILE, "Invalid docker mount '%s', realpath=%s\n", values[i], mount_src); ret = INVALID_DOCKER_MOUNT; @@ -1192,12 +1196,14 @@ static int add_mounts(const struct configuration *command_config, const struct c if (permitted_ro == -1 || permitted_rw == -1) { fprintf(ERRORFILE, "Invalid docker mount '%s', realpath=%s\n", values[i], mount_src); ret = INVALID_DOCKER_MOUNT; + free(mount_src); goto free_and_exit; } // rw mount if (ro == 0) { if (permitted_rw == 0) { fprintf(ERRORFILE, "Invalid docker rw mount '%s', realpath=%s\n", values[i], mount_src); + free(mount_src); ret = INVALID_DOCKER_RW_MOUNT; goto free_and_exit; } else { @@ -1211,6 +1217,7 @@ static int add_mounts(const struct configuration *command_config, const struct c fprintf(ERRORFILE, "Attempting to mount a parent directory '%s' of container-executor.cfg as read-write\n", values[i]); ret = INVALID_DOCKER_RW_MOUNT; + free(mount_src); goto free_and_exit; } } @@ -1219,18 +1226,19 @@ static int add_mounts(const struct configuration *command_config, const struct c if (ro != 0 && permitted_ro == 0 && permitted_rw == 0) { fprintf(ERRORFILE, "Invalid docker ro mount '%s', realpath=%s\n", values[i], mount_src); ret = INVALID_DOCKER_RO_MOUNT; + free(mount_src); goto free_and_exit; } - tmp_buffer_2 = (char *) alloc_and_clear_memory(strlen(values[i]) + strlen(ro_suffix) + 1, sizeof(char)); - strncpy(tmp_buffer_2, values[i], strlen(values[i])); - strncpy(tmp_buffer_2 + strlen(values[i]), ro_suffix, strlen(ro_suffix)); - quote_and_append_arg(&tmp_buffer, &tmp_buffer_size, "-v ", tmp_buffer_2); - ret = add_to_buffer(out, outlen, tmp_buffer); - free(tmp_buffer_2); - free(mount_src); - tmp_buffer_2 = NULL; - mount_src = NULL; - memset(tmp_buffer, 0, tmp_buffer_size); + + ret = add_to_buffer(argv, "-v"); + if (ret != 0) { + ret = BUFFER_TOO_SMALL; + goto free_and_exit; + } + + char *tmp_buffer = make_string("%s%s", values[i], ro_suffix); + ret = add_to_buffer(argv, tmp_buffer); + free(tmp_buffer); if (ret != 0) { ret = BUFFER_TOO_SMALL; goto free_and_exit; @@ -1242,23 +1250,16 @@ static int add_mounts(const struct configuration *command_config, const struct c free_values(permitted_ro_mounts); free_values(permitted_rw_mounts); free_values(values); - free(mount_src); free((void *) container_executor_cfg_path); - free(tmp_buffer); - if (ret != 0) { - memset(out, 0, outlen); - } return ret; } -static int add_ro_mounts(const struct configuration *command_config, const struct configuration *conf, char *out, - const size_t outlen) { - return add_mounts(command_config, conf, "ro-mounts", 1, out, outlen); +static int add_ro_mounts(const struct configuration *command_config, const struct configuration *conf, struct argv *argv) { + return add_mounts(command_config, conf, "ro-mounts", 1, argv); } -static int add_rw_mounts(const struct configuration *command_config, const struct configuration *conf, char *out, - const size_t outlen) { - return add_mounts(command_config, conf, "rw-mounts", 0, out, outlen); +static int add_rw_mounts(const struct configuration *command_config, const struct configuration *conf, struct argv *argv) { + return add_mounts(command_config, conf, "rw-mounts", 0, argv); } static int check_privileges(const char *user) { @@ -1334,8 +1335,7 @@ static int check_privileges(const char *user) { return ret; } -static int set_privileged(const struct configuration *command_config, const struct configuration *conf, char *out, - const size_t outlen) { +static int set_privileged(const struct configuration *command_config, const struct configuration *conf, struct argv *argv) { size_t tmp_buffer_size = 1024; char *user = NULL; char *tmp_buffer = (char *) alloc_and_clear_memory(tmp_buffer_size, sizeof(char)); @@ -1343,7 +1343,7 @@ static int set_privileged(const struct configuration *command_config, const stru char *privileged_container_enabled = get_configuration_value("docker.privileged-containers.enabled", CONTAINER_EXECUTOR_CFG_DOCKER_SECTION, conf); int ret = 0; - int allowed = 0; + int allowed = 1; user = get_configuration_value("user", DOCKER_COMMAND_FILE_SECTION, command_config); if (user == NULL) { @@ -1362,7 +1362,7 @@ static int set_privileged(const struct configuration *command_config, const stru } allowed = check_privileges(user); if (allowed) { - ret = add_to_buffer(out, outlen, "--privileged "); + ret = add_to_buffer(argv, "--privileged"); if (ret != 0) { ret = BUFFER_TOO_SMALL; } @@ -1388,16 +1388,12 @@ static int set_privileged(const struct configuration *command_config, const stru free(value); free(privileged_container_enabled); free(user); - if (ret != 0) { - memset(out, 0, outlen); - } return ret; } -int get_docker_run_command(const char *command_file, const struct configuration *conf, char *out, const size_t outlen) { +int get_docker_run_command(const char *command_file, const struct configuration *conf, struct argv *argv) { int ret = 0, i = 0; char *container_name = NULL, *user = NULL, *image = NULL; - size_t tmp_buffer_size = 1024; char *tmp_buffer = NULL; char **launch_command = NULL; char *privileged = NULL; @@ -1420,124 +1416,123 @@ int get_docker_run_command(const char *command_file, const struct configuration return INVALID_DOCKER_IMAGE_NAME; } - ret = add_docker_config_param(&command_config, out, outlen); + char *docker = get_docker_binary(conf); + ret = add_to_buffer(argv, docker); if (ret != 0) { + free(docker); return BUFFER_TOO_SMALL; } + free(docker); - ret = add_to_buffer(out, outlen, DOCKER_RUN_COMMAND); - if(ret != 0) { + ret = add_docker_config_param(&command_config, argv); + if (ret != 0) { return BUFFER_TOO_SMALL; } + ret = add_to_buffer(argv, DOCKER_RUN_COMMAND); + if(ret != 0) { + return BUFFER_TOO_SMALL; + } - tmp_buffer = (char *) alloc_and_clear_memory(tmp_buffer_size, sizeof(char)); - - quote_and_append_arg(&tmp_buffer, &tmp_buffer_size, " --name=", container_name); - ret = add_to_buffer(out, outlen, tmp_buffer); + tmp_buffer = make_string("--name=%s", container_name); + ret = add_to_buffer(argv, tmp_buffer); if (ret != 0) { return BUFFER_TOO_SMALL; } - memset(tmp_buffer, 0, tmp_buffer_size); privileged = get_configuration_value("privileged", DOCKER_COMMAND_FILE_SECTION, &command_config); - if (privileged == NULL || strcasecmp(privileged, "false") == 0) { - quote_and_append_arg(&tmp_buffer, &tmp_buffer_size, "--user=", user); - ret = add_to_buffer(out, outlen, tmp_buffer); - if (ret != 0) { - return BUFFER_TOO_SMALL; - } - memset(tmp_buffer, 0, tmp_buffer_size); + if (privileged == NULL || strcmp(privileged, "false") == 0) { + char *user_buffer = make_string("--user=%s", user); + ret = add_to_buffer(argv, user_buffer); + free(user_buffer); + if (ret != 0) { + return BUFFER_TOO_SMALL; + } } free(privileged); - ret = detach_container(&command_config, out, outlen); + ret = detach_container(&command_config, argv); if (ret != 0) { return ret; } - ret = rm_container_on_exit(&command_config, out, outlen); + ret = rm_container_on_exit(&command_config, argv); if (ret != 0) { return ret; } - ret = set_container_workdir(&command_config, out, outlen); + ret = set_container_workdir(&command_config, argv); if (ret != 0) { return ret; } - ret = set_network(&command_config, conf, out, outlen); + ret = set_network(&command_config, conf, argv); if (ret != 0) { return ret; } - ret = set_pid_namespace(&command_config, conf, out, outlen); + ret = set_pid_namespace(&command_config, conf, argv); if (ret != 0) { return ret; } - ret = add_ro_mounts(&command_config, conf, out, outlen); + ret = add_ro_mounts(&command_config, conf, argv); if (ret != 0) { return ret; } - ret = add_rw_mounts(&command_config, conf, out, outlen); + ret = add_rw_mounts(&command_config, conf, argv); if (ret != 0) { return ret; } - ret = set_cgroup_parent(&command_config, out, outlen); + ret = set_cgroup_parent(&command_config, argv); if (ret != 0) { return ret; } - ret = set_privileged(&command_config, conf, out, outlen); + ret = set_privileged(&command_config, conf, argv); if (ret != 0) { return ret; } - ret = set_capabilities(&command_config, conf, out, outlen); + ret = set_capabilities(&command_config, conf, argv); if (ret != 0) { return ret; } - ret = set_hostname(&command_config, out, outlen); + ret = set_hostname(&command_config, argv); if (ret != 0) { return ret; } - ret = set_group_add(&command_config, out, outlen); + ret = set_group_add(&command_config, argv); if (ret != 0) { return ret; } - ret = set_devices(&command_config, conf, out, outlen); + ret = set_devices(&command_config, conf, argv); if (ret != 0) { return ret; } - quote_and_append_arg(&tmp_buffer, &tmp_buffer_size, "", image); - ret = add_to_buffer(out, outlen, tmp_buffer); + ret = add_to_buffer(argv, image); if (ret != 0) { return BUFFER_TOO_SMALL; } launch_command = get_configuration_values_delimiter("launch-command", DOCKER_COMMAND_FILE_SECTION, &command_config, ","); - if (check_trusted_image(&command_config, conf) != 0) { launch_command = NULL; } if (launch_command != NULL) { for (i = 0; launch_command[i] != NULL; ++i) { - memset(tmp_buffer, 0, tmp_buffer_size); - quote_and_append_arg(&tmp_buffer, &tmp_buffer_size, "", launch_command[i]); - ret = add_to_buffer(out, outlen, tmp_buffer); + ret = add_to_buffer(argv, launch_command[i]); if (ret != 0) { free_values(launch_command); - free(tmp_buffer); return BUFFER_TOO_SMALL; } } @@ -1547,5 +1542,9 @@ int get_docker_run_command(const char *command_file, const struct configuration return 0; } +void reset(struct argv *argv) { + argv->out = (char **) malloc( sizeof(char *) * DOCKER_ARG_MAX); + argv->index = 0; +} 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 c797ecd..1f2f5c1 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 @@ -33,7 +33,12 @@ #define DOCKER_KILL_COMMAND "kill" #define DOCKER_VOLUME_COMMAND "volume" #define DOCKER_START_COMMAND "start" +#define DOCKER_ARG_MAX 1024 +struct argv { + int index; + char **out; +}; enum docker_error_codes { INVALID_COMMAND_FILE = 1, @@ -77,7 +82,7 @@ char *get_docker_binary(const struct configuration *conf); * @param outlen Size of the output buffer * @return Return code with 0 indicating success and non-zero codes indicating error */ -int get_docker_command(const char* command_file, const struct configuration* conf, char *out, const size_t outlen); +int get_docker_command(const char* command_file, const struct configuration* conf, struct argv *argv); /** * Get the Docker inspect command line string. The function will verify that the params file is meant for the @@ -88,7 +93,7 @@ int get_docker_command(const char* command_file, const struct configuration* con * @param outlen Size of the output buffer * @return Return code with 0 indicating success and non-zero codes indicating error */ -int get_docker_inspect_command(const char* command_file, const struct configuration* conf, char *out, const size_t outlen); +int get_docker_inspect_command(const char* command_file, const struct configuration* conf, struct argv *argv); /** * Get the Docker load command line string. The function will verify that the params file is meant for the load command. @@ -98,7 +103,7 @@ int get_docker_inspect_command(const char* command_file, const struct configurat * @param outlen Size of the output buffer * @return Return code with 0 indicating success and non-zero codes indicating error */ -int get_docker_load_command(const char* command_file, const struct configuration* conf, char *out, const size_t outlen); +int get_docker_load_command(const char* command_file, const struct configuration* conf, struct argv *argv); /** * Get the Docker pull command line string. The function will verify that the params file is meant for the pull command. @@ -108,7 +113,7 @@ int get_docker_load_command(const char* command_file, const struct configuration * @param outlen Size of the output buffer * @return Return code with 0 indicating success and non-zero codes indicating error */ -int get_docker_pull_command(const char* command_file, const struct configuration* conf, char *out, const size_t outlen); +int get_docker_pull_command(const char* command_file, const struct configuration* conf, struct argv *argv); /** * Get the Docker rm command line string. The function will verify that the params file is meant for the rm command. @@ -118,7 +123,7 @@ int get_docker_pull_command(const char* command_file, const struct configuration * @param outlen Size of the output buffer * @return Return code with 0 indicating success and non-zero codes indicating error */ -int get_docker_rm_command(const char* command_file, const struct configuration* conf, char *out, const size_t outlen); +int get_docker_rm_command(const char* command_file, const struct configuration* conf, struct argv *argv); /** * Get the Docker run command line string. The function will verify that the params file is meant for the run command. @@ -128,7 +133,7 @@ int get_docker_rm_command(const char* command_file, const struct configuration* * @param outlen Size of the output buffer * @return Return code with 0 indicating success and non-zero codes indicating error */ -int get_docker_run_command(const char* command_file, const struct configuration* conf, char *out, const size_t outlen); +int get_docker_run_command(const char* command_file, const struct configuration* conf, struct argv *argv); /** * Get the Docker stop command line string. The function will verify that the params file is meant for the stop command. @@ -138,7 +143,7 @@ int get_docker_run_command(const char* command_file, const struct configuration* * @param outlen Size of the output buffer * @return Return code with 0 indicating success and non-zero codes indicating error */ -int get_docker_stop_command(const char* command_file, const struct configuration* conf, char *out, const size_t outlen); +int get_docker_stop_command(const char* command_file, const struct configuration* conf, struct argv *argv); /** * Get the Docker kill command line string. The function will verify that the params file is meant for the kill command. @@ -148,7 +153,7 @@ int get_docker_stop_command(const char* command_file, const struct configuration * @param outlen Size of the output buffer * @return Return code with 0 indicating success and non-zero codes indicating error */ -int get_docker_kill_command(const char* command_file, const struct configuration* conf, char *out, const size_t outlen); +int get_docker_kill_command(const char* command_file, const struct configuration* conf, struct argv *argv); /** * Get the Docker volume command line string. The function will verify that the @@ -159,8 +164,7 @@ int get_docker_kill_command(const char* command_file, const struct configuration * @param outlen Size of the output buffer * @return Return code with 0 indicating success and non-zero codes indicating error */ -int get_docker_volume_command(const char *command_file, const struct configuration *conf, char *out, - const size_t outlen); +int get_docker_volume_command(const char *command_file, const struct configuration *conf, struct argv *argv); /** * Get the Docker start command line string. The function will verify that the params file is meant for the start command. @@ -170,7 +174,7 @@ int get_docker_volume_command(const char *command_file, const struct configurati * @param outlen Size of the output buffer * @return Return code with 0 indicating success and non-zero codes indicating error */ -int get_docker_start_command(const char* command_file, const struct configuration* conf, char *out, const size_t outlen); +int get_docker_start_command(const char* command_file, const struct configuration* conf, struct argv *argv); /** * Give an error message for the supplied error code @@ -186,4 +190,10 @@ const char *get_docker_error_message(const int error_code); */ int docker_module_enabled(const struct configuration *conf); +/** + * Helper function to reset argv data structure. + * @param argv Pointer reference to argv data structure + */ +void reset(struct argv *argv); + #endif diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/string-utils.c b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/string-utils.c index 40b2c25..cb876d8 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/string-utils.c +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/string-utils.c @@ -22,6 +22,7 @@ #include #include #include +#include /* * if all chars in the input str are numbers @@ -156,3 +157,36 @@ cleanup: } return is_container_id; } + +/* + * Format string utility. + */ +char *make_string(const char *fmt, ...) { + va_list ap; + int n; + int size = 100; + char *p, *np; + p = (char *) malloc(sizeof(char) * size); + if (p == NULL) { + return NULL; + } + + while (1) { + va_start(ap, fmt); + n = vsnprintf(p, size, fmt, ap); + va_end(ap); + if (n < 0) { + return NULL; + } + if (n < size) { + return p; + } + size = n + 2; + if ((np = realloc(p, size)) == NULL) { + free(p); + return NULL; + } else { + p = np; + } + } +} diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/string-utils.h b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/string-utils.h index c095eb6..affb3c3 100644 --- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/string-utils.h +++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/impl/utils/string-utils.h @@ -34,4 +34,8 @@ int validate_container_id(const char* input); */ int get_numbers_split_by_comma(const char* input, int** numbers, size_t* n_numbers); +/* + * String format utility + */ +char *make_string(const char *fmt, ...); #endif 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 35b7873..24b4b93 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 @@ -94,45 +94,64 @@ namespace ContainerExecutor { write_file(docker_command_file, contents); } + char* flatten(struct argv *argv) { + size_t string_len = 0; + size_t current_len = 0; + char *buffer = (char *) malloc(8192 * sizeof(char)); + for (int i = 0; i < argv->index; i++) { + string_len = strlen(argv->out[i]); + if (string_len != 0) { + strncpy(buffer + current_len, argv->out[i], string_len); + current_len = current_len + string_len; + if (argv->index - 1 != i) { + strncpy(buffer + current_len, " ", 1); + current_len++; + } + } + } + buffer[current_len] = '\0'; + return buffer; + } + void run_docker_command_test(const std::vector > &file_cmd_vec, const std::vector > &bad_file_cmd_vec, - int (*docker_func)(const char *, const struct configuration *, char *, const size_t)) { - char tmp[8192]; + int (*docker_func)(const char *, const struct configuration *, struct argv *)) { + argv tmp; std::vector >::const_iterator itr; for (itr = file_cmd_vec.begin(); itr != file_cmd_vec.end(); ++itr) { - memset(tmp, 0, 8192); + reset(&tmp); write_command_file(itr->first); - int ret = (*docker_func)(docker_command_file.c_str(), &container_executor_cfg, tmp, 8192); + int ret = (*docker_func)(docker_command_file.c_str(), &container_executor_cfg, &tmp); ASSERT_EQ(0, ret) << "error message: " << get_docker_error_message(ret) << " for input " << itr->first; - ASSERT_STREQ(itr->second.c_str(), tmp); + char *actual = flatten(&tmp); + ASSERT_STREQ(itr->second.c_str(), actual); } std::vector >::const_iterator itr2; for (itr2 = bad_file_cmd_vec.begin(); itr2 != bad_file_cmd_vec.end(); ++itr2) { - memset(tmp, 0, 8192); + reset(&tmp); write_command_file(itr2->first); - int ret = (*docker_func)(docker_command_file.c_str(), &container_executor_cfg, tmp, 8192); + int ret = (*docker_func)(docker_command_file.c_str(), &container_executor_cfg, &tmp); ASSERT_EQ(itr2->second, ret) << " for " << itr2->first << std::endl; - ASSERT_EQ(0, strlen(tmp)); } - int ret = (*docker_func)("unknown-file", &container_executor_cfg, tmp, 8192); + reset(&tmp); + int ret = (*docker_func)("unknown-file", &container_executor_cfg, &tmp); ASSERT_EQ(static_cast(INVALID_COMMAND_FILE), ret); } void run_docker_run_helper_function(const std::vector > &file_cmd_vec, - int (*helper_func)(const struct configuration *, char *, const size_t)) { + int (*helper_func)(const struct configuration *, struct argv *)) { std::vector >::const_iterator itr; for(itr = file_cmd_vec.begin(); itr != file_cmd_vec.end(); ++itr) { struct configuration cfg; - const int buff_len = 1024; - char buff[buff_len]; - memset(buff, 0, buff_len); + argv buff; + reset(&buff); write_command_file(itr->first); int ret = read_config(docker_command_file.c_str(), &cfg); if(ret == 0) { - ret = (*helper_func)(&cfg, buff, buff_len); + ret = (*helper_func)(&cfg, &buff); ASSERT_EQ(0, ret); - ASSERT_STREQ(itr->second.c_str(), buff); + ASSERT_STREQ(itr->second.c_str(), flatten(&buff)); } } } @@ -142,12 +161,12 @@ namespace ContainerExecutor { std::vector > file_cmd_vec; file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=inspect\n format={{.State.Status}}\n name=container_e1_12312_11111_02_000001", - "inspect --format={{.State.Status}} container_e1_12312_11111_02_000001")); + "/usr/bin/docker inspect --format={{.State.Status}} container_e1_12312_11111_02_000001")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=inspect\n" " format={{range(.NetworkSettings.Networks)}}{{.IPAddress}},{{end}}{{.Config.Hostname}}\n" " name=container_e1_12312_11111_02_000001", - "inspect --format={{range(.NetworkSettings.Networks)}}{{.IPAddress}},{{end}}{{.Config.Hostname}} container_e1_12312_11111_02_000001")); + "/usr/bin/docker inspect --format={{range(.NetworkSettings.Networks)}}{{.IPAddress}},{{end}}{{.Config.Hostname}} container_e1_12312_11111_02_000001")); std::vector > bad_file_cmd_vec; bad_file_cmd_vec.push_back(std::make_pair( @@ -179,7 +198,7 @@ namespace ContainerExecutor { std::vector > file_cmd_vec; file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=load\n image=image-id", - "load --i='image-id' ")); + "/usr/bin/docker load --i=image-id")); std::vector > bad_file_cmd_vec; bad_file_cmd_vec.push_back(std::make_pair( @@ -249,7 +268,7 @@ namespace ContainerExecutor { std::vector > file_cmd_vec; file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=pull\n image=image-id", - "pull 'image-id' ")); + "/usr/bin/docker pull image-id")); std::vector > bad_file_cmd_vec; bad_file_cmd_vec.push_back(std::make_pair( @@ -269,7 +288,7 @@ namespace ContainerExecutor { file_cmd_vec.push_back( std::make_pair( "[docker-command-execution]\n docker-command=rm\n name=container_e1_12312_11111_02_000001", - "rm container_e1_12312_11111_02_000001")); + "/usr/bin/docker rm container_e1_12312_11111_02_000001")); std::vector > bad_file_cmd_vec; bad_file_cmd_vec.push_back(std::make_pair( @@ -289,10 +308,10 @@ namespace ContainerExecutor { std::vector > file_cmd_vec; file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=stop\n name=container_e1_12312_11111_02_000001", - "stop container_e1_12312_11111_02_000001")); + "/usr/bin/docker stop container_e1_12312_11111_02_000001")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=stop\n name=container_e1_12312_11111_02_000001\ntime=25", - "stop --time=25 container_e1_12312_11111_02_000001")); + "/usr/bin/docker stop --time=25 container_e1_12312_11111_02_000001")); std::vector > bad_file_cmd_vec; bad_file_cmd_vec.push_back(std::make_pair( @@ -316,10 +335,10 @@ namespace ContainerExecutor { std::vector > file_cmd_vec; file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=kill\n name=container_e1_12312_11111_02_000001", - "kill container_e1_12312_11111_02_000001")); + "/usr/bin/docker kill container_e1_12312_11111_02_000001")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=kill\n name=container_e1_12312_11111_02_000001\nsignal=SIGQUIT", - "kill --signal=SIGQUIT container_e1_12312_11111_02_000001")); + "/usr/bin/docker kill --signal=SIGQUIT container_e1_12312_11111_02_000001")); std::vector > bad_file_cmd_vec; bad_file_cmd_vec.push_back(std::make_pair( @@ -361,7 +380,7 @@ namespace ContainerExecutor { TEST_F(TestDockerUtil, test_detach_container) { std::vector > file_cmd_vec; file_cmd_vec.push_back(std::make_pair( - "[docker-command-execution]\n docker-command=run\n detach=true", "-d ")); + "[docker-command-execution]\n docker-command=run\n detach=true", "-d")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run", "")); @@ -371,7 +390,7 @@ namespace ContainerExecutor { TEST_F(TestDockerUtil, test_rm_container) { std::vector > file_cmd_vec; file_cmd_vec.push_back(std::make_pair( - "[docker-command-execution]\n docker-command=run\n rm=true", "--rm ")); + "[docker-command-execution]\n docker-command=run\n rm=true", "--rm")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run", "")); @@ -381,7 +400,7 @@ namespace ContainerExecutor { TEST_F(TestDockerUtil, test_set_container_workdir) { std::vector > file_cmd_vec; file_cmd_vec.push_back(std::make_pair( - "[docker-command-execution]\n docker-command=run\n workdir=/tmp/test", "--workdir='/tmp/test' ")); + "[docker-command-execution]\n docker-command=run\n workdir=/tmp/test", "--workdir=/tmp/test")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run", "")); @@ -392,7 +411,7 @@ namespace ContainerExecutor { std::vector > file_cmd_vec; file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run\n cgroup-parent=/sys/fs/cgroup/yarn", - "--cgroup-parent='/sys/fs/cgroup/yarn' ")); + "--cgroup-parent=/sys/fs/cgroup/yarn")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run", "")); @@ -402,7 +421,7 @@ namespace ContainerExecutor { TEST_F(TestDockerUtil, test_set_hostname) { std::vector > file_cmd_vec; file_cmd_vec.push_back(std::make_pair( - "[docker-command-execution]\n docker-command=run\n hostname=ctr-id", "--hostname='ctr-id' ")); + "[docker-command-execution]\n docker-command=run\n hostname=ctr-id", "--hostname=ctr-id")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run", "")); @@ -412,7 +431,7 @@ namespace ContainerExecutor { TEST_F(TestDockerUtil, test_set_group_add) { std::vector > file_cmd_vec; file_cmd_vec.push_back(std::make_pair( - "[docker-command-execution]\n docker-command=run\n group-add=1000,1001", "--group-add '1000' --group-add '1001' ")); + "[docker-command-execution]\n docker-command=run\n group-add=1000,1001", "--group-add 1000 --group-add 1001")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run", "")); @@ -421,15 +440,15 @@ namespace ContainerExecutor { TEST_F(TestDockerUtil, test_set_network) { struct configuration container_cfg; - const int buff_len = 1024; - char buff[buff_len]; + argv buff; + reset(&buff); int ret = 0; std::string container_executor_cfg_contents = "[docker]\n docker.allowed.networks=sdn1,bridge"; std::vector > file_cmd_vec; file_cmd_vec.push_back(std::make_pair( - "[docker-command-execution]\n docker-command=run\n net=bridge", "--net='bridge' ")); + "[docker-command-execution]\n docker-command=run\n net=bridge", "--net=bridge")); file_cmd_vec.push_back(std::make_pair( - "[docker-command-execution]\n docker-command=run\n net=sdn1", "--net='sdn1' ")); + "[docker-command-execution]\n docker-command=run\n net=sdn1", "--net=sdn1")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run", "")); write_container_executor_cfg(container_executor_cfg_contents); @@ -441,15 +460,15 @@ namespace ContainerExecutor { } for (itr = file_cmd_vec.begin(); itr != file_cmd_vec.end(); ++itr) { struct configuration cmd_cfg; - memset(buff, 0, buff_len); + reset(&buff); write_command_file(itr->first); ret = read_config(docker_command_file.c_str(), &cmd_cfg); if (ret != 0) { FAIL(); } - ret = set_network(&cmd_cfg, &container_cfg, buff, buff_len); + ret = set_network(&cmd_cfg, &container_cfg, &buff); ASSERT_EQ(0, ret); - ASSERT_STREQ(itr->second.c_str(), buff); + ASSERT_STREQ(itr->second.c_str(), flatten(&buff)); } struct configuration cmd_cfg_1; write_command_file("[docker-command-execution]\n docker-command=run\n net=sdn2"); @@ -457,10 +476,10 @@ namespace ContainerExecutor { if (ret != 0) { FAIL(); } - strcpy(buff, "test string"); - ret = set_network(&cmd_cfg_1, &container_cfg, buff, buff_len); + reset(&buff); + ret = set_network(&cmd_cfg_1, &container_cfg, &buff); ASSERT_EQ(INVALID_DOCKER_NETWORK, ret); - ASSERT_EQ(0, strlen(buff)); + ASSERT_EQ(0, buff.index); container_executor_cfg_contents = "[docker]\n"; write_container_executor_cfg(container_executor_cfg_contents); @@ -468,16 +487,15 @@ namespace ContainerExecutor { if (ret != 0) { FAIL(); } - strcpy(buff, "test string"); - ret = set_network(&cmd_cfg_1, &container_cfg, buff, buff_len); + reset(&buff); + ret = set_network(&cmd_cfg_1, &container_cfg, &buff); ASSERT_EQ(INVALID_DOCKER_NETWORK, ret); - ASSERT_EQ(0, strlen(buff)); + ASSERT_EQ(0, buff.index); } TEST_F(TestDockerUtil, test_set_pid_namespace) { struct configuration container_cfg, cmd_cfg; - const int buff_len = 1024; - char buff[buff_len]; + argv buff; int ret = 0; std::string container_executor_cfg_contents[] = {"[docker]\n docker.host-pid-namespace.enabled=1", "[docker]\n docker.host-pid-namespace.enabled=true", @@ -490,7 +508,7 @@ namespace ContainerExecutor { std::vector >::const_iterator itr; std::vector >::const_iterator itr2; file_cmd_vec.push_back(std::make_pair( - "[docker-command-execution]\n docker-command=run\n pid=host", "--pid='host' ")); + "[docker-command-execution]\n docker-command=run\n pid=host", "--pid='host'")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run", "")); bad_file_cmd_vec.push_back(std::make_pair( @@ -505,26 +523,26 @@ namespace ContainerExecutor { FAIL(); } for (itr = file_cmd_vec.begin(); itr != file_cmd_vec.end(); ++itr) { - memset(buff, 0, buff_len); + reset(&buff); write_command_file(itr->first); ret = read_config(docker_command_file.c_str(), &cmd_cfg); if (ret != 0) { FAIL(); } - ret = set_pid_namespace(&cmd_cfg, &container_cfg, buff, buff_len); + ret = set_pid_namespace(&cmd_cfg, &container_cfg, &buff); ASSERT_EQ(0, ret); - ASSERT_STREQ(itr->second.c_str(), buff); + ASSERT_STREQ(itr->second.c_str(), flatten(&buff)); } for (itr2 = bad_file_cmd_vec.begin(); itr2 != bad_file_cmd_vec.end(); ++itr2) { - memset(buff, 0, buff_len); + reset(&buff); write_command_file(itr2->first); ret = read_config(docker_command_file.c_str(), &cmd_cfg); if (ret != 0) { FAIL(); } - ret = set_pid_namespace(&cmd_cfg, &container_cfg, buff, buff_len); + ret = set_pid_namespace(&cmd_cfg, &container_cfg, &buff); ASSERT_EQ(itr2->second, ret); - ASSERT_EQ(0, strlen(buff)); + ASSERT_EQ(0, buff.index); } } @@ -539,15 +557,14 @@ namespace ContainerExecutor { file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run", "")); for (itr = file_cmd_vec.begin(); itr != file_cmd_vec.end(); ++itr) { - memset(buff, 0, buff_len); write_command_file(itr->first); ret = read_config(docker_command_file.c_str(), &cmd_cfg); if (ret != 0) { FAIL(); } - ret = set_pid_namespace(&cmd_cfg, &container_cfg, buff, buff_len); + ret = set_pid_namespace(&cmd_cfg, &container_cfg, &buff); ASSERT_EQ(0, ret); - ASSERT_STREQ(itr->second.c_str(), buff); + ASSERT_STREQ(itr->second.c_str(), flatten(&buff)); } bad_file_cmd_vec.clear(); bad_file_cmd_vec.push_back(std::make_pair( @@ -557,15 +574,15 @@ namespace ContainerExecutor { "[docker-command-execution]\n docker-command=run\n pid=host", static_cast(PID_HOST_DISABLED))); for (itr2 = bad_file_cmd_vec.begin(); itr2 != bad_file_cmd_vec.end(); ++itr2) { - memset(buff, 0, buff_len); + reset(&buff); write_command_file(itr2->first); ret = read_config(docker_command_file.c_str(), &cmd_cfg); if (ret != 0) { FAIL(); } - ret = set_pid_namespace(&cmd_cfg, &container_cfg, buff, buff_len); + ret = set_pid_namespace(&cmd_cfg, &container_cfg, &buff); ASSERT_EQ(itr2->second, ret); - ASSERT_EQ(0, strlen(buff)); + ASSERT_EQ(0, buff.index); } } } @@ -610,8 +627,7 @@ namespace ContainerExecutor { TEST_F(TestDockerUtil, test_set_privileged) { struct configuration container_cfg, cmd_cfg; - const int buff_len = 1024; - char buff[buff_len]; + argv buff; int ret = 0; std::string container_executor_cfg_contents[] = {"[docker]\n docker.privileged-containers.enabled=1\n docker.privileged-containers.registries=hadoop", "[docker]\n docker.privileged-containers.enabled=true\n docker.privileged-containers.registries=hadoop", @@ -639,24 +655,25 @@ namespace ContainerExecutor { FAIL(); } for (itr = file_cmd_vec.begin(); itr != file_cmd_vec.end(); ++itr) { - memset(buff, 0, buff_len); + reset(&buff); write_command_file(itr->first); ret = read_config(docker_command_file.c_str(), &cmd_cfg); if (ret != 0) { FAIL(); } - ret = set_privileged(&cmd_cfg, &container_cfg, buff, buff_len); + ret = set_privileged(&cmd_cfg, &container_cfg, &buff); ASSERT_EQ(6, ret); - ASSERT_EQ(0, strlen(buff)); + ASSERT_EQ(0, buff.index); } write_command_file("[docker-command-execution]\n docker-command=run\n user=nobody\n privileged=true\n image=nothadoop/image"); ret = read_config(docker_command_file.c_str(), &cmd_cfg); if (ret != 0) { FAIL(); } - ret = set_privileged(&cmd_cfg, &container_cfg, buff, buff_len); + reset(&buff); + ret = set_privileged(&cmd_cfg, &container_cfg, &buff); ASSERT_EQ(PRIVILEGED_CONTAINERS_DISABLED, ret); - ASSERT_EQ(0, strlen(buff)); + ASSERT_EQ(0, buff.index); } @@ -671,31 +688,30 @@ namespace ContainerExecutor { file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run\n user=root\n privileged=false", "")); for (itr = file_cmd_vec.begin(); itr != file_cmd_vec.end(); ++itr) { - memset(buff, 0, buff_len); + reset(&buff); write_command_file(itr->first); ret = read_config(docker_command_file.c_str(), &cmd_cfg); if (ret != 0) { FAIL(); } - ret = set_privileged(&cmd_cfg, &container_cfg, buff, buff_len); + ret = set_privileged(&cmd_cfg, &container_cfg, &buff); ASSERT_EQ(0, ret); - ASSERT_STREQ(itr->second.c_str(), buff); + ASSERT_STREQ(itr->second.c_str(), flatten(&buff)); } write_command_file("[docker-command-execution]\n docker-command=run\n user=root\n privileged=true"); ret = read_config(docker_command_file.c_str(), &cmd_cfg); if (ret != 0) { FAIL(); } - ret = set_privileged(&cmd_cfg, &container_cfg, buff, buff_len); + ret = set_privileged(&cmd_cfg, &container_cfg, &buff); ASSERT_EQ(PRIVILEGED_CONTAINERS_DISABLED, ret); - ASSERT_EQ(0, strlen(buff)); + ASSERT_EQ(0, buff.index); } } TEST_F(TestDockerUtil, test_set_capabilities) { struct configuration container_cfg, cmd_cfg; - const int buff_len = 1024; - char buff[buff_len]; + argv buff; int ret = 0; std::string container_executor_cfg_contents = "[docker]\n" " docker.allowed.capabilities=CHROOT,MKNOD\n" @@ -703,19 +719,19 @@ namespace ContainerExecutor { std::vector > file_cmd_vec; file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run\n image=hadoop/docker-image\n cap-add=CHROOT,MKNOD", - "--cap-drop='ALL' --cap-add='CHROOT' --cap-add='MKNOD' ")); + "--cap-drop=ALL --cap-add=CHROOT --cap-add=MKNOD")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run\n image=nothadoop/docker-image\n cap-add=CHROOT,MKNOD", - "--cap-drop='ALL' ")); + "--cap-drop=ALL")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run\n image=hadoop/docker-image\n cap-add=CHROOT", - "--cap-drop='ALL' --cap-add='CHROOT' ")); + "--cap-drop=ALL --cap-add=CHROOT")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run\n image=hadoop/docker-image\n", - "--cap-drop='ALL' ")); + "--cap-drop=ALL")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run\n image=nothadoop/docker-image\n", - "--cap-drop='ALL' ")); + "--cap-drop=ALL")); write_container_executor_cfg(container_executor_cfg_contents); ret = read_config(container_executor_cfg_file.c_str(), &container_cfg); @@ -724,25 +740,24 @@ namespace ContainerExecutor { FAIL(); } for (itr = file_cmd_vec.begin(); itr != file_cmd_vec.end(); ++itr) { - memset(buff, 0, buff_len); + reset(&buff); write_command_file(itr->first); ret = read_config(docker_command_file.c_str(), &cmd_cfg); if (ret != 0) { FAIL(); } - ret = set_capabilities(&cmd_cfg, &container_cfg, buff, buff_len); + ret = set_capabilities(&cmd_cfg, &container_cfg, &buff); ASSERT_EQ(0, ret); - ASSERT_STREQ(itr->second.c_str(), buff); + ASSERT_STREQ(itr->second.c_str(), flatten(&buff)); } write_command_file("[docker-command-execution]\n docker-command=run\n image=hadoop/docker-image\n cap-add=SETGID"); ret = read_config(docker_command_file.c_str(), &cmd_cfg); if (ret != 0) { FAIL(); } - strcpy(buff, "test string"); - ret = set_capabilities(&cmd_cfg, &container_cfg, buff, buff_len); + reset(&buff); + ret = set_capabilities(&cmd_cfg, &container_cfg, &buff); ASSERT_EQ(INVALID_DOCKER_CAPABILITY, ret); - ASSERT_EQ(0, strlen(buff)); container_executor_cfg_contents = "[docker]\n docker.privileged-containers.registries=hadoop\n"; write_container_executor_cfg(container_executor_cfg_contents); @@ -750,16 +765,15 @@ namespace ContainerExecutor { if (ret != 0) { FAIL(); } - strcpy(buff, "test string"); - ret = set_capabilities(&cmd_cfg, &container_cfg, buff, buff_len); + reset(&buff); + ret = set_capabilities(&cmd_cfg, &container_cfg, &buff); ASSERT_EQ(INVALID_DOCKER_CAPABILITY, ret); - ASSERT_EQ(0, strlen(buff)); } TEST_F(TestDockerUtil, test_set_devices) { struct configuration container_cfg, cmd_cfg; - const int buff_len = 1024; - char buff[buff_len]; + argv buff; + reset(&buff); int ret = 0; std::string container_executor_cfg_contents = "[docker]\n" " docker.privileged-containers.registries=hadoop\n" @@ -767,22 +781,22 @@ namespace ContainerExecutor { std::vector > file_cmd_vec; file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run\n image=hadoop/image\n devices=/dev/test-device:/dev/test-device", - "--device='/dev/test-device:/dev/test-device' ")); + "--device=/dev/test-device:/dev/test-device")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run\n image=hadoop/image\n devices=/dev/device2:/dev/device2", - "--device='/dev/device2:/dev/device2' ")); + "--device=/dev/device2:/dev/device2")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run\n image=hadoop/image\n" " devices=/dev/test-device:/dev/test-device,/dev/device2:/dev/device2", - "--device='/dev/test-device:/dev/test-device' --device='/dev/device2:/dev/device2' ")); + "--device=/dev/test-device:/dev/test-device --device=/dev/device2:/dev/device2")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run\n image=hadoop/image\n" "devices=/dev/nvidiactl:/dev/nvidiactl", - "--device='/dev/nvidiactl:/dev/nvidiactl' ")); + "--device=/dev/nvidiactl:/dev/nvidiactl")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run\n image=hadoop/image\n" "devices=/dev/nvidia1:/dev/nvidia1,/dev/gpu-uvm-tools:/dev/gpu-uvm-tools", - "--device='/dev/nvidia1:/dev/nvidia1' --device='/dev/gpu-uvm-tools:/dev/gpu-uvm-tools' ")); + "--device=/dev/nvidia1:/dev/nvidia1 --device=/dev/gpu-uvm-tools:/dev/gpu-uvm-tools")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run\n image=hadoop/image", "")); write_container_executor_cfg(container_executor_cfg_contents); @@ -793,75 +807,75 @@ namespace ContainerExecutor { FAIL(); } for (itr = file_cmd_vec.begin(); itr != file_cmd_vec.end(); ++itr) { - memset(buff, 0, buff_len); + reset(&buff); write_command_file(itr->first); ret = read_config(docker_command_file.c_str(), &cmd_cfg); if (ret != 0) { FAIL(); } - ret = set_devices(&cmd_cfg, &container_cfg, buff, buff_len); + ret = set_devices(&cmd_cfg, &container_cfg, &buff); ASSERT_EQ(0, ret); - ASSERT_STREQ(itr->second.c_str(), buff); + ASSERT_STREQ(itr->second.c_str(), flatten(&buff)); } write_command_file("[docker-command-execution]\n docker-command=run\n image=nothadoop/image\n devices=/dev/test-device:/dev/test-device"); ret = read_config(docker_command_file.c_str(), &cmd_cfg); if (ret != 0) { FAIL(); } - strcpy(buff, "test string"); - ret = set_devices(&cmd_cfg, &container_cfg, buff, buff_len); + reset(&buff); + ret = set_devices(&cmd_cfg, &container_cfg, &buff); ASSERT_EQ(INVALID_DOCKER_DEVICE, ret); - ASSERT_EQ(0, strlen(buff)); + ASSERT_EQ(0, buff.index); write_command_file("[docker-command-execution]\n docker-command=run\n image=hadoop/image\n devices=/dev/device3:/dev/device3"); ret = read_config(docker_command_file.c_str(), &cmd_cfg); if (ret != 0) { FAIL(); } - strcpy(buff, "test string"); - ret = set_devices(&cmd_cfg, &container_cfg, buff, buff_len); + reset(&buff); + ret = set_devices(&cmd_cfg, &container_cfg, &buff); ASSERT_EQ(INVALID_DOCKER_DEVICE, ret); - ASSERT_EQ(0, strlen(buff)); + ASSERT_EQ(0, buff.index); write_command_file("[docker-command-execution]\n docker-command=run\n image=hadoop/image\n devices=/dev/device1"); ret = read_config(docker_command_file.c_str(), &cmd_cfg); if (ret != 0) { FAIL(); } - strcpy(buff, "test string"); - ret = set_devices(&cmd_cfg, &container_cfg, buff, buff_len); + reset(&buff); + ret = set_devices(&cmd_cfg, &container_cfg, &buff); ASSERT_EQ(INVALID_DOCKER_DEVICE, ret); - ASSERT_EQ(0, strlen(buff)); + ASSERT_EQ(0, buff.index); write_command_file("[docker-command-execution]\n docker-command=run\n image=hadoop/image\n devices=/dev/testnvidia:/dev/testnvidia"); ret = read_config(docker_command_file.c_str(), &cmd_cfg); if (ret != 0) { FAIL(); } - strcpy(buff, "test string"); - ret = set_devices(&cmd_cfg, &container_cfg, buff, buff_len); + reset(&buff); + ret = set_devices(&cmd_cfg, &container_cfg, &buff); ASSERT_EQ(INVALID_DOCKER_DEVICE, ret); - ASSERT_EQ(0, strlen(buff)); + ASSERT_EQ(0, buff.index); write_command_file("[docker-command-execution]\n docker-command=run\n image=hadoop/image\n devices=/dev/gpu-nvidia-uvm:/dev/gpu-nvidia-uvm"); ret = read_config(docker_command_file.c_str(), &cmd_cfg); if (ret != 0) { FAIL(); } - strcpy(buff, "test string"); - ret = set_devices(&cmd_cfg, &container_cfg, buff, buff_len); + reset(&buff); + ret = set_devices(&cmd_cfg, &container_cfg, &buff); ASSERT_EQ(INVALID_DOCKER_DEVICE, ret); - ASSERT_EQ(0, strlen(buff)); + ASSERT_EQ(0, buff.index); write_command_file("[docker-command-execution]\n docker-command=run\n image=hadoop/image\n devices=/dev/device1"); ret = read_config(docker_command_file.c_str(), &cmd_cfg); if (ret != 0) { FAIL(); } - strcpy(buff, "test string"); - ret = set_devices(&cmd_cfg, &container_cfg, buff, buff_len); + reset(&buff); + ret = set_devices(&cmd_cfg, &container_cfg, &buff); ASSERT_EQ(INVALID_DOCKER_DEVICE, ret); - ASSERT_EQ(0, strlen(buff)); + ASSERT_EQ(0, buff.index); container_executor_cfg_contents = "[docker]\n"; write_container_executor_cfg(container_executor_cfg_contents); @@ -869,37 +883,36 @@ namespace ContainerExecutor { if (ret != 0) { FAIL(); } - strcpy(buff, "test string"); - ret = set_devices(&cmd_cfg, &container_cfg, buff, buff_len); + reset(&buff); + ret = set_devices(&cmd_cfg, &container_cfg, &buff); ASSERT_EQ(INVALID_DOCKER_DEVICE, ret); - ASSERT_EQ(0, strlen(buff)); + ASSERT_EQ(0, buff.index); } TEST_F(TestDockerUtil, test_add_rw_mounts) { struct configuration container_cfg, cmd_cfg; - const int buff_len = 1024; - char buff[buff_len]; + argv buff; int ret = 0; std::string container_executor_cfg_contents = "[docker]\n docker.privileged-containers.registries=hadoop\n " - "docker.allowed.rw-mounts=/opt,/var,/usr/bin/cut,..\n " + "docker.allowed.rw-mounts=/opt,/var,/usr/bin/cut\n " "docker.allowed.ro-mounts=/etc/passwd"; std::vector > file_cmd_vec; file_cmd_vec.push_back(std::make_pair( - "[docker-command-execution]\n docker-command=run\n image=hadoop/image\n rw-mounts=/var:/var", "-v '/var:/var' ")); + "[docker-command-execution]\n docker-command=run\n image=hadoop/image\n rw-mounts=/var:/var", "-v /var:/var")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run\n image=nothadoop/image\n rw-mounts=/var:/var", "")); file_cmd_vec.push_back(std::make_pair( - "[docker-command-execution]\n docker-command=run\n image=hadoop/image\n rw-mounts=/var/:/var/", "-v '/var/:/var/' ")); + "[docker-command-execution]\n docker-command=run\n image=hadoop/image\n rw-mounts=/var/:/var/", "-v /var/:/var/")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run\n image=hadoop/image\n rw-mounts=/usr/bin/cut:/usr/bin/cut", - "-v '/usr/bin/cut:/usr/bin/cut' ")); + "-v /usr/bin/cut:/usr/bin/cut")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run\n image=nothadoop/image\n rw-mounts=/lib:/lib", "")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run\n image=hadoop/image\n rw-mounts=/opt:/mydisk1,/var/log/:/mydisk2", - "-v '/opt:/mydisk1' -v '/var/log/:/mydisk2' ")); + "-v /opt:/mydisk1 -v /var/log/:/mydisk2")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run\n image=nothadoop/image\n rw-mounts=/opt:/mydisk1,/var/log/:/mydisk2", "")); @@ -922,15 +935,15 @@ namespace ContainerExecutor { std::vector >::const_iterator itr; for (itr = file_cmd_vec.begin(); itr != file_cmd_vec.end(); ++itr) { - memset(buff, 0, buff_len); + reset(&buff); write_command_file(itr->first); ret = read_config(docker_command_file.c_str(), &cmd_cfg); if (ret != 0) { FAIL(); } - ret = add_rw_mounts(&cmd_cfg, &container_cfg, buff, buff_len); + ret = add_rw_mounts(&cmd_cfg, &container_cfg, &buff); ASSERT_EQ(0, ret); - ASSERT_STREQ(itr->second.c_str(), buff); + ASSERT_STREQ(itr->second.c_str(), flatten(&buff)); } std::vector > bad_file_cmds_vec; @@ -947,16 +960,16 @@ namespace ContainerExecutor { std::vector >::const_iterator itr2; for (itr2 = bad_file_cmds_vec.begin(); itr2 != bad_file_cmds_vec.end(); ++itr2) { - memset(buff, 0, buff_len); + reset(&buff); write_command_file(itr2->first); ret = read_config(docker_command_file.c_str(), &cmd_cfg); if (ret != 0) { FAIL(); } - strcpy(buff, "test string"); - ret = add_rw_mounts(&cmd_cfg, &container_cfg, buff, buff_len); + reset(&buff); + ret = add_rw_mounts(&cmd_cfg, &container_cfg, &buff); ASSERT_EQ(itr2->second, ret); - ASSERT_STREQ("", buff); + ASSERT_STREQ("", flatten(&buff)); } // verify that you can't mount any directory in the container-executor.cfg path @@ -964,16 +977,16 @@ namespace ContainerExecutor { while (strlen(ce_path) != 0) { std::string cmd_file_contents = "[docker-command-execution]\n docker-command=run\n image=hadoop/image\n rw-mounts="; cmd_file_contents.append(ce_path).append(":").append("/etc/hadoop"); - memset(buff, 0, buff_len); + reset(&buff); write_command_file(cmd_file_contents); ret = read_config(docker_command_file.c_str(), &cmd_cfg); if (ret != 0) { FAIL(); } - strcpy(buff, "test string"); - ret = add_rw_mounts(&cmd_cfg, &container_cfg, buff, buff_len); + reset(&buff); + ret = add_rw_mounts(&cmd_cfg, &container_cfg, &buff); ASSERT_EQ(INVALID_DOCKER_RW_MOUNT, ret) << " for input " << cmd_file_contents; - ASSERT_STREQ("", buff); + ASSERT_STREQ("", flatten(&buff)); char *tmp = strrchr(ce_path, '/'); if (tmp != NULL) { *tmp = '\0'; @@ -989,46 +1002,43 @@ namespace ContainerExecutor { if (ret != 0) { FAIL(); } - strcpy(buff, "test string"); - ret = add_rw_mounts(&cmd_cfg, &container_cfg, buff, buff_len); + reset(&buff); + ret = add_rw_mounts(&cmd_cfg, &container_cfg, &buff); ASSERT_EQ(0, ret); - ASSERT_EQ(11, strlen(buff)); + ASSERT_STREQ("", flatten(&buff)); } TEST_F(TestDockerUtil, test_add_ro_mounts) { struct configuration container_cfg, cmd_cfg; - const int buff_len = 1024; - char buff[buff_len]; + argv buff; int ret = 0; std::string container_executor_cfg_contents = "[docker]\n docker.privileged-containers.registries=hadoop\n " - "docker.allowed.rw-mounts=/home/,/var,/usr/bin/cut,..\n " + "docker.allowed.rw-mounts=/home/,/var,/usr/bin/cut\n " "docker.allowed.ro-mounts=/etc/passwd,/etc/group"; std::vector > file_cmd_vec; file_cmd_vec.push_back(std::make_pair( - "[docker-command-execution]\n docker-command=run\n image=hadoop/image\n ro-mounts=/var:/var", "-v '/var:/var:ro' ")); - file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run\n image=nothadoop/image\n ro-mounts=/var:/var", "")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run\n image=nothadoop/image\n ro-mounts=/etc:/etc", "")); file_cmd_vec.push_back(std::make_pair( - "[docker-command-execution]\n docker-command=run\n image=hadoop/image\n ro-mounts=/var/:/var/", "-v '/var/:/var/:ro' ")); + "[docker-command-execution]\n docker-command=run\n image=hadoop/image\n ro-mounts=/var/:/var/", "-v /var/:/var/:ro")); file_cmd_vec.push_back(std::make_pair( - "[docker-command-execution]\n docker-command=run\n image=hadoop/image\n ro-mounts=/home:/home", "-v '/home:/home:ro' ")); + "[docker-command-execution]\n docker-command=run\n image=hadoop/image\n ro-mounts=/home:/home", "-v /home:/home:ro")); file_cmd_vec.push_back(std::make_pair( - "[docker-command-execution]\n docker-command=run\n image=hadoop/image\n ro-mounts=/home/:/home", "-v '/home/:/home:ro' ")); + "[docker-command-execution]\n docker-command=run\n image=hadoop/image\n ro-mounts=/home/:/home", "-v /home/:/home:ro")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run\n image=hadoop/image\n ro-mounts=/usr/bin/cut:/usr/bin/cut", - "-v '/usr/bin/cut:/usr/bin/cut:ro' ")); + "-v /usr/bin/cut:/usr/bin/cut:ro")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run\n image=hadoop/image\n ro-mounts=/etc/group:/etc/group", - "-v '/etc/group:/etc/group:ro' ")); + "-v /etc/group:/etc/group:ro")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run\n image=hadoop/image\n ro-mounts=/etc/passwd:/etc/passwd", - "-v '/etc/passwd:/etc/passwd:ro' ")); + "-v /etc/passwd:/etc/passwd:ro")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run\n image=hadoop/image\n ro-mounts=/var/log:/mydisk1,/etc/passwd:/etc/passwd", - "-v '/var/log:/mydisk1:ro' -v '/etc/passwd:/etc/passwd:ro' ")); + "-v /var/log:/mydisk1:ro -v /etc/passwd:/etc/passwd:ro")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run\n image=hadoop/image\n", "")); write_container_executor_cfg(container_executor_cfg_contents); @@ -1046,15 +1056,15 @@ namespace ContainerExecutor { std::vector >::const_iterator itr; for (itr = file_cmd_vec.begin(); itr != file_cmd_vec.end(); ++itr) { - memset(buff, 0, buff_len); + reset(&buff); write_command_file(itr->first); ret = read_config(docker_command_file.c_str(), &cmd_cfg); if (ret != 0) { FAIL(); } - ret = add_ro_mounts(&cmd_cfg, &container_cfg, buff, buff_len); + ret = add_ro_mounts(&cmd_cfg, &container_cfg, &buff); ASSERT_EQ(0, ret); - ASSERT_STREQ(itr->second.c_str(), buff); + ASSERT_STREQ(itr->second.c_str(), flatten(&buff)); } std::vector > bad_file_cmds_vec; @@ -1068,16 +1078,16 @@ namespace ContainerExecutor { std::vector >::const_iterator itr2; for (itr2 = bad_file_cmds_vec.begin(); itr2 != bad_file_cmds_vec.end(); ++itr2) { - memset(buff, 0, buff_len); + reset(&buff); write_command_file(itr2->first); ret = read_config(docker_command_file.c_str(), &cmd_cfg); if (ret != 0) { FAIL(); } - strcpy(buff, "test string"); - ret = add_ro_mounts(&cmd_cfg, &container_cfg, buff, buff_len); + reset(&buff); + ret = add_ro_mounts(&cmd_cfg, &container_cfg, &buff); ASSERT_EQ(itr2->second, ret); - ASSERT_STREQ("", buff); + ASSERT_STREQ("", flatten(&buff)); } container_executor_cfg_contents = "[docker]\n docker.privileged-containers.registries=hadoop\n"; @@ -1087,10 +1097,10 @@ namespace ContainerExecutor { FAIL(); } write_command_file("[docker-command-execution]\n docker-command=run\n image=hadoop/image\n ro-mounts=/home:/home"); - strcpy(buff, "test string"); - ret = add_ro_mounts(&cmd_cfg, &container_cfg, buff, buff_len); + reset(&buff); + ret = add_ro_mounts(&cmd_cfg, &container_cfg, &buff); ASSERT_EQ(INVALID_DOCKER_RO_MOUNT, ret); - ASSERT_EQ(0, strlen(buff)); + ASSERT_EQ(0, buff.index); } TEST_F(TestDockerUtil, test_docker_run_privileged) { @@ -1113,14 +1123,14 @@ namespace ContainerExecutor { std::vector > file_cmd_vec; file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run\n name=container_e1_12312_11111_02_000001\n image=hadoop/docker-image\n user=nobody", - "run --name='container_e1_12312_11111_02_000001' --user='nobody' --cap-drop='ALL' 'hadoop/docker-image' ")); + "/usr/bin/docker run --name=container_e1_12312_11111_02_000001 --user=nobody --cap-drop=ALL hadoop/docker-image")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run\n name=container_e1_12312_11111_02_000001\n image=nothadoop/docker-image\n user=nobody", - "run --name='container_e1_12312_11111_02_000001' --user='nobody' --cap-drop='ALL' 'nothadoop/docker-image' ")); + "/usr/bin/docker run --name=container_e1_12312_11111_02_000001 --user=nobody --cap-drop=ALL nothadoop/docker-image")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run\n name=container_e1_12312_11111_02_000001\n image=hadoop/docker-image\n user=nobody\n" " launch-command=bash,test_script.sh,arg1,arg2", - "run --name='container_e1_12312_11111_02_000001' --user='nobody' --cap-drop='ALL' 'hadoop/docker-image' 'bash' 'test_script.sh' 'arg1' 'arg2' ")); + "/usr/bin/docker run --name=container_e1_12312_11111_02_000001 --user=nobody --cap-drop=ALL hadoop/docker-image bash test_script.sh arg1 arg2")); // Test non-privileged conatiner with launch command file_cmd_vec.push_back(std::make_pair( @@ -1130,10 +1140,10 @@ namespace ContainerExecutor { " network=bridge\n devices=/dev/test:/dev/test\n" " cap-add=CHOWN,SETUID\n cgroup-parent=ctr-cgroup\n detach=true\n rm=true\n" " launch-command=bash,test_script.sh,arg1,arg2", - "run --name='container_e1_12312_11111_02_000001' --user='nobody' -d --rm -v '/var/log:/var/log:ro' -v '/var/lib:/lib:ro'" - " -v '/usr/bin/cut:/usr/bin/cut:ro' -v '/tmp:/tmp' --cgroup-parent='ctr-cgroup' --cap-drop='ALL' --cap-add='CHOWN'" - " --cap-add='SETUID' --hostname='host-id' --device='/dev/test:/dev/test' 'hadoop/docker-image' 'bash' " - "'test_script.sh' 'arg1' 'arg2' ")); + "/usr/bin/docker run --name=container_e1_12312_11111_02_000001 --user=nobody -d --rm -v /var/log:/var/log:ro -v /var/lib:/lib:ro" + " -v /usr/bin/cut:/usr/bin/cut:ro -v /tmp:/tmp --cgroup-parent=ctr-cgroup --cap-drop=ALL --cap-add=CHOWN" + " --cap-add=SETUID --hostname=host-id --device=/dev/test:/dev/test hadoop/docker-image bash " + "test_script.sh arg1 arg2")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n" " docker-command=run\n name=container_e1_12312_11111_02_000001\n image=nothadoop/docker-image\n user=nobody\n hostname=host-id\n" @@ -1141,8 +1151,8 @@ namespace ContainerExecutor { " network=bridge\n" " cap-add=CHOWN,SETUID\n cgroup-parent=ctr-cgroup\n detach=true\n rm=true\n" " launch-command=bash,test_script.sh,arg1,arg2", - "run --name='container_e1_12312_11111_02_000001' --user='nobody' -d --rm" - " --cgroup-parent='ctr-cgroup' --cap-drop='ALL' --hostname='host-id' 'nothadoop/docker-image' ")); + "/usr/bin/docker run --name=container_e1_12312_11111_02_000001 --user=nobody -d --rm" + " --cgroup-parent=ctr-cgroup --cap-drop=ALL --hostname=host-id nothadoop/docker-image")); // Test non-privileged container and drop all privileges file_cmd_vec.push_back(std::make_pair( @@ -1152,10 +1162,10 @@ namespace ContainerExecutor { " network=bridge\n devices=/dev/test:/dev/test\n net=bridge\n" " cap-add=CHOWN,SETUID\n cgroup-parent=ctr-cgroup\n detach=true\n rm=true\n" " launch-command=bash,test_script.sh,arg1,arg2", - "run --name='container_e1_12312_11111_02_000001' --user='nobody' -d --rm --net='bridge' -v '/var/log:/var/log:ro' -v '/var/lib:/lib:ro'" - " -v '/usr/bin/cut:/usr/bin/cut:ro' -v '/tmp:/tmp' --cgroup-parent='ctr-cgroup' --cap-drop='ALL' --cap-add='CHOWN' " - "--cap-add='SETUID' --hostname='host-id' --device='/dev/test:/dev/test' 'hadoop/docker-image' 'bash'" - " 'test_script.sh' 'arg1' 'arg2' ")); + "/usr/bin/docker run --name=container_e1_12312_11111_02_000001 --user=nobody -d --rm --net=bridge -v /var/log:/var/log:ro -v /var/lib:/lib:ro" + " -v /usr/bin/cut:/usr/bin/cut:ro -v /tmp:/tmp --cgroup-parent=ctr-cgroup --cap-drop=ALL --cap-add=CHOWN " + "--cap-add=SETUID --hostname=host-id --device=/dev/test:/dev/test hadoop/docker-image bash" + " test_script.sh arg1 arg2")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n" " docker-command=run\n name=container_e1_12312_11111_02_000001\n image=nothadoop/docker-image\n user=nobody\n hostname=host-id\n" @@ -1163,8 +1173,8 @@ namespace ContainerExecutor { " network=bridge\n net=bridge\n" " cap-add=CHOWN,SETUID\n cgroup-parent=ctr-cgroup\n detach=true\n rm=true\n" " launch-command=bash,test_script.sh,arg1,arg2", - "run --name='container_e1_12312_11111_02_000001' --user='nobody' -d --rm --net='bridge'" - " --cgroup-parent='ctr-cgroup' --cap-drop='ALL' --hostname='host-id' 'nothadoop/docker-image' ")); + "/usr/bin/docker run --name=container_e1_12312_11111_02_000001 --user=nobody -d --rm --net=bridge" + " --cgroup-parent=ctr-cgroup --cap-drop=ALL --hostname=host-id nothadoop/docker-image")); // Test privileged container file_cmd_vec.push_back(std::make_pair( @@ -1174,10 +1184,10 @@ namespace ContainerExecutor { " network=bridge\n devices=/dev/test:/dev/test\n net=bridge\n privileged=true\n" " cap-add=CHOWN,SETUID\n cgroup-parent=ctr-cgroup\n detach=true\n rm=true\n" " launch-command=bash,test_script.sh,arg1,arg2", - "run --name='container_e1_12312_11111_02_000001' -d --rm --net='bridge' -v '/var/log:/var/log:ro' -v '/var/lib:/lib:ro'" - " -v '/usr/bin/cut:/usr/bin/cut:ro' -v '/tmp:/tmp' --cgroup-parent='ctr-cgroup' --privileged --cap-drop='ALL' " - "--cap-add='CHOWN' --cap-add='SETUID' --hostname='host-id' --device='/dev/test:/dev/test' 'hadoop/docker-image' " - "'bash' 'test_script.sh' 'arg1' 'arg2' ")); + "/usr/bin/docker run --name=container_e1_12312_11111_02_000001 -d --rm --net=bridge -v /var/log:/var/log:ro -v /var/lib:/lib:ro" + " -v /usr/bin/cut:/usr/bin/cut:ro -v /tmp:/tmp --cgroup-parent=ctr-cgroup --privileged --cap-drop=ALL " + "--cap-add=CHOWN --cap-add=SETUID --hostname=host-id --device=/dev/test:/dev/test hadoop/docker-image " + "bash test_script.sh arg1 arg2")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n" @@ -1186,10 +1196,10 @@ namespace ContainerExecutor { " network=bridge\n devices=/dev/test:/dev/test\n net=bridge\n privileged=true\n" " cap-add=CHOWN,SETUID\n cgroup-parent=ctr-cgroup\n detach=true\n rm=true\n group-add=1000,1001\n" " launch-command=bash,test_script.sh,arg1,arg2", - "run --name='container_e1_12312_11111_02_000001' -d --rm --net='bridge' -v '/var/log:/var/log:ro' -v '/var/lib:/lib:ro'" - " -v '/usr/bin/cut:/usr/bin/cut:ro' -v '/tmp:/tmp' --cgroup-parent='ctr-cgroup' --privileged --cap-drop='ALL' " - "--cap-add='CHOWN' --cap-add='SETUID' --hostname='host-id' " - "--device='/dev/test:/dev/test' 'hadoop/docker-image' 'bash' 'test_script.sh' 'arg1' 'arg2' ")); + "/usr/bin/docker run --name=container_e1_12312_11111_02_000001 -d --rm --net=bridge -v /var/log:/var/log:ro -v /var/lib:/lib:ro" + " -v /usr/bin/cut:/usr/bin/cut:ro -v /tmp:/tmp --cgroup-parent=ctr-cgroup --privileged --cap-drop=ALL " + "--cap-add=CHOWN --cap-add=SETUID --hostname=host-id " + "--device=/dev/test:/dev/test hadoop/docker-image bash test_script.sh arg1 arg2")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n" @@ -1197,9 +1207,9 @@ namespace ContainerExecutor { " network=bridge\n net=bridge\n" " detach=true\n rm=true\n group-add=1000,1001\n" " launch-command=bash,test_script.sh,arg1,arg2", - "run --name='container_e1_12312_11111_02_000001' --user='nobody' -d --rm --net='bridge' --cap-drop='ALL' " - "--hostname='host-id' --group-add '1000' --group-add '1001' " - "'docker-image' ")); + "/usr/bin/docker run --name=container_e1_12312_11111_02_000001 --user=nobody -d --rm --net=bridge --cap-drop=ALL " + "--hostname=host-id --group-add 1000 --group-add 1001 " + "docker-image")); std::vector > bad_file_cmd_vec; @@ -1302,11 +1312,11 @@ namespace ContainerExecutor { std::vector > file_cmd_vec; file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run\n name=container_e1_12312_11111_02_000001\n image=docker-image\n user=nobody", - "run --name='container_e1_12312_11111_02_000001' --user='nobody' --cap-drop='ALL' 'docker-image' ")); + "/usr/bin/docker run --name=container_e1_12312_11111_02_000001 --user=nobody --cap-drop=ALL docker-image")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run\n name=container_e1_12312_11111_02_000001\n image=docker-image\n" " user=nobody\n launch-command=bash,test_script.sh,arg1,arg2", - "run --name='container_e1_12312_11111_02_000001' --user='nobody' --cap-drop='ALL' 'docker-image' ")); + "/usr/bin/docker run --name=container_e1_12312_11111_02_000001 --user=nobody --cap-drop=ALL docker-image")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n" @@ -1315,10 +1325,10 @@ namespace ContainerExecutor { " network=bridge\n devices=/dev/test:/dev/test\n" " cap-add=CHOWN,SETUID\n cgroup-parent=ctr-cgroup\n detach=true\n rm=true\n" " launch-command=bash,test_script.sh,arg1,arg2", - "run --name='container_e1_12312_11111_02_000001' --user='nobody' -d --rm -v '/var/log:/var/log:ro' -v '/var/lib:/lib:ro'" - " -v '/usr/bin/cut:/usr/bin/cut:ro' -v '/tmp:/tmp' --cgroup-parent='ctr-cgroup' --cap-drop='ALL' --cap-add='CHOWN'" - " --cap-add='SETUID' --hostname='host-id' --device='/dev/test:/dev/test' 'hadoop/docker-image' 'bash' " - "'test_script.sh' 'arg1' 'arg2' ")); + "/usr/bin/docker run --name=container_e1_12312_11111_02_000001 --user=nobody -d --rm -v /var/log:/var/log:ro -v /var/lib:/lib:ro" + " -v /usr/bin/cut:/usr/bin/cut:ro -v /tmp:/tmp --cgroup-parent=ctr-cgroup --cap-drop=ALL --cap-add=CHOWN" + " --cap-add=SETUID --hostname=host-id --device=/dev/test:/dev/test hadoop/docker-image bash " + "test_script.sh arg1 arg2")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n" " docker-command=run\n name=container_e1_12312_11111_02_000001\n image=nothadoop/docker-image\n user=nobody\n hostname=host-id\n" @@ -1326,8 +1336,8 @@ namespace ContainerExecutor { " network=bridge\n" " cap-add=CHOWN,SETUID\n cgroup-parent=ctr-cgroup\n detach=true\n rm=true\n" " launch-command=bash,test_script.sh,arg1,arg2", - "run --name='container_e1_12312_11111_02_000001' --user='nobody' -d --rm" - " --cgroup-parent='ctr-cgroup' --cap-drop='ALL' --hostname='host-id' 'nothadoop/docker-image' ")); + "/usr/bin/docker run --name=container_e1_12312_11111_02_000001 --user=nobody -d --rm" + " --cgroup-parent=ctr-cgroup --cap-drop=ALL --hostname=host-id nothadoop/docker-image")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n" @@ -1336,10 +1346,10 @@ namespace ContainerExecutor { " network=bridge\n devices=/dev/test:/dev/test\n net=bridge\n" " cap-add=CHOWN,SETUID\n cgroup-parent=ctr-cgroup\n detach=true\n rm=true\n" " launch-command=bash,test_script.sh,arg1,arg2", - "run --name='container_e1_12312_11111_02_000001' --user='nobody' -d --rm --net='bridge' -v '/var/log:/var/log:ro' -v '/var/lib:/lib:ro'" - " -v '/usr/bin/cut:/usr/bin/cut:ro' -v '/tmp:/tmp' --cgroup-parent='ctr-cgroup' --cap-drop='ALL' --cap-add='CHOWN' " - "--cap-add='SETUID' --hostname='host-id' --device='/dev/test:/dev/test' 'hadoop/docker-image' 'bash'" - " 'test_script.sh' 'arg1' 'arg2' ")); + "/usr/bin/docker run --name=container_e1_12312_11111_02_000001 --user=nobody -d --rm --net=bridge -v /var/log:/var/log:ro -v /var/lib:/lib:ro" + " -v /usr/bin/cut:/usr/bin/cut:ro -v /tmp:/tmp --cgroup-parent=ctr-cgroup --cap-drop=ALL --cap-add=CHOWN " + "--cap-add=SETUID --hostname=host-id --device=/dev/test:/dev/test hadoop/docker-image bash" + " test_script.sh arg1 arg2")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n" " docker-command=run\n name=container_e1_12312_11111_02_000001\n image=nothadoop/docker-image\n user=nobody\n hostname=host-id\n" @@ -1347,8 +1357,8 @@ namespace ContainerExecutor { " network=bridge\n net=bridge\n" " cap-add=CHOWN,SETUID\n cgroup-parent=ctr-cgroup\n detach=true\n rm=true\n" " launch-command=bash,test_script.sh,arg1,arg2", - "run --name='container_e1_12312_11111_02_000001' --user='nobody' -d --rm --net='bridge'" - " --cgroup-parent='ctr-cgroup' --cap-drop='ALL' --hostname='host-id' 'nothadoop/docker-image' ")); + "/usr/bin/docker run --name=container_e1_12312_11111_02_000001 --user=nobody -d --rm --net=bridge" + " --cgroup-parent=ctr-cgroup --cap-drop=ALL --hostname=host-id nothadoop/docker-image")); std::vector > bad_file_cmd_vec; bad_file_cmd_vec.push_back(std::make_pair( @@ -1369,33 +1379,33 @@ namespace ContainerExecutor { input_output_map.push_back(std::make_pair( "[docker-command-execution]\n docker-command=inspect\n docker-config=/my-config\n" " format={{.State.Status}}\n name=container_e1_12312_11111_02_000001", - "--config='/my-config' inspect --format={{.State.Status}} container_e1_12312_11111_02_000001")); + "/usr/bin/docker --config=/my-config inspect --format={{.State.Status}} container_e1_12312_11111_02_000001")); input_output_map.push_back(std::make_pair( "[docker-command-execution]\n docker-command=load\n docker-config=/my-config\n image=image-id", - "--config='/my-config' load --i='image-id' ")); + "/usr/bin/docker --config=/my-config load --i=image-id")); input_output_map.push_back(std::make_pair( "[docker-command-execution]\n docker-command=pull\n docker-config=/my-config\n image=image-id", - "--config='/my-config' pull 'image-id' ")); + "/usr/bin/docker --config=/my-config pull image-id")); input_output_map.push_back(std::make_pair( "[docker-command-execution]\n docker-command=rm\n docker-config=/my-config\n name=container_e1_12312_11111_02_000001", - "--config='/my-config' rm container_e1_12312_11111_02_000001")); + "/usr/bin/docker --config=/my-config rm container_e1_12312_11111_02_000001")); input_output_map.push_back(std::make_pair( "[docker-command-execution]\n docker-command=stop\n docker-config=/my-config\n name=container_e1_12312_11111_02_000001", - "--config='/my-config' stop container_e1_12312_11111_02_000001")); + "/usr/bin/docker --config=/my-config stop container_e1_12312_11111_02_000001")); input_output_map.push_back(std::make_pair( "[docker-command-execution]\n docker-command=run\n docker-config=/my-config\n name=container_e1_12312_11111_02_000001\n" " image=docker-image\n user=nobody", - "--config='/my-config' run --name='container_e1_12312_11111_02_000001' --user='nobody' --cap-drop='ALL' 'docker-image' ")); + "/usr/bin/docker --config=/my-config run --name=container_e1_12312_11111_02_000001 --user=nobody --cap-drop=ALL docker-image")); std::vector >::const_iterator itr; - char buffer[4096]; + argv buffer; struct configuration cfg = {0, NULL}; for (itr = input_output_map.begin(); itr != input_output_map.end(); ++itr) { - memset(buffer, 0, 4096); + reset(&buffer); write_command_file(itr->first); - int ret = get_docker_command(docker_command_file.c_str(), &cfg, buffer, 4096); + int ret = get_docker_command(docker_command_file.c_str(), &cfg, &buffer); ASSERT_EQ(0, ret) << "for input " << itr->first; - ASSERT_STREQ(itr->second.c_str(), buffer); + ASSERT_STREQ(itr->second.c_str(), flatten(&buffer)); } } @@ -1430,10 +1440,10 @@ namespace ContainerExecutor { std::vector > file_cmd_vec; file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=volume\n sub-command=create\n volume=volume1 \n driver=driver1", - "volume create --name=volume1 --driver=driver1")); + "/usr/bin/docker volume create --name=volume1 --driver=driver1")); file_cmd_vec.push_back(std::make_pair( "[docker-command-execution]\n docker-command=volume\n format={{.Name}},{{.Driver}}\n sub-command=ls", - "volume ls --format={{.Name}},{{.Driver}}")); + "/usr/bin/docker volume ls --format={{.Name}},{{.Driver}}")); std::vector > bad_file_cmd_vec;