From c1fad1134a7694c8128f35de0e24e52d5c099a20 Mon Sep 17 00:00:00 2001 From: Damian Meden Date: Fri, 19 Jun 2026 11:06:35 +0200 Subject: [PATCH] Add `Test.AddConfigReload()` autest extension (#13075) Config reload AuTests rely on fire-and-forget traffic_ctl calls plus sleeps and log grepping. This makes the tests slow and fragile and cannot verify specific handlers or report reload failures. This adds Test.AddConfigReload() to monitor reload completion and validate task status. It carries filenames through child reload tasks and migrates the applicable tests to the deterministic helper. Fixes: #12965 (cherry picked from commit 70859231d86c384dd8b038e0a58a280c274bf8a9) --- .../config-reload-framework.en.rst | 10 +- .../testing/config-reload-ext.en.rst | 259 ++++++++++++++++++ doc/developer-guide/testing/index.en.rst | 1 + include/mgmt/config/ConfigContext.h | 2 +- include/mgmt/config/ConfigReloadTrace.h | 2 +- src/iocore/net/SSLClientCoordinator.cc | 6 +- src/mgmt/config/ConfigContext.cc | 4 +- src/mgmt/config/ConfigReloadTrace.cc | 4 +- .../autest-site/config_reload.test.ext | 225 +++++++++++++++ .../cache/cache_config_reload.test.py | 16 +- tests/gold_tests/dns/splitdns_reload.test.py | 12 +- .../ip_allow_reload_triggered.test.py | 52 +--- tests/gold_tests/ip_allow/ip_category.test.py | 14 +- .../gold_tests/logging/log_retention.test.py | 8 +- .../parent_config_reload.test.py | 12 +- .../regex_revalidate_miss.test.py | 16 +- tests/gold_tests/remap/remap_acl.test.py | 19 +- tests/gold_tests/remap/remap_reload.test.py | 15 +- tests/gold_tests/tls/ssl_key_dialog.test.py | 16 +- .../tls/ssl_multicert_loader.test.py | 12 +- .../tls_check_cert_selection_reload.test.py | 11 +- tests/gold_tests/tls/tls_client_cert.test.py | 18 +- .../tls_client_cert_override_plugin.test.py | 10 +- .../tls/tls_client_cert_plugin.test.py | 18 +- .../tls/tls_sni_yaml_reload.test.py | 15 +- tests/gold_tests/tls/tls_tunnel.test.py | 10 +- tests/gold_tests/tls/tls_verify4.test.py | 17 +- .../traffic_ctl/remap_inc/remap_inc.test.py | 15 +- .../traffic_ctl/remap_inc/wait_reload.sh | 34 --- 29 files changed, 551 insertions(+), 302 deletions(-) create mode 100644 doc/developer-guide/testing/config-reload-ext.en.rst create mode 100644 tests/gold_tests/autest-site/config_reload.test.ext delete mode 100755 tests/gold_tests/traffic_ctl/remap_inc/wait_reload.sh diff --git a/doc/developer-guide/config-reload-framework.en.rst b/doc/developer-guide/config-reload-framework.en.rst index 8f65350eb2c..3eceee058cf 100644 --- a/doc/developer-guide/config-reload-framework.en.rst +++ b/doc/developer-guide/config-reload-framework.en.rst @@ -912,8 +912,14 @@ After registering a new handler: 7. Use :option:`traffic_ctl config status` ``--format json`` to inspect the raw :ref:`get_reload_config_status` response for automation testing. -**Autests** — the project includes autest helpers for config reload testing. Use -``AddJsonRPCClientRequest`` with ``Request.admin_config_reload()`` to trigger reloads, and +**Autests** — the project includes autest helpers for config reload testing. + +For **end-to-end tests** that trigger a reload via ``traffic_ctl`` and validate the result, use +the :ref:`autest-config-reload` extension (``Test.AddConfigReload()``). +This is the recommended approach for most reload tests. + +For **JSONRPC-level tests** that need fine-grained control over request and response payloads, +use ``AddJsonRPCClientRequest`` with ``Request.admin_config_reload()`` to trigger reloads, and ``Testers.CustomJSONRPCResponse`` to validate responses programmatically. See the existing tests for examples: diff --git a/doc/developer-guide/testing/config-reload-ext.en.rst b/doc/developer-guide/testing/config-reload-ext.en.rst new file mode 100644 index 00000000000..92e5ba15705 --- /dev/null +++ b/doc/developer-guide/testing/config-reload-ext.en.rst @@ -0,0 +1,259 @@ +.. 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. + +.. include:: ../../common.defs + +.. _autest-config-reload: + +Config Reload Test Extension +**************************** + +The ``config_reload.test.ext`` extension provides ``Test.AddConfigReload()`` to +replace the legacy pattern of fire-and-forget ``traffic_ctl config reload`` +followed by log grepping with a deterministic, structured approach. + +The extension is loaded automatically from +``tests/gold_tests/autest-site/config_reload.test.ext``. + + +Why Use This Extension +====================== + +The legacy reload test pattern is fragile: + +.. code-block:: python + + # OLD: fire-and-forget + sleep + log grep + tr = Test.AddTestRun("Reload config") + p = tr.Processes.Process("reload-1") + p.Command = 'traffic_ctl config reload; sleep 30' + p.Env = ts.Env + p.ReturnCode = Any(0, -2) + p.Ready = When.FileContains( + ts.Disk.diags_log.Name, "finished loading", 2) + p.Timeout = 20 + tr.Processes.Default.StartBefore(p) + tr.Processes.Default.Command = 'echo "waiting for reload"' + tr.TimeOut = 25 + +Problems with this approach: + +- Relies on exact log text that can change across versions. +- Uses ``sleep`` for synchronization, leading to slow and flaky tests. +- Does not validate *which* config handler ran. +- Does not detect reload failures. + +The new pattern is a single call: + +.. code-block:: python + + # NEW: deterministic, validates specific handlers + tr = Test.AddConfigReload(ts, expect_tasks=["sni.yaml"], + description="Reload after sni.yaml touch") + + +How It Works +============ + +``AddConfigReload`` uses ``traffic_ctl config reload -m`` (monitor mode) to +trigger a reload and **block until it completes**. Monitor mode polls the server +for the reload status, so there is no sleeping or guessing. The default timeout +is **30 seconds** (configurable via the ``timeout`` parameter). + +When ``expect_tasks`` or ``expect_absent_tasks`` is set, a second test run +queries the ``get_reload_config_status`` JSONRPC endpoint and validates the task +tree via ``CustomJSONRPCResponse``. This gives tests access to the full +structured result — including per-task status, subtasks, and descriptions — +without relying on the human-readable output of ``traffic_ctl``. + +When neither ``expect_tasks`` nor ``expect_absent_tasks`` is set, only the exit +code is validated (no JSONRPC query). This is useful for reloads where you only +care that the reload succeeded (exit code 0). + + +Test.AddConfigReload +==================== + +Triggers a config reload, blocks until completion, and validates the result. + +.. code-block:: python + + tr = Test.AddConfigReload( + ts, # ATS process object + expect="success", # "success", "fail", "timeout", or "any" + token=None, # custom token (auto-generated if None) + data=None, # inline YAML or @file path + force=False, # --force flag + timeout="30s", # monitor timeout + initial_wait=1.0, # seconds before first poll + refresh_int=0.5, # seconds between polls + expect_tasks=None, # list or dict of expected handler names + expect_absent_tasks=None, # list of handler names that must NOT appear + description=None, # test run description (recommended) + ) + +Parameters +---------- + +``ts`` + The ATS process object (from ``Test.MakeATSProcess()``). + +``expect`` + Expected outcome: + + - ``"success"`` — exit code 0 (all handlers succeeded) + - ``"fail"`` — exit code 2 (one or more handlers failed) + - ``"timeout"`` — exit code 75 (monitor timed out) + - ``"any"`` — exit code 0 or 2 (don't care about outcome) + + Default: ``"success"``. + +``token`` + A custom reload token string. If ``None``, an auto-generated token + (``autest-reload-1``, ``autest-reload-2``, ...) is used. Tokens are unique + per test file. + +``data`` + Inline YAML content or a ``@file`` path to pass via ``--data``. When the + value starts with ``@``, it is passed as-is (e.g. ``@/path/to/file.yaml``). + Otherwise the string is shell-quoted and passed inline. + + .. note:: + + The ``--data`` flag is accepted by ``traffic_ctl config reload`` but + individual reload handlers do not yet consume inline data. This parameter + is reserved for future use. + +``force`` + If ``True``, adds the ``--force`` flag to start a new reload even when one + is already in progress. See the ``traffic_ctl config reload`` documentation + for details on force behavior. + +``timeout`` + Duration string for the monitor timeout (e.g. ``"30s"``, ``"1m"``). This + controls how long ``traffic_ctl config reload -m`` will poll before giving + up. Default: ``"30s"``. Set to ``None`` to disable the timeout (not + recommended). + +``initial_wait`` + Seconds to wait before the first poll, giving the server time to schedule + handlers. Default: ``1.0``. + +``refresh_int`` + Seconds between status polls. Default: ``0.5``. + +``expect_tasks`` + Expected handler/config names in the reload. Accepts two forms: + + - **List** — checks that each name appears somewhere in the task tree: + + .. code-block:: python + + expect_tasks=["ip_allow.yaml", "sni.yaml"] + + - **Dict** — checks presence *and* per-task status: + + .. code-block:: python + + expect_tasks={"sni.yaml": "fail", "SSLConfig": "success"} + + When not set (``None``), no JSONRPC validation is performed — only the exit + code is checked. + +``expect_absent_tasks`` + A list of handler/config names that must **not** appear in the reload task + tree. Useful for verifying that touching an unrelated file did not trigger + a specific handler. + +``description`` + Description for the ``TestRun``. **Recommended** — always pass a description + for readable test output. When omitted, an auto-generated description is + used (e.g. ``"Reload config [autest-reload-1]"``). + +Return Value +------------ + +Returns the reload ``TestRun`` object (the first test run). Callers can add +extra assertions or ``StillRunningAfter`` references: + +.. code-block:: python + + tr = Test.AddConfigReload(ts, expect_tasks=["remap.config"], + description="Reload after remap.config edit") + tr.StillRunningAfter = ts + tr.StillRunningAfter = origin_server + + +.. note:: + + Standalone record-triggered reloads (via ``traffic_ctl config set`` without + an explicit ``config reload``) do not create tasks in the reload framework + and cannot be verified with this extension. + + +Examples +======== + +Basic reload after touching a config file: + +.. code-block:: python + + tr = Test.AddTestRun("Touch ip_allow.yaml") + tr.Processes.Default.Command = f"touch {config_dir}/ip_allow.yaml" + tr.Processes.Default.ReturnCode = 0 + tr.StillRunningAfter = ts + + tr = Test.AddConfigReload(ts, expect_tasks=["ip_allow.yaml"], + description="Reload after ip_allow.yaml touch") + +Expecting a reload failure (e.g. broken sni.yaml): + +.. code-block:: python + + tr = Test.AddConfigReload(ts, expect="fail", expect_tasks=["sni.yaml"], + description="Reload with broken sni.yaml") + +Verifying a handler was NOT triggered: + +.. code-block:: python + + tr = Test.AddConfigReload(ts, expect_absent_tasks=["ip_allow.yaml"], + description="Reload (should NOT trigger ip_allow)") + +Per-task status validation: + +.. code-block:: python + + tr = Test.AddConfigReload( + ts, + expect="fail", + expect_tasks={"sni.yaml": "fail", "SSLConfig": "success"}, + description="Reload with mixed task outcomes", + ) + +Reload with inline YAML data: + +.. code-block:: python + + # NOTE: --data is accepted by traffic_ctl but individual reload handlers + # do not yet consume inline data. Reserved for future use. + tr = Test.AddConfigReload( + ts, + data="ip_allow:\n - apply: in\n ip_addrs: 0/0\n action: allow", + expect_tasks=["ip_allow.yaml"], + description="Reload with inline ip_allow data", + ) diff --git a/doc/developer-guide/testing/index.en.rst b/doc/developer-guide/testing/index.en.rst index 363dabc4e55..d14c2542e5f 100644 --- a/doc/developer-guide/testing/index.en.rst +++ b/doc/developer-guide/testing/index.en.rst @@ -26,3 +26,4 @@ Testing Traffic Server :maxdepth: 2 autests.en + config-reload-ext.en diff --git a/include/mgmt/config/ConfigContext.h b/include/mgmt/config/ConfigContext.h index 49807c02dd6..30ebe886eb9 100644 --- a/include/mgmt/config/ConfigContext.h +++ b/include/mgmt/config/ConfigContext.h @@ -170,7 +170,7 @@ class ConfigContext /// Each dependent reports its own status (in_progress/complete/fail) and the parent /// task aggregates them. The dependent context also inherits the parent's supplied YAML node. /// - [[nodiscard]] ConfigContext add_dependent_ctx(std::string_view description = ""); + [[nodiscard]] ConfigContext add_dependent_ctx(std::string_view description = "", std::string_view filename = ""); /// Get supplied YAML node (for RPC-based reloads). /// A default-constructed YAML::Node is Undefined (operator bool() == false). diff --git a/include/mgmt/config/ConfigReloadTrace.h b/include/mgmt/config/ConfigReloadTrace.h index 6f5529a2bb3..b325c707b1f 100644 --- a/include/mgmt/config/ConfigReloadTrace.h +++ b/include/mgmt/config/ConfigReloadTrace.h @@ -222,7 +222,7 @@ class ConfigReloadTask : public std::enable_shared_from_this /// Create a child sub-task and return a ConfigContext wrapping it. /// The child inherits the parent's token and if passed, the supplied YAML content. - [[nodiscard]] ConfigContext add_child(std::string_view description = ""); + [[nodiscard]] ConfigContext add_child(std::string_view description = "", std::string_view filename = ""); self_type &log(std::string const &text); self_type &log(DiagsLevel level, std::string const &text); diff --git a/src/iocore/net/SSLClientCoordinator.cc b/src/iocore/net/SSLClientCoordinator.cc index 89b73f8cee0..4122707f229 100644 --- a/src/iocore/net/SSLClientCoordinator.cc +++ b/src/iocore/net/SSLClientCoordinator.cc @@ -38,11 +38,11 @@ SSLClientCoordinator::reconfigure(ConfigContext reconf_ctx) // The SSLConfig owns the client cert context storage and the SNIConfig will load // into it. SSLConfig::reconfigure(reconf_ctx.add_dependent_ctx("SSLConfig")); - SNIConfig::reconfigure(reconf_ctx.add_dependent_ctx("SNIConfig")); - SSLCertificateConfig::reconfigure(reconf_ctx.add_dependent_ctx("SSLCertificateConfig")); + SNIConfig::reconfigure(reconf_ctx.add_dependent_ctx("SNIConfig", ts::filename::SNI)); + SSLCertificateConfig::reconfigure(reconf_ctx.add_dependent_ctx("SSLCertificateConfig", ts::filename::SSL_MULTICERT)); #if TS_USE_QUIC == 1 if (HttpProxyPort::hasQUIC()) { - QUICCertConfig::reconfigure(reconf_ctx.add_dependent_ctx("QUICCertConfig")); + QUICCertConfig::reconfigure(reconf_ctx.add_dependent_ctx("QUICCertConfig", ts::filename::SSL_MULTICERT)); } #endif reconf_ctx.complete("SSL configs reloaded"); diff --git a/src/mgmt/config/ConfigContext.cc b/src/mgmt/config/ConfigContext.cc index 7dd81a58ca3..fc5d2772c7a 100644 --- a/src/mgmt/config/ConfigContext.cc +++ b/src/mgmt/config/ConfigContext.cc @@ -142,10 +142,10 @@ ConfigContext::get_description() const } ConfigContext -ConfigContext::add_dependent_ctx(std::string_view description) +ConfigContext::add_dependent_ctx(std::string_view description, std::string_view filename) { if (auto p = _task.lock()) { - auto child = p->add_child(description); + auto child = p->add_child(description, filename); // child task will get the full content of the parent task // TODO: eventually we can have a "key" passed so child module // only gets their node of interest. diff --git a/src/mgmt/config/ConfigReloadTrace.cc b/src/mgmt/config/ConfigReloadTrace.cc index db322d441d7..aae0b0f0196 100644 --- a/src/mgmt/config/ConfigReloadTrace.cc +++ b/src/mgmt/config/ConfigReloadTrace.cc @@ -80,13 +80,13 @@ ConfigReloadProgress::get_configured_check_interval() } ConfigContext -ConfigReloadTask::add_child(std::string_view description) +ConfigReloadTask::add_child(std::string_view description, std::string_view filename) { std::unique_lock lock(_mutex); // Read token directly - can't call get_token() as it would deadlock (tries to acquire shared_lock on same mutex) auto trace = std::make_shared(_info.token, description, false, shared_from_this()); _info.sub_tasks.push_back(trace); - return ConfigContext{std::move(trace), description}; + return ConfigContext{std::move(trace), description, filename}; } ConfigReloadTask & diff --git a/tests/gold_tests/autest-site/config_reload.test.ext b/tests/gold_tests/autest-site/config_reload.test.ext new file mode 100644 index 00000000000..8a9f352223c --- /dev/null +++ b/tests/gold_tests/autest-site/config_reload.test.ext @@ -0,0 +1,225 @@ +''' +AuTest extension for config reload operations. + +Provides Test.AddConfigReload() to replace the legacy pattern of +fire-and-forget `traffic_ctl config reload` followed by log grepping via +When.FileContains("finished loading", N). + +Test.AddConfigReload(ts, ...) + Triggers a reload via `traffic_ctl config reload -m` (monitor mode), + which blocks until the reload reaches a terminal state (default timeout + 30s), then optionally validates the task tree via the + get_reload_config_status JSONRPC endpoint. + +Note: standalone record-triggered reloads (via traffic_ctl config set, with +no explicit config reload) do not create tasks in the reload framework and +cannot be verified with this extension. +''' +# 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 os +import jsonrpc + +_reload_counter = 0 + +_EXPECT_EXIT_CODES = { + "success": 0, + "fail": 2, + "timeout": 75, +} + + +def _next_token(): + global _reload_counter + _reload_counter += 1 + return f"autest-reload-{_reload_counter}" + + +def _shell_quote(s): + """Single-quote a string for shell, escaping embedded single quotes.""" + return "'" + s.replace("'", "'\\''") + "'" + + +def _task_matches(info, name): + """Check if a task matches the given name by description, filename, or basename.""" + for field in ("description", "filename"): + val = info.get(field) + if not val or val == "": + continue + if val == name or os.path.basename(val) == name: + return True + return False + + +def _collect_task_names(info, names=None): + """Recursively collect human-friendly task identifiers from the task tree.""" + if names is None: + names = set() + if isinstance(info, dict): + for field in ("description", "filename"): + val = info.get(field) + if val and val != "": + basename = os.path.basename(val) + names.add(basename if basename != val else val) + for sub in info.get("sub_tasks", []): + _collect_task_names(sub, names) + return names + + +def _find_task(info, name): + """Find a task by description or filename (supports basename matching).""" + if isinstance(info, dict): + if _task_matches(info, name): + return info + for sub in info.get("sub_tasks", []): + found = _find_task(sub, name) + if found: + return found + return None + + +def _make_task_validator(expect_tasks, expect_absent_tasks): + """Build a CustomJSONRPCResponse callback for task validation.""" + + def validator(resp): + if resp.is_error(): + return (False, f"RPC error: {resp.error_as_str()}") + + result = resp.__dict__.get("result", {}) + tasks_list = result.get("tasks", []) + if not tasks_list: + if expect_tasks: + return (False, "No reload tasks in response") + if expect_absent_tasks: + return (True, "No tasks present, absence confirmed") + return (True, "No tasks expected, none found") + + info = tasks_list[0] + all_names = _collect_task_names(info) + + if expect_tasks: + items = expect_tasks.items() if isinstance(expect_tasks, dict) else [(t, None) for t in expect_tasks] + for task_name, task_status in items: + if task_name not in all_names: + return (False, f"Task '{task_name}' not found in reload. Found: {sorted(all_names)}") + if task_status is not None: + task = _find_task(info, task_name) + actual = task.get("status", "unknown") if task else "unknown" + if actual != task_status: + return (False, f"Task '{task_name}' status is '{actual}', expected '{task_status}'") + + if expect_absent_tasks: + for task_name in expect_absent_tasks: + if task_name in all_names: + return (False, f"Task '{task_name}' should NOT be present but was found in: {sorted(all_names)}") + + return (True, "All task assertions passed") + + return validator + + +def AddConfigReload( + self, + ts, + expect="success", + token=None, + data=None, + force=False, + timeout="30s", + initial_wait=1.0, + refresh_int=0.5, + expect_tasks=None, + expect_absent_tasks=None, + delay_start=None, + description=None, +): + """Trigger a config reload, block until completion, and validate the result. + + Creates one or two TestRuns: + 1. Runs `traffic_ctl config reload -m` to trigger and monitor the reload. + Asserts the exit code based on the `expect` parameter. + 2. (Optional) If expect_tasks or expect_absent_tasks is set, queries the + get_reload_config_status JSONRPC endpoint and validates the task tree + using CustomJSONRPCResponse. + + Args: + ts: ATS process object. + expect: "success" (exit 0), "fail" (exit 2), "timeout" (exit 75), + or "any" (exit 0 or 2). + token: Custom reload token. Auto-generated if None. + data: Inline YAML string or @file path for --data flag. + force: If True, adds --force. + timeout: Timeout duration string for --timeout (e.g. "30s", "1m"). + Set to None to disable. + initial_wait: Seconds before first poll (--initial-wait). + refresh_int: Seconds between polls (--refresh-int). + expect_tasks: List of task names expected in the reload, or a dict + mapping task names to expected statuses (e.g. {"sni.yaml": "fail"}). + expect_absent_tasks: List of task names that must NOT appear in the reload. + delay_start: Seconds to wait before starting the reload TestRun. + Useful when the previous step writes a config file and CI may + run fast enough that the filesystem timestamp hasn't changed. + description: Custom TestRun description. + + Returns: + The reload TestRun object (first test run). + """ + if expect not in _EXPECT_EXIT_CODES and expect != "any": + raise ValueError(f"expect must be one of {list(_EXPECT_EXIT_CODES) + ['any']}, got '{expect}'") + + if token is None: + token = _next_token() + + if description is None: + description = f"Reload config [{token}]" + if expect != "success": + description += f" (expect {expect})" + + tr = self.AddTestRun(description) + if delay_start is not None: + tr.DelayStart = delay_start + tr.Processes.Default.Env = ts.Env + tr.StillRunningAfter = ts + + cmd = f"traffic_ctl config reload -m -t {_shell_quote(token)}" + cmd += f" -w {initial_wait} -r {refresh_int}" + + if timeout is not None: + cmd += f" -T {_shell_quote(timeout)}" + if force: + cmd += " --force" + if data is not None: + cmd += f" --data {_shell_quote(data)}" + + tr.Processes.Default.Command = cmd + + if expect == "any": + tr.Processes.Default.ReturnCode = Any(0, 2) + else: + tr.Processes.Default.ReturnCode = _EXPECT_EXIT_CODES[expect] + + if expect_tasks or expect_absent_tasks: + vtr = self.AddTestRun(f"Verify [{token}] tasks") + vtr.AddJsonRPCClientRequest(ts, jsonrpc.Request.get_reload_config_status(token=token)) + vtr.Processes.Default.Streams.stdout = Testers.CustomJSONRPCResponse( + _make_task_validator(expect_tasks, expect_absent_tasks)) + vtr.StillRunningAfter = ts + + return tr + + +ExtendTest(AddConfigReload, name="AddConfigReload") diff --git a/tests/gold_tests/cache/cache_config_reload.test.py b/tests/gold_tests/cache/cache_config_reload.test.py index 21bb7998287..52ca11aad66 100644 --- a/tests/gold_tests/cache/cache_config_reload.test.py +++ b/tests/gold_tests/cache/cache_config_reload.test.py @@ -49,12 +49,8 @@ tr.Processes.Default.ReturnCode = 0 tr.StillRunningAfter = ts -tr = Test.AddTestRun("Reload after cache.config touch") -tr.Processes.Default.Env = ts.Env -tr.Processes.Default.Command = 'traffic_ctl config reload --show-details --token reload_cache_test' -tr.Processes.Default.ReturnCode = Any(0, 2) -tr.StillRunningAfter = ts -tr.Processes.Default.Streams.stdout = Testers.ContainsExpression("cache.config", "Reload output should reference cache.config") +tr = Test.AddConfigReload( + ts, expect="any", expect_tasks=["cache.config"], token="reload_cache_test", description="Reload after cache.config touch") # --- Test 2: Touch hosting.config and reload --- @@ -64,9 +60,5 @@ tr.Processes.Default.ReturnCode = 0 tr.StillRunningAfter = ts -tr = Test.AddTestRun("Reload after hosting.config touch") -tr.Processes.Default.Env = ts.Env -tr.Processes.Default.Command = 'traffic_ctl config reload --show-details --token reload_hosting_test' -tr.Processes.Default.ReturnCode = Any(0, 2) -tr.StillRunningAfter = ts -tr.Processes.Default.Streams.stdout = Testers.ContainsExpression("hosting.config", "Reload output should reference hosting.config") +tr = Test.AddConfigReload( + ts, expect="any", expect_tasks=["hosting.config"], token="reload_hosting_test", description="Reload after hosting.config touch") diff --git a/tests/gold_tests/dns/splitdns_reload.test.py b/tests/gold_tests/dns/splitdns_reload.test.py index aa058675305..0e254e0a179 100644 --- a/tests/gold_tests/dns/splitdns_reload.test.py +++ b/tests/gold_tests/dns/splitdns_reload.test.py @@ -73,17 +73,7 @@ def run(self): tr.Processes.Default.ReturnCode = 0 tr.StillRunningAfter = self.ts - tr = Test.AddTestRun("Reload after splitdns.config touch") - p = tr.Processes.Process("reload-1") - p.Command = 'traffic_ctl config reload; sleep 30' - p.Env = self.ts.Env - p.ReturnCode = Any(0, -2) - # Wait for 2nd "finished loading" (1st is startup) - p.Ready = When.FileContains(self.ts.Disk.diags_log.Name, "splitdns.config finished loading", 2) - p.Timeout = 20 - tr.Processes.Default.StartBefore(p) - tr.Processes.Default.Command = ('echo "waiting for splitdns.config reload"') - tr.TimeOut = 25 + tr = Test.AddConfigReload(self.ts, expect_tasks=["splitdns.config"], description="Reload after splitdns.config touch") tr.StillRunningAfter = self.ts diff --git a/tests/gold_tests/ip_allow/ip_allow_reload_triggered.test.py b/tests/gold_tests/ip_allow/ip_allow_reload_triggered.test.py index 3466e9de066..4a8195c0371 100644 --- a/tests/gold_tests/ip_allow/ip_allow_reload_triggered.test.py +++ b/tests/gold_tests/ip_allow/ip_allow_reload_triggered.test.py @@ -112,16 +112,7 @@ tr.StillRunningAfter = server reload_counter += 1 -tr = Test.AddTestRun("Reload after ip_allow.yaml touch") -p = tr.Processes.Process(f"reload-{reload_counter}") -p.Command = 'traffic_ctl config reload; sleep 30' -p.Env = ts.Env -p.ReturnCode = Any(0, -2) -p.Ready = When.FileContains(ts.Disk.diags_log.Name, "ip_allow.yaml finished loading", 1 + reload_counter) -p.Timeout = 20 -tr.Processes.Default.StartBefore(p) -tr.Processes.Default.Command = 'echo "waiting for ip_allow reload after ip_allow.yaml touch"' -tr.TimeOut = 25 +tr = Test.AddConfigReload(ts, expect_tasks=["ip_allow.yaml"], description="Reload after ip_allow.yaml touch") tr.StillRunningAfter = ts # ================================================================ @@ -136,16 +127,7 @@ tr.StillRunningAfter = ts reload_counter += 1 -tr = Test.AddTestRun("Reload after ip_categories touch") -p = tr.Processes.Process(f"reload-{reload_counter}") -p.Command = 'traffic_ctl config reload; sleep 30' -p.Env = ts.Env -p.ReturnCode = Any(0, -2) -p.Ready = When.FileContains(ts.Disk.diags_log.Name, "ip_allow.yaml finished loading", 1 + reload_counter) -p.Timeout = 20 -tr.Processes.Default.StartBefore(p) -tr.Processes.Default.Command = 'echo "waiting for ip_allow reload after ip_categories touch"' -tr.TimeOut = 25 +tr = Test.AddConfigReload(ts, expect_tasks=["ip_allow.yaml"], description="Reload after ip_categories touch") tr.StillRunningAfter = ts # ================================================================ @@ -156,24 +138,13 @@ # instead of ip_categories.yaml when the record was ""). # ================================================================ -tr = Test.AddTestRun("Touch hosting.config and reload (should NOT trigger ip_allow)") -tr.Processes.Default.Command = ( - f"touch {os.path.join(config_dir, 'hosting.config')} && " - f"sleep 1 && " - f"traffic_ctl config reload && " - f"sleep 5") -tr.Processes.Default.Env = ts.Env -tr.Processes.Default.ReturnCode = Any(0, -2) -tr.Processes.Default.Timeout = 15 -tr.StillRunningAfter = ts - -tr = Test.AddTestRun("Verify ip_allow loaded exactly 3 times (no false trigger)") -tr.DelayStart = 3 -tr.Processes.Default.Command = (f"grep -c 'ip_allow.yaml finished loading' {ts.Disk.diags_log.Name} " - f"| grep -qx 3") +tr = Test.AddTestRun("Touch hosting.config before reload") +tr.Processes.Default.Command = f"touch {os.path.join(config_dir, 'hosting.config')}" tr.Processes.Default.ReturnCode = 0 tr.StillRunningAfter = ts +tr = Test.AddConfigReload(ts, expect_absent_tasks=["ip_allow.yaml"], description="Reload (should NOT trigger ip_allow)") + # ================================================================ # Test 4: Functional — change ip_categories content, verify behavior # Proves that add_file_dependency() not only triggers the @@ -198,16 +169,7 @@ # 4c: Reload and wait for ip_allow to pick up the change reload_counter += 1 -tr = Test.AddTestRun("Reload after ip_categories content change") -p = tr.Processes.Process(f"reload-{reload_counter}") -p.Command = 'traffic_ctl config reload; sleep 30' -p.Env = ts.Env -p.ReturnCode = Any(0, -2) -p.Ready = When.FileContains(ts.Disk.diags_log.Name, "ip_allow.yaml finished loading", 1 + reload_counter) -p.Timeout = 20 -tr.Processes.Default.StartBefore(p) -tr.Processes.Default.Command = 'echo "waiting for reload after ip_categories content change"' -tr.TimeOut = 25 +tr = Test.AddConfigReload(ts, expect_tasks=["ip_allow.yaml"], description="Reload after ip_categories content change") tr.StillRunningAfter = ts # 4d: GET should now be denied (falls to catch-all: only HEAD allowed) diff --git a/tests/gold_tests/ip_allow/ip_category.test.py b/tests/gold_tests/ip_allow/ip_category.test.py index 20fd5c53422..e9067967a6b 100644 --- a/tests/gold_tests/ip_allow/ip_category.test.py +++ b/tests/gold_tests/ip_allow/ip_category.test.py @@ -197,21 +197,9 @@ def _configure_traffic_server(self) -> None: # Reload the ip_allow.yaml file. ts = Test_ip_category._ts - tr = Test.AddTestRun(f"Reload the configuration file.") Test_ip_category._reload_counter += 1 - p = tr.Processes.Process(f"reload-{Test_ip_category._reload_counter}") - # The sleep is added to give time for the reload to happen. - p.Command = 'traffic_ctl config reload; sleep 30' - p.Env = ts.Env - # Killing the sleep can result in a -2 return code. - p.ReturnCode = Any(0, -2) - p.Ready = When.FileContains( - ts.Disk.diags_log.Name, "ip_allow.yaml finished loading", 1 + Test_ip_category._reload_counter) - p.Timeout = 20 + tr = Test.AddConfigReload(ts, expect_tasks=["ip_allow.yaml"], description="Reload the configuration") tr.StillRunningAfter = ts - tr.Processes.Default.StartBefore(p) - tr.Processes.Default.Command = 'echo "waiting upon traffic server to reload"' - tr.TimeOut = 20 return ts = Test.MakeATSProcess("ts", enable_cache=False, enable_tls=True) diff --git a/tests/gold_tests/logging/log_retention.test.py b/tests/gold_tests/logging/log_retention.test.py index 8b21343d0e7..0743dd814e0 100644 --- a/tests/gold_tests/logging/log_retention.test.py +++ b/tests/gold_tests/logging/log_retention.test.py @@ -478,13 +478,7 @@ def get_command_to_rotate_thrice(self): test.tr.StillRunningAfter = test.ts test.tr.StillRunningAfter = test.server -tr = Test.AddTestRun("Perform a config reload") -tr.Processes.Default.Command = "traffic_ctl config reload" -tr.Processes.Default.Env = test.ts.Env -tr.Processes.Default.ReturnCode = 0 -tr.Processes.Default.TimeOut = 5 -tr.TimeOut = 5 -tr.StillRunningAfter = test.ts +tr = Test.AddConfigReload(test.ts, description="Perform a config reload") tr.StillRunningAfter = test.server tr = Test.AddTestRun("Get the log to rotate.") diff --git a/tests/gold_tests/parent_config/parent_config_reload.test.py b/tests/gold_tests/parent_config/parent_config_reload.test.py index acdf31a5cb4..5e71a82bfbd 100644 --- a/tests/gold_tests/parent_config/parent_config_reload.test.py +++ b/tests/gold_tests/parent_config/parent_config_reload.test.py @@ -50,17 +50,7 @@ tr.Processes.Default.ReturnCode = 0 tr.StillRunningAfter = ts -tr = Test.AddTestRun("Reload after parent.config touch") -p = tr.Processes.Process("reload-1") -p.Command = 'traffic_ctl config reload; sleep 30' -p.Env = ts.Env -p.ReturnCode = Any(0, -2) -# Wait for the 2nd "finished loading" (1st is startup) -p.Ready = When.FileContains(ts.Disk.diags_log.Name, "parent.config finished loading", 2) -p.Timeout = 20 -tr.Processes.Default.StartBefore(p) -tr.Processes.Default.Command = 'echo "waiting for parent.config reload after file touch"' -tr.TimeOut = 25 +tr = Test.AddConfigReload(ts, expect_tasks=["parent.config"], description="Reload after parent.config touch") tr.StillRunningAfter = ts # ================================================================ diff --git a/tests/gold_tests/pluginTest/regex_revalidate/regex_revalidate_miss.test.py b/tests/gold_tests/pluginTest/regex_revalidate/regex_revalidate_miss.test.py index 96ba108f14b..fb998209816 100644 --- a/tests/gold_tests/pluginTest/regex_revalidate/regex_revalidate_miss.test.py +++ b/tests/gold_tests/pluginTest/regex_revalidate/regex_revalidate_miss.test.py @@ -222,21 +222,19 @@ ps.Streams.stdout.Content = Testers.ContainsExpression("X-Cache: hit-fresh", "expected cache hit response") tr.StillRunningAfter = ts -# 12 Stage - Reload of same time updated rules file -tr = Test.AddTestRun("Reload same config") -ps = tr.Processes.Default +# 12 Stage - Touch the rules file to trigger reload detection +tr = Test.AddTestRun("Touch regex_revalidate config") +tr.Processes.Default.Command = f'touch {regex_revalidate_conf_path}' +tr.Processes.Default.ReturnCode = 0 tr.StillRunningAfter = ts tr.StillRunningAfter = server -ps.Command = f'touch {regex_revalidate_conf_path} ; traffic_ctl config reload' -ps.Env = ts.Env -ps.ReturnCode = 0 -ps.TimeOut = 5 -tr.TimeOut = 5 + +tr = Test.AddConfigReload(ts, description="Reload same config") +tr.StillRunningAfter = server # 13 Request, Cache hit expected tr = Test.AddTestRun("Cache hit path1") ps = tr.Processes.Default -tr.DelayStart = 5 tr.MakeCurlCommand(curl_and_args + ' http://ats/path1', ts=ts) ps.ReturnCode = 0 ps.Streams.stdout.Content = Testers.ContainsExpression("X-Cache: hit-fresh", "expected cache hit response") diff --git a/tests/gold_tests/remap/remap_acl.test.py b/tests/gold_tests/remap/remap_acl.test.py index 0f5b0f5f23e..33fef92e3ce 100644 --- a/tests/gold_tests/remap/remap_acl.test.py +++ b/tests/gold_tests/remap/remap_acl.test.py @@ -153,25 +153,10 @@ def _configure_traffic_server(self) -> int: remap_cfg_path, '\n'.join(remap_config_lines), ip_allow_path, '\n'.join(self._ip_allow_lines))) # - # Kick off the ATS config reload. + # Kick off the ATS config reload and await completion. # - tr = Test.AddTestRun("Reload the ATS configuration") - p = tr.Processes.Default - p.Command = 'traffic_ctl config reload' - p.Env = ts.Env - tr.StillRunningAfter = ts - - # - # Await the config reload to finish. - # - tr = Test.AddTestRun("Await config reload") - p = tr.Processes.Default Test_remap_acl._ts_reload_counter += 1 - count = 1 + Test_remap_acl._ts_reload_counter - condwait = os.path.join(Test.Variables.AtsTestToolsDir, 'condwait') - p.Command = (f"'{condwait}' 30 --contains '{ts.Disk.diags_log.Name}' " - f"'remap.config finished loading' {count}") - p.Env = ts.Env + tr = Test.AddConfigReload(ts, expect_tasks=["remap.config"], description="Reload the ATS configuration") tr.StillRunningAfter = ts else: diff --git a/tests/gold_tests/remap/remap_reload.test.py b/tests/gold_tests/remap/remap_reload.test.py index a0337fc9444..b49a1ab4e90 100644 --- a/tests/gold_tests/remap/remap_reload.test.py +++ b/tests/gold_tests/remap/remap_reload.test.py @@ -80,15 +80,10 @@ def update_remap_config(path: str, lines: list) -> None: f"map http://bravo.ex http://bravo.ex:{pv_port}", ])) -tr = Test.AddTestRun("remap_config reload, fails") -tr.Processes.Default.Env = tm.Env -tr.Processes.Default.Command = 'sleep 2; traffic_ctl config reload' +tr = Test.AddConfigReload(tm, expect="fail", expect_tasks=["remap.config"], delay_start=2, description="remap_config reload, fails") tr = Test.AddTestRun("after first reload") -await_config_reload = tr.Processes.Process('config_reload_failed', 'sleep 30') -await_config_reload.Ready = When.FileContains(tm.Disk.diags_log.Name, "configuration is invalid") tr.AddVerifierClientProcess("client_2", replay_file_2, http_ports=[tm.Variables.port]) -tr.Processes.Default.StartBefore(await_config_reload) tr = Test.AddTestRun("Change remap.config to have more than three lines") p = tr.Processes.Default @@ -104,14 +99,10 @@ def update_remap_config(path: str, lines: list) -> None: f"map http://india.ex http://india.ex:{pv_port}", ])) -tr = Test.AddTestRun("remap_config reload, succeeds") -tr.Processes.Default.Env = tm.Env -tr.Processes.Default.Command = 'sleep 2; traffic_ctl config reload' +tr = Test.AddConfigReload( + tm, expect="success", expect_tasks=["remap.config"], delay_start=2, description="remap_config reload, succeeds") tr = Test.AddTestRun("post update charlie") -await_config_reload = tr.Processes.Process('config_reload_succeeded', 'sleep 30') -await_config_reload.Ready = When.FileContains(tm.Disk.diags_log.Name, "remap.config finished loading", 2) -tr.Processes.Default.StartBefore(await_config_reload) tr.AddVerifierClientProcess("client_3", replay_file_3, http_ports=[tm.Variables.port]) tr = Test.AddTestRun("post update golf") diff --git a/tests/gold_tests/tls/ssl_key_dialog.test.py b/tests/gold_tests/tls/ssl_key_dialog.test.py index dd9438f371c..b22c3bb702c 100644 --- a/tests/gold_tests/tls/ssl_key_dialog.test.py +++ b/tests/gold_tests/tls/ssl_key_dialog.test.py @@ -76,22 +76,8 @@ tr2.Processes.Default.Env = ts.Env tr2.Processes.Default.ReturnCode = 0 -tr2reload = Test.AddTestRun("Reload config") -tr2reload.StillRunningAfter = ts +tr2reload = Test.AddConfigReload(ts, expect_tasks=["ssl_multicert.config"], description="Reload config") tr2reload.StillRunningAfter = server -tr2reload.Processes.Default.Command = 'traffic_ctl config reload' -# Need to copy over the environment so traffic_ctl knows where to find the unix domain socket -tr2reload.Processes.Default.Env = ts.Env -tr2reload.Processes.Default.ReturnCode = 0 - -tr2reload = Test.AddTestRun("Await config reload") -p = tr2reload.Processes.Default -p.Command = 'echo awaiting config reload' -p.Env = ts.Env -p.ReturnCode = 0 -await_config_reload = tr.Processes.Process(f'config_reload_succeeded', 'sleep 30') -await_config_reload.Ready = When.FileContains(ts.Disk.diags_log.Name, "ssl_multicert.config finished loading", 2) -p.StartBefore(await_config_reload) tr3 = Test.AddTestRun("use a key with passphrase") tr3.Setup.Copy("ssl/signer.pem") diff --git a/tests/gold_tests/tls/ssl_multicert_loader.test.py b/tests/gold_tests/tls/ssl_multicert_loader.test.py index 1dfce76b652..96e2655464d 100644 --- a/tests/gold_tests/tls/ssl_multicert_loader.test.py +++ b/tests/gold_tests/tls/ssl_multicert_loader.test.py @@ -20,7 +20,7 @@ sni_domain = 'example.com' -ts = Test.MakeATSProcess("ts", enable_tls=True) +ts = Test.MakeATSProcess("ts", enable_tls=True, disable_log_checks=True) server = Test.MakeOriginServer("server") server2 = Test.MakeOriginServer("server3") request_header = {"headers": f"GET / HTTP/1.1\r\nHost: {sni_domain}\r\n\r\n", "timestamp": "1469733493.993", "body": ""} @@ -68,19 +68,13 @@ tr2.Processes.Default.Env = ts.Env tr2.Processes.Default.ReturnCode = 0 -tr2reload = Test.AddTestRun("Reload config") -tr2reload.StillRunningAfter = ts +tr2reload = Test.AddConfigReload(ts, expect="fail", expect_tasks=["ssl_multicert.config"], description="Reload config") tr2reload.StillRunningAfter = server -tr2reload.Processes.Default.Command = 'traffic_ctl config reload' -tr2reload.Processes.Default.Env = ts.Env -tr2reload.Processes.Default.ReturnCode = 0 -ts.Disk.diags_log.Content = Testers.ContainsExpression('ERROR: ', 'ERROR') # Reload of ssl_multicert.config should fail, BUT the old config structure # should be in place to successfully answer for the test domain tr3 = Test.AddTestRun("Make request again for $sni_domain") -# Wait for the reload to complete -tr3.Processes.Default.StartBefore(server2, ready=When.FileContains(ts.Disk.diags_log.Name, 'failed to load certificate ', 1)) +tr3.Processes.Default.StartBefore(server2) tr3.StillRunningAfter = ts tr3.StillRunningAfter = server tr3.MakeCurlCommand( diff --git a/tests/gold_tests/tls/tls_check_cert_selection_reload.test.py b/tests/gold_tests/tls/tls_check_cert_selection_reload.test.py index 51d092a844e..ab72d600258 100644 --- a/tests/gold_tests/tls/tls_check_cert_selection_reload.test.py +++ b/tests/gold_tests/tls/tls_check_cert_selection_reload.test.py @@ -96,18 +96,11 @@ # Need to copy over the environment so traffic_ctl knows where to find the unix domain socket tr.Processes.Default.ReturnCode = 0 -tr = Test.AddTestRun("Reload config") -tr.StillRunningAfter = ts +tr = Test.AddConfigReload(ts, expect_tasks=["ssl_multicert.config"], description="Reload config") tr.StillRunningAfter = server -tr.Processes.Default.Command = 'traffic_ctl config reload' -# Need to copy over the environment so traffic_ctl knows where to find the unix domain socket -tr.Processes.Default.Env = ts.Env -tr.Processes.Default.ReturnCode = 0 tr = Test.AddTestRun("Try with signer 1 again") -# Wait for the reload to complete -tr.Processes.Default.StartBefore( - server3, ready=When.FileContains(ts.Disk.diags_log.Name, 'ssl_multicert.config finished loading', 2)) +tr.Processes.Default.StartBefore(server3) tr.StillRunningAfter = ts tr.StillRunningAfter = server tr.MakeCurlCommand( diff --git a/tests/gold_tests/tls/tls_client_cert.test.py b/tests/gold_tests/tls/tls_client_cert.test.py index c848c735faa..b7fb49a302b 100644 --- a/tests/gold_tests/tls/tls_client_cert.test.py +++ b/tests/gold_tests/tls/tls_client_cert.test.py @@ -182,19 +182,13 @@ tr2.Processes.Default.Env = ts.Env tr2.Processes.Default.ReturnCode = 0 -tr2reload = Test.AddTestRun("Reload config") -tr2reload.StillRunningAfter = ts +tr2reload = Test.AddConfigReload(ts, expect_tasks=["sni.yaml"], description="Reload config") tr2reload.StillRunningAfter = server tr2reload.StillRunningAfter = server2 -tr2reload.Processes.Default.Command = 'traffic_ctl config reload' -# Need to copy over the environment so traffic_ctl knows where to find the unix domain socket -tr2reload.Processes.Default.Env = ts.Env -tr2reload.Processes.Default.ReturnCode = 0 # Should succeed tr3bar = Test.AddTestRun("Make request with other bar cert to first server") -# Wait for the reload to complete -tr3bar.Processes.Default.StartBefore(server3, ready=When.FileContains(ts.Disk.diags_log.Name, 'sni.yaml finished loading', 2)) +tr3bar.Processes.Default.StartBefore(server3) tr3bar.StillRunningAfter = ts tr3bar.StillRunningAfter = server tr3bar.StillRunningAfter = server2 @@ -245,18 +239,12 @@ trupdate.Processes.Default.Env = ts.Env trupdate.Processes.Default.ReturnCode = 0 -trreload = Test.AddTestRun("Reload config after renaming certs") -trreload.StillRunningAfter = ts +trreload = Test.AddConfigReload(ts, expect_tasks=["sni.yaml"], description="Reload config after renaming certs") trreload.StillRunningAfter = server trreload.StillRunningAfter = server2 -trreload.Processes.Default.Command = 'traffic_ctl config reload' -trreload.Processes.Default.Env = ts.Env -trreload.Processes.Default.ReturnCode = 0 # Should succeed tr4bar = Test.AddTestRun("Make request with renamed bar cert to second server") -# Wait for the reload to complete -tr4bar.DelayStart = 10 tr4bar.StillRunningAfter = ts tr4bar.StillRunningAfter = server tr4bar.StillRunningAfter = server2 diff --git a/tests/gold_tests/tls/tls_client_cert_override_plugin.test.py b/tests/gold_tests/tls/tls_client_cert_override_plugin.test.py index c9af9e2cca3..88692fe8076 100644 --- a/tests/gold_tests/tls/tls_client_cert_override_plugin.test.py +++ b/tests/gold_tests/tls/tls_client_cert_override_plugin.test.py @@ -174,18 +174,12 @@ trupdate.Processes.Default.Env = ts.Env trupdate.Processes.Default.ReturnCode = 0 -tr2reload = Test.AddTestRun("Reload config") -tr2reload.StillRunningAfter = ts +tr2reload = Test.AddConfigReload(ts, expect_tasks=["sni.yaml"], description="Reload config") tr2reload.StillRunningAfter = server tr2reload.StillRunningAfter = server2 -tr2reload.Processes.Default.Command = 'traffic_ctl config reload' -# Need to copy over the environment so traffic_ctl knows where to find the unix domain socket -tr2reload.Processes.Default.Env = ts.Env -tr2reload.Processes.Default.ReturnCode = 0 tr3bar = Test.AddTestRun("Make request with other foo. badcase1 should now work") -# Wait for the reload to complete -tr3bar.Processes.Default.StartBefore(server3, ready=When.FileContains(ts.Disk.diags_log.Name, 'sni.yaml finished loading', 3)) +tr3bar.Processes.Default.StartBefore(server3) tr3bar.StillRunningAfter = ts tr3bar.StillRunningAfter = server tr3bar.StillRunningAfter = server2 diff --git a/tests/gold_tests/tls/tls_client_cert_plugin.test.py b/tests/gold_tests/tls/tls_client_cert_plugin.test.py index 3a8ef7776db..4d8fcfff857 100644 --- a/tests/gold_tests/tls/tls_client_cert_plugin.test.py +++ b/tests/gold_tests/tls/tls_client_cert_plugin.test.py @@ -179,19 +179,13 @@ tr2.Processes.Default.Env = ts.Env tr2.Processes.Default.ReturnCode = 0 -tr2reload = Test.AddTestRun("Reload config") -tr2reload.StillRunningAfter = ts +tr2reload = Test.AddConfigReload(ts, expect_tasks=["sni.yaml"], description="Reload config") tr2reload.StillRunningAfter = server tr2reload.StillRunningAfter = server2 -tr2reload.Processes.Default.Command = 'traffic_ctl config reload' -# Need to copy over the environment so traffic_ctl knows where to find the unix domain socket -tr2reload.Processes.Default.Env = ts.Env -tr2reload.Processes.Default.ReturnCode = 0 # Should succeed tr3bar = Test.AddTestRun("Make request with other bar cert to first server") -# Wait for the reload to complete -tr3bar.Processes.Default.StartBefore(server3, ready=When.FileContains(ts.Disk.diags_log.Name, 'sni.yaml finished loading', 2)) +tr3bar.Processes.Default.StartBefore(server3) tr3bar.StillRunningAfter = ts tr3bar.StillRunningAfter = server tr3bar.StillRunningAfter = server2 @@ -242,18 +236,12 @@ trupdate.Processes.Default.Env = ts.Env trupdate.Processes.Default.ReturnCode = 0 -trreload = Test.AddTestRun("Reload config after renaming certs") -trreload.StillRunningAfter = ts +trreload = Test.AddConfigReload(ts, expect_tasks=["sni.yaml"], description="Reload config after renaming certs") trreload.StillRunningAfter = server trreload.StillRunningAfter = server2 -trreload.Processes.Default.Command = 'traffic_ctl config reload' -trreload.Processes.Default.Env = ts.Env -trreload.Processes.Default.ReturnCode = 0 # Should succeed tr4bar = Test.AddTestRun("Make request with renamed bar cert to second server") -# Wait for the reload to complete -tr4bar.DelayStart = 10 tr4bar.StillRunningAfter = ts tr4bar.StillRunningAfter = server tr4bar.StillRunningAfter = server2 diff --git a/tests/gold_tests/tls/tls_sni_yaml_reload.test.py b/tests/gold_tests/tls/tls_sni_yaml_reload.test.py index 8e2e0b2772b..9cd1aef082c 100644 --- a/tests/gold_tests/tls/tls_sni_yaml_reload.test.py +++ b/tests/gold_tests/tls/tls_sni_yaml_reload.test.py @@ -20,7 +20,7 @@ sni_domain = 'example.com' -ts = Test.MakeATSProcess("ts", enable_tls=True) +ts = Test.MakeATSProcess("ts", enable_tls=True, disable_log_checks=True) server = Test.MakeOriginServer("server") server2 = Test.MakeOriginServer("server3") request_header = {"headers": f"GET / HTTP/1.1\r\nHost: {sni_domain}\r\n\r\n", "timestamp": "1469733493.993", "body": ""} @@ -72,8 +72,6 @@ tr.Processes.Default.ReturnCode = 0 tr.Processes.Default.Streams.stdout = Testers.ExcludesExpression("Could Not Connect", "Verify curl could successfully connect") tr.Processes.Default.Streams.stderr = Testers.IncludesExpression(f"CN={sni_domain}", f"Verify curl used the {sni_domain} SNI") -ts.Disk.diags_log.Content = Testers.IncludesExpression( - "SSL negotiation finished successfully", "Verify that the TLS handshake was successful") # This config reload should fail because it references non-existent TLS key files trupd = Test.AddTestRun("Update config file") @@ -96,20 +94,13 @@ trupd.Processes.Default.Env = ts.Env trupd.Processes.Default.ReturnCode = 0 -tr2reload = Test.AddTestRun("Reload config") -tr2reload.StillRunningAfter = ts +tr2reload = Test.AddConfigReload(ts, expect="fail", expect_tasks=["sni.yaml"], description="Reload config") tr2reload.StillRunningAfter = server -tr2reload.Processes.Default.Command = 'traffic_ctl config reload' -tr2reload.Processes.Default.Env = ts.Env -tr2reload.Processes.Default.ReturnCode = 0 -ts.Disk.diags_log.Content = Testers.ContainsExpression( - 'sni.yaml failed to load', 'reload should result in failure to load sni.yaml') tr3 = Test.AddTestRun(f"Make request again for {sni_domain} that should still work") -# Wait for the reload to complete tr3.Setup.Copy("ssl/signed-bar.pem") tr3.Setup.Copy("ssl/signed-bar.key") -tr3.Processes.Default.StartBefore(server2, ready=When.FileContains(ts.Disk.diags_log.Name, "signed-notexist.pem", 1)) +tr3.Processes.Default.StartBefore(server2) tr3.StillRunningAfter = ts tr3.StillRunningAfter = server tr3.MakeCurlCommand( diff --git a/tests/gold_tests/tls/tls_tunnel.test.py b/tests/gold_tests/tls/tls_tunnel.test.py index 251defe4c39..0ada379458f 100644 --- a/tests/gold_tests/tls/tls_tunnel.test.py +++ b/tests/gold_tests/tls/tls_tunnel.test.py @@ -353,21 +353,15 @@ p.Streams.All += Testers.ContainsExpression('data: 0', 'Verify that the first data packet was received.') p.Streams.All += Testers.ContainsExpression('data: 1', 'Verify that the second data packet was received.') -trreload = Test.AddTestRun("Reload config") -trreload.StillRunningAfter = ts +trreload = Test.AddConfigReload(ts, expect="success", expect_tasks=["sni.yaml"], description="Reload config") trreload.StillRunningAfter = server_foo trreload.StillRunningAfter = server_bar -trreload.Processes.Default.Command = 'traffic_ctl config reload' -# Need to copy over the environment so traffic_ctl knows where to find the unix domain socket -trreload.Processes.Default.Env = ts.Env -trreload.Processes.Default.ReturnCode = 0 # Should terminate on traffic_server (not tunnel) tr = Test.AddTestRun("foo.com no Tunnel-test") tr.TimeOut = 30 tr.StillRunningAfter = ts -# Wait for the reload to complete by running the sni_reload_done test -tr.Processes.Default.StartBefore(server2, ready=When.FileContains(ts.Disk.diags_log.Name, 'sni.yaml finished loading', 2)) +tr.Processes.Default.StartBefore(server2) tr.MakeCurlCommand("-v --resolve 'foo.com:{0}:127.0.0.1' -k https://foo.com:{0}".format(ts.Variables.ssl_port), ts=ts) tr.Processes.Default.Streams.All += Testers.ContainsExpression("Not Found on Accelerato", "Terminates on on Traffic Server") tr.Processes.Default.Streams.All += Testers.ContainsExpression("ATS", "Terminate on Traffic Server") diff --git a/tests/gold_tests/tls/tls_verify4.test.py b/tests/gold_tests/tls/tls_verify4.test.py index bab09093229..c82d279fe7e 100644 --- a/tests/gold_tests/tls/tls_verify4.test.py +++ b/tests/gold_tests/tls/tls_verify4.test.py @@ -128,15 +128,8 @@ tr2.Processes.Default.Env = ts.Env tr2.Processes.Default.ReturnCode = 0 -# Change the config to PERMISSIVE. Same command should work now -trreload = Test.AddTestRun("Reload config") -trreload.StillRunningAfter = ts +trreload = Test.AddConfigReload(ts, description="Reload config") trreload.StillRunningAfter = server -# takes a few seconds for the reload to be ready for the next connection -trreload.Processes.Default.Command = 'traffic_ctl config reload; sleep 5' -# Need to copy over the environment so traffic_ctl knows where to find the unix domain socket -trreload.Processes.Default.Env = ts.Env -trreload.Processes.Default.ReturnCode = 0 tragain = Test.AddTestRun("permissive-after-update") tragain.MakeCurlCommand("-k -H \"host: random3.com\" https://127.0.0.1:{0}".format(ts.Variables.ssl_port), ts=ts) @@ -172,14 +165,8 @@ tr2.Processes.Default.Env = ts.Env tr2.Processes.Default.ReturnCode = 0 -trreload = Test.AddTestRun("Reload config again") -trreload.StillRunningAfter = ts +trreload = Test.AddConfigReload(ts, description="Reload config to ENFORCED") trreload.StillRunningAfter = server -# takes a few seconds for the reload to be ready for the next connection -trreload.Processes.Default.Command = 'traffic_ctl config reload; sleep 5' -# Need to copy over the environment so traffic_ctl knows where to find the unix domain socket -trreload.Processes.Default.Env = ts.Env -trreload.Processes.Default.ReturnCode = 0 tragain = Test.AddTestRun("enforced-after-update") tragain.MakeCurlCommand("-k -H \"host: random4.com\" https://127.0.0.1:{0}".format(ts.Variables.ssl_port), ts=ts) diff --git a/tests/gold_tests/traffic_ctl/remap_inc/remap_inc.test.py b/tests/gold_tests/traffic_ctl/remap_inc/remap_inc.test.py index 52984a8ad6b..7e7824cb29e 100644 --- a/tests/gold_tests/traffic_ctl/remap_inc/remap_inc.test.py +++ b/tests/gold_tests/traffic_ctl/remap_inc/remap_inc.test.py @@ -14,16 +14,12 @@ # See the License for the specific language governing permissions and # limitations under the License. -import os - Test.Summary = ''' Test traffic_ctl config reload with remap.config .include directive ''' Test.ContinueOnFail = False -Test.Setup.Copy("wait_reload.sh") - # Define ATS and configure ts = Test.MakeATSProcess("ts", enable_cache=False) nameserver = Test.MakeDNServer("dns", default='127.0.0.1') @@ -53,16 +49,7 @@ tr.Processes.Default.ReturnCode = 0 tr.StillRunningAfter = ts -tr = Test.AddTestRun("Reload config") -tr.StillRunningAfter = ts -tr.Processes.Default.Command = f'traffic_ctl config reload' -# Need to copy over the environment so traffic_ctl knows where to find the unix domain socket -tr.Processes.Default.Env = ts.Env -tr.Processes.Default.ReturnCode = 0 - -tr = Test.AddTestRun("Wait for config reload") -tr.Processes.Default.Command = './wait_reload.sh ' + os.path.join(ts.Variables.LOGDIR, 'diags.log') -tr.Processes.Default.ReturnCode = 0 +tr = Test.AddConfigReload(ts, expect_tasks=["remap.config"], description="Reload remap.config") tr.StillRunningAfter = ts tr = Test.AddTestRun("Get response from generator") diff --git a/tests/gold_tests/traffic_ctl/remap_inc/wait_reload.sh b/tests/gold_tests/traffic_ctl/remap_inc/wait_reload.sh deleted file mode 100755 index e0ace41f878..00000000000 --- a/tests/gold_tests/traffic_ctl/remap_inc/wait_reload.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/bin/bash - -# 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. - -# Wait till remap.config finishes loading two times. - -WAIT=60 -LOG_FILE="$1" - -while (( WAIT > 0 )) -do - N=$( grep -F 'NOTE: remap.config finished loading' $LOG_FILE | wc -l ) - if [[ $N = 2 ]] ; then - exit 0 - fi - sleep 1 - let WAIT=WAIT-1 -done -echo TIMEOUT -exit 1