You are viewing a plain text version of this content. The canonical link for it is here.
Posted to common-commits@hadoop.apache.org by wa...@apache.org on 2017/09/28 23:46:00 UTC

[2/4] hadoop git commit: YARN-6623. Add support to turn off launching privileged containers in the container-executor. (Varun Vasudev via wangda)

http://git-wip-us.apache.org/repos/asf/hadoop/blob/d3b1c631/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/test/utils/test_docker_util.cc
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..c627ca8
--- /dev/null
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/main/native/container-executor/test/utils/test_docker_util.cc
@@ -0,0 +1,1122 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+#include <fstream>
+#include "errno.h"
+
+extern "C" {
+#include "utils/docker-util.c"
+}
+
+namespace ContainerExecutor {
+
+  class TestDockerUtil : public ::testing::Test {
+  protected:
+    virtual void SetUp() {
+      docker_command_file = "docker-command.cmd";
+      container_executor_cfg_file = "container-executor.cfg";
+      container_executor_cfg.size = 0;
+      container_executor_cfg.sections = NULL;
+    }
+
+    virtual void TearDown() {
+      remove(docker_command_file.c_str());
+      remove(container_executor_cfg_file.c_str());
+      delete_ce_file();
+    }
+
+    struct configuration container_executor_cfg;
+    std::string docker_command_file;
+    std::string container_executor_cfg_file;
+
+
+    void write_file(const std::string fname, const std::string contents) {
+      std::ofstream command_file;
+      command_file.open(fname.c_str());
+      command_file << contents;
+      command_file.close();
+    }
+
+    int create_ce_file() {
+      int ret = 0;
+      const char *fname = HADOOP_CONF_DIR "/" CONF_FILENAME;
+      if (strcmp("../etc/hadoop/container-executor.cfg", fname) == 0) {
+        ret = mkdir("../etc", 0755);
+        if (ret == 0 || errno == EEXIST) {
+          ret = mkdir("../etc/hadoop", 0755);
+          if (ret == 0 || errno == EEXIST) {
+            write_file("../etc/hadoop/container-executor.cfg", "");
+            return 0;
+          } else {
+            std::cerr << "Could not create ../etc/hadoop, " << strerror(errno) << std::endl;
+          }
+        } else {
+          std::cerr << "Could not create ../etc, " << strerror(errno) << std::endl;
+        }
+      }
+      std::cerr << "Could not create " << fname << std::endl;
+      return 1;
+    }
+
+    void delete_ce_file() {
+      const char *fname = HADOOP_CONF_DIR "/" CONF_FILENAME;
+      if (strcmp("../etc/hadoop/container-executor.cfg", fname) == 0) {
+        struct stat buffer;
+        if (stat(fname, &buffer) == 0) {
+          remove("../etc/hadoop/container-executor.cfg");
+          rmdir("../etc/hadoop");
+          rmdir("../etc");
+        }
+      }
+    }
+
+    void write_container_executor_cfg(const std::string contents) {
+      write_file(container_executor_cfg_file, contents);
+    }
+
+    void write_command_file(const std::string contents) {
+      write_file(docker_command_file, contents);
+    }
+
+    void run_docker_command_test(const std::vector<std::pair<std::string, std::string> > &file_cmd_vec,
+                                 const std::vector<std::pair<std::string, int> > &bad_file_cmd_vec,
+                                 int (*docker_func)(const char *, const struct configuration *, char *, const size_t)) {
+      char tmp[8192];
+      std::vector<std::pair<std::string, std::string> >::const_iterator itr;
+      for (itr = file_cmd_vec.begin(); itr != file_cmd_vec.end(); ++itr) {
+        memset(tmp, 0, 8192);
+        write_command_file(itr->first);
+        int ret = (*docker_func)(docker_command_file.c_str(), &container_executor_cfg, tmp, 8192);
+        ASSERT_EQ(0, ret) << "error message: " << get_docker_error_message(ret) << " for input " << itr->first;
+        ASSERT_STREQ(itr->second.c_str(), tmp);
+      }
+
+      std::vector<std::pair<std::string, int> >::const_iterator itr2;
+      for (itr2 = bad_file_cmd_vec.begin(); itr2 != bad_file_cmd_vec.end(); ++itr2) {
+        memset(tmp, 0, 8192);
+        write_command_file(itr2->first);
+        int ret = (*docker_func)(docker_command_file.c_str(), &container_executor_cfg, tmp, 8192);
+        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);
+      ASSERT_EQ(static_cast<int>(INVALID_COMMAND_FILE), ret);
+    }
+
+    void run_docker_run_helper_function(const std::vector<std::pair<std::string, std::string> > &file_cmd_vec,
+                                        int (*helper_func)(const struct configuration *, char *, const size_t)) {
+      std::vector<std::pair<std::string, std::string> >::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);
+        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);
+          ASSERT_EQ(0, ret);
+          ASSERT_STREQ(itr->second.c_str(), buff);
+        }
+      }
+    }
+  };
+
+  TEST_F(TestDockerUtil, test_docker_inspect) {
+    std::vector<std::pair<std::string, std::string> > file_cmd_vec;
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[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"));
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[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"));
+
+    std::vector<std::pair<std::string, int> > bad_file_cmd_vec;
+    bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
+        "[docker-command-execution]\n  docker-command=run\n  format='{{.State.Status}}'",
+        static_cast<int>(INCORRECT_COMMAND)));
+    bad_file_cmd_vec.push_back(
+        std::make_pair<std::string, int>("docker-command=inspect\n  format='{{.State.Status}}'",
+                                         static_cast<int>(INCORRECT_COMMAND)));
+    bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
+        "[docker-command-execution]\n  docker-command=inspect\n  format={{.State.Status}}\n  name=",
+        static_cast<int>(INVALID_DOCKER_CONTAINER_NAME)));
+    bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
+        "[docker-command-execution]\n  docker-command=inspect\n  format={{.State.Status}}",
+        static_cast<int>(INVALID_DOCKER_CONTAINER_NAME)));
+    bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
+        "[docker-command-execution]\n  docker-command=inspect\n  format=\n  name=container_e1_12312_11111_02_000001",
+        static_cast<int>(INVALID_DOCKER_INSPECT_FORMAT)));
+    bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
+        "[docker-command-execution]\n  docker-command=inspect\n  name=container_e1_12312_11111_02_000001",
+        static_cast<int>(INVALID_DOCKER_INSPECT_FORMAT)));
+    bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
+        "[docker-command-execution]\n  docker-command=inspect\n format={{.IPAddress}}\n  name=container_e1_12312_11111_02_000001",
+        static_cast<int>(INVALID_DOCKER_INSPECT_FORMAT)));
+
+    run_docker_command_test(file_cmd_vec, bad_file_cmd_vec, get_docker_inspect_command);
+  }
+
+  TEST_F(TestDockerUtil, test_docker_load) {
+    std::vector<std::pair<std::string, std::string> > file_cmd_vec;
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=load\n  image=image-id",
+        "load --i='image-id' "));
+
+    std::vector<std::pair<std::string, int> > bad_file_cmd_vec;
+    bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
+        "[docker-command-execution]\n  docker-command=run\n  image=image-id", static_cast<int>(INCORRECT_COMMAND)));
+    bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
+        "docker-command=load\n  image=image-id", static_cast<int>(INCORRECT_COMMAND)));
+    bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
+        "[docker-command-execution]\n  docker-command=load\n  image=", static_cast<int>(INVALID_DOCKER_IMAGE_NAME)));
+    bad_file_cmd_vec.push_back(std::make_pair<std::string, int>("[docker-command-execution]\n  docker-command=load",
+                                                                static_cast<int>(INVALID_DOCKER_IMAGE_NAME)));
+
+    run_docker_command_test(file_cmd_vec, bad_file_cmd_vec, get_docker_load_command);
+  }
+
+  TEST_F(TestDockerUtil, test_docker_validate_image_name) {
+    const char *good_input[] = {
+        "ubuntu",
+        "ubuntu:latest",
+        "ubuntu:14.04",
+        "ubuntu:LATEST",
+        "registry.com:5000/user/ubuntu",
+        "registry.com:5000/user/ubuntu:latest",
+        "registry.com:5000/user/ubuntu:0.1.2.3",
+        "registry.com/user/ubuntu",
+        "registry.com/user/ubuntu:latest",
+        "registry.com/user/ubuntu:0.1.2.3",
+        "registry.com/user/ubuntu:test-image",
+        "registry.com/user/ubuntu:test_image",
+        "registry.com/ubuntu",
+        "user/ubuntu",
+        "user/ubuntu:0.1.2.3",
+        "user/ubuntu:latest",
+        "user/ubuntu:test_image",
+        "user/ubuntu.test:test_image",
+        "user/ubuntu-test:test-image",
+        "registry.com/ubuntu/ubuntu/ubuntu"
+    };
+
+    const char *bad_input[] = {
+        "UBUNTU",
+        "registry.com|5000/user/ubuntu",
+        "registry.com | 5000/user/ubuntu",
+        "ubuntu' || touch /tmp/file #",
+        "ubuntu || touch /tmp/file #",
+        "''''''''",
+        "bad_host_name:5000/user/ubuntu",
+        "registry.com:foo/ubuntu/ubuntu/ubuntu",
+        "registry.com/ubuntu:foo/ubuntu/ubuntu"
+    };
+
+    int good_input_size = sizeof(good_input) / sizeof(char *);
+    int i = 0;
+    for (i = 0; i < good_input_size; i++) {
+      int op = validate_docker_image_name(good_input[i]);
+      ASSERT_EQ(0, op);
+    }
+
+    int bad_input_size = sizeof(bad_input) / sizeof(char *);
+    int j = 0;
+    for (j = 0; j < bad_input_size; j++) {
+      int op = validate_docker_image_name(bad_input[j]);
+      ASSERT_EQ(1, op);
+    }
+  }
+
+  TEST_F(TestDockerUtil, test_docker_pull) {
+    std::vector<std::pair<std::string, std::string> > file_cmd_vec;
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=pull\n  image=image-id",
+        "pull 'image-id' "));
+
+    std::vector<std::pair<std::string, int> > bad_file_cmd_vec;
+    bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
+        "[docker-command-execution]\n  docker-command=run\n  image=image-id", static_cast<int>(INCORRECT_COMMAND)));
+    bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
+        "docker-command=pull\n  image=image-id", static_cast<int>(INCORRECT_COMMAND)));
+    bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
+        "[docker-command-execution]\n  docker-command=pull\n  image=", static_cast<int>(INVALID_DOCKER_IMAGE_NAME)));
+    bad_file_cmd_vec.push_back(std::make_pair<std::string, int>("[docker-command-execution]\n  docker-command=pull",
+                                                                static_cast<int>(INVALID_DOCKER_IMAGE_NAME)));
+
+    run_docker_command_test(file_cmd_vec, bad_file_cmd_vec, get_docker_pull_command);
+  }
+
+  TEST_F(TestDockerUtil, test_docker_rm) {
+    std::vector<std::pair<std::string, std::string> > file_cmd_vec;
+    file_cmd_vec.push_back(
+        std::make_pair<std::string, std::string>(
+            "[docker-command-execution]\n  docker-command=rm\n  name=container_e1_12312_11111_02_000001",
+            "rm container_e1_12312_11111_02_000001"));
+
+    std::vector<std::pair<std::string, int> > bad_file_cmd_vec;
+    bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
+        "[docker-command-execution]\n  docker-command=run\n  name=container_e1_12312_11111_02_000001",
+        static_cast<int>(INCORRECT_COMMAND)));
+    bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
+        "docker-command=rm\n  name=ctr-id", static_cast<int>(INCORRECT_COMMAND)));
+    bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
+        "[docker-command-execution]\n  docker-command=rm\n  name=", static_cast<int>(INVALID_DOCKER_CONTAINER_NAME)));
+    bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
+        "[docker-command-execution]\n  docker-command=rm", static_cast<int>(INVALID_DOCKER_CONTAINER_NAME)));
+
+    run_docker_command_test(file_cmd_vec, bad_file_cmd_vec, get_docker_rm_command);
+  }
+
+  TEST_F(TestDockerUtil, test_docker_stop) {
+    std::vector<std::pair<std::string, std::string> > file_cmd_vec;
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=stop\n  name=container_e1_12312_11111_02_000001",
+        "stop container_e1_12312_11111_02_000001"));
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[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"));
+
+    std::vector<std::pair<std::string, int> > bad_file_cmd_vec;
+    bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
+        "[docker-command-execution]\n  docker-command=run\n  name=container_e1_12312_11111_02_000001",
+        static_cast<int>(INCORRECT_COMMAND)));
+    bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
+        "docker-command=stop\n  name=ctr-id", static_cast<int>(INCORRECT_COMMAND)));
+    bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
+        "[docker-command-execution]\n  docker-command=stop\n  name=", static_cast<int>(INVALID_DOCKER_CONTAINER_NAME)));
+    bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
+        "[docker-command-execution]\n  docker-command=stop", static_cast<int>(INVALID_DOCKER_CONTAINER_NAME)));
+    bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
+        "[docker-command-execution]\n  docker-command=stop\n  name=container_e1_12312_11111_02_000001\n  time=abcd",
+        static_cast<int>(INVALID_DOCKER_STOP_COMMAND)));
+
+
+    run_docker_command_test(file_cmd_vec, bad_file_cmd_vec, get_docker_stop_command);
+  }
+
+  TEST_F(TestDockerUtil, test_detach_container) {
+    std::vector<std::pair<std::string, std::string> > file_cmd_vec;
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run\n  detach=true", "-d "));
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run", ""));
+
+    run_docker_run_helper_function(file_cmd_vec, detach_container);
+  }
+
+  TEST_F(TestDockerUtil, test_rm_container) {
+    std::vector<std::pair<std::string, std::string> > file_cmd_vec;
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run\n  rm=true", "--rm "));
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run", ""));
+
+    run_docker_run_helper_function(file_cmd_vec, rm_container_on_exit);
+  }
+
+  TEST_F(TestDockerUtil, test_set_container_workdir) {
+    std::vector<std::pair<std::string, std::string> > file_cmd_vec;
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run\n  workdir=/tmp/test", "--workdir='/tmp/test' "));
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run", ""));
+
+    run_docker_run_helper_function(file_cmd_vec, set_container_workdir);
+  }
+
+  TEST_F(TestDockerUtil, test_set_cgroup_parent) {
+    std::vector<std::pair<std::string, std::string> > file_cmd_vec;
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run\n  cgroup-parent=/sys/fs/cgroup/yarn",
+        "--cgroup-parent='/sys/fs/cgroup/yarn' "));
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run", ""));
+
+    run_docker_run_helper_function(file_cmd_vec, set_cgroup_parent);
+  }
+
+  TEST_F(TestDockerUtil, test_set_hostname) {
+    std::vector<std::pair<std::string, std::string> > file_cmd_vec;
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run\n  hostname=ctr-id", "--hostname='ctr-id' "));
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run", ""));
+
+    run_docker_run_helper_function(file_cmd_vec, set_hostname);
+  }
+
+  TEST_F(TestDockerUtil, test_set_group_add) {
+    std::vector<std::pair<std::string, std::string> > file_cmd_vec;
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[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<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run", ""));
+
+    run_docker_run_helper_function(file_cmd_vec, set_group_add);
+  }
+
+  TEST_F(TestDockerUtil, test_set_network) {
+    struct configuration container_cfg;
+    const int buff_len = 1024;
+    char buff[buff_len];
+    int ret = 0;
+    std::string container_executor_cfg_contents = "[docker]\n  docker.allowed.networks=sdn1,bridge";
+    std::vector<std::pair<std::string, std::string> > file_cmd_vec;
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run\n  net=bridge", "--net='bridge' "));
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run\n  net=sdn1", "--net='sdn1' "));
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run", ""));
+    write_container_executor_cfg(container_executor_cfg_contents);
+    ret = read_config(container_executor_cfg_file.c_str(), &container_cfg);
+
+    std::vector<std::pair<std::string, std::string> >::const_iterator itr;
+    if (ret != 0) {
+      FAIL();
+    }
+    for (itr = file_cmd_vec.begin(); itr != file_cmd_vec.end(); ++itr) {
+      struct configuration cmd_cfg;
+      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_network(&cmd_cfg, &container_cfg, buff, buff_len);
+      ASSERT_EQ(0, ret);
+      ASSERT_STREQ(itr->second.c_str(), buff);
+    }
+    struct configuration cmd_cfg_1;
+    write_command_file("[docker-command-execution]\n  docker-command=run\n  net=sdn2");
+    ret = read_config(docker_command_file.c_str(), &cmd_cfg_1);
+    if (ret != 0) {
+      FAIL();
+    }
+    strcpy(buff, "test string");
+    ret = set_network(&cmd_cfg_1, &container_cfg, buff, buff_len);
+    ASSERT_EQ(INVALID_DOCKER_NETWORK, ret);
+    ASSERT_EQ(0, strlen(buff));
+
+    container_executor_cfg_contents = "[docker]\n";
+    write_container_executor_cfg(container_executor_cfg_contents);
+    ret = read_config(container_executor_cfg_file.c_str(), &container_cfg);
+    if (ret != 0) {
+      FAIL();
+    }
+    strcpy(buff, "test string");
+    ret = set_network(&cmd_cfg_1, &container_cfg, buff, buff_len);
+    ASSERT_EQ(INVALID_DOCKER_NETWORK, ret);
+    ASSERT_EQ(0, strlen(buff));
+  }
+
+  TEST_F(TestDockerUtil, test_check_mount_permitted) {
+    const char *permitted_mounts[] = {"/usr/", "/bin/ls", NULL};
+    std::vector<std::pair<std::string, int> > test_data;
+    test_data.push_back(std::make_pair<std::string, int>("/usr", 1));
+    test_data.push_back(std::make_pair<std::string, int>("/usr/", 1));
+    test_data.push_back(std::make_pair<std::string, int>("/bin/ls", 1));
+    test_data.push_back(std::make_pair<std::string, int>("//bin/", 0));
+    test_data.push_back(std::make_pair<std::string, int>("/tmp/random-file", -1));
+
+    std::vector<std::pair<std::string, int> >::const_iterator itr;
+    for (itr = test_data.begin(); itr != test_data.end(); ++itr) {
+      int ret = check_mount_permitted(permitted_mounts, itr->first.c_str());
+      ASSERT_EQ(itr->second, ret) << "for input " << itr->first;
+    }
+  }
+
+  TEST_F(TestDockerUtil, test_normalize_mounts) {
+    const int entries = 4;
+    const char *permitted_mounts[] = {"/home", "/usr", "/bin/ls", NULL};
+    const char *expected[] = {"/home/", "/usr/", "/bin/ls", NULL};
+    char **ptr = static_cast<char **>(malloc(entries * sizeof(char *)));
+    for (int i = 0; i < entries; ++i) {
+      if (permitted_mounts[i] != NULL) {
+        ptr[i] = strdup(permitted_mounts[i]);
+      } else {
+        ptr[i] = NULL;
+      }
+    }
+    normalize_mounts(ptr);
+    for (int i = 0; i < entries; ++i) {
+      ASSERT_STREQ(expected[i], ptr[i]);
+    }
+  }
+
+  TEST_F(TestDockerUtil, test_set_privileged) {
+    struct configuration container_cfg, cmd_cfg;
+    const int buff_len = 1024;
+    char buff[buff_len];
+    int ret = 0;
+    std::string container_executor_cfg_contents[] = {"[docker]\n  docker.privileged-containers.enabled=1",
+                                                     "[docker]\n  docker.privileged-containers.enabled=0",
+                                                     "[docker]\n"};
+    std::vector<std::pair<std::string, std::string> > file_cmd_vec;
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run\n  privileged=true", "--privileged "));
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run\n  privileged=false", ""));
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run", ""));
+    write_container_executor_cfg(container_executor_cfg_contents[0]);
+    ret = read_config(container_executor_cfg_file.c_str(), &container_cfg);
+
+    std::vector<std::pair<std::string, std::string> >::const_iterator itr;
+    if (ret != 0) {
+      FAIL();
+    }
+    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_privileged(&cmd_cfg, &container_cfg, buff, buff_len);
+      ASSERT_EQ(0, ret);
+      ASSERT_STREQ(itr->second.c_str(), buff);
+    }
+
+    // check default case and when it's turned off
+    for (int i = 1; i < 3; ++i) {
+      write_container_executor_cfg(container_executor_cfg_contents[i]);
+      ret = read_config(container_executor_cfg_file.c_str(), &container_cfg);
+      if (ret != 0) {
+        FAIL();
+      }
+      file_cmd_vec.clear();
+      file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+          "[docker-command-execution]\n  docker-command=run\n  privileged=false", ""));
+      file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+          "[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_privileged(&cmd_cfg, &container_cfg, buff, buff_len);
+        ASSERT_EQ(0, ret);
+        ASSERT_STREQ(itr->second.c_str(), buff);
+      }
+      write_command_file("[docker-command-execution]\n  docker-command=run\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);
+      ASSERT_EQ(PRIVILEGED_CONTAINERS_DISABLED, ret);
+      ASSERT_EQ(0, strlen(buff));
+    }
+  }
+
+  TEST_F(TestDockerUtil, test_set_capabilities) {
+    struct configuration container_cfg, cmd_cfg;
+    const int buff_len = 1024;
+    char buff[buff_len];
+    int ret = 0;
+    std::string container_executor_cfg_contents = "[docker]\n  docker.allowed.capabilities=CHROOT,MKNOD";
+    std::vector<std::pair<std::string, std::string> > file_cmd_vec;
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run\n  cap-add=CHROOT,MKNOD",
+        "--cap-drop='ALL' --cap-add='CHROOT' --cap-add='MKNOD' "));
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run\n  cap-add=CHROOT", "--cap-drop='ALL' --cap-add='CHROOT' "));
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run", "--cap-drop='ALL' "));
+    write_container_executor_cfg(container_executor_cfg_contents);
+    ret = read_config(container_executor_cfg_file.c_str(), &container_cfg);
+
+    std::vector<std::pair<std::string, std::string> >::const_iterator itr;
+    if (ret != 0) {
+      FAIL();
+    }
+    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_capabilities(&cmd_cfg, &container_cfg, buff, buff_len);
+      ASSERT_EQ(0, ret);
+      ASSERT_STREQ(itr->second.c_str(), buff);
+    }
+    write_command_file("[docker-command-execution]\n  docker-command=run\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);
+    ASSERT_EQ(INVALID_DOCKER_CAPABILITY, ret);
+    ASSERT_EQ(0, strlen(buff));
+
+    container_executor_cfg_contents = "[docker]\n";
+    write_container_executor_cfg(container_executor_cfg_contents);
+    ret = read_config(container_executor_cfg_file.c_str(), &container_cfg);
+    if (ret != 0) {
+      FAIL();
+    }
+    strcpy(buff, "test string");
+    ret = set_capabilities(&cmd_cfg, &container_cfg, buff, buff_len);
+    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];
+    int ret = 0;
+    std::string container_executor_cfg_contents = "[docker]\n  docker.allowed.devices=/dev/test-device,/dev/device2";
+    std::vector<std::pair<std::string, std::string> > file_cmd_vec;
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run\n  devices=/dev/test-device:/dev/test-device",
+        "--device='/dev/test-device:/dev/test-device' "));
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run\n  devices=/dev/device2:/dev/device2",
+        "--device='/dev/device2:/dev/device2' "));
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run\n  "
+            "devices=/dev/test-device:/dev/test-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<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run\n", ""));
+    write_container_executor_cfg(container_executor_cfg_contents);
+    ret = read_config(container_executor_cfg_file.c_str(), &container_cfg);
+
+    std::vector<std::pair<std::string, std::string> >::const_iterator itr;
+    if (ret != 0) {
+      FAIL();
+    }
+    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_devices(&cmd_cfg, &container_cfg, buff, buff_len);
+      ASSERT_EQ(0, ret);
+      ASSERT_STREQ(itr->second.c_str(), buff);
+    }
+    write_command_file("[docker-command-execution]\n  docker-command=run\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);
+    ASSERT_EQ(INVALID_DOCKER_DEVICE, ret);
+    ASSERT_EQ(0, strlen(buff));
+
+    write_command_file("[docker-command-execution]\n  docker-command=run\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);
+    ASSERT_EQ(INVALID_DOCKER_DEVICE, ret);
+    ASSERT_EQ(0, strlen(buff));
+
+    container_executor_cfg_contents = "[docker]\n";
+    write_container_executor_cfg(container_executor_cfg_contents);
+    ret = read_config(container_executor_cfg_file.c_str(), &container_cfg);
+    if (ret != 0) {
+      FAIL();
+    }
+    strcpy(buff, "test string");
+    ret = set_devices(&cmd_cfg, &container_cfg, buff, buff_len);
+    ASSERT_EQ(INVALID_DOCKER_DEVICE, ret);
+    ASSERT_EQ(0, strlen(buff));
+  }
+
+
+  TEST_F(TestDockerUtil, test_add_rw_mounts) {
+    struct configuration container_cfg, cmd_cfg;
+    const int buff_len = 1024;
+    char buff[buff_len];
+    int ret = 0;
+    std::string container_executor_cfg_contents = "[docker]\n  docker.allowed.rw-mounts=/usr,/var,/bin/ls,..\n  "
+                                                              "docker.allowed.ro-mounts=/bin/cat";
+    std::vector<std::pair<std::string, std::string> > file_cmd_vec;
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run\n  rw-mounts=/var:/var", "-v '/var:/var' "));
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run\n  rw-mounts=/var/:/var/", "-v '/var/:/var/' "));
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run\n  rw-mounts=/usr:/usr", "-v '/usr:/usr' "));
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run\n  rw-mounts=/usr/:/usr", "-v '/usr/:/usr' "));
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run\n  rw-mounts=/bin/ls:/bin/ls", "-v '/bin/ls:/bin/ls' "));
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run\n  rw-mounts=/usr/bin:/mydisk1,/var/log/:/mydisk2",
+        "-v '/usr/bin:/mydisk1' -v '/var/log/:/mydisk2' "));
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run\n", ""));
+    write_container_executor_cfg(container_executor_cfg_contents);
+    ret = read_config(container_executor_cfg_file.c_str(), &container_cfg);
+    if (ret != 0) {
+      FAIL();
+    }
+
+    ret = create_ce_file();
+    if (ret != 0) {
+      std::cerr << "Could not create ce file, skipping test" << std::endl;
+      return;
+    }
+
+    std::vector<std::pair<std::string, std::string> >::const_iterator itr;
+
+    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 = add_rw_mounts(&cmd_cfg, &container_cfg, buff, buff_len);
+      ASSERT_EQ(0, ret);
+      ASSERT_STREQ(itr->second.c_str(), buff);
+    }
+
+    std::vector<std::pair<std::string, int> > bad_file_cmds_vec;
+    bad_file_cmds_vec.push_back(std::make_pair<std::string, int>(
+        "[docker-command-execution]\n  docker-command=run\n  rw-mounts=/home:/home",
+        static_cast<int>(INVALID_DOCKER_RW_MOUNT)));
+    bad_file_cmds_vec.push_back(std::make_pair<std::string, int>(
+        "[docker-command-execution]\n  docker-command=run\n  rw-mounts=/bin/cat:/bin/cat",
+        static_cast<int>(INVALID_DOCKER_RW_MOUNT)));
+    bad_file_cmds_vec.push_back(std::make_pair<std::string, int>(
+        "[docker-command-execution]\n  docker-command=run\n  rw-mounts=/blah:/blah",
+        static_cast<int>(INVALID_DOCKER_MOUNT)));
+
+    std::vector<std::pair<std::string, int> >::const_iterator itr2;
+
+    for (itr2 = bad_file_cmds_vec.begin(); itr2 != bad_file_cmds_vec.end(); ++itr2) {
+      memset(buff, 0, buff_len);
+      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);
+      ASSERT_EQ(itr2->second, ret);
+      ASSERT_STREQ("", buff);
+    }
+
+    // verify that you can't mount any directory in the container-executor.cfg path
+    char *ce_path = realpath("../etc/hadoop/container-executor.cfg", NULL);
+    while (strlen(ce_path) != 0) {
+      std::string cmd_file_contents = "[docker-command-execution]\n  docker-command=run\n  rw-mounts=";
+      cmd_file_contents.append(ce_path).append(":").append("/etc/hadoop");
+      memset(buff, 0, buff_len);
+      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);
+      ASSERT_EQ(INVALID_DOCKER_RW_MOUNT, ret) << " for input " << cmd_file_contents;
+      ASSERT_STREQ("", buff);
+      char *tmp = strrchr(ce_path, '/');
+      if (tmp != NULL) {
+        *tmp = '\0';
+      }
+    }
+    free(ce_path);
+
+    container_executor_cfg_contents = "[docker]\n";
+    write_container_executor_cfg(container_executor_cfg_contents);
+    ret = read_config(container_executor_cfg_file.c_str(), &container_cfg);
+    if (ret != 0) {
+      FAIL();
+    }
+    strcpy(buff, "test string");
+    ret = add_rw_mounts(&cmd_cfg, &container_cfg, buff, buff_len);
+    ASSERT_EQ(INVALID_DOCKER_RW_MOUNT, ret);
+    ASSERT_EQ(0, strlen(buff));
+  }
+
+  TEST_F(TestDockerUtil, test_add_ro_mounts) {
+    struct configuration container_cfg, cmd_cfg;
+    const int buff_len = 1024;
+    char buff[buff_len];
+    int ret = 0;
+    std::string container_executor_cfg_contents = "[docker]\n  docker.allowed.rw-mounts=/usr,/var,/bin/ls\n  "
+                                                              "docker.allowed.ro-mounts=/bin/cat,/bin/ln";
+    std::vector<std::pair<std::string, std::string> > file_cmd_vec;
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run\n  ro-mounts=/var:/var", "-v '/var:/var:ro' "));
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run\n  ro-mounts=/var/:/var/", "-v '/var/:/var/:ro' "));
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run\n  ro-mounts=/usr:/usr", "-v '/usr:/usr:ro' "));
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run\n  ro-mounts=/usr/:/usr", "-v '/usr/:/usr:ro' "));
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run\n  ro-mounts=/bin/ls:/bin/ls", "-v '/bin/ls:/bin/ls:ro' "));
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run\n  ro-mounts=/bin/ln:/bin/ln", "-v '/bin/ln:/bin/ln:ro' "));
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run\n  ro-mounts=/bin/cat:/bin/cat",
+        "-v '/bin/cat:/bin/cat:ro' "));
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run\n  ro-mounts=/usr/bin:/mydisk1,/bin/cat:/bin/cat",
+        "-v '/usr/bin:/mydisk1:ro' -v '/bin/cat:/bin/cat:ro' "));
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run\n", ""));
+    write_container_executor_cfg(container_executor_cfg_contents);
+    ret = read_config(container_executor_cfg_file.c_str(), &container_cfg);
+    if (ret != 0) {
+      FAIL();
+    }
+
+    ret = create_ce_file();
+    if (ret != 0) {
+      std::cerr << "Could not create ce file, skipping test" << std::endl;
+      return;
+    }
+
+    std::vector<std::pair<std::string, std::string> >::const_iterator itr;
+
+    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 = add_ro_mounts(&cmd_cfg, &container_cfg, buff, buff_len);
+      ASSERT_EQ(0, ret);
+      ASSERT_STREQ(itr->second.c_str(), buff);
+    }
+
+    std::vector<std::pair<std::string, int> > bad_file_cmds_vec;
+    bad_file_cmds_vec.push_back(std::make_pair<std::string, int>(
+        "[docker-command-execution]\n  docker-command=run\n  ro-mounts=/home:/home",
+        static_cast<int>(INVALID_DOCKER_RO_MOUNT)));
+    bad_file_cmds_vec.push_back(std::make_pair<std::string, int>(
+        "[docker-command-execution]\n  docker-command=run\n  ro-mounts=/blah:/blah",
+        static_cast<int>(INVALID_DOCKER_MOUNT)));
+
+    std::vector<std::pair<std::string, int> >::const_iterator itr2;
+
+    for (itr2 = bad_file_cmds_vec.begin(); itr2 != bad_file_cmds_vec.end(); ++itr2) {
+      memset(buff, 0, buff_len);
+      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);
+      ASSERT_EQ(itr2->second, ret);
+      ASSERT_STREQ("", buff);
+    }
+
+    container_executor_cfg_contents = "[docker]\n";
+    write_container_executor_cfg(container_executor_cfg_contents);
+    ret = read_config(container_executor_cfg_file.c_str(), &container_cfg);
+    if (ret != 0) {
+      FAIL();
+    }
+    write_command_file("[docker-command-execution]\n  docker-command=run\n  ro-mounts=/home:/home");
+    strcpy(buff, "test string");
+    ret = add_ro_mounts(&cmd_cfg, &container_cfg, buff, buff_len);
+    ASSERT_EQ(INVALID_DOCKER_RO_MOUNT, ret);
+    ASSERT_EQ(0, strlen(buff));
+  }
+
+  TEST_F(TestDockerUtil, test_docker_run_privileged) {
+
+    std::string container_executor_contents = "[docker]\n  docker.allowed.ro-mounts=/var,/etc,/bin/ls\n"
+        "  docker.allowed.rw-mounts=/tmp\n  docker.allowed.networks=bridge\n "
+        "  docker.privileged-containers.enabled=1\n  docker.allowed.capabilities=CHOWN,SETUID\n"
+        "  docker.allowed.devices=/dev/test";
+    write_file(container_executor_cfg_file, container_executor_contents);
+    int ret = read_config(container_executor_cfg_file.c_str(), &container_executor_cfg);
+    if (ret != 0) {
+      FAIL();
+    }
+    ret = create_ce_file();
+    if (ret != 0) {
+      std::cerr << "Could not create ce file, skipping test" << std::endl;
+      return;
+    }
+
+    std::vector<std::pair<std::string, std::string> > file_cmd_vec;
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run\n  name=container_e1_12312_11111_02_000001\n  image=docker-image\n  user=test",
+        "run --name='container_e1_12312_11111_02_000001' --user='test' --cap-drop='ALL' 'docker-image' "));
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=run\n  name=container_e1_12312_11111_02_000001\n  image=docker-image\n  user=test\n"
+            "  launch-command=bash,test_script.sh,arg1,arg2",
+        "run --name='container_e1_12312_11111_02_000001' --user='test' --cap-drop='ALL' 'docker-image' 'bash' 'test_script.sh' 'arg1' 'arg2' "));
+
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n"
+            "  docker-command=run\n  name=container_e1_12312_11111_02_000001\n  image=docker-image\n  user=test\n  hostname=host-id\n"
+            "  ro-mounts=/var/log:/var/log,/var/lib:/lib,/bin/ls:/bin/ls\n  rw-mounts=/tmp:/tmp\n"
+            "  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='test' -d --rm -v '/var/log:/var/log:ro' -v '/var/lib:/lib:ro'"
+            " -v '/bin/ls:/bin/ls: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' 'docker-image' 'bash' "
+            "'test_script.sh' 'arg1' 'arg2' "));
+
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n"
+            "  docker-command=run\n  name=container_e1_12312_11111_02_000001\n  image=docker-image\n  user=test\n  hostname=host-id\n"
+            "  ro-mounts=/var/log:/var/log,/var/lib:/lib,/bin/ls:/bin/ls\n  rw-mounts=/tmp:/tmp\n"
+            "  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='test' -d --rm --net='bridge' -v '/var/log:/var/log:ro' -v '/var/lib:/lib:ro'"
+            " -v '/bin/ls:/bin/ls: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' 'docker-image' 'bash'"
+            " 'test_script.sh' 'arg1' 'arg2' "));
+
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n"
+            "  docker-command=run\n  name=container_e1_12312_11111_02_000001\n  image=docker-image\n  user=test\n  hostname=host-id\n"
+            "  ro-mounts=/var/log:/var/log,/var/lib:/lib,/bin/ls:/bin/ls\n  rw-mounts=/tmp:/tmp\n"
+            "  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' --user='test' -d --rm --net='bridge' -v '/var/log:/var/log:ro' -v '/var/lib:/lib:ro'"
+            " -v '/bin/ls:/bin/ls: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' 'docker-image' "
+            "'bash' 'test_script.sh' 'arg1' 'arg2' "));
+
+
+    file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n"
+            "  docker-command=run\n  name=container_e1_12312_11111_02_000001\n  image=docker-image\n  user=test\n  hostname=host-id\n"
+            "  ro-mounts=/var/log:/var/log,/var/lib:/lib,/bin/ls:/bin/ls\n  rw-mounts=/tmp:/tmp\n"
+            "  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' --user='test' -d --rm --net='bridge' -v '/var/log:/var/log:ro' -v '/var/lib:/lib:ro'"
+            " -v '/bin/ls:/bin/ls:ro' -v '/tmp:/tmp' --cgroup-parent='ctr-cgroup' --privileged --cap-drop='ALL' "
+            "--cap-add='CHOWN' --cap-add='SETUID' --hostname='host-id' --group-add '1000' --group-add '1001' "
+            "--device='/dev/test:/dev/test' 'docker-image' 'bash' 'test_script.sh' 'arg1' 'arg2' "));
+
+
+    std::vector<std::pair<std::string, int> > bad_file_cmd_vec;
+
+    bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
+        "[docker-command-execution]\n  docker-command=run\n  image=docker-image\n  user=test",
+        static_cast<int>(INVALID_DOCKER_CONTAINER_NAME)));
+    bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
+        "[docker-command-execution]\n  docker-command=run\n  name=container_e1_12312_11111_02_000001\n  user=test\n",
+        static_cast<int>(INVALID_DOCKER_IMAGE_NAME)));
+    bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
+        "[docker-command-execution]\n  docker-command=run\n  name=container_e1_12312_11111_02_000001\n  image=docker-image\n",
+        static_cast<int>(INVALID_DOCKER_USER_NAME)));
+
+    // invalid rw mount
+    bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
+        "[docker-command-execution]\n"
+            "  docker-command=run\n  name=container_e1_12312_11111_02_000001\n  image=docker-image\n  user=test\n  hostname=host-id\n"
+            "  ro-mounts=/var/lib:/lib,/bin/ls:/bin/ls\n  rw-mounts=/var/log:/var/log\n"
+            "  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",
+        static_cast<int>(INVALID_DOCKER_RW_MOUNT)));
+
+    // invalid ro mount
+    bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
+        "[docker-command-execution]\n"
+            "  docker-command=run\n  name=container_e1_12312_11111_02_000001\n  image=docker-image\n  user=test\n  hostname=host-id\n"
+            "  ro-mounts=/bin:/bin,/bin/ls:/bin/ls\n  rw-mounts=/tmp:/tmp\n"
+            "  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",
+        static_cast<int>(INVALID_DOCKER_RO_MOUNT)));
+
+    // invalid capability
+    bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
+        "[docker-command-execution]\n"
+            "  docker-command=run\n  name=container_e1_12312_11111_02_000001\n  image=docker-image\n  user=test\n  hostname=host-id\n"
+            "  ro-mounts=/bin/ls:/bin/ls\n  rw-mounts=/tmp:/tmp\n"
+            "  network=bridge\n  devices=/dev/test:/dev/test\n"
+            "  cap-add=CHOWN,SETUID,SETGID\n  cgroup-parent=ctr-cgroup\n  detach=true\n  rm=true\n"
+            "  launch-command=bash,test_script.sh,arg1,arg2",
+        static_cast<int>(INVALID_DOCKER_CAPABILITY)));
+
+    // invalid device
+    bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
+        "[docker-command-execution]\n"
+            "  docker-command=run\n  name=container_e1_12312_11111_02_000001\n  image=docker-image\n  user=test\n  hostname=host-id\n"
+            "  ro-mounts=/var/log:/var/log,/var/lib:/lib,/bin/ls:/bin/ls\n  rw-mounts=/tmp:/tmp\n"
+            "  network=bridge\n  devices=/dev/dev1:/dev/dev1\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",
+        static_cast<int>(INVALID_DOCKER_DEVICE)));
+
+    // invalid network
+    bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
+        "[docker-command-execution]\n"
+            "  docker-command=run\n  name=container_e1_12312_11111_02_000001\n  image=docker-image\n  user=test\n  hostname=host-id\n"
+            "  ro-mounts=/var/log:/var/log,/var/lib:/lib,/bin/ls:/bin/ls\n  rw-mounts=/tmp:/tmp\n"
+            "  network=bridge\n  devices=/dev/test:/dev/test\n  privileged=true\n  net=host\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",
+        static_cast<int>(INVALID_DOCKER_NETWORK)));
+
+    run_docker_command_test(file_cmd_vec, bad_file_cmd_vec, get_docker_run_command);
+  }
+
+  TEST_F(TestDockerUtil, test_docker_run_no_privileged) {
+
+    std::string container_executor_contents[] = {"[docker]\n  docker.allowed.ro-mounts=/var,/etc,/bin/ls\n"
+                                                     "  docker.allowed.rw-mounts=/tmp\n  docker.allowed.networks=bridge\n "
+                                                     "  docker.allowed.capabilities=CHOWN,SETUID\n"
+                                                     "  docker.allowed.devices=/dev/test",
+                                                 "[docker]\n  docker.allowed.ro-mounts=/var,/etc,/bin/ls\n"
+                                                     "  docker.allowed.rw-mounts=/tmp\n  docker.allowed.networks=bridge\n "
+                                                     "  docker.allowed.capabilities=CHOWN,SETUID\n"
+                                                     "  privileged=0\n"
+                                                     "  docker.allowed.devices=/dev/test"};
+    for (int i = 0; i < 2; ++i) {
+      write_file(container_executor_cfg_file, container_executor_contents[i]);
+      int ret = read_config(container_executor_cfg_file.c_str(), &container_executor_cfg);
+      if (ret != 0) {
+        FAIL();
+      }
+      ret = create_ce_file();
+      if (ret != 0) {
+        std::cerr << "Could not create ce file, skipping test" << std::endl;
+        return;
+      }
+
+      std::vector<std::pair<std::string, std::string> > file_cmd_vec;
+      file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+          "[docker-command-execution]\n  docker-command=run\n  name=container_e1_12312_11111_02_000001\n  image=docker-image\n  user=test",
+          "run --name='container_e1_12312_11111_02_000001' --user='test' --cap-drop='ALL' 'docker-image' "));
+      file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+          "[docker-command-execution]\n  docker-command=run\n  name=container_e1_12312_11111_02_000001\n  image=docker-image\n"
+              "  user=test\n  launch-command=bash,test_script.sh,arg1,arg2",
+          "run --name='container_e1_12312_11111_02_000001' --user='test' --cap-drop='ALL' 'docker-image' 'bash' 'test_script.sh' 'arg1' 'arg2' "));
+
+      file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+          "[docker-command-execution]\n"
+              "  docker-command=run\n  name=container_e1_12312_11111_02_000001\n  image=docker-image\n  user=test\n  hostname=host-id\n"
+              "  ro-mounts=/var/log:/var/log,/var/lib:/lib,/bin/ls:/bin/ls\n  rw-mounts=/tmp:/tmp\n"
+              "  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='test' -d --rm -v '/var/log:/var/log:ro' -v '/var/lib:/lib:ro'"
+              " -v '/bin/ls:/bin/ls: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' 'docker-image' 'bash' "
+              "'test_script.sh' 'arg1' 'arg2' "));
+
+      file_cmd_vec.push_back(std::make_pair<std::string, std::string>(
+          "[docker-command-execution]\n"
+              "  docker-command=run\n  name=container_e1_12312_11111_02_000001\n  image=docker-image\n  user=test\n  hostname=host-id\n"
+              "  ro-mounts=/var/log:/var/log,/var/lib:/lib,/bin/ls:/bin/ls\n  rw-mounts=/tmp:/tmp\n"
+              "  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='test' -d --rm --net='bridge' -v '/var/log:/var/log:ro' -v '/var/lib:/lib:ro'"
+              " -v '/bin/ls:/bin/ls: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' 'docker-image' 'bash'"
+              " 'test_script.sh' 'arg1' 'arg2' "));
+
+      std::vector<std::pair<std::string, int> > bad_file_cmd_vec;
+      bad_file_cmd_vec.push_back(std::make_pair<std::string, int>(
+          "[docker-command-execution]\n"
+              "  docker-command=run\n  name=container_e1_12312_11111_02_000001\n  image=docker-image\n  user=test\n  hostname=host-id\n"
+              "  ro-mounts=/var/log:/var/log,/var/lib:/lib,/bin/ls:/bin/ls\n  rw-mounts=/tmp:/tmp\n"
+              "  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",
+          static_cast<int>(PRIVILEGED_CONTAINERS_DISABLED)));
+
+      run_docker_command_test(file_cmd_vec, bad_file_cmd_vec, get_docker_run_command);
+    }
+  }
+
+  TEST_F(TestDockerUtil, test_docker_config_param) {
+    std::vector<std::pair<std::string, std::string> > input_output_map;
+    input_output_map.push_back(std::make_pair<std::string, std::string>(
+        "[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"));
+    input_output_map.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=load\n  docker-config=/my-config\n  image=image-id",
+        "--config='/my-config' load --i='image-id' "));
+    input_output_map.push_back(std::make_pair<std::string, std::string>(
+        "[docker-command-execution]\n  docker-command=pull\n  docker-config=/my-config\n  image=image-id",
+        "--config='/my-config' pull 'image-id' "));
+    input_output_map.push_back(std::make_pair<std::string, std::string>(
+        "[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"));
+    input_output_map.push_back(std::make_pair<std::string, std::string>(
+        "[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"));
+    input_output_map.push_back(std::make_pair<std::string, std::string>(
+        "[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=test",
+        "--config='/my-config' run --name='container_e1_12312_11111_02_000001' --user='test' --cap-drop='ALL' 'docker-image' "));
+
+    std::vector<std::pair<std::string, std::string> >::const_iterator itr;
+    char buffer[4096];
+    struct configuration cfg = {0, NULL};
+    for (itr = input_output_map.begin(); itr != input_output_map.end(); ++itr) {
+      memset(buffer, 0, 4096);
+      write_command_file(itr->first);
+      int ret = get_docker_command(docker_command_file.c_str(), &cfg, buffer, 4096);
+      ASSERT_EQ(0, ret) << "for input " << itr->first;
+      ASSERT_STREQ(itr->second.c_str(), buffer);
+    }
+  }
+
+  TEST_F(TestDockerUtil, test_docker_module_enabled) {
+
+    std::vector<std::pair<std::string, int> > input_out_vec;
+    input_out_vec.push_back(std::make_pair<std::string, int>("[docker]\n  module.enabled=true", 1));
+    input_out_vec.push_back(std::make_pair<std::string, int>("[docker]\n  module.enabled=false", 0));
+    input_out_vec.push_back(std::make_pair<std::string, int>("[docker]\n  module.enabled=1", 0));
+    input_out_vec.push_back(std::make_pair<std::string, int>("[docker]\n", 0));
+
+    for (size_t i = 0; i < input_out_vec.size(); ++i) {
+      write_file(container_executor_cfg_file, input_out_vec[i].first);
+      int ret = read_config(container_executor_cfg_file.c_str(), &container_executor_cfg);
+      if (ret != 0) {
+        FAIL();
+      }
+      ret = docker_module_enabled(&container_executor_cfg);
+      ASSERT_EQ(input_out_vec[i].second, ret) << " incorrect output for "
+                                              << input_out_vec[i].first;
+    }
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/hadoop/blob/d3b1c631/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/TestDockerContainerRuntime.java
----------------------------------------------------------------------
diff --git a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/TestDockerContainerRuntime.java b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/TestDockerContainerRuntime.java
index e548790..fbfee54 100644
--- a/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/TestDockerContainerRuntime.java
+++ b/hadoop-yarn-project/hadoop-yarn/hadoop-yarn-server/hadoop-yarn-server-nodemanager/src/test/java/org/apache/hadoop/yarn/server/nodemanager/containermanager/linux/runtime/TestDockerContainerRuntime.java
@@ -295,32 +295,37 @@ public class TestDockerContainerRuntime {
     List<String> args = op.getArguments();
     String dockerCommandFile = args.get(11);
 
-    //This is the expected docker invocation for this case
-    StringBuffer expectedCommandTemplate = new StringBuffer("run --name=%1$s ")
-        .append("--user=%2$s -d ")
-        .append("--workdir=%3$s ")
-        .append("--net=host ")
-        .append("--hostname=" + defaultHostname + " ")
-        .append(getExpectedTestCapabilitiesArgumentString())
-        .append(getExpectedCGroupsMountString())
-        .append("-v %4$s:%4$s ")
-        .append("-v %5$s:%5$s ")
-        .append("-v %6$s:%6$s ")
-        .append("-v %7$s:%7$s ")
-        .append("-v %8$s:%8$s ").append("%9$s ")
-        .append("bash %10$s/launch_container.sh");
-
-    String expectedCommand = String
-        .format(expectedCommandTemplate.toString(), containerId, runAsUser,
-            containerWorkDir, containerLocalDirs.get(0), filecacheDirs.get(0),
-            containerWorkDir, containerLogDirs.get(0), userLocalDirs.get(0),
-            image, containerWorkDir);
-
     List<String> dockerCommands = Files.readAllLines(Paths.get
             (dockerCommandFile), Charset.forName("UTF-8"));
 
-    Assert.assertEquals(1, dockerCommands.size());
-    Assert.assertEquals(expectedCommand, dockerCommands.get(0));
+    int expected = 13;
+    int counter = 0;
+    Assert.assertEquals(expected, dockerCommands.size());
+    Assert.assertEquals("[docker-command-execution]",
+        dockerCommands.get(counter++));
+    Assert.assertEquals("  cap-add=SYS_CHROOT,NET_BIND_SERVICE",
+        dockerCommands.get(counter++));
+    Assert.assertEquals("  cap-drop=ALL", dockerCommands.get(counter++));
+    Assert.assertEquals("  detach=true", dockerCommands.get(counter++));
+    Assert.assertEquals("  docker-command=run", dockerCommands.get(counter++));
+    Assert.assertEquals("  hostname=ctr-id", dockerCommands.get(counter++));
+    Assert
+        .assertEquals("  image=busybox:latest", dockerCommands.get(counter++));
+    Assert.assertEquals(
+        "  launch-command=bash,/test_container_work_dir/launch_container.sh",
+        dockerCommands.get(counter++));
+    Assert.assertEquals("  name=container_id", dockerCommands.get(counter++));
+    Assert.assertEquals("  net=host", dockerCommands.get(counter++));
+    Assert.assertEquals(
+        "  rw-mounts=/test_container_local_dir:/test_container_local_dir,"
+            + "/test_filecache_dir:/test_filecache_dir,"
+            + "/test_container_work_dir:/test_container_work_dir,"
+            + "/test_container_log_dir:/test_container_log_dir,"
+            + "/test_user_local_dir:/test_user_local_dir",
+        dockerCommands.get(counter++));
+    Assert.assertEquals("  user=run_as_user", dockerCommands.get(counter++));
+    Assert.assertEquals("  workdir=/test_container_work_dir",
+        dockerCommands.get(counter++));
   }
 
   @Test
@@ -347,10 +352,13 @@ public class TestDockerContainerRuntime {
 
     String uid = "";
     String gid = "";
+    String[] groups = {};
     Shell.ShellCommandExecutor shexec1 = new Shell.ShellCommandExecutor(
         new String[]{"id", "-u", runAsUser});
     Shell.ShellCommandExecutor shexec2 = new Shell.ShellCommandExecutor(
         new String[]{"id", "-g", runAsUser});
+    Shell.ShellCommandExecutor shexec3 = new Shell.ShellCommandExecutor(
+        new String[]{"id", "-G", runAsUser});
     try {
       shexec1.execute();
       // get rid of newline at the end
@@ -365,37 +373,48 @@ public class TestDockerContainerRuntime {
     } catch (Exception e) {
       LOG.info("Could not run id -g command: " + e);
     }
+    try {
+      shexec3.execute();
+      groups = shexec3.getOutput().replace("\n", " ").split(" ");
+    } catch (Exception e) {
+      LOG.info("Could not run id -G command: " + e);
+    }
     uidGidPair = uid + ":" + gid;
 
-    //This is the expected docker invocation for this case
-    StringBuffer expectedCommandTemplate = new StringBuffer("run --name=%1$s ")
-        .append("--user=%2$s -d ")
-        .append("--workdir=%3$s ")
-        .append("--net=host ")
-        .append("--hostname=" + defaultHostname + " ")
-        .append(getExpectedTestCapabilitiesArgumentString())
-        .append(getExpectedCGroupsMountString())
-        .append("-v %4$s:%4$s ")
-        .append("-v %5$s:%5$s ")
-        .append("-v %6$s:%6$s ")
-        .append("-v %7$s:%7$s ")
-        .append("-v %8$s:%8$s ")
-        .append("(--group-add \\d+ )*")
-        .append("%9$s ")
-        .append("bash %10$s/launch_container.sh");
-
-    String expectedCommand = String
-        .format(expectedCommandTemplate.toString(), containerId, uidGidPair,
-            containerWorkDir, containerLocalDirs.get(0), filecacheDirs.get(0),
-            containerWorkDir, containerLogDirs.get(0), userLocalDirs.get(0),
-            image, containerWorkDir);
-
     List<String> dockerCommands = Files.readAllLines(
         Paths.get(dockerCommandFile), Charset.forName("UTF-8"));
 
-    Assert.assertEquals(1, dockerCommands.size());
-    //Assert.assertEquals(expectedCommand, dockerCommands.get(0));
-    Assert.assertTrue(dockerCommands.get(0).matches(expectedCommand));
+    Assert.assertEquals(14, dockerCommands.size());
+    int counter = 0;
+    Assert.assertEquals("[docker-command-execution]",
+        dockerCommands.get(counter++));
+    Assert.assertEquals("  cap-add=SYS_CHROOT,NET_BIND_SERVICE",
+        dockerCommands.get(counter++));
+    Assert.assertEquals("  cap-drop=ALL", dockerCommands.get(counter++));
+    Assert.assertEquals("  detach=true", dockerCommands.get(counter++));
+    Assert.assertEquals("  docker-command=run", dockerCommands.get(counter++));
+    Assert.assertEquals("  group-add=" + String.join(",", groups),
+        dockerCommands.get(counter++));
+    Assert.assertEquals("  hostname=ctr-id",
+        dockerCommands.get(counter++));
+    Assert
+        .assertEquals("  image=busybox:latest", dockerCommands.get(counter++));
+    Assert.assertEquals(
+        "  launch-command=bash,/test_container_work_dir/launch_container.sh",
+        dockerCommands.get(counter++));
+    Assert.assertEquals("  name=container_id", dockerCommands.get(counter++));
+    Assert
+        .assertEquals("  net=host", dockerCommands.get(counter++));
+    Assert.assertEquals(
+        "  rw-mounts=/test_container_local_dir:/test_container_local_dir,"
+            + "/test_filecache_dir:/test_filecache_dir,"
+            + "/test_container_work_dir:/test_container_work_dir,"
+            + "/test_container_log_dir:/test_container_log_dir,"
+            + "/test_user_local_dir:/test_user_local_dir",
+        dockerCommands.get(counter++));
+    Assert.assertEquals("  user=" + uidGidPair, dockerCommands.get(counter++));
+    Assert.assertEquals("  workdir=/test_container_work_dir",
+        dockerCommands.get(counter++));
   }
 
   @Test
@@ -481,29 +500,38 @@ public class TestDockerContainerRuntime {
     String dockerCommandFile = args.get(11);
 
     //This is the expected docker invocation for this case
-    StringBuffer expectedCommandTemplate =
-        new StringBuffer("run --name=%1$s ").append("--user=%2$s -d ")
-            .append("--workdir=%3$s ")
-            .append("--net=" + allowedNetwork + " ")
-            .append("--hostname=" + expectedHostname + " ")
-            .append(getExpectedTestCapabilitiesArgumentString())
-            .append(getExpectedCGroupsMountString())
-            .append("-v %4$s:%4$s ").append("-v %5$s:%5$s ")
-            .append("-v %6$s:%6$s ").append("-v %7$s:%7$s ")
-            .append("-v %8$s:%8$s ").append("%9$s ")
-            .append("bash %10$s/launch_container.sh");
-
-    String expectedCommand = String
-        .format(expectedCommandTemplate.toString(), containerId, runAsUser,
-            containerWorkDir, containerLocalDirs.get(0), filecacheDirs.get(0),
-            containerWorkDir, containerLogDirs.get(0), userLocalDirs.get(0),
-            image, containerWorkDir);
-
     List<String> dockerCommands = Files
         .readAllLines(Paths.get(dockerCommandFile), Charset.forName("UTF-8"));
-
-    Assert.assertEquals(1, dockerCommands.size());
-    Assert.assertEquals(expectedCommand, dockerCommands.get(0));
+    int expected = 13;
+    int counter = 0;
+    Assert.assertEquals(expected, dockerCommands.size());
+    Assert.assertEquals("[docker-command-execution]",
+        dockerCommands.get(counter++));
+    Assert.assertEquals("  cap-add=SYS_CHROOT,NET_BIND_SERVICE",
+        dockerCommands.get(counter++));
+    Assert.assertEquals("  cap-drop=ALL", dockerCommands.get(counter++));
+    Assert.assertEquals("  detach=true", dockerCommands.get(counter++));
+    Assert.assertEquals("  docker-command=run", dockerCommands.get(counter++));
+    Assert.assertEquals("  hostname=test.hostname",
+        dockerCommands.get(counter++));
+    Assert
+        .assertEquals("  image=busybox:latest", dockerCommands.get(counter++));
+    Assert.assertEquals(
+        "  launch-command=bash,/test_container_work_dir/launch_container.sh",
+        dockerCommands.get(counter++));
+    Assert.assertEquals("  name=container_id", dockerCommands.get(counter++));
+    Assert
+        .assertEquals("  net=" + allowedNetwork, dockerCommands.get(counter++));
+    Assert.assertEquals(
+        "  rw-mounts=/test_container_local_dir:/test_container_local_dir,"
+            + "/test_filecache_dir:/test_filecache_dir,"
+            + "/test_container_work_dir:/test_container_work_dir,"
+            + "/test_container_log_dir:/test_container_log_dir,"
+            + "/test_user_local_dir:/test_user_local_dir",
+        dockerCommands.get(counter++));
+    Assert.assertEquals("  user=run_as_user", dockerCommands.get(counter++));
+    Assert.assertEquals("  workdir=/test_container_work_dir",
+        dockerCommands.get(counter++));
   }
 
   @Test
@@ -537,30 +565,37 @@ public class TestDockerContainerRuntime {
 
     //This is the expected docker invocation for this case. customNetwork1
     // ("sdn1") is the expected network to be used in this case
-    StringBuffer expectedCommandTemplate =
-        new StringBuffer("run --name=%1$s ").append("--user=%2$s -d ")
-            .append("--workdir=%3$s ")
-            .append("--net=" + customNetwork1 + " ")
-            .append("--hostname=" + defaultHostname + " ")
-            .append(getExpectedTestCapabilitiesArgumentString())
-            .append(getExpectedCGroupsMountString())
-            .append("-v %4$s:%4$s ").append("-v %5$s:%5$s ")
-            .append("-v %6$s:%6$s ").append("-v %7$s:%7$s ")
-            .append("-v %8$s:%8$s ").append("%9$s ")
-            .append("bash %10$s/launch_container.sh");
-
-    String expectedCommand = String
-        .format(expectedCommandTemplate.toString(), containerId, runAsUser,
-            containerWorkDir, containerLocalDirs.get(0), filecacheDirs.get(0),
-            containerWorkDir, containerLogDirs.get(0), userLocalDirs.get(0),
-            image, containerWorkDir);
-
     List<String> dockerCommands = Files
         .readAllLines(Paths.get(dockerCommandFile), Charset.forName("UTF-8"));
 
-    Assert.assertEquals(1, dockerCommands.size());
-    Assert.assertEquals(expectedCommand, dockerCommands.get(0));
-
+    int expected = 13;
+    int counter = 0;
+    Assert.assertEquals(expected, dockerCommands.size());
+    Assert.assertEquals("[docker-command-execution]",
+        dockerCommands.get(counter++));
+    Assert.assertEquals("  cap-add=SYS_CHROOT,NET_BIND_SERVICE",
+        dockerCommands.get(counter++));
+    Assert.assertEquals("  cap-drop=ALL", dockerCommands.get(counter++));
+    Assert.assertEquals("  detach=true", dockerCommands.get(counter++));
+    Assert.assertEquals("  docker-command=run", dockerCommands.get(counter++));
+    Assert.assertEquals("  hostname=ctr-id", dockerCommands.get(counter++));
+    Assert
+        .assertEquals("  image=busybox:latest", dockerCommands.get(counter++));
+    Assert.assertEquals(
+        "  launch-command=bash,/test_container_work_dir/launch_container.sh",
+        dockerCommands.get(counter++));
+    Assert.assertEquals("  name=container_id", dockerCommands.get(counter++));
+    Assert.assertEquals("  net=sdn1", dockerCommands.get(counter++));
+    Assert.assertEquals(
+        "  rw-mounts=/test_container_local_dir:/test_container_local_dir,"
+            + "/test_filecache_dir:/test_filecache_dir,"
+            + "/test_container_work_dir:/test_container_work_dir,"
+            + "/test_container_log_dir:/test_container_log_dir,"
+            + "/test_user_local_dir:/test_user_local_dir",
+        dockerCommands.get(counter++));
+    Assert.assertEquals("  user=run_as_user", dockerCommands.get(counter++));
+    Assert.assertEquals("  workdir=/test_container_work_dir",
+        dockerCommands.get(counter++));
 
     //now set an explicit (non-default) allowedNetwork and ensure that it is
     // used.
@@ -575,28 +610,37 @@ public class TestDockerContainerRuntime {
 
     //This is the expected docker invocation for this case. customNetwork2
     // ("sdn2") is the expected network to be used in this case
-    expectedCommandTemplate =
-        new StringBuffer("run --name=%1$s ").append("--user=%2$s -d ")
-            .append("--workdir=%3$s ")
-            .append("--net=" + customNetwork2 + " ")
-            .append("--hostname=" + defaultHostname + " ")
-            .append(getExpectedTestCapabilitiesArgumentString())
-            .append(getExpectedCGroupsMountString())
-            .append("-v %4$s:%4$s ").append("-v %5$s:%5$s ")
-            .append("-v %6$s:%6$s ").append("-v %7$s:%7$s ")
-            .append("-v %8$s:%8$s ").append("%9$s ")
-            .append("bash %10$s/launch_container.sh");
-
-    expectedCommand = String
-        .format(expectedCommandTemplate.toString(), containerId, runAsUser,
-            containerWorkDir, containerLocalDirs.get(0), filecacheDirs.get(0),
-            containerWorkDir, containerLogDirs.get(0), userLocalDirs.get(0),
-            image, containerWorkDir);
     dockerCommands = Files
         .readAllLines(Paths.get(dockerCommandFile), Charset.forName("UTF-8"));
+    counter = 0;
+    Assert.assertEquals(expected, dockerCommands.size());
+    Assert.assertEquals("[docker-command-execution]",
+        dockerCommands.get(counter++));
+    Assert.assertEquals("  cap-add=SYS_CHROOT,NET_BIND_SERVICE",
+        dockerCommands.get(counter++));
+    Assert.assertEquals("  cap-drop=ALL", dockerCommands.get(counter++));
+    Assert.assertEquals("  detach=true", dockerCommands.get(counter++));
+    Assert.assertEquals("  docker-command=run", dockerCommands.get(counter++));
+    Assert.assertEquals("  hostname=ctr-id", dockerCommands.get(counter++));
+    Assert
+        .assertEquals("  image=busybox:latest", dockerCommands.get(counter++));
+    Assert.assertEquals(
+        "  launch-command=bash,/test_container_work_dir/launch_container.sh",
+        dockerCommands.get(counter++));
+
+    Assert.assertEquals("  name=container_id", dockerCommands.get(counter++));
+    Assert.assertEquals("  net=sdn2", dockerCommands.get(counter++));
+    Assert.assertEquals(
+        "  rw-mounts=/test_container_local_dir:/test_container_local_dir,"
+            + "/test_filecache_dir:/test_filecache_dir,"
+            + "/test_container_work_dir:/test_container_work_dir,"
+            + "/test_container_log_dir:/test_container_log_dir,"
+            + "/test_user_local_dir:/test_user_local_dir",
+        dockerCommands.get(counter++));
+    Assert.assertEquals("  user=run_as_user", dockerCommands.get(counter++));
+    Assert.assertEquals("  workdir=/test_container_work_dir",
+        dockerCommands.get(counter++));
 
-    Assert.assertEquals(1, dockerCommands.size());
-    Assert.assertEquals(expectedCommand, dockerCommands.get(0));
 
     //disallowed network should trigger a launch failure
 
@@ -630,7 +674,8 @@ public class TestDockerContainerRuntime {
     List<String> dockerCommands = Files.readAllLines(Paths.get
         (dockerCommandFile), Charset.forName("UTF-8"));
 
-    Assert.assertEquals(1, dockerCommands.size());
+    int expected = 13;
+    Assert.assertEquals(expected, dockerCommands.size());
 
     String command = dockerCommands.get(0);
 
@@ -738,13 +783,35 @@ public class TestDockerContainerRuntime {
     List<String> dockerCommands = Files.readAllLines(Paths.get
         (dockerCommandFile), Charset.forName("UTF-8"));
 
-    Assert.assertEquals(1, dockerCommands.size());
-
-    String command = dockerCommands.get(0);
-
-    //submitting user is whitelisted. ensure --privileged is in the invocation
-    Assert.assertTrue("Did not find expected '--privileged' in docker run args "
-        + ": " + command, command.contains("--privileged"));
+    int expected = 14;
+    int counter = 0;
+    Assert.assertEquals(expected, dockerCommands.size());
+    Assert.assertEquals("[docker-command-execution]",
+        dockerCommands.get(counter++));
+    Assert.assertEquals("  cap-add=SYS_CHROOT,NET_BIND_SERVICE",
+        dockerCommands.get(counter++));
+    Assert.assertEquals("  cap-drop=ALL", dockerCommands.get(counter++));
+    Assert.assertEquals("  detach=true", dockerCommands.get(counter++));
+    Assert.assertEquals("  docker-command=run", dockerCommands.get(counter++));
+    Assert.assertEquals("  hostname=ctr-id", dockerCommands.get(counter++));
+    Assert
+        .assertEquals("  image=busybox:latest", dockerCommands.get(counter++));
+    Assert.assertEquals(
+        "  launch-command=bash,/test_container_work_dir/launch_container.sh",
+        dockerCommands.get(counter++));
+    Assert.assertEquals("  name=container_id", dockerCommands.get(counter++));
+    Assert.assertEquals("  net=host", dockerCommands.get(counter++));
+    Assert.assertEquals("  privileged=true", dockerCommands.get(counter++));
+    Assert.assertEquals(
+        "  rw-mounts=/test_container_local_dir:/test_container_local_dir,"
+            + "/test_filecache_dir:/test_filecache_dir,"
+            + "/test_container_work_dir:/test_container_work_dir,"
+            + "/test_container_log_dir:/test_container_log_dir,"
+            + "/test_user_local_dir:/test_user_local_dir",
+        dockerCommands.get(counter++));
+    Assert.assertEquals("  user=run_as_user", dockerCommands.get(counter++));
+    Assert.assertEquals("  workdir=/test_container_work_dir",
+        dockerCommands.get(counter++));
   }
 
   @Test
@@ -833,15 +900,33 @@ public class TestDockerContainerRuntime {
     List<String> dockerCommands = Files.readAllLines(Paths.get
         (dockerCommandFile), Charset.forName("UTF-8"));
 
-    Assert.assertEquals(1, dockerCommands.size());
-
-    String command = dockerCommands.get(0);
-
-    Assert.assertTrue("Did not find expected " +
-        "/test_local_dir/test_resource_file:test_mount mount in docker " +
-        "run args : " + command,
-        command.contains(" -v /test_local_dir/test_resource_file:test_mount" +
-            ":ro "));
+    Assert.assertEquals(14, dockerCommands.size());
+    Assert.assertEquals("[docker-command-execution]", dockerCommands.get(0));
+    Assert.assertEquals("  cap-add=SYS_CHROOT,NET_BIND_SERVICE",
+        dockerCommands.get(1));
+    Assert.assertEquals("  cap-drop=ALL", dockerCommands.get(2));
+    Assert.assertEquals("  detach=true", dockerCommands.get(3));
+    Assert.assertEquals("  docker-command=run", dockerCommands.get(4));
+    Assert.assertEquals("  hostname=ctr-id", dockerCommands.get(5));
+    Assert.assertEquals("  image=busybox:latest", dockerCommands.get(6));
+    Assert.assertEquals(
+        "  launch-command=bash,/test_container_work_dir/launch_container.sh",
+        dockerCommands.get(7));
+    Assert.assertEquals("  name=container_id", dockerCommands.get(8));
+    Assert.assertEquals("  net=host", dockerCommands.get(9));
+    Assert.assertEquals(
+        "  ro-mounts=/test_local_dir/test_resource_file:test_mount",
+        dockerCommands.get(10));
+    Assert.assertEquals(
+        "  rw-mounts=/test_container_local_dir:/test_container_local_dir,"
+            + "/test_filecache_dir:/test_filecache_dir,"
+            + "/test_container_work_dir:/test_container_work_dir,"
+            + "/test_container_log_dir:/test_container_log_dir,"
+            + "/test_user_local_dir:/test_user_local_dir",
+        dockerCommands.get(11));
+    Assert.assertEquals("  user=run_as_user", dockerCommands.get(12));
+    Assert.assertEquals("  workdir=/test_container_work_dir",
+        dockerCommands.get(13));
   }
 
   @Test
@@ -885,20 +970,35 @@ public class TestDockerContainerRuntime {
     List<String> dockerCommands = Files.readAllLines(Paths.get
         (dockerCommandFile), Charset.forName("UTF-8"));
 
-    Assert.assertEquals(1, dockerCommands.size());
-
-    String command = dockerCommands.get(0);
+    Assert.assertEquals(14, dockerCommands.size());
+    Assert.assertEquals("[docker-command-execution]", dockerCommands.get(0));
+    Assert.assertEquals("  cap-add=SYS_CHROOT,NET_BIND_SERVICE",
+        dockerCommands.get(1));
+    Assert.assertEquals("  cap-drop=ALL", dockerCommands.get(2));
+    Assert.assertEquals("  detach=true", dockerCommands.get(3));
+    Assert.assertEquals("  docker-command=run", dockerCommands.get(4));
+    Assert.assertEquals("  hostname=ctr-id", dockerCommands.get(5));
+    Assert.assertEquals("  image=busybox:latest", dockerCommands.get(6));
+    Assert.assertEquals(
+        "  launch-command=bash,/test_container_work_dir/launch_container.sh",
+        dockerCommands.get(7));
+    Assert.assertEquals("  name=container_id", dockerCommands.get(8));
+    Assert.assertEquals("  net=host", dockerCommands.get(9));
+    Assert.assertEquals(
+        "  ro-mounts=/test_local_dir/test_resource_file:test_mount1,"
+            + "/test_local_dir/test_resource_file:test_mount2",
+        dockerCommands.get(10));
+    Assert.assertEquals(
+        "  rw-mounts=/test_container_local_dir:/test_container_local_dir,"
+            + "/test_filecache_dir:/test_filecache_dir,"
+            + "/test_container_work_dir:/test_container_work_dir,"
+            + "/test_container_log_dir:/test_container_log_dir,"
+            + "/test_user_local_dir:/test_user_local_dir",
+        dockerCommands.get(11));
+    Assert.assertEquals("  user=run_as_user", dockerCommands.get(12));
+    Assert.assertEquals("  workdir=/test_container_work_dir",
+        dockerCommands.get(13));
 
-    Assert.assertTrue("Did not find expected " +
-        "/test_local_dir/test_resource_file:test_mount1 mount in docker " +
-        "run args : " + command,
-        command.contains(" -v /test_local_dir/test_resource_file:test_mount1" +
-            ":ro "));
-    Assert.assertTrue("Did not find expected " +
-        "/test_local_dir/test_resource_file:test_mount2 mount in docker " +
-        "run args : " + command,
-        command.contains(" -v /test_local_dir/test_resource_file:test_mount2" +
-            ":ro "));
   }
 
   @Test
@@ -930,8 +1030,10 @@ public class TestDockerContainerRuntime {
       IOException {
     List<String> dockerCommands = getDockerCommandsForSignal(
         ContainerExecutor.Signal.TERM);
-    Assert.assertEquals(1, dockerCommands.size());
-    Assert.assertEquals("stop container_id", dockerCommands.get(0));
+    Assert.assertEquals(3, dockerCommands.size());
+    Assert.assertEquals("[docker-command-execution]", dockerCommands.get(0));
+    Assert.assertEquals("  docker-command=stop", dockerCommands.get(1));
+    Assert.assertEquals("  name=container_id", dockerCommands.get(2));
   }
 
   @Test
@@ -940,8 +1042,10 @@ public class TestDockerContainerRuntime {
       IOException {
     List<String> dockerCommands = getDockerCommandsForSignal(
         ContainerExecutor.Signal.KILL);
-    Assert.assertEquals(1, dockerCommands.size());
-    Assert.assertEquals("stop container_id", dockerCommands.get(0));
+    Assert.assertEquals(3, dockerCommands.size());
+    Assert.assertEquals("[docker-command-execution]", dockerCommands.get(0));
+    Assert.assertEquals("  docker-command=stop", dockerCommands.get(1));
+    Assert.assertEquals("  name=container_id", dockerCommands.get(2));
   }
 
   @Test
@@ -950,8 +1054,10 @@ public class TestDockerContainerRuntime {
       IOException {
     List<String> dockerCommands = getDockerCommandsForSignal(
         ContainerExecutor.Signal.QUIT);
-    Assert.assertEquals(1, dockerCommands.size());
-    Assert.assertEquals("stop container_id", dockerCommands.get(0));
+    Assert.assertEquals(3, dockerCommands.size());
+    Assert.assertEquals("[docker-command-execution]", dockerCommands.get(0));
+    Assert.assertEquals("  docker-command=stop", dockerCommands.get(1));
+    Assert.assertEquals("  name=container_id", dockerCommands.get(2));
   }
 
   private List<String> getDockerCommandsForSignal(


---------------------------------------------------------------------
To unsubscribe, e-mail: common-commits-unsubscribe@hadoop.apache.org
For additional commands, e-mail: common-commits-help@hadoop.apache.org