brbzull0 commented on code in PR #13070:
URL: https://github.com/apache/trafficserver/pull/13070#discussion_r3057540294


##########
src/proxy/Plugin.cc:
##########
@@ -376,3 +405,256 @@ plugin_init(bool validateOnly)
   }
   return retVal;
 }
+
+config::ConfigResult<PluginYAMLEntries>
+parse_plugin_yaml(const char *yaml_path)
+{
+  config::ConfigResult<PluginYAMLEntries> result;
+  YAML::Node                              root;
+
+  try {
+    root = YAML::LoadFile(yaml_path);
+  } catch (const YAML::Exception &e) {
+    result.errata.note("failed to parse: {}", e.what());
+    return result;
+  }
+
+  if (!root["plugins"] || !root["plugins"].IsSequence()) {
+    result.errata.note("missing or invalid 'plugins' sequence");
+    return result;
+  }
+
+  struct IndexedEntry {
+    int             seq_idx;
+    PluginYAMLEntry entry;
+  };
+
+  std::vector<IndexedEntry> indexed;
+  int                       seq_idx = 0;
+
+  for (const auto &node : root["plugins"]) {
+    PluginYAMLEntry entry;
+
+    if (!node["path"]) {
+      result.errata.note("plugin entry #{} missing required 'path' field", 
seq_idx + 1);
+      return result;
+    }
+    entry.path = node["path"].as<std::string>();
+
+    if (auto n = node["enabled"]; n) {
+      entry.enabled = n.as<bool>();
+    }
+    if (auto n = node["load_order"]; n) {
+      entry.load_order = n.as<int>();
+    }
+    if (auto n = node["params"]; n && n.IsSequence()) {
+      for (const auto &p : n) {
+        entry.params.emplace_back(p.as<std::string>());
+      }
+    }
+    if (auto n = node["config"]; n) {
+      if (n.IsScalar()) {
+        entry.config_literal = n.as<std::string>();
+      } else {
+        result.errata.note("plugin '{}': 'config' must be a scalar (use 
literal block '|' for multi-line content)", entry.path);
+        return result;
+      }
+    }
+
+    indexed.push_back({seq_idx++, std::move(entry)});
+  }
+
+  std::stable_sort(indexed.begin(), indexed.end(), [](const IndexedEntry &a, 
const IndexedEntry &b) {
+    const bool a_has = a.entry.load_order >= 0;
+    const bool b_has = b.entry.load_order >= 0;
+
+    if (a_has && b_has) {
+      return a.entry.load_order < b.entry.load_order;
+    }
+    return a_has && !b_has;
+  });
+
+  result.value.reserve(indexed.size());
+  for (auto &[_, entry] : indexed) {
+    result.value.emplace_back(std::move(entry));
+  }
+
+  return result;
+}
+
+/// Write inline config content to a temp file, returning the path on success.
+static std::optional<std::string>
+write_inline_config(const PluginYAMLEntry &entry, int index)
+{
+  char tmp_path[PATH_NAME_MAX];
+
+  std::string_view stem{entry.path};
+  if (auto pos = stem.rfind('/'); pos != std::string_view::npos) {
+    stem = stem.substr(pos + 1);
+  }
+  if (auto pos = stem.rfind('.'); pos != std::string_view::npos) {
+    stem = stem.substr(0, pos);
+  }
+
+  snprintf(tmp_path, sizeof(tmp_path), "%s/.%.*s_inline_%d.conf", 
RecConfigReadConfigDir().c_str(), static_cast<int>(stem.size()),
+           stem.data(), index);
+
+  int fd = open(tmp_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
+  if (fd < 0) {
+    Error("%s: failed to create temp config for %s: %s", 
ts::filename::PLUGIN_YAML, entry.path.c_str(), strerror(errno));
+    return std::nullopt;
+  }
+
+  auto n = write(fd, entry.config_literal.data(), entry.config_literal.size());
+  close(fd);
+
+  if (n < 0 || static_cast<size_t>(n) != entry.config_literal.size()) {
+    Error("%s: failed to write inline config for %s", 
ts::filename::PLUGIN_YAML, entry.path.c_str());
+    return std::nullopt;
+  }

Review Comment:
   low risk



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]

Reply via email to