Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
379 changes: 374 additions & 5 deletions doc/appendices/command-line/traffic_ctl.en.rst

Large diffs are not rendered by default.

708 changes: 708 additions & 0 deletions doc/developer-guide/config-reload-framework.en.rst

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions doc/developer-guide/index.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ duplicate bugs is encouraged, but not required.
plugins/index.en
cripts/index.en
config-vars.en
config-reload-framework.en
api/index.en
continuous-integration/index.en
documentation/index.en
Expand Down
305 changes: 296 additions & 9 deletions doc/developer-guide/jsonrpc/jsonrpc-api.en.rst
Original file line number Diff line number Diff line change
Expand Up @@ -922,27 +922,67 @@ admin_config_reload
Description
~~~~~~~~~~~

Instruct |TS| to start the reloading process. You can find more information about config reload here(add link TBC)
Initiate a configuration reload. This method returns immediately — the actual reload runs
asynchronously on background threads (``ET_TASK``). The response contains a **token** that the
caller uses to track the reload's progress and query its final status via
:ref:`get_reload_config_status`.

This method supports two modes:

- **File-based reload** (default) — re-reads all registered configuration files from disk and invokes
their handlers for any files whose modification time has changed.
- **Inline reload** — when the ``configs`` parameter is present, the supplied YAML content is passed
directly to the targeted handler(s) at runtime. Inline content is **not persisted to disk** — a
server restart will revert to the file-based configuration.

Each reload is assigned a **token** that can be used to query its status via
:ref:`get_reload_config_status`. If no token is provided, the server generates one automatically.

Only one reload can be active at a time. If a reload is already in progress, the request is rejected
unless ``force`` is set to ``true``.

For more information about the configuration reload framework, see
:ref:`config-reload-framework`.


Parameters
~~~~~~~~~~

* ``params``: Omitted
All parameters are optional.

.. note::
=================== ============= ================================================================================================================
Field Type Description
=================== ============= ================================================================================================================
``token`` |str| Custom token for this reload. Must be unique. If omitted, the server generates one (e.g. ``rldtk-<timestamp>``).
``force`` ``bool`` Force a new reload even if one is in progress. Default: ``false``. Use with caution.
``configs`` ``object`` YAML content for inline reload. Each key is a registry key (e.g. ``ip_allow``, ``sni``), and each value is the
full configuration content for that handler. When present, triggers an inline reload instead of a file-based one.
=================== ============= ================================================================================================================

There is no need to add any parameters here.

Result
~~~~~~

A |str| with the success message indicating that the command was acknowledged by the server.
On success, the response contains:

=================== ============= ================================================================================================================
Field Type Description
=================== ============= ================================================================================================================
``token`` |str| The token assigned to this reload (server-generated or the one provided in the request).
``message`` ``array`` Human-readable status messages.
``created_time`` |str| Timestamp when the reload task was created.
=================== ============= ================================================================================================================

If a reload is already in progress (and ``force`` is not set), the response includes an ``errors`` array
with code ``RELOAD_IN_PROGRESS`` and the ``tasks`` array with the current reload's status.


Examples
~~~~~~~~


**File-based reload (default):**

Request:

.. code-block:: json
Expand All @@ -951,18 +991,265 @@ Request:
{
"id": "89fc5aea-0740-11eb-82c0-001fc69cc946",
"jsonrpc": "2.0",
"method": "admin_config_reload"
"method": "admin_config_reload",
"params": {
"token": "deploy-v2.1"
}
}


Response:

The response will contain the default `success_response` or a proper rpc error, check :ref:`jsonrpc-node-errors` for mode details.
.. code-block:: json
:linenos:

{
"jsonrpc": "2.0",
"result": {
"token": "deploy-v2.1",
"message": ["Reload task scheduled"],
"created_time": "2025 Feb 17 12:00:00"
},
"id": "89fc5aea-0740-11eb-82c0-001fc69cc946"
}


**Inline reload (with ``configs``):**

The ``configs`` parameter is a map where each key is a **registry key** (e.g. ``ip_allow``, ``sni``)
and each value is the **config content** — the inner data, not the full file structure. For example,
``ip_allow.yaml`` on disk wraps rules under an ``ip_allow:`` top-level key, but when injecting via
RPC, you pass the rules array directly. The handler receives this content via
``ctx.supplied_yaml()`` and is responsible for using it without the file's wrapper key.

Request:

.. code-block:: json
:linenos:

{
"id": "b1c2d3e4-0001-0001-0001-000000000001",
"jsonrpc": "2.0",
"method": "admin_config_reload",
"params": {
"token": "update-ip-and-sni",
"configs": {
"ip_allow": [
{
"apply": "in",
"ip_addrs": "0.0.0.0/0",
"action": "allow",
"methods": "ALL"
}
],
"sni": [
{
"fqdn": "*.example.com",
"verify_client": "NONE"
}
]
}
}
}

Response:

.. code-block:: json
:linenos:

{
"jsonrpc": "2.0",
"result": {
"token": "update-ip-and-sni",
"message": ["Inline reload scheduled"],
"created_time": "2025 Feb 17 14:30:10"
},
"id": "b1c2d3e4-0001-0001-0001-000000000001"
}

.. note::

Inline reload requires the target config handler to support ``ConfigSource::FileAndRpc``.
Handlers that only support ``ConfigSource::FileOnly`` will return an error for the
corresponding key.


Validation:
**Reload already in progress:**

.. code-block:: json
:linenos:

{
"jsonrpc": "2.0",
"result": {
"errors": [
{
"message": "Reload ongoing with token 'deploy-v2.1'",
"code": 1
}
],
"tasks": []
},
"id": "89fc5aea-0740-11eb-82c0-001fc69cc946"
}


.. _get_reload_config_status:

get_reload_config_status
------------------------

|method|

Description
~~~~~~~~~~~

You can request for the record `proxy.process.proxy.reconfigure_time` which will be updated with the time of the requested update.
Query the status of configuration reloads. Can retrieve a specific reload by token, or the last
``N`` reloads from the history.

Each reload status includes an overall result, a task tree with per-handler status, durations,
and optional log messages.


Parameters
~~~~~~~~~~

All parameters are optional. If neither is provided, returns the most recent reload.

=================== ============= ================================================================================================================
Field Type Description
=================== ============= ================================================================================================================
``token`` |str| Token of the reload to query. Takes precedence over ``count`` if both are provided.
``count`` ``number`` Number of recent reloads to return. Use ``0`` to return the full history. Default: ``1``.
=================== ============= ================================================================================================================

``traffic_ctl`` maps ``--count all`` to ``count: 0`` in the RPC request. The server keeps a
rolling history of the last 100 reloads — when the limit is reached, the oldest entry is evicted
to make room for new ones. ``count: 0`` returns the full history, most recent first.


Result
~~~~~~

The response contains a ``tasks`` array. Each element represents a reload operation with the following
structure:

======================= ============= ===================================================================
Field Type Description
======================= ============= ===================================================================
``config_token`` |str| The reload token.
``status`` |str| Overall status: ``success``, ``fail``, ``in_progress``, ``timeout``.
``description`` |str| Human-readable description.
``config_key`` |str| Registry key used for deduplication (empty for main tasks).
``filename`` |str| Associated filename (empty for the main task).
``meta`` ``object`` Metadata: ``created_time_ms``, ``last_updated_time_ms``, ``main_task``.
``log`` ``array`` Log messages from the handler.
``sub_tasks`` ``array`` Nested sub-tasks (same structure, recursive).
======================= ============= ===================================================================


Examples
~~~~~~~~


**Query a specific reload by token:**

Request:

.. code-block:: json
:linenos:

{
"id": "f1e2d3c4-0001-0001-0001-000000000001",
"jsonrpc": "2.0",
"method": "get_reload_config_status",
"params": {
"token": "deploy-v2.1"
}
}

Response:

.. code-block:: json
:linenos:

{
"jsonrpc": "2.0",
"result": {
"tasks": [
{
"config_token": "deploy-v2.1",
"status": "success",
"description": "Main reload task - 2025 Feb 17 12:00:00",
"config_key": "",
"filename": "",
"meta": {
"created_time_ms": "1739808000123",
"last_updated_time_ms": "1739808000368",
"main_task": "true"
},
"log": [],
"sub_tasks": [
{
"config_token": "deploy-v2.1",
"status": "success",
"description": "ip_allow",
"config_key": "ip_allow",
"filename": "/opt/ats/etc/trafficserver/ip_allow.yaml",
"meta": {
"created_time_ms": "1739808000200",
"last_updated_time_ms": "1739808000218",
"main_task": "false"
},
"log": [],
"logs": ["Finished loading"],
"sub_tasks": []
}
]
}
]
},
"id": "f1e2d3c4-0001-0001-0001-000000000001"
}


**Query reload history (last 3):**

Request:

.. code-block:: json
:linenos:

{
"id": "a1b2c3d4-0001-0001-0001-000000000002",
"jsonrpc": "2.0",
"method": "get_reload_config_status",
"params": {
"count": 3
}
}

Response contains up to 3 entries in the ``tasks`` array.


**Token not found:**

.. code-block:: json
:linenos:

{
"jsonrpc": "2.0",
"result": {
"errors": [
{
"message": "Token 'nonexistent' not found",
"code": 4
}
],
"token": "nonexistent"
},
"id": "f1e2d3c4-0001-0001-0001-000000000001"
}


Host
Expand Down
7 changes: 3 additions & 4 deletions include/iocore/dns/SplitDNSProcessor.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,14 +46,13 @@ struct SplitDNSConfig {

static bool isSplitDNSEnabled();

static void reconfigure();
static void reconfigure(ConfigContext ctx = {});
static SplitDNS *acquire();
static void release(SplitDNS *params);
static void print();

static int m_id;
static Ptr<ProxyMutex> dnsHandler_mutex;
static ConfigUpdateHandler<SplitDNSConfig> *splitDNSUpdate;
static int m_id;
static Ptr<ProxyMutex> dnsHandler_mutex;

static int gsplit_dns_enabled;
};
Loading