This is an automated email from the ASF dual-hosted git repository.
cmcfarlen pushed a commit to branch 10.1.x
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/10.1.x by this push:
new 58dda60c57 traffic_ctl - Set the appropriate error exit code. (#12308)
(#12327)
58dda60c57 is described below
commit 58dda60c57c1525a08be3b6dd96895c51671feb5
Author: Damian Meden <[email protected]>
AuthorDate: Wed Jul 2 16:51:07 2025 +0200
traffic_ctl - Set the appropriate error exit code. (#12308) (#12327)
Beside errors in the logic which was already covered this also marks the
return code to error when the RPC sends back a response with some sort
of failure.
With this change traffic_ctl callers can now validate the exit code also
considering the RPC errors/failures.
(cherry picked from commit 5e334de06b0a64d5416b582ccef648e9093b10b3)
---
src/traffic_ctl/CtrlCommands.cc | 3 +++
src/traffic_ctl/CtrlPrinters.cc | 9 +++++--
src/traffic_ctl/CtrlPrinters.h | 2 ++
src/traffic_ctl/TrafficCtlStatus.h | 28 ++++++++++++++++++++++
src/traffic_ctl/traffic_ctl.cc | 15 +++++-------
.../traffic_ctl/traffic_ctl_config_output.test.py | 3 +++
.../traffic_ctl/traffic_ctl_test_utils.py | 24 +++++++++++++++++--
7 files changed, 71 insertions(+), 13 deletions(-)
diff --git a/src/traffic_ctl/CtrlCommands.cc b/src/traffic_ctl/CtrlCommands.cc
index 7a94ad067c..31fb78cf82 100644
--- a/src/traffic_ctl/CtrlCommands.cc
+++ b/src/traffic_ctl/CtrlCommands.cc
@@ -34,6 +34,7 @@
#include "jsonrpc/CtrlRPCRequests.h"
#include "jsonrpc/ctrl_yaml_codecs.h"
+#include "TrafficCtlStatus.h"
namespace
{
/// We use yamlcpp as codec implementation.
@@ -498,6 +499,7 @@ DirectRPCCommand::from_file_request()
}
} catch (std::exception const &ex) {
+ App_Exit_Status_Code = CTRL_EX_ERROR;
_printer->write_output(swoc::bwprint(text, "Error found: {}\n",
ex.what()));
}
}
@@ -529,6 +531,7 @@ DirectRPCCommand::read_from_input()
_printer->write_output("--> Request sent.\n");
_printer->write_output(swoc::bwprint(text, "\n<-- {}\n", response));
} catch (std::exception const &ex) {
+ App_Exit_Status_Code = CTRL_EX_ERROR;
_printer->write_output(swoc::bwprint(text, "Error found: {}\n",
ex.what()));
}
}
diff --git a/src/traffic_ctl/CtrlPrinters.cc b/src/traffic_ctl/CtrlPrinters.cc
index caf0f09b82..40fc02971e 100644
--- a/src/traffic_ctl/CtrlPrinters.cc
+++ b/src/traffic_ctl/CtrlPrinters.cc
@@ -29,6 +29,8 @@
#include "jsonrpc/ctrl_yaml_codecs.h"
#include "PrintUtils.h"
+#include "TrafficCtlStatus.h"
+
swoc::BufferWriter &
bwformat(swoc::BufferWriter &w, swoc::bwf::Spec const &spec, FloatDate const
&wrap)
{
@@ -43,6 +45,7 @@ void
print_record_error_list(std::vector<shared::rpc::RecordLookUpResponse::RecordError>
const &errors)
{
if (auto iter = std::begin(errors); iter != std::end(errors)) {
+ App_Exit_Status_Code = CTRL_EX_ERROR; // Set the exit code to error, so we
can return it later.
std::cout << "------------ Errors ----------\n";
std::cout << *iter;
++iter;
@@ -64,8 +67,10 @@ BasePrinter::write_output(shared::rpc::JSONRPCResponse const
&response)
}
if (response.is_error()) {
- // If an error is present, then as per the specs we can ignore the
jsonrpc.result field, so we print the error and we are done
- // here!
+ App_Exit_Status_Code = CTRL_EX_ERROR; // Set the exit code to error, so we
can return it later.
+
+ // If an error is present, then as per the specs we can ignore the
jsonrpc.result field,
+ // so we print the error and we are done here!
std::cout << response.error.as<shared::rpc::JSONRPCError>(); // Already
formatted.
return;
}
diff --git a/src/traffic_ctl/CtrlPrinters.h b/src/traffic_ctl/CtrlPrinters.h
index 844a364d26..33c2241055 100644
--- a/src/traffic_ctl/CtrlPrinters.h
+++ b/src/traffic_ctl/CtrlPrinters.h
@@ -90,6 +90,8 @@ public:
/// be called.
/// @param response the server response.
///
+ /// @note If there is an error, App_Exit_Status_Code will be set to
CTRL_EX_ERROR.
+ ///
void write_output(shared::rpc::JSONRPCResponse const &response);
///
diff --git a/src/traffic_ctl/TrafficCtlStatus.h
b/src/traffic_ctl/TrafficCtlStatus.h
new file mode 100644
index 0000000000..b7d758fd25
--- /dev/null
+++ b/src/traffic_ctl/TrafficCtlStatus.h
@@ -0,0 +1,28 @@
+
+/**
+@section license License
+
+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.
+*/
+#pragma once
+
+constexpr int CTRL_EX_OK = 0;
+// EXIT_FAILURE can also be used.
+constexpr int CTRL_EX_ERROR = 2;
+constexpr int CTRL_EX_UNIMPLEMENTED = 3;
+
+extern int App_Exit_Status_Code; //!< Global variable to store the exit status
code of the application.
diff --git a/src/traffic_ctl/traffic_ctl.cc b/src/traffic_ctl/traffic_ctl.cc
index 37299f39ad..28e64f0ab3 100644
--- a/src/traffic_ctl/traffic_ctl.cc
+++ b/src/traffic_ctl/traffic_ctl.cc
@@ -32,13 +32,10 @@
#include "CtrlCommands.h"
#include "FileConfigCommand.h"
+#include "TrafficCtlStatus.h"
-constexpr int CTRL_EX_OK = 0;
-constexpr int CTRL_EX_ERROR = 2;
-constexpr int CTRL_EX_UNIMPLEMENTED = 3;
-
-int status_code{CTRL_EX_OK};
-
+// Define the global variable
+int App_Exit_Status_Code = CTRL_EX_OK; // Initialize it to a default value
namespace
{
void
@@ -70,7 +67,7 @@ main([[maybe_unused]] int argc, const char **argv)
auto CtrlUnimplementedCommand = [](std::string_view cmd) {
std::cout << "Command " << cmd << " unimplemented.\n";
- status_code = CTRL_EX_UNIMPLEMENTED;
+ App_Exit_Status_Code = CTRL_EX_UNIMPLEMENTED;
};
parser.add_description("Apache Traffic Server RPC CLI");
@@ -242,9 +239,9 @@ main([[maybe_unused]] int argc, const char **argv)
// Execute
args.invoke();
} catch (std::exception const &ex) {
- status_code = CTRL_EX_ERROR;
+ App_Exit_Status_Code = CTRL_EX_ERROR;
std::cerr << "Error found:\n" << ex.what() << '\n';
}
- return status_code;
+ return App_Exit_Status_Code;
}
diff --git a/tests/gold_tests/traffic_ctl/traffic_ctl_config_output.test.py
b/tests/gold_tests/traffic_ctl/traffic_ctl_config_output.test.py
index d4643527db..ecf30a924e 100644
--- a/tests/gold_tests/traffic_ctl/traffic_ctl_config_output.test.py
+++ b/tests/gold_tests/traffic_ctl/traffic_ctl_config_output.test.py
@@ -76,3 +76,6 @@
traffic_ctl.config().diff().as_records().validate_with_goldfile("diff_yaml.gold"
##### CONFIG DESCRIBE
# don't really care about values, but just output and that the command
actually went through
traffic_ctl.config().describe("proxy.config.http.server_ports").validate_with_goldfile("describe.gold")
+
+# Make sure that the command returns an exit code of 2
+traffic_ctl.config().get("invalid.should.set.the.exit.code.to.2").validate_with_exit_code(2)
diff --git a/tests/gold_tests/traffic_ctl/traffic_ctl_test_utils.py
b/tests/gold_tests/traffic_ctl/traffic_ctl_test_utils.py
index c8a2d57576..caf74825d6 100644
--- a/tests/gold_tests/traffic_ctl/traffic_ctl_test_utils.py
+++ b/tests/gold_tests/traffic_ctl/traffic_ctl_test_utils.py
@@ -54,12 +54,31 @@ def MakeGoldFileWithText(content, dir, test_number,
add_new_line=True):
return gold_filepath
-class Config():
+class Common():
+ """
+ Handy class to map common traffic_ctl test options.
+ """
+
+ def __init__(self, tr, finish_callback):
+ self._tr = tr
+ self._finish_callback = finish_callback
+
+ def validate_with_exit_code(self, exit_code: int):
+ """
+ Sets the exit code for the test.
+ """
+ self._tr.Processes.Default.ReturnCode = exit_code
+ self._finish_callback(self)
+ return self
+
+
+class Config(Common):
"""
Handy class to map traffic_ctl config options.
"""
def __init__(self, dir, tr, tn):
+ super().__init__(tr, lambda x: self.__finish())
self._cmd = "traffic_ctl config "
self._tr = tr
self._dir = dir
@@ -105,12 +124,13 @@ class Config():
self.__finish()
-class Server():
+class Server(Common):
"""
Handy class to map traffic_ctl server options.
"""
def __init__(self, dir, tr, tn):
+ super().__init__(tr, lambda x: self.__finish())
self._cmd = "traffic_ctl server "
self._tr = tr
self._dir = dir