You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@trafficserver.apache.org by zw...@apache.org on 2018/08/13 18:29:18 UTC

[trafficserver] 03/03: Runroot: Add feature to use runroot by providing yaml file

This is an automated email from the ASF dual-hosted git repository.

zwoop pushed a commit to branch 8.0.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git

commit ea89d097086392e684034d95e2e74cad9b3c1f50
Author: Xavier Chi <ch...@gmail.com>
AuthorDate: Fri Jul 20 15:14:18 2018 -0500

    Runroot: Add feature to use runroot by providing yaml file
    
    (cherry picked from commit 37aa9fefc729ab320b2acffca480ce37ea3f21c6)
---
 lib/ts/runroot.cc                              | 81 +++++++++++++-------------
 lib/ts/runroot.h                               |  4 --
 src/traffic_layout/engine.cc                   | 39 ++++++++++++-
 tests/gold_tests/runroot/runroot_error.test.py |  4 +-
 4 files changed, 80 insertions(+), 48 deletions(-)

diff --git a/lib/ts/runroot.cc b/lib/ts/runroot.cc
index 38edaa4..8e5f0f4 100644
--- a/lib/ts/runroot.cc
+++ b/lib/ts/runroot.cc
@@ -38,6 +38,7 @@ datadir, libexecdir, libdir, runtimedir, cachedir.
 */
 
 #include "ts/ink_error.h"
+#include "ts/ink_file.h"
 #include "ts/I_Layout.h"
 #include "runroot.h"
 
@@ -47,27 +48,33 @@ datadir, libexecdir, libdir, runtimedir, cachedir.
 #include <unistd.h>
 #include <yaml-cpp/yaml.h>
 
-static std::string using_runroot = {};
+static std::string runroot_file = {};
 
 // the function for the checking of the yaml file in the passed in path
