rsyslog/tests/yaml-script-msgvar.sh
Rainer Gerhards e8fa2034fe feat: add YAML as an alternative configuration format
rsyslog now accepts .yaml / .yml files as a full alternative to
RainerScript configuration.  Whenever a .yaml or .yml file is
referenced (e.g. via $IncludeConfig or as the main config), it is
routed through the new yamlconf loader instead of the bison/flex
parser.  RainerScript and YAML configurations may coexist.

Supported top-level sections
  global:          global settings
  main_queue:      main queue settings
  modules:         module loading (load:, params:)
  inputs:          input objects  templates:       string, subtree, plugin, and list templates
                   (including all property/constant modifiers)
  rulesets:        rulesets with optional script: block (raw
                   RainerScript), filter/action shortcut (if:/then:),
                   and the full statements: block:
                     action:, set:, unset:, call:, call_indirect:,
                     foreach:, if:, stop:, continue:,
                     reload_lookup_table:
  outputs:         output objects (top-level convenience alias)
  include:         recursive includes (.yaml processed immediately;
                   .conf files pushed to LIFO stack in reverse order
                   for correct document-order processing)

Implementation notes
  - Thin front-end over existing cnfobj/nvlst/cnfDoObj() machinery;
    all parameter validation happens downstream unchanged.
  - Script blocks synthesised as RainerScript strings and injected via
    cnfAddConfigBuffer() (requires two trailing NUL bytes).
  - YAML -> YAML includes are synchronous recursive calls;
    YAML -> .conf includes use the flex buffer stack.
  - Mixed include lists (.yaml + .conf) emit a warning because strict
    document order cannot be preserved across the two mechanisms.
  - Built conditionally: --with-libyaml / HAVE_LIBYAML.

Tests
  19 new shell tests cover: basic config, modules, inputs, templates
  (string/subtree/list with modifiers), rulesets with script/filter/
  statements blocks, stop/continue, set/unset, foreach, call,
  call_indirect, reload_lookup_table, includes, error handling.

Documentation
  doc/source/configuration/yaml_config.rst  (new reference page)
  Inline comments in yamlconf.c explain all invariants and non-obvious
  design choices (es_getBufAddr non-null-termination, LIFO stack
  ordering, cnfAddConfigBuffer double-NUL requirement, etc.)

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-03-27 09:41:37 +01:00

60 lines
1.7 KiB
Bash
Executable File

#!/bin/bash
# Tests a more complex inline RainerScript script: block in YAML:
# - set $!nbr message variable from a field() extraction
# - nested if expression using cnum() and arithmetic comparison
# - two sequential actions (unconditional + conditional)
# Sends 500 messages; all pass the outer if (contain "msgnum:"), but only
# messages 0-199 reach the second action (the rest are stopped early to keep
# the test fast). seq_check 0 499 verifies all 500 reach the first action.
#
# Added 2025, released under ASL 2.0
. ${srcdir:=.}/diag.sh init
require_plugin imtcp
export NUMMESSAGES=500
export QUEUE_EMPTY_CHECK_FUNC=wait_file_lines
generate_conf
add_conf '
include(file="'${RSYSLOG_DYNNAME}'.yaml")
'
cat > "${RSYSLOG_DYNNAME}.yaml" << 'YAMLEOF'
modules:
- load: "../plugins/imtcp/.libs/imtcp"
templates:
- name: outfmt
type: string
string: "%msg:F,58:2%\n"
- name: varfmt
type: string
string: "%$!nbr%\n"
rulesets:
- name: main
script: |
if $msg contains "msgnum:" then {
action(type="omfile" template="outfmt" file="${RSYSLOG_OUT_LOG}")
set $!nbr = field($msg, 58, 2);
if cnum($!nbr) >= 200 then
stop
action(type="omfile" template="varfmt" file="${RSYSLOG_DYNNAME}.detail")
}
YAMLEOF
sed -i \
-e "s|\${RSYSLOG_OUT_LOG}|${RSYSLOG_OUT_LOG}|g" \
-e "s|\${RSYSLOG_DYNNAME}|${RSYSLOG_DYNNAME}|g" \
"${RSYSLOG_DYNNAME}.yaml"
add_conf '
input(type="imtcp" port="0" listenPortFileName="'${RSYSLOG_DYNNAME}'.tcpflood_port"
ruleset="main")
'
startup
tcpflood -m $NUMMESSAGES
shutdown_when_empty
wait_shutdown
seq_check 0 499
# The detail file should contain exactly the first 200 messages (0-199)
SEQ_CHECK_FILE="${RSYSLOG_DYNNAME}.detail" seq_check 0 199
exit_test