Skip to content

plugin.config to plugin.yaml migration. - #13070

Merged
brbzull0 merged 2 commits into
apache:masterfrom
brbzull0:plugin-yaml-migration
Apr 15, 2026
Merged

plugin.config to plugin.yaml migration. #13070
brbzull0 merged 2 commits into
apache:masterfrom
brbzull0:plugin-yaml-migration

Conversation

@brbzull0

@brbzull0 brbzull0 commented Apr 8, 2026

Copy link
Copy Markdown
Contributor

Migration from plugin.config to plugin.yaml. When both files exist, plugin.yaml takes precedence; plugin.config is used as a fallback.


New??? capabilities over plugin.config:

  • enabled: false — replaces the old practice of commenting out lines in plugin.config to disable a plugin. In YAML, commenting out a multi-line plugin entry (path, params, etc) is more cumbersome than commenting a single line in the old format. With enabled: false the entire entry stays in the file for visibility and easy re-enabling, but the plugin is completely skipped at startup (no dlopen, no TSPluginInit).

  • load_order — optional integer that controls plugin loading priority. By default, plugins load top-to-bottom in YAML sequence order (same as plugin.config). When load_order is set, those plugins load first sorted by ascending value; plugins sharing the same value keep their relative file order (stable sort). Plugins without load_order load after all ordered ones. Most deployments won't need this — reordering a single line in plugin.config was trivial, but moving a multi-line YAML block is more error-prone, so load_order exists to let you change loading priority without rearranging entries. Useful for quick testing and troubleshooting, or when automation tools may reorder entries.

  • params — YAML sequence of string arguments with $record variable expansion

  • Startup logging — each plugin produces a NOTE-level log line with its index, path, and load/skip status:

    [NOTE] plugin.yaml loading ...
    [NOTE] plugin #1 loading: stats_over_http.so
    [NOTE] plugin #2 loading: header_rewrite.so (load_order: 10)
    [NOTE] plugin #3 skipped: experimental_plugin.so (enabled: false)
    [NOTE] plugin.yaml: 2 plugins loaded, 1 disabled
    [NOTE]   #1 stats_over_http.so                            loaded
    [NOTE]   #2 header_rewrite.so            load_order: 10   loaded
    [NOTE]   -- experimental_plugin.so                        disabled
    
  • traffic_ctl plugin list — new JSONRPC-based CLI command for runtime introspection of loaded plugins:

    $ traffic_ctl plugin list
    source: plugin.yaml
      #  plugin                          load_order   status
     1  stats_over_http.so                --           loaded
     2  header_rewrite.so                 10           loaded
     3  experimental_plugin.so            --           disabled
    
  • traffic_ctl config convert plugin_config — automated migration tool that converts plugin.config to plugin.yaml; commented-out lines become enabled: false entries (use --skip-disabled to omit them entirely)

Example

plugins:
  - path: stats_over_http.so

  - path: header_rewrite.so
    params:
      - etc/trafficserver/header_rewrite.config

  - path: experimental_plugin.so
    enabled: false       # was commented out in plugin.config
    params:
      - --verbose

Feedback requested: Inline config field

I take the liberty to add this feature to this PR, a config field that allows embedding a plugin's configuration directly in plugin.yaml instead of maintaining a separate file. This is intended for quick tests and simple configs where a standalone file is overkill.

How it works

The config field accepts a YAML block scalar (|). At startup the literal text is written to a temporary file in the config directory (named .<plugin_name>_inline_<index>.conf) and the path is passed to the plugin as an argument. Existing plugins work without code changes — they receive a file path in argv just as they do today.

The inline config file path is inserted as a bare positional argument at argv[1], before any params entries. This works for the common convention where plugins take a config file as their first argument (e.g., header_rewrite.so, txn_box.so). Plugins that require a flag before the filename (e.g., --config <file>) should use params with a separate file instead.

Why block scalar only

Only literal block scalars (|) are accepted. Structured YAML (mappings, sequences) is rejected. The reason: re-serializing structured YAML through YAML::Emitter loses quoting semantics. Plugins like txn_box assign meaning to YAML quoting (e.g., "literal" vs extractor-name), and round-tripping through an emitter strips those quotes. A block scalar preserves the exact text the operator wrote.

Example

plugins:
  - path: header_rewrite.so
    config: |
      cond %{SEND_RESPONSE_HDR_HOOK}
        set-header X-Custom "hello"

  - path: txn_box.so
    config: |
      txn_box:
        when: proxy-rsp
        do:
          - proxy-rsp-field<X-TxnBox>: "inline-config-active"

Notes

  • The block scalar restriction is intentional for now — re-serializing structured YAML through YAML::Emitter strips quoting that plugins like txn_box rely on. Supporting structured YAML can be revisited if needed.
  • Temporary inline config files are cleaned up at startup before new ones are created (matching the PluginFactory::cleanup() pattern). This handles both graceful shutdowns and crashes.