-// if found return the path, if not return empty string
-std::string
-check_path(const std::string &path)
+// if found return the path to the yaml file, if not return empty string.
+static std::string
+get_yaml_path(const std::string &path)
 {
-  std::string whole_path = path;
-  std::string yaml_path  = Layout::relative_to(whole_path, "runroot_path.yml");
   std::ifstream check_file;
-  check_file.open(yaml_path);
-  if (check_file.good()) {
-    return whole_path;
+  if (ink_file_is_directory(path.c_str())) {
+    std::string yaml_path = Layout::relative_to(path, "runroot_path.yml");
+    check_file.open(yaml_path);
+    if (check_file.good()) {
+      return yaml_path;
+    }
+  } else {
+    check_file.open(path);
+    if (check_file.good() && path.substr(path.find_last_of("/") + 1) == "runroot_path.yml") {
+      return path;
+    }
   }
   return {};
 }
 
 // the function for the checking of the yaml file in passed in directory or parent directory
-// if found return the parent path containing the yaml file
-std::string
-check_parent_path(const std::string &path)
+// if found return the parent path to the yaml file
+static std::string
+get_parent_yaml_path(const std::string &path)
 {
   std::string whole_path = path;
   if (whole_path.back() == '/') {
@@ -79,25 +86,17 @@ check_parent_path(const std::string &path)
     if (whole_path.empty()) {
       return {};
     }
-    if (!check_path(whole_path).empty()) {
-      return whole_path;
+    std::string yaml_file = get_yaml_path(whole_path);
+    if (!yaml_file.empty()) {
+      return yaml_file;
     }
     whole_path = whole_path.substr(0, whole_path.find_last_of("/"));
   }
   return {};
 }
 
-// until I get a <filesystem> impl in
-bool
-is_directory(const char *directory)
-{
-  struct stat buffer;
-  int result = stat(directory, &buffer);
-  return (!result && (S_IFDIR & buffer.st_mode)) ? true : false;
-}
-
 // handler for ts runroot
-// this function set up using_runroot
+// this function set up runroot_file
 void
 runroot_handler(const char **argv, bool json)
 {
@@ -121,12 +120,12 @@ runroot_handler(const char **argv, bool json)
   if (!arg.empty() && arg != prefix) {
     // 1. pass in path
     prefix += "=";
-    path = check_path(arg.substr(prefix.size(), arg.size() - 1));
+    path = get_yaml_path(arg.substr(prefix.size(), arg.size() - 1));
     if (!path.empty()) {
       if (!json) {
         ink_notice("using command line path as RUNROOT");
       }
-      using_runroot = path;
+      runroot_file = path;
       return;
     } else {
       if (!json) {
@@ -137,10 +136,10 @@ runroot_handler(const char **argv, bool json)
 
   // 2. check Environment variable
   char *env_val = getenv("TS_RUNROOT");
-  if ((env_val != nullptr) && is_directory(env_val)) {
-    path = check_path(env_val);
+  if (env_val) {
+    path = get_yaml_path(env_val);
     if (!path.empty()) {
-      using_runroot = env_val;
+      runroot_file = path;
       if (!json) {
         ink_notice("using the environment variable TS_RUNROOT");
       }
@@ -155,9 +154,9 @@ runroot_handler(const char **argv, bool json)
   // 3. find cwd or parent path of cwd to check
   char cwd[PATH_MAX] = {0};
   if (getcwd(cwd, sizeof(cwd)) != nullptr) {
-    path = check_parent_path(cwd);
+    path = get_parent_yaml_path(cwd);
     if (!path.empty()) {
-      using_runroot = path;
+      runroot_file = path;
       if (!json) {
         ink_notice("using cwd as TS_RUNROOT");
       }
@@ -170,9 +169,9 @@ runroot_handler(const char **argv, bool json)
   if ((argv[0] != nullptr) && realpath(argv[0], RealBinPath) != nullptr) {
     std::string bindir = RealBinPath;
     bindir             = bindir.substr(0, bindir.find_last_of("/")); // getting the bin dir not executable path
-    path               = check_parent_path(bindir);
+    path               = get_parent_yaml_path(bindir);
     if (!path.empty()) {
-      using_runroot = path;
+      runroot_file = path;
       if (!json) {
         ink_notice("using the installed dir as TS_RUNROOT");
       }
@@ -209,11 +208,13 @@ runroot_map_default()
 
 // return a map of all path in runroot_path.yml
 RunrootMapType
-runroot_map(const std::string &prefix)
+runroot_map(const std::string &file)
 {
   RunrootMapType map;
   try {
-    YAML::Node yamlfile = YAML::LoadFile(Layout::relative_to(prefix, "runroot_path.yml"));
+    YAML::Node yamlfile = YAML::LoadFile(file);
+    std::string prefix  = file.substr(0, file.find_last_of("/"));
+
     for (auto it : yamlfile) {
       // key value pairs of dirs
       std::string value = it.second.as<std::string>();
@@ -223,7 +224,7 @@ runroot_map(const std::string &prefix)
       map[it.first.as<std::string>()] = value;
     }
   } catch (YAML::Exception &e) {
-    ink_warning("Unable to read runroot_path.yml from '%s': %s", prefix.c_str(), e.what());
+    ink_warning("Unable to read '%s': %s", file.c_str(), e.what());
     ink_notice("Continuing with default value");
     return RunrootMapType{};
   }
@@ -236,19 +237,19 @@ runroot_map(const std::string &prefix)
 RunrootMapType
 check_runroot()
 {
-  if (using_runroot.empty()) {
+  if (runroot_file.empty()) {
     return RunrootMapType{};
   }
 
-  int len = using_runroot.size();
+  int len = runroot_file.size();
   if ((len + 1) > PATH_NAME_MAX) {
     ink_fatal("runroot path is too big: %d, max %d\n", len, PATH_NAME_MAX - 1);
   }
-  return runroot_map(using_runroot);
+  return runroot_map(runroot_file);
 }
 
 bool
 use_runroot()
 {
-  return !using_runroot.empty();
+  return !runroot_file.empty();
 }
diff --git a/lib/ts/runroot.h b/lib/ts/runroot.h
index a06636f..fcb44e4 100644
--- a/lib/ts/runroot.h
+++ b/lib/ts/runroot.h
@@ -48,10 +48,6 @@ const std::string LAYOUT_CACHEDIR      = "cachedir";
 
 typedef std::unordered_map<std::string, std::string> RunrootMapType;
 
-std::string check_path(const std::string &path);
-
-std::string check_parent_path(const std::string &path);
-
 void runroot_handler(const char **argv, bool json = false);
 
 // get a map from default layout
diff --git a/src/traffic_layout/engine.cc b/src/traffic_layout/engine.cc
index 764514d..36c21e9 100644
--- a/src/traffic_layout/engine.cc
+++ b/src/traffic_layout/engine.cc
@@ -46,6 +46,41 @@
 // for nftw check_directory
 std::string directory_check;
 
+// the function for the checking of the yaml file in the passed in path
+// if found return the path, if not return empty string
+std::string
+check_path(const std::string &path)
+{
+  std::ifstream check_file;
+  check_file.open(Layout::relative_to(path, "runroot_path.yml"));
+  if (check_file.good()) {
+    return path;
+  }
+  return {};
+}
+
+// the function for the checking of the yaml file in passed in directory or parent directory
+// if found return the parent path containing the yaml file
+std::string
+check_parent_path(const std::string &path)
+{
+  std::string yaml_path = path;
+  if (yaml_path.back() == '/') {
+    yaml_path.pop_back();
+  }
+  // go up to 4 level of parent directories
+  for (int i = 0; i < 4; i++) {
+    if (yaml_path.empty()) {
+      return {};
+    }
+    if (!check_path(yaml_path).empty()) {
+      return yaml_path;
+    }
+    yaml_path = yaml_path.substr(0, yaml_path.find_last_of("/"));
+  }
+  return {};
+}
+
 // check if we can create the runroot using path
 // return true if the path is good to use
 static bool
@@ -340,7 +375,7 @@ RunrootEngine::clean_runroot()
     }
   } else {
     // handle the map and deleting of each directories specified in the yml file
-    RunrootMapType map = runroot_map(clean_root);
+    RunrootMapType map = runroot_map(Layout::relative_to(clean_root, "runroot_path.yml"));
     map.erase(LAYOUT_PREFIX);
     map.erase(LAYOUT_EXEC_PREFIX);
     for (auto it : map) {
@@ -728,7 +763,7 @@ RunrootEngine::verify_runroot()
     path_map = runroot_map_default();
     std::cout << "Verifying default build ..." << std::endl;
   } else {
-    path_map = runroot_map(path);
+    path_map = runroot_map(Layout::relative_to(path, "runroot_path.yml"));
   }
 
   RunrootMapType permission_map; // contains rwx bits
diff --git a/tests/gold_tests/runroot/runroot_error.test.py b/tests/gold_tests/runroot/runroot_error.test.py
index 2776243..e32df98 100644
--- a/tests/gold_tests/runroot/runroot_error.test.py
+++ b/tests/gold_tests/runroot/runroot_error.test.py
@@ -62,9 +62,9 @@ f.Exists = False
 path_invalid = os.path.join(ts_root, "tmp")
 tr = Test.AddTestRun("remove invalid runroot")
 tr.Processes.Default.Command = "$ATS_BIN/traffic_layout remove --path " + path_invalid
-tr.Processes.Default.Streams.All = Testers.ContainsExpression("Unable to read runroot_path.yml", "remove incorrect usage")
+tr.Processes.Default.Streams.All = Testers.ContainsExpression("Unable to read", "remove incorrect usage")
 
 # verify invalid runroot
 tr = Test.AddTestRun("verify invalid runroot")
 tr.Processes.Default.Command = "$ATS_BIN/traffic_layout verify --path " + path_invalid
-tr.Processes.Default.Streams.All = Testers.ContainsExpression("Unable to read runroot_path.yml", "verify incorrect usage")
+tr.Processes.Default.Streams.All = Testers.ContainsExpression("Unable to read", "verify incorrect usage")