This is an automated email from the ASF dual-hosted git repository.
dmeden pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/trafficserver.git
The following commit(s) were added to refs/heads/master by this push:
new 425939c6d0 traffic_ctl - Implement `server status` command option.
(#12183)
425939c6d0 is described below
commit 425939c6d0d2ee9eca89a2fe5278d8fd5be539a0
Author: Damian Meden <[email protected]>
AuthorDate: Tue Apr 22 10:40:12 2025 +0200
traffic_ctl - Implement `server status` command option. (#12183)
* traffic_ctl - Implement server status command option.
With the removal of traffic_manager we lost this command option, so now
this change makes ATS to respond the rpc call with some basic
`TSSystemState`
Information, like intimidation status, draining status, etc.
The output is a simple json output.
Command option is read only, no change is done in the internal ATS state.
Example:
$ traffic_ctl server status | jq
{
"initialized_done": "true",
"is_ssl_handshaking_stopped": "false",
"is_draining": "false",
"is_event_system_shut_down": "false"
}
This also includes some autests to validate the output. Changes to
existing traffic_ctl autest machinery is made to make it simpler to
extend and add more tests.
* Fix docs
---
doc/appendices/command-line/traffic_ctl.en.rst | 19 ++-
include/mgmt/rpc/handlers/server/Server.h | 2 +
src/mgmt/rpc/handlers/server/Server.cc | 23 +++
src/traffic_ctl/CtrlCommands.cc | 10 ++
src/traffic_ctl/CtrlCommands.h | 3 +
src/traffic_ctl/CtrlPrinters.cc | 7 +-
src/traffic_ctl/CtrlPrinters.h | 9 ++
src/traffic_ctl/jsonrpc/CtrlRPCRequests.h | 9 ++
src/traffic_ctl/traffic_ctl.cc | 12 +-
src/traffic_server/RpcAdminPubHandlers.cc | 6 +-
.../traffic_ctl/traffic_ctl_config_output.test.py | 146 +-----------------
.../traffic_ctl/traffic_ctl_server_output.test.py | 45 ++++++
...ig_output.test.py => traffic_ctl_test_utils.py} | 169 +++++++++++----------
13 files changed, 223 insertions(+), 237 deletions(-)
diff --git a/doc/appendices/command-line/traffic_ctl.en.rst
b/doc/appendices/command-line/traffic_ctl.en.rst
index 8eaee48e6d..c6009a4964 100644
--- a/doc/appendices/command-line/traffic_ctl.en.rst
+++ b/doc/appendices/command-line/traffic_ctl.en.rst
@@ -46,7 +46,7 @@ of subcommands that control different aspects of Traffic
Server:
:program:`traffic_ctl metric`
Manipulate performance and status metrics
:program:`traffic_ctl server`
- Stop, restart and examine the server
+ Examine the server
:program:`traffic_ctl storage`
Manipulate cache storage
:program:`traffic_ctl plugin`
@@ -385,10 +385,25 @@ traffic_ctl server
Drop the number of active client connections.
+
+.. _traffic-control-command-server-status:
+
.. program:: traffic_ctl server
.. option:: status
- Option not yet available
+ Display basic |TS| internal running information.
+
+ Example:
+
+ .. code-block:: bash
+
+ $ traffic_ctl server status | jq
+ {
+ "initialized_done": "true",
+ "is_ssl_handshaking_stopped": "false",
+ "is_draining": "false",
+ "is_event_system_shut_down": "false"
+ }
.. _traffic-control-command-server-debug:
diff --git a/include/mgmt/rpc/handlers/server/Server.h
b/include/mgmt/rpc/handlers/server/Server.h
index 2806ec4155..face7053f4 100644
--- a/include/mgmt/rpc/handlers/server/Server.h
+++ b/include/mgmt/rpc/handlers/server/Server.h
@@ -27,4 +27,6 @@ namespace rpc::handlers::server
swoc::Rv<YAML::Node> server_start_drain(std::string_view const &id, YAML::Node
const ¶ms);
swoc::Rv<YAML::Node> server_stop_drain(std::string_view const &id, YAML::Node
const &);
void server_shutdown(YAML::Node const &);
+swoc::Rv<YAML::Node> get_server_status(std::string_view const &id, YAML::Node
const &);
+
} // namespace rpc::handlers::server
diff --git a/src/mgmt/rpc/handlers/server/Server.cc
b/src/mgmt/rpc/handlers/server/Server.cc
index 3bccc8ef0b..c032e7a7ff 100644
--- a/src/mgmt/rpc/handlers/server/Server.cc
+++ b/src/mgmt/rpc/handlers/server/Server.cc
@@ -127,4 +127,27 @@ server_shutdown(YAML::Node const &)
{
sync_cache_dir_on_shutdown();
}
+
+swoc::Rv<YAML::Node>
+get_server_status(std::string_view const & /* params ATS_UNUSED */, YAML::Node
const & /* params ATS_UNUSED */)
+{
+ swoc::Rv<YAML::Node> resp;
+ try {
+ auto bts = [](bool val) -> std::string { return val ? "true" : "false"; };
+
+ YAML::Node data;
+ data["initialized_done"] =
bts(!TSSystemState::is_initializing());
+ data["is_ssl_handshaking_stopped"] =
bts(TSSystemState::is_ssl_handshaking_stopped());
+ data["is_draining"] = bts(TSSystemState::is_draining());
+ data["is_event_system_shut_down"] =
bts(TSSystemState::is_event_system_shut_down());
+
+ resp.result()["data"] = data;
+
+ } catch (std::exception const &ex) {
+ resp.errata()
+ .assign(std::error_code{errors::Codes::SERVER})
+ .note("Error found when calling get_server_status API: {}", ex.what());
+ }
+ return resp;
+}
} // namespace rpc::handlers::server
diff --git a/src/traffic_ctl/CtrlCommands.cc b/src/traffic_ctl/CtrlCommands.cc
index ae290c463e..7a94ad067c 100644
--- a/src/traffic_ctl/CtrlCommands.cc
+++ b/src/traffic_ctl/CtrlCommands.cc
@@ -562,6 +562,9 @@ ServerCommand::ServerCommand(ts::Arguments *args) :
CtrlCommand(args)
} else if (get_parsed_arguments()->get(DEBUG_STR)) {
_printer = std::make_unique<GenericPrinter>(printOpts);
_invoked_func = [&]() { server_debug(); };
+ } else if (get_parsed_arguments()->get(STATUS_STR)) {
+ _printer = std::make_unique<ServerStatusPrinter>(printOpts);
+ _invoked_func = [&]() { server_status(); };
}
}
@@ -609,6 +612,13 @@ ServerCommand::server_debug()
}
}
+void
+ServerCommand::server_status()
+{
+ shared::rpc::JSONRPCResponse response = invoke_rpc(GetServerStatusRequest{});
+ _printer->write_output(response);
+}
+
//
//------------------------------------------------------------------------------------------------------------------------------------
StorageCommand::StorageCommand(ts::Arguments *args) : CtrlCommand(args)
{
diff --git a/src/traffic_ctl/CtrlCommands.h b/src/traffic_ctl/CtrlCommands.h
index 3da9222291..e20d70d8dd 100644
--- a/src/traffic_ctl/CtrlCommands.h
+++ b/src/traffic_ctl/CtrlCommands.h
@@ -220,8 +220,11 @@ private:
static inline const std::string TAGS_STR{"tags"};
static inline const std::string CLIENT_IP_STR{"client_ip"};
+ static inline const std::string STATUS_STR{"status"};
+
void server_drain();
void server_debug();
+ void server_status();
};
//
//
-----------------------------------------------------------------------------------------------------------------------------------
diff --git a/src/traffic_ctl/CtrlPrinters.cc b/src/traffic_ctl/CtrlPrinters.cc
index 1458cc8a9f..caf0f09b82 100644
--- a/src/traffic_ctl/CtrlPrinters.cc
+++ b/src/traffic_ctl/CtrlPrinters.cc
@@ -359,4 +359,9 @@ RPCAPIPrinter::write_output(YAML::Node const &result)
}
}
//------------------------------------------------------------------------------------------------------------------------------------
-//---------------------------------------------------------------------------------------------------------------------------------
+void
+ServerStatusPrinter::write_output(YAML::Node const &result)
+{
+ write_output_json(result["data"] ? result["data"] : result);
+}
+//-------------------------------------------------------------------------------------------------------------------------------------
diff --git a/src/traffic_ctl/CtrlPrinters.h b/src/traffic_ctl/CtrlPrinters.h
index d0e8a4bbd8..844a364d26 100644
--- a/src/traffic_ctl/CtrlPrinters.h
+++ b/src/traffic_ctl/CtrlPrinters.h
@@ -283,3 +283,12 @@ public:
RPCAPIPrinter(BasePrinter::Options opt) : BasePrinter(opt) {}
};
//------------------------------------------------------------------------------------------------------------------------------------
+//------------------------------------------------------------------------------------------------------------------------------------
+class ServerStatusPrinter : public BasePrinter
+{
+ void write_output(YAML::Node const &result) override;
+
+public:
+ ServerStatusPrinter(BasePrinter::Options opt) : BasePrinter(opt) {}
+};
+//------------------------------------------------------------------------------------------------------------------------------------
diff --git a/src/traffic_ctl/jsonrpc/CtrlRPCRequests.h
b/src/traffic_ctl/jsonrpc/CtrlRPCRequests.h
index 7ca103d036..862ecc68b3 100644
--- a/src/traffic_ctl/jsonrpc/CtrlRPCRequests.h
+++ b/src/traffic_ctl/jsonrpc/CtrlRPCRequests.h
@@ -161,6 +161,15 @@ struct ServerStopDrainRequest : shared::rpc::ClientRequest
{
}
};
//------------------------------------------------------------------------------------------------------------------------------------
+struct GetServerStatusRequest : shared::rpc::ClientRequest {
+ using super = ClientRequest;
+ std::string
+ get_method() const override
+ {
+ return "get_server_status";
+ }
+};
+//------------------------------------------------------------------------------------------------------------------------------------
struct SetStorageDeviceOfflineRequest : shared::rpc::ClientRequest {
using super = shared::rpc::ClientRequest;
struct Params {
diff --git a/src/traffic_ctl/traffic_ctl.cc b/src/traffic_ctl/traffic_ctl.cc
index d760681e1e..37299f39ad 100644
--- a/src/traffic_ctl/traffic_ctl.cc
+++ b/src/traffic_ctl/traffic_ctl.cc
@@ -169,18 +169,8 @@ main([[maybe_unused]] int argc, const char **argv)
// server commands
server_command.add_command("backtrace", "Show a full stack trace of the
traffic_server process",
[&]() { CtrlUnimplementedCommand("backtrace"); });
- server_command.add_command("restart", "Restart Traffic Server", [&]() {
CtrlUnimplementedCommand("restart"); })
- .add_example_usage("traffic_ctl server restart [OPTIONS]")
- .add_option("--drain", "", "Wait for client connections to drain before
restarting");
- server_command.add_command("start", "Start the proxy", [&]() {
CtrlUnimplementedCommand("start"); })
- .add_example_usage("traffic_ctl server start [OPTIONS]")
- .add_option("--clear-cache", "", "Clear the disk cache on startup")
- .add_option("--clear-hostdb", "", "Clear the DNS cache on startup");
- server_command.add_command("status", "Show the proxy status", [&]() {
CtrlUnimplementedCommand("status"); })
+ server_command.add_command("status", "Show the proxy status", [&]() {
command->execute(); })
.add_example_usage("traffic_ctl server status");
- server_command.add_command("stop", "Stop the proxy", [&]() {
CtrlUnimplementedCommand("stop"); })
- .add_example_usage("traffic_ctl server stop [OPTIONS]")
- .add_option("--drain", "", "Wait for client connections to drain before
stopping");
server_command.add_command("drain", "Drain the requests", [&]() {
command->execute(); })
.add_example_usage("traffic_ctl server drain [OPTIONS]")
.add_option("--no-new-connection", "-N", "Wait for new connections down to
threshold before starting draining")
diff --git a/src/traffic_server/RpcAdminPubHandlers.cc
b/src/traffic_server/RpcAdminPubHandlers.cc
index 99a2b20120..7e6e0fdff7 100644
--- a/src/traffic_server/RpcAdminPubHandlers.cc
+++ b/src/traffic_server/RpcAdminPubHandlers.cc
@@ -55,10 +55,8 @@ register_admin_jsonrpc_handlers()
{{rpc::RESTRICTED_API}});
rpc::add_method_handler("admin_server_stop_drain", &server_stop_drain,
&core_ats_rpc_service_provider_handle,
{{rpc::RESTRICTED_API}});
- rpc::add_notification_handler("admin_server_shutdown", &server_shutdown,
&core_ats_rpc_service_provider_handle,
- {{rpc::RESTRICTED_API}});
- rpc::add_notification_handler("admin_server_restart", &server_shutdown,
&core_ats_rpc_service_provider_handle,
- {{rpc::RESTRICTED_API}});
+ rpc::add_method_handler("get_server_status", &get_server_status,
&core_ats_rpc_service_provider_handle,
+ {{rpc::NON_RESTRICTED_API}});
// storage
using namespace rpc::handlers::storage;
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 cdfe65ab72..d4643527db 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
@@ -13,8 +13,13 @@
# 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.
-
+import sys
import os
+
+# To include util classes
+sys.path.insert(0, f'{Test.TestDirectory}')
+
+from traffic_ctl_test_utils import Make_traffic_ctl
# import ruamel.yaml Uncomment only when GoldFilePathFor is used.
Test.Summary = '''
@@ -23,143 +28,6 @@ Test traffic_ctl config output responses.
Test.ContinueOnFail = True
-TestNumber = 0
-
-
-def IncTestNumber():
- global TestNumber
- TestNumber = TestNumber + 1
-
-
-# This function can(eventually) be used to have a single yaml file and read
nodes from it.
-# The idea would be to avoid having multiple gold files with yaml content.
-# The only issue would be the comments, this is because how the yaml lib reads
yaml,
-# comments aren't rendered in the same way as traffic_ctl throws it, it
should only
-# be used if no comments need to be compared.
-#
-# def GoldFilePathFor(node:str, main_file="gold/test_gold_file.yaml"):
-# if node == "":
-# raise Exception("node should not be empty")
-
-# yaml = ruamel.yaml.YAML()
-# yaml.indent(sequence=4, offset=2)
-# with open(os.path.join(Test.TestDirectory, main_file), 'r') as f:
-# content = yaml.load(f)
-
-# node_data = content[node]
-# data_dirname = 'generated_gold_files'
-# data_path = os.path.join(Test.TestDirectory, data_dirname)
-# os.makedirs(data_path, exist_ok=True)
-# gold_filepath = os.path.join(data_path, f'test_{TestNumber}.gold')
-# with open(os.path.join(data_path, f'test_{TestNumber}.gold'), 'w') as
gold_file:
-# yaml.dump(node_data, gold_file)
-
-# return gold_filepath
-
-
-def MakeGoldFileWithText(content, add_new_line=True):
- data_path = os.path.join(Test.TestDirectory, "gold")
- os.makedirs(data_path, exist_ok=True)
- gold_filepath = os.path.join(data_path, f'test_{TestNumber}.gold')
- with open(gold_filepath, 'w') as gold_file:
- if add_new_line:
- content = f"{content}\n"
- gold_file.write(content)
-
- return gold_filepath
-
-
-class Config():
- """
- Handy class to map traffic_ctl config options.
- """
-
- def __init__(self, tr):
- self._cmd = "traffic_ctl config "
- self._tr = tr
-
- def diff(self):
- self._cmd = f'{self._cmd} diff'
- return self
-
- def get(self, value):
- self._cmd = f'{self._cmd} get {value}'
- return self
-
- def match(self, value):
- self._cmd = f'{self._cmd} match {value}'
- return self
-
- def describe(self, value):
- self._cmd = f'{self._cmd} describe {value}'
- return self
-
- def as_records(self):
- self._cmd = f'{self._cmd} --records'
- return self
-
- def with_default(self):
- self._cmd = f'{self._cmd} --default'
- return self
-
- def __finish(self):
- """
- Sets the command to the test. Make sure this gets called after
- validation is set. Without this call the test will fail.
- """
- self._tr.Processes.Default.Command = self._cmd
-
- def validate_with_goldfile(self, file: str):
- self._tr.Processes.Default.Streams.stdout = os.path.join("gold", file)
- self.__finish()
-
- def validate_with_text(self, text: str):
- self._tr.Processes.Default.Streams.stdout = MakeGoldFileWithText(text)
- self.__finish()
-
-
-class TrafficCtl(Config):
- """
- Single TS instance with multiple tests.
- Every time a config() is called, a new test is created.
- """
-
- def __init__(self, records_yaml=None):
- self._current_test_number = TestNumber
-
- self._ts = Test.MakeATSProcess(f"ts_{TestNumber}")
- if records_yaml != None:
- self._ts.Disk.records_config.update(records_yaml)
- self._tests = []
-
- def __get_index(self):
- return self._current_test_number
-
- def add_test(self):
-
- tr = Test.AddTestRun(f"test {TestNumber}")
- if TestNumber == 0:
- tr.Processes.Default.StartBefore(self._ts)
- IncTestNumber()
-
- tr.Processes.Default.Env = self._ts.Env
- tr.DelayStart = 3
- tr.Processes.Default.ReturnCode = 0
- tr.StillRunningAfter = self._ts
-
- self._tests.insert(self.__get_index(), tr)
- return self
-
- def config(self):
- self.add_test()
- return Config(self._tests[self.__get_index()])
-
-
-def Make_traffic_ctl(records_yaml):
- tctl = TrafficCtl(records_yaml)
- return tctl
-
-
records_yaml = '''
udp:
threads: 1
@@ -170,7 +38,7 @@ records_yaml = '''
throttling_interval_msec: 0
'''
-traffic_ctl = Make_traffic_ctl(records_yaml)
+traffic_ctl = Make_traffic_ctl(Test, records_yaml)
##### CONFIG GET
diff --git a/tests/gold_tests/traffic_ctl/traffic_ctl_server_output.test.py
b/tests/gold_tests/traffic_ctl/traffic_ctl_server_output.test.py
new file mode 100644
index 0000000000..747eb2a97f
--- /dev/null
+++ b/tests/gold_tests/traffic_ctl/traffic_ctl_server_output.test.py
@@ -0,0 +1,45 @@
+# 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.
+
+import sys
+import os
+
+# To include util classes
+sys.path.insert(0, f'{Test.TestDirectory}')
+
+from traffic_ctl_test_utils import Make_traffic_ctl
+
+Test.Summary = '''
+Test traffic_ctl different commands.
+'''
+
+Test.ContinueOnFail = True
+
+Test.Summary = 'Basic test for traffic_ctl server command features.'
+
+traffic_ctl = Make_traffic_ctl(Test)
+######
+# traffic_ctl server status
+traffic_ctl.server().status().validate_with_text(
+ '{"initialized_done": "true", "is_ssl_handshaking_stopped": "false",
"is_draining": "false", "is_event_system_shut_down": "false"}'
+)
+# Drain ats so we can check the output.
+traffic_ctl.server().drain().exec()
+
+# After the drain, server status should reflect this change.
+traffic_ctl.server().status().validate_with_text(
+ '{"initialized_done": "true", "is_ssl_handshaking_stopped": "false",
"is_draining": "true", "is_event_system_shut_down": "false"}'
+)
diff --git a/tests/gold_tests/traffic_ctl/traffic_ctl_config_output.test.py
b/tests/gold_tests/traffic_ctl/traffic_ctl_test_utils.py
similarity index 60%
copy from tests/gold_tests/traffic_ctl/traffic_ctl_config_output.test.py
copy to tests/gold_tests/traffic_ctl/traffic_ctl_test_utils.py
index cdfe65ab72..c8a2d57576 100644
--- a/tests/gold_tests/traffic_ctl/traffic_ctl_config_output.test.py
+++ b/tests/gold_tests/traffic_ctl/traffic_ctl_test_utils.py
@@ -15,21 +15,6 @@
# limitations under the License.
import os
-# import ruamel.yaml Uncomment only when GoldFilePathFor is used.
-
-Test.Summary = '''
-Test traffic_ctl config output responses.
-'''
-
-Test.ContinueOnFail = True
-
-TestNumber = 0
-
-
-def IncTestNumber():
- global TestNumber
- TestNumber = TestNumber + 1
-
# This function can(eventually) be used to have a single yaml file and read
nodes from it.
# The idea would be to avoid having multiple gold files with yaml content.
@@ -57,10 +42,10 @@ def IncTestNumber():
# return gold_filepath
-def MakeGoldFileWithText(content, add_new_line=True):
- data_path = os.path.join(Test.TestDirectory, "gold")
+def MakeGoldFileWithText(content, dir, test_number, add_new_line=True):
+ data_path = os.path.join(dir, "gold")
os.makedirs(data_path, exist_ok=True)
- gold_filepath = os.path.join(data_path, f'test_{TestNumber}.gold')
+ gold_filepath = os.path.join(data_path, f'test_{test_number}.gold')
with open(gold_filepath, 'w') as gold_file:
if add_new_line:
content = f"{content}\n"
@@ -74,9 +59,11 @@ class Config():
Handy class to map traffic_ctl config options.
"""
- def __init__(self, tr):
+ def __init__(self, dir, tr, tn):
self._cmd = "traffic_ctl config "
self._tr = tr
+ self._dir = dir
+ self._tn = tn
def diff(self):
self._cmd = f'{self._cmd} diff'
@@ -114,20 +101,88 @@ class Config():
self.__finish()
def validate_with_text(self, text: str):
- self._tr.Processes.Default.Streams.stdout = MakeGoldFileWithText(text)
+ self._tr.Processes.Default.Streams.stdout = MakeGoldFileWithText(text,
self._dir, self._tn)
self.__finish()
-class TrafficCtl(Config):
+class Server():
+ """
+ Handy class to map traffic_ctl server options.
+ """
+
+ def __init__(self, dir, tr, tn):
+ self._cmd = "traffic_ctl server "
+ self._tr = tr
+ self._dir = dir
+ self._tn = tn
+
+ def status(self):
+ self._cmd = f'{self._cmd} status '
+ return self
+
+ def drain(self, undo=False):
+ self._cmd = f'{self._cmd} drain '
+ if undo:
+ self._cmd = f'{self._cmd} --undo'
+ return self
+
+ def as_json(self):
+ self._cmd = f'{self._cmd} -f json'
+ return self
+
+ """
+ If you need to just run the command with no validation, this is ok in the
context of a test, but not to be
+ used in isolation(as to run traffic_ctl commands)
+ """
+
+ def exec(self):
+ self.__finish()
+
+ def __finish(self):
+ """
+ Sets the command to the test. Make sure this gets called after
+ validation is set. Without this call the test will fail.
+ """
+ self._tr.Processes.Default.Command = self._cmd
+
+ def validate_with_text(self, text: str):
+ self._tr.Processes.Default.Streams.stdout = MakeGoldFileWithText(text,
self._dir, self._tn)
+ self.__finish()
+
+
+'''
+
+Handy wrapper around traffic_ctl, ATS and the autest output validation
mechanism.
+The Idea is to use this as a way to validate traffic_ctl output and not to
execute traffic_ctl command(though it can and is
+recommended in the context of test)
+
+Example for a single test.
+
+# create the traffic_ctl wrapper.
+traffic_ctl = Make_traffic_ctl(Test, records_yaml)
+
+## if the output is simple, then you can just
+traffic_ctl.config().get("proxy.config.diags.debug.enabled").validate_with_text("proxy.config.diags.debug.enabled:
1")
+
+# if the poutput is a bit complex, then you can just set your own gold file.
+traffic_ctl.config().get("proxy.config.diags.debug.tags").as_records().validate_with_goldfile("your_gold_file.gold")
+
+
+'''
+
+
+class TrafficCtl(Config, Server):
"""
Single TS instance with multiple tests.
Every time a config() is called, a new test is created.
"""
- def __init__(self, records_yaml=None):
- self._current_test_number = TestNumber
+ def __init__(self, test, records_yaml=None):
+ self._testNumber = 0
+ self._current_test_number = self._testNumber
- self._ts = Test.MakeATSProcess(f"ts_{TestNumber}")
+ self._Test = test
+ self._ts = self._Test.MakeATSProcess(f"ts_{self._testNumber}")
if records_yaml != None:
self._ts.Disk.records_config.update(records_yaml)
self._tests = []
@@ -137,10 +192,10 @@ class TrafficCtl(Config):
def add_test(self):
- tr = Test.AddTestRun(f"test {TestNumber}")
- if TestNumber == 0:
+ tr = self._Test.AddTestRun(f"test {self._testNumber}")
+ if self._testNumber == 0:
tr.Processes.Default.StartBefore(self._ts)
- IncTestNumber()
+ self._testNumber = self._testNumber + 1
tr.Processes.Default.Env = self._ts.Env
tr.DelayStart = 3
@@ -152,59 +207,13 @@ class TrafficCtl(Config):
def config(self):
self.add_test()
- return Config(self._tests[self.__get_index()])
-
-
-def Make_traffic_ctl(records_yaml):
- tctl = TrafficCtl(records_yaml)
- return tctl
-
+ return Config(self._Test.TestDirectory,
self._tests[self.__get_index()], self._testNumber)
-records_yaml = '''
- udp:
- threads: 1
- diags:
- debug:
- enabled: 1
- tags: rpc
- throttling_interval_msec: 0
- '''
-
-traffic_ctl = Make_traffic_ctl(records_yaml)
-
-##### CONFIG GET
-
-# YAML output
-traffic_ctl.config().get("proxy.config.diags.debug.tags").as_records().validate_with_goldfile("t1_yaml.gold")
-# Default output
-traffic_ctl.config().get("proxy.config.diags.debug.enabled").validate_with_text("proxy.config.diags.debug.enabled:
1")
-# Default output with default.
-traffic_ctl.config().get("proxy.config.diags.debug.tags").with_default() \
- .validate_with_text("proxy.config.diags.debug.tags: rpc # default
http|dns")
-
-# Now same output test but with defaults, traffic_ctl supports adding default
value
-# when using --records.
-traffic_ctl.config().get("proxy.config.diags.debug.tags").as_records().with_default().validate_with_goldfile("t2_yaml.gold")
-traffic_ctl.config().get(
- "proxy.config.diags.debug.tags proxy.config.diags.debug.enabled
proxy.config.diags.debug.throttling_interval_msec").as_records(
- ).with_default().validate_with_goldfile("t3_yaml.gold")
-
-##### CONFIG MATCH
-traffic_ctl.config().match("threads").with_default().validate_with_goldfile("match.gold")
-
-# The idea is to check the traffic_ctl yaml emitter when a value starts with
the
-# same prefix of a node like:
-# diags:
-# logfile:
-# logfile_perm: rw-r--r--
-#
-# traffic_ctl have a special logic to deal with cases like this, so better
test it.
-traffic_ctl.config().match("diags.logfile").as_records().validate_with_goldfile("t4_yaml.gold")
+ def server(self):
+ self.add_test()
+ return Server(self._Test.TestDirectory,
self._tests[self.__get_index()], self._testNumber)
-##### CONFIG DIFF
-traffic_ctl.config().diff().validate_with_goldfile("diff.gold")
-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")
+def Make_traffic_ctl(test, records_yaml=None):
+ tctl = TrafficCtl(test, records_yaml)
+ return tctl