Part of #12753

Introduce plugin.yaml, a YAML-based configuration file for global
plugins that replaces the legacy line-based plugin.config format.

New capabilities over plugin.config:
- enabled: false to disable plugins without removing them
- load_order for explicit plugin loading priority
- NOTE-level startup log per plugin with load status
- traffic_ctl plugin list via JSONRPC for runtime introspection
- traffic_ctl config convert plugin_config for automated migration
- Fallback: plugin.yaml takes precedence; plugin.config used if absent
@brbzull0 brbzull0 self-assigned this Apr 8, 2026
@brbzull0 brbzull0 added Plugins YAML Configuration traffic_ctl traffic_ctl related work. Feedback Needed Request people to provide feedback. labels Apr 8, 2026
@brbzull0
brbzull0 force-pushed the plugin-yaml-migration branch from 7212d08 to 61c1493 Compare April 8, 2026 10:33
@brbzull0
brbzull0 marked this pull request as ready for review April 8, 2026 11:39
@brbzull0 brbzull0 added this to the 11.0.0 milestone Apr 8, 2026
@masaori335
masaori335 requested review from Copilot and masaori335 April 8, 2026 22:35

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR migrates global plugin configuration from the legacy plugin.config format to a new plugin.yaml format (with plugin.yaml taking precedence when both exist), adds runtime introspection via traffic_ctl plugin list, and provides a traffic_ctl conversion tool to assist with migration.

Changes:

  • Implement plugin.yaml parsing/loading (enabled/disabled entries, load_order, inline config, startup logging) with fallback to plugin.config.
  • Add traffic_ctl config convert plugin_config and gold tests for conversion output.
  • Add JSONRPC plumbing + traffic_ctl plugin list for reporting loaded/disabled plugins, plus documentation and unit/integration tests.

Reviewed changes

Copilot reviewed 34 out of 34 changed files in this pull request and generated 12 comments.

Show a summary per file
File Description
tests/gold_tests/traffic_ctl/convert_plugin_config/legacy_config/basic.config Legacy input fixture for converter gold tests.
tests/gold_tests/traffic_ctl/convert_plugin_config/legacy_config/commented.config Legacy input fixture covering commented-out plugins.
tests/gold_tests/traffic_ctl/convert_plugin_config/legacy_config/quoted.config Legacy input fixture covering quoted args.
tests/gold_tests/traffic_ctl/convert_plugin_config/gold/basic.yaml Expected YAML output for basic conversion.
tests/gold_tests/traffic_ctl/convert_plugin_config/gold/commented.yaml Expected YAML output including enabled: false for commented lines.
tests/gold_tests/traffic_ctl/convert_plugin_config/gold/quoted.yaml Expected YAML output for quoted-arg conversion.
tests/gold_tests/traffic_ctl/convert_plugin_config/gold/skip_disabled.yaml Expected YAML output when --skip-disabled is used.
tests/gold_tests/traffic_ctl/convert_plugin_config/convert_plugin_config.test.py Gold test runner for traffic_ctl config convert plugin_config.
tests/gold_tests/pluginTest/plugin_yaml/plugin_yaml.test.py Integration coverage for plugin.yaml precedence, inline config, and enabled: false.
src/traffic_server/traffic_server.cc Switch startup/verify paths to call plugin_yaml_init() and adjust messaging.
src/traffic_server/RpcAdminPubHandlers.cc Register new JSONRPC handler for plugin listing.
src/mgmt/rpc/handlers/plugins/Plugins.cc Implement admin_plugin_get_list JSONRPC handler.
src/traffic_ctl/traffic_ctl.cc Add traffic_ctl config convert plugin_config and traffic_ctl plugin list commands.
src/traffic_ctl/CtrlCommands.h Wire plugin list subcommand into CLI command class.
src/traffic_ctl/CtrlCommands.cc Implement traffic_ctl plugin list output formatting.
src/traffic_ctl/jsonrpc/CtrlRPCRequests.h Add request/response structs for plugin list RPC.
src/traffic_ctl/jsonrpc/ctrl_yaml_codecs.h Add YAML codec to decode plugin list response.
src/traffic_ctl/ConvertConfigCommand.h Add plugin_config conversion entry point + --skip-disabled flag storage.
src/traffic_ctl/ConvertConfigCommand.cc Implement plugin.config → plugin.yaml conversion flow.
src/proxy/Plugin.cc Add plugin.yaml parsing/loading, inline-config temp file support, and load summary tracking.
include/proxy/Plugin.h Expose plugin_yaml_init, parse_plugin_yaml, and plugin load summary types/accessor.
include/tscore/Filenames.h Add PLUGIN_YAML filename constant.
include/mgmt/rpc/handlers/plugins/Plugins.h Declare new get_plugin_list handler.
src/config/plugin_config.cc Add legacy plugin.config parser + YAML marshaller for the converter tool.
include/config/plugin_config.h Public header for legacy plugin.config parse/marshal support.
src/config/unit_tests/test_plugin_config.cc Unit tests for legacy plugin.config parser/marshaller.
src/config/CMakeLists.txt Build/link new config converter library code and unit tests.
src/proxy/unit_tests/test_PluginYAML.cc Unit tests for plugin.yaml parsing semantics (enabled, params, ordering, config scalar).
src/proxy/unit_tests/CMakeLists.txt Link new plugin YAML unit tests into test_proxy.
doc/release-notes/whats-new.en.rst Release note entry for plugin.yaml + new traffic_ctl commands.
doc/appendices/command-line/traffic_ctl.en.rst Document traffic_ctl plugin list and config convert plugin_config.
doc/admin-guide/files/plugin.yaml.en.rst New admin-guide reference for plugin.yaml schema and behavior.
doc/admin-guide/files/plugin.config.en.rst Add deprecation guidance + migration instructions to plugin.yaml.
doc/admin-guide/files/index.en.rst Add plugin.yaml to the configuration files index.

Comment thread src/proxy/Plugin.cc
Comment thread src/proxy/Plugin.cc
Comment thread src/proxy/Plugin.cc Outdated
Comment thread src/proxy/Plugin.cc
Comment thread src/proxy/Plugin.cc
Comment thread src/traffic_ctl/ConvertConfigCommand.cc
Comment thread src/config/plugin_config.cc Outdated
Comment thread doc/appendices/command-line/traffic_ctl.en.rst Outdated
Comment thread src/proxy/unit_tests/test_PluginYAML.cc
Comment thread src/config/unit_tests/test_plugin_config.cc
@masaori335

Copy link
Copy Markdown
Contributor

The inline config field with YAML block scalar seems neat. This is very useful for configs in few lines.

@brbzull0
brbzull0 force-pushed the plugin-yaml-migration branch 2 times, most recently from 3585d6e to 18e0948 Compare April 9, 2026 11:46
Add the 'config' field to plugin.yaml entries, allowing plugin
configuration to be embedded directly using a YAML block scalar (|).
The literal text is written to a temporary file at startup and passed
to the plugin as an argument. Only scalar values are accepted;
structured YAML is rejected to preserve quoting semantics that
plugins like txn_box rely on.

Made-with: Cursor
@brbzull0
brbzull0 force-pushed the plugin-yaml-migration branch from 18e0948 to ef2db7f Compare April 9, 2026 18:05

@masaori335 masaori335 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you!

@brbzull0
brbzull0 merged commit 42fb570 into apache:master Apr 15, 2026
15 checks passed
cmcfarlen pushed a commit that referenced this pull request Jul 6, 2026
* proxy/unit_tests: restore IpAllow::subjects stub definition

#13278 dropped this definition, but test_proxy links ts::http
(which references IpAllow::subjects) ahead of ts::proxy (which
defines it). GNU ld's single-pass archive scan then leaves the
symbol unresolved, breaking the Linux build; macOS links fine.
master avoids this incidentally via test_PluginYAML.cc from the
unbackported plugin.yaml migration (#13070).

* tls autests: use ssl_multicert.config instead of yaml

These tests were backported from master, where the default cert
config is ssl_multicert.yaml and the harness exposes
ts.Disk.ssl_multicert_yaml. On 10.2.x the default is still legacy
ssl_multicert.config and no ssl_multicert_yaml Disk attribute is
registered, so the tests failed at collection. Switch them to the
ssl_multicert.config one-liner used by the other 10.2.x TLS tests.

* curl 8.20 test update: curl PROXY destination changes (#13239)

curl 8.20 intentionally mirrors --haproxy-clientip into both PROXY
addresses to keep the header address family consistent. The
TSVConnPPInfo AuTest still expected the older destination address, so
jobs with newer curl failed even though ATS preserved the PROXY metadata
it received.

This relaxes the destination-address expectation to accept either curl
behavior while continuing to verify the source address and PROXY
metadata. This also wraps the long curl command strings while leaving
the test's request flow unchanged.

(cherry picked from commit ad0ce02)

* fedora:44: Trim remap ACL reload waits (#13237)

The remap ACL AuTests run hundreds of reload scenarios in a single case,
and the Fedora 44 shard is sensitive to extra reload-wait overhead,
causing the tests to hang. Their reload sentinel also counted only
explicit reloads, even though the log contains the startup load marker
too.

This replaces the long-lived sleep Ready helper with a short command
that exits once the expected reload marker count is present. This also
waits for the startup marker plus the explicit reload count, so each
scenario observes the reload it just requested.

(cherry picked from commit c52eeda)

---------

Co-authored-by: Brian Neradt <brian.neradt@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Configuration Feedback Needed Request people to provide feedback. Incompatible Plugins traffic_ctl traffic_ctl related work. YAML

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants