[TS API] Add plugin API for the config reload framework.#13146
Draft
brbzull0 wants to merge 5 commits intoapache:masterfrom
Draft
[TS API] Add plugin API for the config reload framework.#13146brbzull0 wants to merge 5 commits intoapache:masterfrom
brbzull0 wants to merge 5 commits intoapache:masterfrom
Conversation
added 5 commits
May 7, 2026 11:47
Expose the centralized config reload framework to plugins via a new TSCfg* C API so they can register configuration files alongside core ATS configs and participate in the reload status, RPC inline-YAML, and diagnostics machinery on equal footing. Public API (include/ts/ts.h, include/ts/apidefs.h.in): - TSCfgRegister(const TSCfgRegistrationInfo *) registers a plugin config with a TSCfgLoadCb handler. The plugin's canonical name is captured automatically from TSPluginRegister and surfaced in logs and traffic_ctl output. - TSCfgRegistrationInfo and TSCfgFileDependencyInfo option structs keep the API extensible without breaking source compatibility. - TSCfgAttachTrigger, TSCfgAddFileDependency, TSCfgSetEnabled cover reload triggers, file dependencies, and runtime enable/disable. TSCfgAddFileDependency supports operator-tunable filename via filename_record and inline-YAML routing via dep_key. - TSCfgLoadCtx handler-context API: InProgress / Complete / Fail for deferred completion, AddLog for severity-aware messages, AddSubtask for nested handlers, and getters for filename, reload token, the RPC-supplied YAML, and reload directives. - TSCfgLoadCb callback type and TSCfgSourceType enum. Core integration: - ConfigRegistry::register_plugin_config attributes plugin name to the entry; ConfigContext / ConfigReloadTrace propagate it through tasks and logs. - traffic_ctl config status renders plugin attribution and task trees with severity-prefixed log lines. - regex_revalidate migrated to the new API as the reference example. Tests: - cfg_plugin_test exercises every public API entrypoint. - cfg_plugin_deferred_test demonstrates two-stage deferred completion via scheduled continuations on ET_TASK. - cfg_plugin_directives_test covers _reload directive routing. - New autests: config_reload_plugin_api, config_reload_deferred, config_reload_directives_plugin, config_reload_ssl_bulk, config_reload_ssl_state. Documentation: - doc/developer-guide/api/functions/TSCfgRegister.en.rst consolidates the reference for TSCfgRegister and TSCfgLoadCtx. - doc/developer-guide/config-reload-framework.en.rst gains a Plugin Configuration Reload section with example, lifecycle, and traffic_ctl status output. Ref: apache#12967
Contributor
There was a problem hiding this comment.
Pull request overview
This PR exposes the existing config-reload framework (ConfigRegistry/ConfigContext/ReloadCoordinator) to global plugins via a new TSCfg* API, allowing plugin-owned config reloads to participate in the same reload lifecycle, status tracking, and JSONRPC/YAML payload flow as core configs.
Changes:
- Introduces a plugin-facing registration + per-reload context API (
TSCfgRegister, triggers/deps, andTSCfgLoadCtx*functions). - Propagates plugin ownership into reload task metadata and
traffic_ctl config statusoutput ([plugin: <name>]andmeta.plugin_name). - Adds gold tests and unit tests covering plugin reload behavior, directives separation, deferred completion, and SSL reload status propagation.
Reviewed changes
Copilot reviewed 26 out of 26 changed files in this pull request and generated 6 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/gold_tests/jsonrpc/plugins/CMakeLists.txt | Adds new autest plugins for exercising TSCfg*. |
| tests/gold_tests/jsonrpc/plugins/cfg_plugin_test.cc | Test plugin covering core TSCfg* APIs and subtask logging. |
| tests/gold_tests/jsonrpc/plugins/cfg_plugin_deferred_test.cc | Test plugin demonstrating deferred completion contract. |
| tests/gold_tests/jsonrpc/plugins/cfg_plugin_directives_test.cc | Test plugin validating _reload directive extraction vs content. |
| tests/gold_tests/jsonrpc/config_reload_ssl_state.test.py | New gold test validating SSL reload status propagation and severity tags. |
| tests/gold_tests/jsonrpc/config_reload_ssl_bulk.test.py | New gold test exercising bulk SSL reload status detail and partial failure. |
| tests/gold_tests/jsonrpc/config_reload_plugin_api.test.py | End-to-end gold test for the new plugin API and status output. |
| tests/gold_tests/jsonrpc/config_reload_directives_plugin.test.py | Gold test validating directive delivery via plugin API. |
| tests/gold_tests/jsonrpc/config_reload_deferred.test.py | Gold test validating deferred plugin completion within a full reload. |
| src/traffic_ctl/jsonrpc/CtrlRPCRequests.h | Adds plugin_name to reload task metadata in the client model. |
| src/traffic_ctl/jsonrpc/ctrl_yaml_codecs.h | Decodes meta.plugin_name from YAML into the traffic_ctl model. |
| src/traffic_ctl/CtrlPrinters.cc | Prints plugin ownership tag in task tree output. |
| src/records/unit_tests/test_ConfigRegistry.cc | Adds unit coverage for plugin registration plumbing + dependency collision behavior. |
| src/mgmt/config/FileManager.cc | Routes file mtime updates for plugin registry keys directly into ConfigRegistry reload scheduling. |
| src/mgmt/config/ConfigRegistry.cc | Adds plugin registration entrypoint, directive extraction helper, and plugin name propagation into contexts/tasks. |
| src/mgmt/config/ConfigContext.cc | Adds get_reload_token() and plugin name setter forwarding into task info. |
| src/api/InkAPI.cc | Implements the TSCfg* plugin API layer and TSCfgLoadCtx wrapper semantics. |
| plugins/regex_revalidate/regex_revalidate.cc | Migrates plugin reload integration from TSMgmtUpdateRegister to TSCfgRegister. |
| include/ts/ts.h | Public API declarations and detailed doxygen for TSCfg*. |
| include/ts/apidefs.h.in | Adds new plugin API types/enums and option structs for ABI-stable registration. |
| include/records/YAMLConfigReloadTaskEncoder.h | Encodes plugin_name into JSONRPC YAML task metadata. |
| include/mgmt/config/ConfigReloadTrace.h | Adds plugin_name to reload task info and setter. |
| include/mgmt/config/ConfigRegistry.h | Adds plugin registration API and _reload extraction helper declaration. |
| include/mgmt/config/ConfigContext.h | Adds reload-token getter and plugin-name propagation hook. |
| doc/developer-guide/config-reload-framework.en.rst | Documents plugin participation and traffic_ctl ownership tagging. |
| doc/developer-guide/api/functions/TSCfgRegister.en.rst | New reference page for TSCfgRegister and the TSCfgLoadCtx* family. |
Comment on lines
+489
to
+497
| if (passed_config.IsMap() && passed_config["_reload"]) { | ||
| auto directives = passed_config["_reload"]; | ||
| if (!directives.IsMap()) { | ||
| Warning("Config '%.*s': _reload must be a YAML map, ignoring directives", static_cast<int>(key.size()), key.data()); | ||
| } else { | ||
| Dbg(dbg_ctl, "Config '%.*s' has reload directives", static_cast<int>(key.size()), key.data()); | ||
| ctx.set_reload_directives(directives); | ||
| } | ||
| passed_config.remove("_reload"); |
Comment on lines
+230
to
+232
| ``TSPluginInit``, before ``TSPluginRegister``, with a null or | ||
| incomplete ``info`` struct, or if another plugin (or core) has | ||
| already registered the same key. |
Comment on lines
+129
to
+134
| tr.Processes.Default.Streams.stdout = All( | ||
| Testers.IncludesExpression('[plugin]', 'Plugin task should have [plugin] tag'), | ||
| Testers.IncludesExpression('greet=world', 'Should show greeting in status'), | ||
| Testers.IncludesExpression('success', 'Should show success'), | ||
| Testers.IncludesExpression('handler entered', 'TSCfgLoadCtxAddLog message should appear'), | ||
| ) |
| tr.Processes.Default.Env = ts.Env | ||
| tr.Processes.Default.ReturnCode = 0 | ||
| tr.Processes.Default.Streams.stdout = All( | ||
| Testers.IncludesExpression('[plugin]', 'Failed task should have [plugin] tag'), |
| Testers.IncludesExpression('directive_version=2.0', 'Plugin should see version directive'), | ||
| Testers.IncludesExpression('content_greeting=hello_directives', 'Plugin should see greeting in content'), | ||
| Testers.IncludesExpression('success', 'Should complete successfully'), | ||
| Testers.IncludesExpression('[plugin]', 'Should have plugin tag'), |
Comment on lines
+592
to
+599
| config_reload(TSCfgLoadCtx ctx, void *data) | ||
| { | ||
| auto *pstate = static_cast<plugin_state_t *>(data); | ||
|
|
||
| Dbg(dbg_ctl, "Config reload via ConfigRegistry"); | ||
| bool const updated = do_config_reload(pstate); | ||
| TSCfgLoadCtxComplete(ctx, updated ? "regex_revalidate config reloaded" : "regex_revalidate config unchanged"); | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds a small
TSCfg*plugin-facing API that lets plugins registerconfiguration files with the same reload framework core configs
already use (
ConfigRegistry/ConfigContext). Plugin reloads thensurface in
traffic_ctl config statuswith full state tracking,can receive RPC payloads, and follow the deferred-completion
contract - none of which were available via
TSMgmtUpdateRegister.Motivation
Today, plugins react to
traffic_ctl config reloadonly viaTSMgmtUpdateRegister. That gives them a notification but nothingelse: no per-key targeting, no payload, no
_reloaddirectives,no companion files, no way to surface reload outcome in
config status. Every plugin that wants config-reload behaviour ends upre-implementing pieces of the framework -
regex_revalidate, forexample, ships its own file-mtime watcher.
This PR exposes the framework directly so plugins integrate with
it instead of re-implementing it.
New API surface
Types & enums (in
include/ts/apidefs.h.in)TSCfgLoadCtx— opaque per-reload handle.TSCfgLoadCb— plugin reload callback signature.TSCfgSourceType—FILE_ONLY/FILE_AND_RPC.TSCfgLogLevel—NOTE/WARNING/ERROR.TSCfgRegistrationInfo— option struct forTSCfgRegister.TSCfgFileDependencyInfo— option struct forTSCfgAddFileDependency.TSYaml— opaque alias forYAML::Node*(pre-existing JSONRPC type, reused).Registration (called from
TSPluginInit)TSCfgRegisterts.h:1285InkAPI.cc:3335TSCfgAttachReloadTriggerts.h:1330InkAPI.cc:3409TSCfgAddFileDependencyts.h:1347InkAPI.cc:3435Per-reload context (used inside the plugin's
TSCfgLoadCb)TSCfgLoadCtxInProgressts.h:1371InkAPI.cc:3519TSCfgLoadCtxCompletets.h:1384InkAPI.cc:3535TSCfgLoadCtxFailts.h:1397InkAPI.cc:3541TSCfgLoadCtxAddLogts.h:1412InkAPI.cc:3547TSCfgLoadCtxAddSubtaskts.h:1427InkAPI.cc:3572TSCfgLoadCtxGetFilenamets.h:1460InkAPI.cc:3596TSCfgLoadCtxGetReloadTokents.h:1476InkAPI.cc:3608TSCfgLoadCtxGetSuppliedYamlts.h:1490InkAPI.cc:3620TSCfgLoadCtxGetReloadDirectivests.h:1503InkAPI.cc:3636What this gives plugins, on top of
TSMgmtUpdateRegisterregistered file or trigger record actually changes.
TS_CFG_SOURCE_FILE_AND_RPCreceive YAML content via JSONRPC and react to
_reloaddirectives.log entries appear in
traffic_ctl config statusforconfig reload, file changes, and record changes during a reload cycle.aggregate into the parent's status.
TSCfgAddFileDependencydeclares an extrafile whose changes invoke the same handler, optionally routing
inline RPC content via
dep_key.and finish on another thread later. Same contract core handlers
already have.
Limitations
TSRemapInit/TSRemapNewInstance); the reload framework is centred on globalplugins.
is_requiredis propagated toFileManagerbut not enforced atreload time today (catalog/inspection only).
TSCfgAttachReloadTriggeris not a free-form record-changesubscription; it triggers a reload of the registered config and
nothing else.
Documentation
doc/developer-guide/api/functions/TSCfgRegister.en.rstconsolidates
TSCfgRegister,TSCfgAttachReloadTrigger,TSCfgAddFileDependency, and the fullTSCfgLoadCtx*family.doc/developer-guide/config-reload-framework.en.rstcovering plugin reload, with example, lifecycle, and
traffic_ctl config statusoutput.Fixes: #12967