Skip to content

Update traffic ctl exit code#13022

Draft
cmcfarlen wants to merge 4 commits intoapache:10.2.xfrom
cmcfarlen:update-traffic_ctl-exit-code
Draft

Update traffic ctl exit code#13022
cmcfarlen wants to merge 4 commits intoapache:10.2.xfrom
cmcfarlen:update-traffic_ctl-exit-code

Conversation

@cmcfarlen
Copy link
Contributor

Draft PR against 10.2.x since master branch is quite different here.

We are having an issue where traffic_ctl was returning a non-zero exit code when encountering config items that are unused. This PR adds a new feature --error-level that defaults to error. This is used to set the exit code when responses from the server contain errata. It will find the worst errata severity and then compare that to the error level and if greater, will set the error exit code.

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR updates traffic_ctl exit-status behavior to avoid returning a non-zero exit code for responses that only contain low-severity errata (e.g., unused config items), by introducing a configurable severity threshold.

Changes:

  • Add --error-level/-e CLI option (default: error) to control when an RPC “errata” response should affect the process exit code.
  • Compute exit status from the worst errata severity found in a JSON-RPC error response.
  • Adjust JSON-RPC errata encoding to emit per-entry severity in the error.data[*].code field so clients can evaluate severity.

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.

File Description
src/traffic_ctl/traffic_ctl.cc Adds global threshold, parses --error-level, and implements appExitCodeFromResponse.
src/traffic_ctl/TrafficCtlStatus.h Declares new global threshold and exit-code helper for use across traffic_ctl sources.
src/traffic_ctl/CtrlPrinters.cc Uses appExitCodeFromResponse to set traffic_ctl exit status for JSON-RPC error responses.
include/mgmt/rpc/jsonrpc/json/YAMLCodec.h Encodes errata entry “code” as severity to support severity-based exit-code decisions.

Comment on lines +56 to +60
auto err = response.error.as<shared::rpc::JSONRPCError>();
swoc::Errata::severity_type most_severe = static_cast<swoc::Errata::severity_type>(ERRATA_DIAG);

for (auto const &[code, msg] : err.data) {
swoc::Errata::severity_type sev(code);
Copy link

Copilot AI Mar 25, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

appExitCodeFromResponse can return CTRL_EX_OK for real JSON-RPC errors when err.data is empty (e.g., protocol/decoder errors or execution errors without errata details). Because most_severe is initialized to ERRATA_DIAG and only updated from err.data, an error response with no data entries will incorrectly exit 0 by default. Consider treating err.data.empty() as an error (return CTRL_EX_ERROR), or incorporate the top-level JSONRPCError::code into the decision so non-errata errors still produce a non-zero exit status.

Copilot uses AI. Check for mistakes.
for (auto const &err : errata) {
int severity = err.severity(ERRATA_DIAG);
json << YAML::BeginMap;
json << YAML::Key << "code" << YAML::Value << errata.code().value();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a bug in my code. it's printing errata.code all the time. It should be the particular error not the one set in the jsonrpc response.

json << YAML::BeginMap;
json << YAML::Key << "code" << YAML::Value << errata.code().value();
// using "code" as the key here because this is decoded into a `JSONRPCError`
json << YAML::Key << "code" << YAML::Value << severity;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if use the severity here in the code field we are changing the meaning from "error code" to "severity level" which is not the original intention.

I think we should use severity as part of the error definition instead:

// the only new stuff would be the severity.
struct JSONRPCError {
  int32_t     code;
  std::string message;
  struct DataEntry {
    int32_t     code;
    int32_t     severity{-1}; // -1 = not present (assume ERROR)
    std::string message;
  };
  std::vector<DataEntry> data;
};

This can be set by the handlers as you already did in the test, something like this:

resp.errata().assign(std::error_code{errors::Codes::SERVER})
  .note(ERRATA_WARN, "Server already draining.");

// json:

{
  "jsonrpc": "2.0",
  "error": {
    "code": 9,
    "message": "Error during execution",
    "data": [
      {
        "code": 2,
        "severity": 4,
        "message": "Server already draining."
      }
    ]
  },
  "id": "..."
}

then we can add the severity if present:

for (auto const &err : errata) {
  json << YAML::BeginMap;
  json << YAML::Key << "code" << YAML::Value << errata.code().value();
  if (err.has_severity()) {
    json << YAML::Key << "severity" << YAML::Value
         << static_cast<int>(err.severity());
  }
  json << YAML::Key << "message" << YAML::Value
       << std::string{err.text().data(), err.text().size()};
  json << YAML::EndMap;
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Annotation class doesn't have code, only severity and text.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants