mirror of
https://github.com/rsyslog/rsyslog.git
synced 2026-04-17 05:40:50 +02:00
Merge pull request #6679 from rgerhards/codex/config-translate-mode
[codex] runtime: add config translation mode
This commit is contained in:
commit
20f521a1c7
@ -18,7 +18,7 @@ EXTRA_DIST = \
|
||||
contrib/gnutls/cert.pem \
|
||||
contrib/gnutls/key.pem
|
||||
|
||||
SUBDIRS = doc compat runtime grammar . plugins/immark plugins/imuxsock plugins/imtcp plugins/imudp plugins/omtesting
|
||||
SUBDIRS = doc compat grammar runtime . plugins/immark plugins/imuxsock plugins/imtcp plugins/imudp plugins/omtesting
|
||||
# external plugin driver is always enabled (core component)
|
||||
SUBDIRS += plugins/mmexternal
|
||||
|
||||
|
||||
7
action.c
7
action.c
@ -89,6 +89,7 @@
|
||||
#include "ruleset.h"
|
||||
#include "parserif.h"
|
||||
#include "statsobj.h"
|
||||
#include "runtime/translate.h"
|
||||
|
||||
/* AIXPORT : cs renamed to legacy_cs as clashes with libpthreads variable in complete file*/
|
||||
#ifdef _AIX
|
||||
@ -302,6 +303,8 @@ rsRetVal actionDestruct(action_t *const pThis) {
|
||||
|
||||
if (!strcmp((char *)modGetName(pThis->pMod), "builtin:omdiscard")) {
|
||||
/* discard actions will be optimized out */
|
||||
nvlstDestruct(pThis->pSyntaxLst);
|
||||
pThis->pSyntaxLst = NULL;
|
||||
FINALIZE;
|
||||
}
|
||||
|
||||
@ -321,6 +324,7 @@ rsRetVal actionDestruct(action_t *const pThis) {
|
||||
free((void *)pThis->pszErrFile);
|
||||
free((void *)pThis->pszExternalStateFile);
|
||||
free(pThis->pszName);
|
||||
nvlstDestruct(pThis->pSyntaxLst);
|
||||
free(pThis->ppTpl);
|
||||
free(pThis->peParamPassing);
|
||||
freeWrkrDataTable(pThis);
|
||||
@ -2217,6 +2221,9 @@ rsRetVal addAction(action_t **ppAction,
|
||||
CHKiRet(actionConstruct(&pAction)); /* create action object first */
|
||||
pAction->pMod = pMod;
|
||||
pAction->pModData = pModData;
|
||||
if (rsconfTranslateEnabled() && lst != NULL && pAction->pSyntaxLst == NULL) {
|
||||
pAction->pSyntaxLst = rsconfTranslateCloneNvlst(lst);
|
||||
}
|
||||
if (actParams == NULL) { /* use legacy systemn */
|
||||
pAction->pszName = cs.pszActionName;
|
||||
pAction->iResumeInterval = cs.glbliActionResumeInterval;
|
||||
|
||||
1
action.h
1
action.h
@ -82,6 +82,7 @@ struct action_s {
|
||||
time_t tLastOccur; /* time last occurrence was seen (for timing them out) */
|
||||
struct modInfo_s *pMod; /* pointer to output module handling this selector */
|
||||
void *pModData; /* pointer to module data - content is module-specific */
|
||||
struct nvlst *pSyntaxLst; /* cloned config syntax for translation/export */
|
||||
sbool bRepMsgHasMsg; /* "message repeated..." has msg fragment in it (0-no, 1-yes) */
|
||||
rsRetVal (*submitToActQ)(action_t *, wti_t *, smsg_t *); /* function submit message to action queue */
|
||||
rsRetVal (*qConstruct)(struct queue_s *pThis);
|
||||
|
||||
@ -4904,7 +4904,11 @@ struct cnfstmt *cnfstmtNewUnset(char *var) {
|
||||
}
|
||||
|
||||
struct cnfstmt *cnfstmtNewContinue(void) {
|
||||
return cnfstmtNew(S_NOP);
|
||||
struct cnfstmt *cnfstmt = cnfstmtNew(S_NOP);
|
||||
if (cnfstmt != NULL) {
|
||||
cnfstmt->printable = (uchar *)strdup("continue");
|
||||
}
|
||||
return cnfstmt;
|
||||
}
|
||||
|
||||
struct cnfstmt *cnfstmtNewPRIFILT(char *prifilt, struct cnfstmt *t_then) {
|
||||
|
||||
@ -81,6 +81,8 @@ librsyslog_la_SOURCES = \
|
||||
prop.h \
|
||||
ratelimit.c \
|
||||
ratelimit.h \
|
||||
translate.c \
|
||||
translate.h \
|
||||
yamlconf.c \
|
||||
yamlconf.h \
|
||||
lookup.c \
|
||||
@ -118,7 +120,7 @@ librsyslog_la_SOURCES = \
|
||||
if WITH_MODDIRS
|
||||
librsyslog_la_CPPFLAGS = -DSD_EXPORT_SYMBOLS -D_PATH_MODDIR=\"$(pkglibdir)/:$(moddirs)\"
|
||||
else
|
||||
librsyslog_la_CPPFLAGS = -DSD_EXPORT_SYMBOLS -D_PATH_MODDIR=\"$(pkglibdir)/\" -I\$(top_srcdir) -I\$(top_srcdir)/grammar
|
||||
librsyslog_la_CPPFLAGS = -DSD_EXPORT_SYMBOLS -D_PATH_MODDIR=\"$(pkglibdir)/\" -I\$(top_srcdir) -I\$(top_srcdir)/grammar -I\$(top_builddir)/grammar
|
||||
endif
|
||||
#librsyslog_la_LDFLAGS = -module -avoid-version
|
||||
librsyslog_la_CPPFLAGS += $(PTHREADS_CFLAGS) $(RSRT_CFLAGS) $(LIBUUID_CFLAGS) $(LIBFASTJSON_CFLAGS) ${LIBESTR_CFLAGS} $(LIBYAML_CFLAGS)
|
||||
|
||||
@ -70,6 +70,7 @@
|
||||
#include "template.h"
|
||||
#include "timezones.h"
|
||||
#include "ratelimit.h"
|
||||
#include "translate.h"
|
||||
#ifdef HAVE_LIBYAML
|
||||
#include "yamlconf.h"
|
||||
#endif
|
||||
@ -596,7 +597,6 @@ void ATTR_NONNULL() cnfDoObj(struct cnfobj *const o) {
|
||||
int bDestructObj = 1;
|
||||
int bChkUnuse = 1;
|
||||
assert(o != NULL);
|
||||
|
||||
dbgprintf("cnf:global:obj: ");
|
||||
cnfobjPrint(o);
|
||||
|
||||
@ -609,6 +609,10 @@ void ATTR_NONNULL() cnfDoObj(struct cnfobj *const o) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (rsconfTranslateEnabled()) {
|
||||
rsconfTranslateCaptureObj(o, cnfcurrfn, yylineno);
|
||||
}
|
||||
|
||||
switch (o->objType) {
|
||||
case CNFOBJ_GLOBAL:
|
||||
glblProcessCnf(o);
|
||||
@ -664,11 +668,18 @@ void ATTR_NONNULL() cnfDoObj(struct cnfobj *const o) {
|
||||
}
|
||||
|
||||
void cnfDoScript(struct cnfstmt *script) {
|
||||
if (rsconfTranslateEnabled()) {
|
||||
rsconfTranslateCaptureScript(script, cnfcurrfn, yylineno);
|
||||
}
|
||||
dbgprintf("cnf:global:script\n");
|
||||
ruleset.AddScript(ruleset.GetCurrent(loadConf), script);
|
||||
}
|
||||
|
||||
void cnfDoCfsysline(char *ln) {
|
||||
if (rsconfTranslateEnabled()) {
|
||||
rsconfTranslateAddUnsupported(cnfcurrfn, yylineno, "legacy $-directive '%s' is not supported by the translator",
|
||||
ln);
|
||||
}
|
||||
DBGPRINTF("cnf:global:cfsysline: %s\n", ln);
|
||||
/* the legacy system needs the "$" stripped */
|
||||
conf.cfsysline((uchar *)ln + 1);
|
||||
@ -676,6 +687,10 @@ void cnfDoCfsysline(char *ln) {
|
||||
}
|
||||
|
||||
void cnfDoBSDTag(char *ln) {
|
||||
if (rsconfTranslateEnabled()) {
|
||||
rsconfTranslateAddUnsupported(cnfcurrfn, yylineno,
|
||||
"BSD-style tag block '%s' is not supported by the translator", ln);
|
||||
}
|
||||
DBGPRINTF("cnf:global:BSD tag: %s\n", ln);
|
||||
LogError(0, RS_RET_BSD_BLOCKS_UNSUPPORTED,
|
||||
"BSD-style blocks are no longer supported in rsyslog, "
|
||||
@ -686,6 +701,10 @@ void cnfDoBSDTag(char *ln) {
|
||||
}
|
||||
|
||||
void cnfDoBSDHost(char *ln) {
|
||||
if (rsconfTranslateEnabled()) {
|
||||
rsconfTranslateAddUnsupported(cnfcurrfn, yylineno,
|
||||
"BSD-style host block '%s' is not supported by the translator", ln);
|
||||
}
|
||||
DBGPRINTF("cnf:global:BSD host: %s\n", ln);
|
||||
LogError(0, RS_RET_BSD_BLOCKS_UNSUPPORTED,
|
||||
"BSD-style blocks are no longer supported in rsyslog, "
|
||||
@ -1557,7 +1576,7 @@ static rsRetVal load(rsconf_t **cnf, uchar *confFile) {
|
||||
* If not, terminate. -- rgerhards, 2008-07-25
|
||||
* TODO: iConfigVerify -- should it be pulled from the config, or leave as is (option)?
|
||||
*/
|
||||
if (iConfigVerify) {
|
||||
if (iConfigVerify && !rsconfTranslateEnabled()) {
|
||||
if (iRet == RS_RET_OK) iRet = RS_RET_VALIDATION_RUN;
|
||||
FINALIZE;
|
||||
}
|
||||
|
||||
1325
runtime/translate.c
Normal file
1325
runtime/translate.c
Normal file
File diff suppressed because it is too large
Load Diff
102
runtime/translate.h
Normal file
102
runtime/translate.h
Normal file
@ -0,0 +1,102 @@
|
||||
/** @file translate.h
|
||||
* @brief Interfaces for canonical config translation.
|
||||
*
|
||||
* Copyright 2026 Rainer Gerhards and Adiscon GmbH.
|
||||
*
|
||||
* Licensed 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
|
||||
* -or-
|
||||
* see COPYING.ASL20 in the source distribution
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
#ifndef RUNTIME_TRANSLATE_H_INCLUDED
|
||||
#define RUNTIME_TRANSLATE_H_INCLUDED
|
||||
|
||||
#include "rsyslog.h"
|
||||
#include "grammar/rainerscript.h"
|
||||
|
||||
/** @brief Supported translation output formats. */
|
||||
enum rsconfTranslateFormat { RSCONF_TRANSLATE_NONE = 0, RSCONF_TRANSLATE_RAINERSCRIPT, RSCONF_TRANSLATE_YAML };
|
||||
|
||||
/**
|
||||
* @brief Configure translation mode for the current validation run.
|
||||
*
|
||||
* Resets any previously retained translation state before enabling the
|
||||
* selected output format.
|
||||
*
|
||||
* @param fmt Translation output format, or @c RSCONF_TRANSLATE_NONE to disable.
|
||||
*/
|
||||
void rsconfTranslateConfigure(enum rsconfTranslateFormat fmt);
|
||||
|
||||
/**
|
||||
* @brief Release all retained translation state.
|
||||
*/
|
||||
void rsconfTranslateCleanup(void);
|
||||
|
||||
/**
|
||||
* @brief Check whether translation capture is enabled.
|
||||
*
|
||||
* @return Non-zero when config translation is active.
|
||||
*/
|
||||
int rsconfTranslateEnabled(void);
|
||||
|
||||
/**
|
||||
* @brief Check whether translation capture hit a fatal error.
|
||||
*
|
||||
* @return Non-zero when translation should fail instead of writing output.
|
||||
*/
|
||||
int rsconfTranslateHasFatal(void);
|
||||
|
||||
/**
|
||||
* @brief Clone a name-value list for later translation output.
|
||||
*
|
||||
* @param lst List head to clone.
|
||||
* @return Cloned list, or NULL on allocation failure.
|
||||
*/
|
||||
struct nvlst *rsconfTranslateCloneNvlst(const struct nvlst *lst);
|
||||
|
||||
/**
|
||||
* @brief Capture a config object before normal processing consumes it.
|
||||
*
|
||||
* @param o Parsed config object.
|
||||
* @param source Source file name, if known.
|
||||
* @param line Source line number.
|
||||
*/
|
||||
void rsconfTranslateCaptureObj(const struct cnfobj *o, const char *source, int line);
|
||||
|
||||
/**
|
||||
* @brief Capture executable script statements for later emission.
|
||||
*
|
||||
* @param script Statement tree to serialize.
|
||||
* @param source Source file name, if known.
|
||||
* @param line Source line number.
|
||||
*/
|
||||
void rsconfTranslateCaptureScript(const struct cnfstmt *script, const char *source, int line);
|
||||
|
||||
/**
|
||||
* @brief Record a fatal unsupported construct for translation.
|
||||
*
|
||||
* @param source Source file name, if known.
|
||||
* @param line Source line number.
|
||||
* @param fmt Printf-style explanation of the unsupported construct.
|
||||
*/
|
||||
void rsconfTranslateAddUnsupported(const char *source, int line, const char *fmt, ...)
|
||||
__attribute__((format(printf, 3, 4)));
|
||||
|
||||
/**
|
||||
* @brief Write the translated configuration document.
|
||||
*
|
||||
* @param path Output path, or "-" for stdout.
|
||||
* @return rsyslog status code for the write operation.
|
||||
*/
|
||||
rsRetVal rsconfTranslateWriteFile(const char *path);
|
||||
|
||||
#endif
|
||||
@ -1935,6 +1935,9 @@ rsRetVal yamlconf_load(const char *fname) {
|
||||
char *seen_keys[YAMLCONF_MAX_TOPKEYS];
|
||||
int seen_count = 0;
|
||||
DEFiRet;
|
||||
char *prev_cnfcurrfn = cnfcurrfn;
|
||||
|
||||
cnfcurrfn = (char *)fname;
|
||||
|
||||
fh = fopen(fname, "r");
|
||||
if (fh == NULL) {
|
||||
@ -2049,6 +2052,7 @@ finalize_it:
|
||||
for (int ki = 0; ki < seen_count; ++ki) free(seen_keys[ki]);
|
||||
if (parserInit) yaml_parser_delete(&parser);
|
||||
if (fh) fclose(fh);
|
||||
cnfcurrfn = prev_cnfcurrfn;
|
||||
RETiRet;
|
||||
}
|
||||
|
||||
|
||||
@ -557,6 +557,8 @@ TESTS_DEFAULT_VALGRIND = \
|
||||
TESTS_LIBGCRYPT_VALGRIND = \
|
||||
queue-encryption-disk_keyfile-vg.sh
|
||||
TESTS_LIBYAML = \
|
||||
config-translate-rs-to-yaml.sh \
|
||||
config-translate-yaml-to-rs.sh \
|
||||
ratelimit_hup.sh \
|
||||
yaml-basic.sh \
|
||||
yaml-basic-yamlonly.sh \
|
||||
@ -1209,6 +1211,13 @@ TESTS_PMNULL = \
|
||||
TESTS_OMSTDOUT = \
|
||||
omstdout-basic.sh
|
||||
|
||||
TESTS_LIBYAML_IMTCP = \
|
||||
config-translate-rs-roundtrip.sh \
|
||||
config-translate-yaml-roundtrip.sh
|
||||
|
||||
TESTS_LIBYAML_OMSTDOUT = \
|
||||
config-translate-legacy-warning.sh
|
||||
|
||||
TESTS_PMNORMALIZE = \
|
||||
pmnormalize-basic.sh \
|
||||
pmnormalize-invld-rulebase.sh \
|
||||
@ -1721,6 +1730,8 @@ EXTRA_DIST += $(TESTS_OSSL_WRONG_OPT)
|
||||
EXTRA_DIST += $(TESTS_DEFAULT_VALGRIND)
|
||||
EXTRA_DIST += $(TESTS_LIBGCRYPT_VALGRIND)
|
||||
EXTRA_DIST += $(TESTS_LIBYAML)
|
||||
EXTRA_DIST += $(TESTS_LIBYAML_IMTCP)
|
||||
EXTRA_DIST += $(TESTS_LIBYAML_OMSTDOUT)
|
||||
EXTRA_DIST += $(TESTS_IMTCP)
|
||||
EXTRA_DIST += $(TESTS_IMTCP_YAML)
|
||||
EXTRA_DIST += $(TESTS_IMTCP_VALGRIND)
|
||||
@ -2082,6 +2093,12 @@ endif # ENABLE_LIBGCRYPT
|
||||
endif # HAVE_VALGRIND
|
||||
if HAVE_LIBYAML
|
||||
TESTS += $(TESTS_LIBYAML)
|
||||
if ENABLE_IMTCP_TESTS
|
||||
TESTS += $(TESTS_LIBYAML_IMTCP)
|
||||
endif # ENABLE_IMTCP_TESTS
|
||||
if ENABLE_OMSTDOUT
|
||||
TESTS += $(TESTS_LIBYAML_OMSTDOUT)
|
||||
endif # ENABLE_OMSTDOUT
|
||||
endif # HAVE_LIBYAML
|
||||
endif # ENABLE_DEFAULT_TESTS
|
||||
|
||||
|
||||
25
tests/config-translate-legacy-warning.sh
Executable file
25
tests/config-translate-legacy-warning.sh
Executable file
@ -0,0 +1,25 @@
|
||||
#!/bin/bash
|
||||
# check translation warnings for legacy selector syntax.
|
||||
#
|
||||
# Part of the testbench for rsyslog.
|
||||
#
|
||||
# This file is part of rsyslog.
|
||||
# Released under ASL 2.0
|
||||
. ${srcdir:=.}/diag.sh init
|
||||
export ASAN_OPTIONS="${ASAN_OPTIONS:-detect_leaks=0}"
|
||||
modpath="../runtime/.libs:../plugins/omstdout/.libs:../.libs"
|
||||
|
||||
cat > "${RSYSLOG_DYNNAME}.conf" <<'RS_EOF'
|
||||
module(load="omstdout")
|
||||
*.* :omstdout:
|
||||
RS_EOF
|
||||
|
||||
../tools/rsyslogd -N1 -f "${RSYSLOG_DYNNAME}.conf" -F yaml -o "${RSYSLOG_DYNNAME}.yaml" -M"$modpath"
|
||||
|
||||
content_check '# TRANSLATION WARNING: top-level statements normalized into explicit RSYSLOG_DefaultRuleset' "${RSYSLOG_DYNNAME}.yaml"
|
||||
content_check '# TRANSLATION WARNING: legacy action syntax preserved as script text' "${RSYSLOG_DYNNAME}.yaml"
|
||||
content_check 'name: "RSYSLOG_DefaultRuleset"' "${RSYSLOG_DYNNAME}.yaml"
|
||||
content_check '*.* :omstdout:' "${RSYSLOG_DYNNAME}.yaml"
|
||||
|
||||
echo SUCCESS: legacy translation warning coverage
|
||||
exit_test
|
||||
85
tests/config-translate-rs-roundtrip.sh
Executable file
85
tests/config-translate-rs-roundtrip.sh
Executable file
@ -0,0 +1,85 @@
|
||||
#!/bin/bash
|
||||
# check canonical RainerScript -> YAML -> RainerScript round-trip.
|
||||
#
|
||||
# Part of the testbench for rsyslog.
|
||||
#
|
||||
# This file is part of rsyslog.
|
||||
# Released under ASL 2.0
|
||||
. ${srcdir:=.}/diag.sh init
|
||||
require_plugin imtcp
|
||||
export ASAN_OPTIONS="${ASAN_OPTIONS:-detect_leaks=0}"
|
||||
modpath="../runtime/.libs:../plugins/imtcp/.libs:../.libs"
|
||||
outlog="/tmp/${RSYSLOG_DYNNAME}.roundtrip.log"
|
||||
portfile="${RSYSLOG_DYNNAME}.tcpflood_port"
|
||||
|
||||
cat > "${RSYSLOG_DYNNAME}.conf" <<RS_EOF
|
||||
global(defaultNetstreamDriverCAFile="${srcdir}/tls-certs/ca.pem"
|
||||
defaultNetstreamDriverCertFile="${srcdir}/tls-certs/cert.pem"
|
||||
defaultNetstreamDriverKeyFile="${srcdir}/tls-certs/key.pem")
|
||||
|
||||
module(load="../plugins/imtcp/.libs/imtcp"
|
||||
StreamDriver.Name="gtls"
|
||||
StreamDriver.Mode="1"
|
||||
StreamDriver.AuthMode="x509/name"
|
||||
PermittedPeer=["rsyslog-client"])
|
||||
input(type="imtcp" listenPortFileName="${portfile}" port="0")
|
||||
|
||||
template(name="outfmt" type="string" string="%msg:F,58:2%\n")
|
||||
|
||||
ruleset(name="main") {
|
||||
action(type="omfile" file="${outlog}" template="outfmt")
|
||||
}
|
||||
RS_EOF
|
||||
|
||||
../tools/rsyslogd -N1 -f "${RSYSLOG_DYNNAME}.conf" -F yaml -o "${RSYSLOG_DYNNAME}.roundtrip.yaml" -M"$modpath" || error_exit $?
|
||||
../tools/rsyslogd -N1 -f "${RSYSLOG_DYNNAME}.roundtrip.yaml" -F rainerscript -o "${RSYSLOG_DYNNAME}.roundtrip.conf" -M"$modpath" || error_exit $?
|
||||
|
||||
cat > "${RSYSLOG_DYNNAME}.expected.yaml" <<YAML_EOF
|
||||
version: 2
|
||||
|
||||
global:
|
||||
defaultNetstreamDriverCAFile: "${srcdir}/tls-certs/ca.pem"
|
||||
defaultNetstreamDriverCertFile: "${srcdir}/tls-certs/cert.pem"
|
||||
defaultNetstreamDriverKeyFile: "${srcdir}/tls-certs/key.pem"
|
||||
|
||||
modules:
|
||||
- load: "../plugins/imtcp/.libs/imtcp"
|
||||
PermittedPeer: ["rsyslog-client"]
|
||||
StreamDriver.AuthMode: "x509/name"
|
||||
StreamDriver.Mode: "1"
|
||||
StreamDriver.Name: "gtls"
|
||||
inputs:
|
||||
- type: "imtcp"
|
||||
listenPortFileName: "${portfile}"
|
||||
port: "0"
|
||||
templates:
|
||||
- name: "outfmt"
|
||||
type: "string"
|
||||
string: "%msg:F,58:2%\n"
|
||||
rulesets:
|
||||
- name: "main"
|
||||
script: |
|
||||
action(type="omfile" file="${outlog}" template="outfmt")
|
||||
YAML_EOF
|
||||
cmp_exact_file "${RSYSLOG_DYNNAME}.expected.yaml" "${RSYSLOG_DYNNAME}.roundtrip.yaml"
|
||||
|
||||
cat > "${RSYSLOG_DYNNAME}.expected.conf" <<RS_EOF
|
||||
global(defaultNetstreamDriverCAFile="${srcdir}/tls-certs/ca.pem" defaultNetstreamDriverCertFile="${srcdir}/tls-certs/cert.pem" defaultNetstreamDriverKeyFile="${srcdir}/tls-certs/key.pem")
|
||||
|
||||
module(load="../plugins/imtcp/.libs/imtcp" PermittedPeer=["rsyslog-client"] StreamDriver.AuthMode="x509/name" StreamDriver.Mode="1" StreamDriver.Name="gtls")
|
||||
|
||||
input(type="imtcp" listenPortFileName="${portfile}" port="0")
|
||||
|
||||
template(name="outfmt" type="string" string="%msg:F,58:2%\n")
|
||||
|
||||
ruleset(name="main") {
|
||||
action(type="omfile" file="${outlog}" template="outfmt")
|
||||
}
|
||||
|
||||
RS_EOF
|
||||
cmp_exact_file "${RSYSLOG_DYNNAME}.expected.conf" "${RSYSLOG_DYNNAME}.roundtrip.conf"
|
||||
|
||||
../tools/rsyslogd -N1 -f "${RSYSLOG_DYNNAME}.roundtrip.conf" -M"$modpath" || error_exit $?
|
||||
|
||||
echo SUCCESS: RainerScript round-trip translation
|
||||
exit_test
|
||||
40
tests/config-translate-rs-to-yaml.sh
Executable file
40
tests/config-translate-rs-to-yaml.sh
Executable file
@ -0,0 +1,40 @@
|
||||
#!/bin/bash
|
||||
# check canonical translation from RainerScript to YAML.
|
||||
#
|
||||
# Part of the testbench for rsyslog.
|
||||
#
|
||||
# This file is part of rsyslog.
|
||||
# Released under ASL 2.0
|
||||
. ${srcdir:=.}/diag.sh init
|
||||
export ASAN_OPTIONS="${ASAN_OPTIONS:-detect_leaks=0}"
|
||||
modpath="../runtime/.libs:../plugins/omstdout/.libs:../.libs"
|
||||
|
||||
cat > "${RSYSLOG_DYNNAME}.conf" <<'RS_EOF'
|
||||
module(load="omstdout")
|
||||
main_queue(queue.type="Direct")
|
||||
ruleset(name="main") {
|
||||
action(type="omstdout")
|
||||
}
|
||||
RS_EOF
|
||||
|
||||
../tools/rsyslogd -N1 -f "${RSYSLOG_DYNNAME}.conf" -F yaml -o "${RSYSLOG_DYNNAME}.yaml" -M"$modpath"
|
||||
|
||||
cat > "${RSYSLOG_DYNNAME}.expected.yaml" <<'YAML_EOF'
|
||||
version: 2
|
||||
|
||||
mainqueue:
|
||||
queue.type: "Direct"
|
||||
|
||||
modules:
|
||||
- load: "omstdout"
|
||||
rulesets:
|
||||
- name: "main"
|
||||
script: |
|
||||
action(type="omstdout")
|
||||
YAML_EOF
|
||||
cmp_exact_file "${RSYSLOG_DYNNAME}.expected.yaml" "${RSYSLOG_DYNNAME}.yaml"
|
||||
|
||||
../tools/rsyslogd -N1 -f "${RSYSLOG_DYNNAME}.yaml" -M"$modpath"
|
||||
|
||||
echo SUCCESS: RainerScript to YAML translation
|
||||
exit_test
|
||||
77
tests/config-translate-yaml-roundtrip.sh
Executable file
77
tests/config-translate-yaml-roundtrip.sh
Executable file
@ -0,0 +1,77 @@
|
||||
#!/bin/bash
|
||||
# check canonical YAML -> RainerScript -> YAML round-trip.
|
||||
#
|
||||
# Part of the testbench for rsyslog.
|
||||
#
|
||||
# This file is part of rsyslog.
|
||||
# Released under ASL 2.0
|
||||
. ${srcdir:=.}/diag.sh init
|
||||
export ASAN_OPTIONS="${ASAN_OPTIONS:-detect_leaks=0}"
|
||||
modpath="../runtime/.libs:../plugins/imtcp/.libs:../.libs"
|
||||
outlog="/tmp/${RSYSLOG_DYNNAME}.roundtrip.log"
|
||||
portfile="${RSYSLOG_DYNNAME}.tcpflood_port"
|
||||
|
||||
cat > "${RSYSLOG_DYNNAME}.yaml" <<YAML_EOF
|
||||
version: 2
|
||||
|
||||
global:
|
||||
defaultNetstreamDriverCAFile: "${srcdir}/tls-certs/ca.pem"
|
||||
defaultNetstreamDriverCertFile: "${srcdir}/tls-certs/cert.pem"
|
||||
defaultNetstreamDriverKeyFile: "${srcdir}/tls-certs/key.pem"
|
||||
|
||||
modules:
|
||||
- load: "../plugins/imtcp/.libs/imtcp"
|
||||
PermittedPeer: ["rsyslog-client"]
|
||||
StreamDriver.AuthMode: "x509/name"
|
||||
StreamDriver.Mode: "1"
|
||||
StreamDriver.Name: "gtls"
|
||||
inputs:
|
||||
- type: "imtcp"
|
||||
listenPortFileName: "${portfile}"
|
||||
port: "0"
|
||||
templates:
|
||||
- name: "outfmt"
|
||||
type: "string"
|
||||
string: "%msg:F,58:2%\\n"
|
||||
rulesets:
|
||||
- name: "main"
|
||||
script: |
|
||||
action(type="omfile" file="${outlog}" template="outfmt")
|
||||
YAML_EOF
|
||||
|
||||
../tools/rsyslogd -N1 -f "${RSYSLOG_DYNNAME}.yaml" -F rainerscript -o "${RSYSLOG_DYNNAME}.roundtrip.conf" -M"$modpath" || error_exit $?
|
||||
../tools/rsyslogd -N1 -f "${RSYSLOG_DYNNAME}.roundtrip.conf" -F yaml -o "${RSYSLOG_DYNNAME}.roundtrip.yaml" -M"$modpath" || error_exit $?
|
||||
|
||||
cat > "${RSYSLOG_DYNNAME}.expected.yaml" <<YAML_EOF
|
||||
version: 2
|
||||
|
||||
global:
|
||||
defaultNetstreamDriverCAFile: "${srcdir}/tls-certs/ca.pem"
|
||||
defaultNetstreamDriverCertFile: "${srcdir}/tls-certs/cert.pem"
|
||||
defaultNetstreamDriverKeyFile: "${srcdir}/tls-certs/key.pem"
|
||||
|
||||
modules:
|
||||
- load: "../plugins/imtcp/.libs/imtcp"
|
||||
PermittedPeer: ["rsyslog-client"]
|
||||
StreamDriver.AuthMode: "x509/name"
|
||||
StreamDriver.Mode: "1"
|
||||
StreamDriver.Name: "gtls"
|
||||
inputs:
|
||||
- type: "imtcp"
|
||||
listenPortFileName: "${portfile}"
|
||||
port: "0"
|
||||
templates:
|
||||
- name: "outfmt"
|
||||
type: "string"
|
||||
string: "%msg:F,58:2%\\n"
|
||||
rulesets:
|
||||
- name: "main"
|
||||
script: |
|
||||
action(type="omfile" file="${outlog}" template="outfmt")
|
||||
YAML_EOF
|
||||
cmp_exact_file "${RSYSLOG_DYNNAME}.expected.yaml" "${RSYSLOG_DYNNAME}.roundtrip.yaml"
|
||||
|
||||
../tools/rsyslogd -N1 -f "${RSYSLOG_DYNNAME}.roundtrip.yaml" -M"$modpath" || error_exit $?
|
||||
|
||||
echo SUCCESS: YAML round-trip translation
|
||||
exit_test
|
||||
41
tests/config-translate-yaml-to-rs.sh
Executable file
41
tests/config-translate-yaml-to-rs.sh
Executable file
@ -0,0 +1,41 @@
|
||||
#!/bin/bash
|
||||
# check canonical translation from YAML to RainerScript.
|
||||
#
|
||||
# Part of the testbench for rsyslog.
|
||||
#
|
||||
# This file is part of rsyslog.
|
||||
# Released under ASL 2.0
|
||||
. ${srcdir:=.}/diag.sh init
|
||||
export ASAN_OPTIONS="${ASAN_OPTIONS:-detect_leaks=0}"
|
||||
modpath="../runtime/.libs:../plugins/omstdout/.libs:../.libs"
|
||||
|
||||
cat > "${RSYSLOG_DYNNAME}.yaml" <<'YAML_EOF'
|
||||
version: 2
|
||||
modules:
|
||||
- load: "omstdout"
|
||||
mainqueue:
|
||||
queue.type: "Direct"
|
||||
rulesets:
|
||||
- name: "main"
|
||||
script: |
|
||||
action(type="omstdout")
|
||||
YAML_EOF
|
||||
|
||||
../tools/rsyslogd -N1 -f "${RSYSLOG_DYNNAME}.yaml" -F rainerscript -o "${RSYSLOG_DYNNAME}.out.conf" -M"$modpath"
|
||||
|
||||
cat > "${RSYSLOG_DYNNAME}.expected.conf" <<'RS_EOF'
|
||||
main_queue(queue.type="Direct")
|
||||
|
||||
module(load="omstdout")
|
||||
|
||||
ruleset(name="main") {
|
||||
action(type="omstdout")
|
||||
}
|
||||
|
||||
RS_EOF
|
||||
cmp_exact_file "${RSYSLOG_DYNNAME}.expected.conf" "${RSYSLOG_DYNNAME}.out.conf"
|
||||
|
||||
../tools/rsyslogd -N1 -f "${RSYSLOG_DYNNAME}.out.conf" -M"$modpath"
|
||||
|
||||
echo SUCCESS: YAML to RainerScript translation
|
||||
exit_test
|
||||
@ -451,6 +451,28 @@ cmp_exact() {
|
||||
fi;
|
||||
}
|
||||
|
||||
# compare two files for exact content
|
||||
# $1 is the expected file, $2 is the actual file
|
||||
cmp_exact_file() {
|
||||
expected_file="$1"
|
||||
actual_file="$2"
|
||||
if [ "$expected_file" == "" ] || [ "$actual_file" == "" ]; then
|
||||
printf 'Testbench ERROR, cmp_exact_file() needs expected and actual filenames!\n'
|
||||
error_exit 100
|
||||
fi
|
||||
cmp "$expected_file" "$actual_file" > /dev/null
|
||||
if [ $? -ne 0 ]; then
|
||||
printf 'invalid response generated\n'
|
||||
printf '################# %s is:\n' "$actual_file"
|
||||
cat -n "$actual_file"
|
||||
printf '################# %s is expected:\n' "$expected_file"
|
||||
cat -n "$expected_file"
|
||||
printf '\n#################### diff is:\n'
|
||||
diff -u "$expected_file" "$actual_file"
|
||||
error_exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# code common to all startup...() functions
|
||||
startup_common() {
|
||||
instance=
|
||||
|
||||
@ -66,6 +66,7 @@
|
||||
#include "srUtils.h"
|
||||
#include "rainerscript.h"
|
||||
#include "rsconf.h"
|
||||
#include "translate.h"
|
||||
#include "cfsysline.h"
|
||||
#include "datetime.h"
|
||||
#include "operatingstate.h"
|
||||
@ -1431,6 +1432,8 @@ static void initAll(int argc, char **argv) {
|
||||
int iHelperUOpt;
|
||||
int bChDirRoot = 1; /* change the current working directory to "/"? */
|
||||
char *arg; /* for command line option processing */
|
||||
char *configOutputPath = NULL;
|
||||
enum rsconfTranslateFormat iTranslateFmt = RSCONF_TRANSLATE_NONE;
|
||||
char cwdbuf[128]; /* buffer to obtain/display current working directory */
|
||||
int parentPipeFD = 0; /* fd of pipe to parent, if auto-backgrounding */
|
||||
DEFiRet;
|
||||
@ -1453,15 +1456,16 @@ static void initAll(int argc, char **argv) {
|
||||
* before processing complex configurations that might depend on it.
|
||||
*/
|
||||
#if defined(_AIX)
|
||||
while ((ch = getopt(argc, argv, "46ACDdf:hi:M:nN:o:qQS:T:u:vwxR")) != EOF) {
|
||||
while ((ch = getopt(argc, argv, "46ACDdf:F:hi:M:nN:o:qQS:T:u:vwxR")) != EOF) {
|
||||
#else
|
||||
while ((ch = getopt(argc, argv, "46ACDdf:hi:M:nN:o:qQS:T:u:vwx")) != EOF) {
|
||||
while ((ch = getopt(argc, argv, "46ACDdf:F:hi:M:nN:o:qQS:T:u:vwx")) != EOF) {
|
||||
#endif
|
||||
switch ((char)ch) {
|
||||
case '4':
|
||||
case '6':
|
||||
case 'A':
|
||||
case 'f': /* configuration file */
|
||||
case 'F': /* translation output format */
|
||||
case 'i': /* pid file name */
|
||||
case 'n': /* don't fork */
|
||||
case 'N': /* enable config verify mode */
|
||||
@ -1580,36 +1584,27 @@ static void initAll(int argc, char **argv) {
|
||||
case 'N': /* enable config verify mode */
|
||||
iConfigVerify = (arg == NULL) ? 0 : atoi(arg);
|
||||
break;
|
||||
case 'F':
|
||||
if (arg == NULL) {
|
||||
fprintf(stderr, "rsyslogd: -F requires a format argument\n");
|
||||
exit(1);
|
||||
}
|
||||
if (!strcasecmp(arg, "yaml")) {
|
||||
iTranslateFmt = RSCONF_TRANSLATE_YAML;
|
||||
} else if (!strcasecmp(arg, "rainerscript")) {
|
||||
iTranslateFmt = RSCONF_TRANSLATE_RAINERSCRIPT;
|
||||
} else {
|
||||
fprintf(stderr, "rsyslogd: unsupported translation format '%s'\n", arg);
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
if (fp_rs_full_conf_output != NULL) {
|
||||
fprintf(stderr,
|
||||
"warning: -o option given multiple times. Now "
|
||||
"using value %s\n",
|
||||
if (configOutputPath != NULL) {
|
||||
fprintf(stderr, "warning: -o option given multiple times. Now using value %s\n",
|
||||
(arg == NULL) ? "-" : arg);
|
||||
fclose(fp_rs_full_conf_output);
|
||||
fp_rs_full_conf_output = NULL;
|
||||
}
|
||||
if (arg == NULL || !strcmp(arg, "-")) {
|
||||
fp_rs_full_conf_output = stdout;
|
||||
} else {
|
||||
fp_rs_full_conf_output = fopen(arg, "w");
|
||||
}
|
||||
if (fp_rs_full_conf_output == NULL) {
|
||||
perror(arg);
|
||||
fprintf(stderr,
|
||||
"rsyslogd: cannot open config output file %s - "
|
||||
"-o option will be ignored\n",
|
||||
arg);
|
||||
} else {
|
||||
time_t tTime;
|
||||
struct tm tp;
|
||||
datetime.GetTime(&tTime);
|
||||
localtime_r(&tTime, &tp);
|
||||
fprintf(fp_rs_full_conf_output,
|
||||
"## full conf created by rsyslog version %s at "
|
||||
"%4.4d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d ##\n",
|
||||
VERSION, tp.tm_year + 1900, tp.tm_mon + 1, tp.tm_mday, tp.tm_hour, tp.tm_min, tp.tm_sec);
|
||||
}
|
||||
configOutputPath = arg;
|
||||
arg = NULL;
|
||||
break;
|
||||
case 'q': /* add hostname if DNS resolving has failed */
|
||||
fprintf(stderr,
|
||||
@ -1681,6 +1676,38 @@ static void initAll(int argc, char **argv) {
|
||||
|
||||
if (iRet != RS_RET_END_OF_LINKEDLIST) FINALIZE;
|
||||
|
||||
if (iTranslateFmt != RSCONF_TRANSLATE_NONE) {
|
||||
if (!iConfigVerify) {
|
||||
fprintf(stderr, "rsyslogd: -F requires -N1 config validation mode\n");
|
||||
ABORT_FINALIZE(RS_RET_ERR);
|
||||
}
|
||||
if (configOutputPath == NULL) {
|
||||
fprintf(stderr, "rsyslogd: -F requires -o <path>\n");
|
||||
ABORT_FINALIZE(RS_RET_ERR);
|
||||
}
|
||||
rsconfTranslateConfigure(iTranslateFmt);
|
||||
} else if (configOutputPath != NULL) {
|
||||
if (!strcmp(configOutputPath, "-")) {
|
||||
fp_rs_full_conf_output = stdout;
|
||||
} else {
|
||||
fp_rs_full_conf_output = fopen(configOutputPath, "w");
|
||||
}
|
||||
if (fp_rs_full_conf_output == NULL) {
|
||||
perror(configOutputPath);
|
||||
fprintf(stderr, "rsyslogd: cannot open config output file %s - -o option will be ignored\n",
|
||||
configOutputPath);
|
||||
} else {
|
||||
time_t tTime;
|
||||
struct tm tp;
|
||||
datetime.GetTime(&tTime);
|
||||
localtime_r(&tTime, &tp);
|
||||
fprintf(fp_rs_full_conf_output,
|
||||
"## full conf created by rsyslog version %s at "
|
||||
"%4.4d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d ##\n",
|
||||
VERSION, tp.tm_year + 1900, tp.tm_mon + 1, tp.tm_mday, tp.tm_hour, tp.tm_min, tp.tm_sec);
|
||||
}
|
||||
}
|
||||
|
||||
if (iConfigVerify) {
|
||||
doFork = 0;
|
||||
fprintf(stderr, "rsyslogd: version %s, config validation run (level %d), master config %s\n", VERSION,
|
||||
@ -1825,6 +1852,12 @@ static void initAll(int argc, char **argv) {
|
||||
}
|
||||
CHKiRet(localRet);
|
||||
|
||||
if (iTranslateFmt != RSCONF_TRANSLATE_NONE) {
|
||||
CHKiRet(rsconfTranslateWriteFile(configOutputPath));
|
||||
iRet = RS_RET_VALIDATION_RUN;
|
||||
FINALIZE;
|
||||
}
|
||||
|
||||
CHKiRet(rsyslogd_InitStdRatelimiters());
|
||||
|
||||
if (bChDirRoot) {
|
||||
@ -1888,6 +1921,7 @@ static void initAll(int argc, char **argv) {
|
||||
}
|
||||
|
||||
finalize_it:
|
||||
rsconfTranslateCleanup();
|
||||
if (iRet == RS_RET_VALIDATION_RUN) {
|
||||
fprintf(stderr, "rsyslogd: End of config validation run. Bye.\n");
|
||||
exit(0);
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user