Copilot commented on code in PR #13191:
URL: https://github.com/apache/trafficserver/pull/13191#discussion_r3285792373


##########
src/iocore/cache/Store.cc:
##########
@@ -218,25 +220,90 @@ Span::~Span()
 Result
 Store::read_config()
 {
-  ats_scoped_str storage_path(RecConfigReadConfigPath(nullptr, 
ts::filename::STORAGE));
+  config::StorageConfig parsed;
+
+  // Check storage.yaml, storage.config and volume.config
+  ats_scoped_str storage_yaml_path(RecConfigReadConfigPath(nullptr, 
ts::filename::STORAGE_YAML));
+  const bool     yaml_exists = storage_yaml_path && 
swoc::file::exists(swoc::file::path(storage_yaml_path.get()));
+
+  ats_scoped_str storage_config_path(RecConfigReadConfigPath(nullptr, 
ts::filename::STORAGE));
+  const bool     storage_config_exists = storage_config_path && 
swoc::file::exists(swoc::file::path(storage_config_path.get()));
 
-  Note("%s loading ...", ts::filename::STORAGE);
+  ats_scoped_str volume_config_path(RecConfigReadConfigPath(nullptr, 
ts::filename::VOLUME));
+  const bool     volume_config_exists = volume_config_path && 
swoc::file::exists(swoc::file::path(volume_config_path.get()));
 
   config::StorageParser parser;
-  auto                  parse_result = parser.parse(storage_path.get());
-  if (!parse_result.ok()) {
-    std::string msg;
-    for (auto const &annotation : parse_result.errata) {
-      if (!msg.empty()) {
-        msg += "; ";
+
+  if (yaml_exists) {
+    Note("%s loading ...", ts::filename::STORAGE_YAML);
+
+    auto parse_result = parser.parse(storage_yaml_path.get());
+    if (!parse_result.ok()) {
+      std::string msg;
+      for (auto const &annotation : parse_result.errata) {
+        if (!msg.empty()) {
+          msg += "; ";
+        }
+        msg += std::string(annotation.text());
+      }
+      return Result::failure("failed to load %s: %s", 
ts::filename::STORAGE_YAML, msg.c_str());
+    }
+    parsed = std::move(parse_result.value);
+
+    // If a legacy storage.config or volume.config also exists, warn that it 
is being ignored.
+    if (storage_config_exists) {
+      Warning("%s exists alongside %s; the legacy file is ignored. "
+              "Use 'traffic_ctl config convert storage' to migrate or remove 
storage.yaml",
+              ts::filename::STORAGE, ts::filename::STORAGE_YAML);
+    }
+
+    if (volume_config_exists) {
+      Warning("%s exists alongside %s; the legacy file is ignored. "
+              "Use 'traffic_ctl config convert storage' to migrate or remove 
storage.yaml",
+              ts::filename::VOLUME, ts::filename::STORAGE_YAML);

Review Comment:
   The warning text says to "migrate or remove storage.yaml" when storage.yaml 
is present and storage.config is being ignored. In this scenario operators 
should remove the legacy file (storage.config), not storage.yaml; the current 
message is misleading.
   



##########
src/iocore/cache/Store.cc:
##########
@@ -218,25 +220,90 @@ Span::~Span()
 Result
 Store::read_config()
 {
-  ats_scoped_str storage_path(RecConfigReadConfigPath(nullptr, 
ts::filename::STORAGE));
+  config::StorageConfig parsed;
+
+  // Check storage.yaml, storage.config and volume.config
+  ats_scoped_str storage_yaml_path(RecConfigReadConfigPath(nullptr, 
ts::filename::STORAGE_YAML));
+  const bool     yaml_exists = storage_yaml_path && 
swoc::file::exists(swoc::file::path(storage_yaml_path.get()));
+
+  ats_scoped_str storage_config_path(RecConfigReadConfigPath(nullptr, 
ts::filename::STORAGE));
+  const bool     storage_config_exists = storage_config_path && 
swoc::file::exists(swoc::file::path(storage_config_path.get()));
 
-  Note("%s loading ...", ts::filename::STORAGE);
+  ats_scoped_str volume_config_path(RecConfigReadConfigPath(nullptr, 
ts::filename::VOLUME));
+  const bool     volume_config_exists = volume_config_path && 
swoc::file::exists(swoc::file::path(volume_config_path.get()));
 
   config::StorageParser parser;
-  auto                  parse_result = parser.parse(storage_path.get());
-  if (!parse_result.ok()) {
-    std::string msg;
-    for (auto const &annotation : parse_result.errata) {
-      if (!msg.empty()) {
-        msg += "; ";
+
+  if (yaml_exists) {
+    Note("%s loading ...", ts::filename::STORAGE_YAML);
+
+    auto parse_result = parser.parse(storage_yaml_path.get());
+    if (!parse_result.ok()) {
+      std::string msg;
+      for (auto const &annotation : parse_result.errata) {
+        if (!msg.empty()) {
+          msg += "; ";
+        }
+        msg += std::string(annotation.text());
+      }
+      return Result::failure("failed to load %s: %s", 
ts::filename::STORAGE_YAML, msg.c_str());
+    }
+    parsed = std::move(parse_result.value);
+
+    // If a legacy storage.config or volume.config also exists, warn that it 
is being ignored.
+    if (storage_config_exists) {
+      Warning("%s exists alongside %s; the legacy file is ignored. "
+              "Use 'traffic_ctl config convert storage' to migrate or remove 
storage.yaml",
+              ts::filename::STORAGE, ts::filename::STORAGE_YAML);
+    }
+
+    if (volume_config_exists) {
+      Warning("%s exists alongside %s; the legacy file is ignored. "
+              "Use 'traffic_ctl config convert storage' to migrate or remove 
storage.yaml",

Review Comment:
   Same issue as above: when storage.yaml exists and volume.config is ignored, 
the warning advises removing storage.yaml, but the operator action should be to 
remove the legacy volume.config (or keep it knowing it is ignored). Update the 
message accordingly.
   



##########
src/iocore/cache/Store.cc:
##########
@@ -218,25 +220,90 @@ Span::~Span()
 Result
 Store::read_config()
 {
-  ats_scoped_str storage_path(RecConfigReadConfigPath(nullptr, 
ts::filename::STORAGE));
+  config::StorageConfig parsed;
+
+  // Check storage.yaml, storage.config and volume.config
+  ats_scoped_str storage_yaml_path(RecConfigReadConfigPath(nullptr, 
ts::filename::STORAGE_YAML));
+  const bool     yaml_exists = storage_yaml_path && 
swoc::file::exists(swoc::file::path(storage_yaml_path.get()));
+
+  ats_scoped_str storage_config_path(RecConfigReadConfigPath(nullptr, 
ts::filename::STORAGE));
+  const bool     storage_config_exists = storage_config_path && 
swoc::file::exists(swoc::file::path(storage_config_path.get()));
 
-  Note("%s loading ...", ts::filename::STORAGE);
+  ats_scoped_str volume_config_path(RecConfigReadConfigPath(nullptr, 
ts::filename::VOLUME));
+  const bool     volume_config_exists = volume_config_path && 
swoc::file::exists(swoc::file::path(volume_config_path.get()));
 
   config::StorageParser parser;
-  auto                  parse_result = parser.parse(storage_path.get());
-  if (!parse_result.ok()) {
-    std::string msg;
-    for (auto const &annotation : parse_result.errata) {
-      if (!msg.empty()) {
-        msg += "; ";
+
+  if (yaml_exists) {
+    Note("%s loading ...", ts::filename::STORAGE_YAML);
+
+    auto parse_result = parser.parse(storage_yaml_path.get());
+    if (!parse_result.ok()) {
+      std::string msg;
+      for (auto const &annotation : parse_result.errata) {
+        if (!msg.empty()) {
+          msg += "; ";
+        }
+        msg += std::string(annotation.text());
+      }
+      return Result::failure("failed to load %s: %s", 
ts::filename::STORAGE_YAML, msg.c_str());
+    }
+    parsed = std::move(parse_result.value);
+
+    // If a legacy storage.config or volume.config also exists, warn that it 
is being ignored.
+    if (storage_config_exists) {
+      Warning("%s exists alongside %s; the legacy file is ignored. "
+              "Use 'traffic_ctl config convert storage' to migrate or remove 
storage.yaml",
+              ts::filename::STORAGE, ts::filename::STORAGE_YAML);
+    }
+
+    if (volume_config_exists) {
+      Warning("%s exists alongside %s; the legacy file is ignored. "
+              "Use 'traffic_ctl config convert storage' to migrate or remove 
storage.yaml",
+              ts::filename::VOLUME, ts::filename::STORAGE_YAML);
+    }
+  } else {
+    // Fall back to legacy storage.config + volume.config.
+    Note("%s not found, falling back to %s + %s", ts::filename::STORAGE_YAML, 
ts::filename::STORAGE, ts::filename::VOLUME);
+
+    if (!storage_config_exists) {
+      return Result::failure("neither %s nor %s found", 
ts::filename::STORAGE_YAML, ts::filename::STORAGE);
+    }
+
+    if (!volume_config_exists) {
+      return Result::failure("neither %s nor %s found", 
ts::filename::STORAGE_YAML, ts::filename::VOLUME);
+    }

Review Comment:
   Fallback path currently hard-requires volume.config to exist (returns 
failure if missing). That conflicts with the documented behavior in 
storage.yaml.en.rst which says volume.config is optional and missing should be 
treated as "no volumes configured". Either adjust the implementation to allow a 
missing/empty volume.config (e.g., merge with an empty volumes config), or 
update the docs to state it is required.



##########
doc/admin-guide/files/storage.yaml.en.rst:
##########
@@ -559,3 +559,27 @@ shares the remaining 1.5GB (4GB - 2GB - 512MB) and caches 
objects up to 1MB.
        - id: 3
          size: 40%
          ram_cache_cutoff: 1M
+
+
+Backward compatibility
+======================
+
+For backward compatibility |TS| also accepts the legacy
+:file:`storage.config` and :file:`volume.config` files. The selection rule at
+startup is:
+
+* If :file:`storage.yaml` exists in the configuration directory, it is loaded
+  and any :file:`storage.config` / :file:`volume.config` present alongside it
+  is ignored. A warning is logged in this case so that operators notice the
+  legacy file is being skipped.
+* If :file:`storage.yaml` does not exist, |TS| falls back to
+  :file:`storage.config` (required) and :file:`volume.config` (optional).
+  A missing :file:`volume.config` is treated as "no volumes configured".

Review Comment:
   The backward-compatibility section states volume.config is optional when 
storage.yaml is absent, but the current implementation in 
src/iocore/cache/Store.cc fails startup if volume.config is missing. Please 
align the documentation with the actual behavior (or update the implementation 
to match the documented optional behavior).
   



##########
src/iocore/cache/Store.cc:
##########
@@ -218,25 +220,90 @@ Span::~Span()
 Result
 Store::read_config()
 {
-  ats_scoped_str storage_path(RecConfigReadConfigPath(nullptr, 
ts::filename::STORAGE));
+  config::StorageConfig parsed;
+
+  // Check storage.yaml, storage.config and volume.config
+  ats_scoped_str storage_yaml_path(RecConfigReadConfigPath(nullptr, 
ts::filename::STORAGE_YAML));
+  const bool     yaml_exists = storage_yaml_path && 
swoc::file::exists(swoc::file::path(storage_yaml_path.get()));
+
+  ats_scoped_str storage_config_path(RecConfigReadConfigPath(nullptr, 
ts::filename::STORAGE));
+  const bool     storage_config_exists = storage_config_path && 
swoc::file::exists(swoc::file::path(storage_config_path.get()));
 
-  Note("%s loading ...", ts::filename::STORAGE);
+  ats_scoped_str volume_config_path(RecConfigReadConfigPath(nullptr, 
ts::filename::VOLUME));
+  const bool     volume_config_exists = volume_config_path && 
swoc::file::exists(swoc::file::path(volume_config_path.get()));

Review Comment:
   Store::read_config() resolves volume.config using 
RecConfigReadConfigPath(nullptr, ts::filename::VOLUME), which ignores the 
configurable record proxy.config.cache.volume_filename. This makes custom 
volume.config locations ineffective even though the record exists. Use 
RecConfigReadConfigPath("proxy.config.cache.volume_filename", 
ts::filename::VOLUME) (and base existence checks on that) so runtime behavior 
matches the configuration knob.
   



##########
src/iocore/cache/Cache.cc:
##########
@@ -971,6 +971,6 @@ ink_cache_init(ts::ModuleVersion v)
 
   Result result = theCacheStore.read_config();
   if (result.failed()) {
-    Fatal("Failed to read cache configuration %s: %s", ts::filename::STORAGE, 
result.message());
+    Fatal("Failed to read cache configuration %s: %s", 
ts::filename::STORAGE_YAML, result.message());

Review Comment:
   This fatal log always names storage.yaml as the cache configuration file, 
but Store::read_config() can successfully fall back to 
storage.config/volume.config and failures may mention those files. Consider 
making this message filename-agnostic (or reflect which source was attempted) 
to avoid misleading operators during legacy fallback.
   



-- 
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