From 7c4d96970081db459c5f03f47026a8156d783f4e Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Thu, 29 Oct 2026 15:26:34 +0900 Subject: [PATCH 01/11] utils: prefer configuration-relative file paths Signed-off-by: Hiroshi Hatake --- include/fluent-bit/flb_utils.h | 2 ++ src/flb_utils.c | 32 ++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/include/fluent-bit/flb_utils.h b/include/fluent-bit/flb_utils.h index 0b499acaa4f..12d58cb53b9 100644 --- a/include/fluent-bit/flb_utils.h +++ b/include/fluent-bit/flb_utils.h @@ -69,6 +69,8 @@ int flb_utils_proxy_url_split(const char *in_url, char **out_protocol, char **out_host, char **out_port); int flb_utils_read_file(char *path, char **out_buf, size_t *out_size); int flb_utils_read_file_offset(char *path, off_t offset_start, off_t offset_end, char **out_buf, size_t *out_size); +const char *flb_utils_resolve_config_path(const char *path, const char *conf_path, + char *buf, size_t size); char *flb_utils_get_os_name(); int flb_utils_uuid_v4_gen(char *buf); int flb_utils_get_machine_id(char **out_id, size_t *out_size); diff --git a/src/flb_utils.c b/src/flb_utils.c index 7d86a810406..54d14e9ceb7 100644 --- a/src/flb_utils.c +++ b/src/flb_utils.c @@ -25,6 +25,7 @@ #include #include +#include #include #include @@ -66,6 +67,37 @@ extern struct flb_aws_error_reporter *error_reporter; */ #define FLB_UTILS_FRAGMENT_PRIVATE_BLOCK_DESCRIPTOR 0xE0 +/* Prefer a file beside the main configuration over a same-named file in CWD. */ +const char *flb_utils_resolve_config_path(const char *path, const char *conf_path, + char *buf, size_t size) +{ + int ret; + size_t len; + struct stat st; + + if (!path || !conf_path || path[0] == '/') { + return path; + } +#ifdef _WIN32 + if (path[0] == '\\' || (path[0] && path[1] == ':')) { + return path; + } +#endif + + len = strlen(conf_path); + ret = snprintf(buf, size, "%s%s%s", conf_path, + len > 0 && conf_path[len - 1] == '/' ? "" : "/", path); + if (ret < 0 || (size_t) ret >= size) { + return NULL; + } + + if (stat(buf, &st) == 0 || errno != ENOENT) { + return buf; + } + + return path; +} + void flb_utils_error(int err) { char *msg = NULL; From 96de14dd43a688330e904531084390a45aa6d0c6 Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Thu, 29 Oct 2026 15:26:55 +0900 Subject: [PATCH 02/11] filter_lua: prefer configuration-relative scripts Signed-off-by: Hiroshi Hatake --- plugins/filter_lua/lua_config.c | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/plugins/filter_lua/lua_config.c b/plugins/filter_lua/lua_config.c index 01e743dbc63..0b6a7285fdf 100644 --- a/plugins/filter_lua/lua_config.c +++ b/plugins/filter_lua/lua_config.c @@ -41,7 +41,6 @@ struct lua_filter *lua_config_create(struct flb_filter_instance *ins, const char *script = NULL; const char *tmp = NULL; (void) config; - struct stat st; struct lua_filter *lf; struct mk_list *split = NULL; struct mk_list *head = NULL; @@ -81,20 +80,12 @@ struct lua_filter *lua_config_create(struct flb_filter_instance *ins, return NULL; } - /* Compose path */ - ret = stat(script, &st); - if (ret == -1 && errno == ENOENT) { - if (script[0] == '/') { - flb_plg_error(lf->ins, "cannot access script '%s'", script); - flb_free(lf); - return NULL; - } - - if (config->conf_path) { - snprintf(buf, sizeof(buf) - 1, "%s%s", - config->conf_path, script); - script = buf; - } + script = flb_utils_resolve_config_path(script, config->conf_path, + buf, sizeof(buf)); + if (!script) { + flb_plg_error(lf->ins, "script path is too long"); + flb_free(lf); + return NULL; } /* Validate script path */ From 2101052ee9be373927d6a107cef8930af18b615b Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Thu, 29 Oct 2026 15:26:56 +0900 Subject: [PATCH 03/11] filter_wasm: prefer configuration-relative programs Signed-off-by: Hiroshi Hatake --- plugins/filter_wasm/filter_wasm.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/plugins/filter_wasm/filter_wasm.c b/plugins/filter_wasm/filter_wasm.c index 81377c5987a..a3049b97eef 100644 --- a/plugins/filter_wasm/filter_wasm.c +++ b/plugins/filter_wasm/filter_wasm.c @@ -318,6 +318,8 @@ static int cb_wasm_pre_run(struct flb_filter_instance *f_ins, { struct flb_filter_wasm *ctx = NULL; int ret = -1; + char path[PATH_MAX + 1]; + const char *resolved; /* Allocate space for the configuration */ ctx = flb_calloc(1, sizeof(struct flb_filter_wasm)); @@ -332,7 +334,9 @@ static int cb_wasm_pre_run(struct flb_filter_instance *f_ins, } /* Check accessibility for the wasm path */ - ret = access(ctx->wasm_path, R_OK); + resolved = flb_utils_resolve_config_path(ctx->wasm_path, config->conf_path, + path, sizeof(path)); + ret = resolved ? access(resolved, R_OK) : -1; if (ret != 0) { flb_plg_error(f_ins, "cannot access wasm program at %s", ctx->wasm_path); goto pre_run_error; @@ -356,6 +360,8 @@ static int cb_wasm_init(struct flb_filter_instance *f_ins, struct flb_wasm_config *wasm_conf = NULL; int ret = -1; const char *tmp; + const char *resolved; + char path[PATH_MAX + 1]; int event_format; /* Allocate space for the configuration */ @@ -407,7 +413,12 @@ static int cb_wasm_init(struct flb_filter_instance *f_ins, flb_filter_set_context(f_ins, ctx); /* Instantiate the WASM module once and store it in the context */ - ctx->wasm = flb_wasm_instantiate(config, ctx->wasm_path, + resolved = flb_utils_resolve_config_path(ctx->wasm_path, config->conf_path, + path, sizeof(path)); + if (!resolved) { + goto init_error; + } + ctx->wasm = flb_wasm_instantiate(config, resolved, ctx->accessible_dir_list, ctx->wasm_conf); From f9cfd32a25daaee466b1bd88b518142238e428f6 Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Thu, 29 Oct 2026 15:26:57 +0900 Subject: [PATCH 04/11] processor_fts: prefer configuration-relative policy scripts Signed-off-by: Hiroshi Hatake --- plugins/processor_fts/fts.h | 1 + plugins/processor_fts/fts_runtime.c | 21 ++++++++++++++++++++- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/plugins/processor_fts/fts.h b/plugins/processor_fts/fts.h index 952c37b19af..897fdea2006 100644 --- a/plugins/processor_fts/fts.h +++ b/plugins/processor_fts/fts.h @@ -89,6 +89,7 @@ struct fts_value { struct fts_runtime { struct flb_luajit *vm; char *script; + char *resolved_script; char *code; char *call; char *error_mode; diff --git a/plugins/processor_fts/fts_runtime.c b/plugins/processor_fts/fts_runtime.c index 51b3d2033e9..38b85271d3c 100644 --- a/plugins/processor_fts/fts_runtime.c +++ b/plugins/processor_fts/fts_runtime.c @@ -18,6 +18,7 @@ */ #include +#include #ifdef FLB_HAVE_LUAJIT #include #endif @@ -165,6 +166,8 @@ void fts_runtime_destroy(struct fts_runtime *ctx) flb_free(ctx->undo); ctx->undo = NULL; ctx->undo_size = 0; + flb_free(ctx->resolved_script); + ctx->resolved_script = NULL; if (ctx->vm) { flb_luajit_destroy(ctx->vm); @@ -311,7 +314,7 @@ static int initialize_policy(lua_State *l) ret = flb_luajit_load_buffer(ctx->vm, ctx->code, strlen(ctx->code), "fts_policy"); } else { - ret = flb_luajit_load_script(ctx->vm, ctx->script); + ret = flb_luajit_load_script(ctx->vm, ctx->resolved_script ? ctx->resolved_script : ctx->script); } if (ret != 0) { @@ -344,6 +347,22 @@ int fts_runtime_initialize(struct fts_runtime *ctx, struct flb_config *config) { lua_State *l; int ret; + char path[PATH_MAX + 1]; + const char *resolved; + + if (ctx->script) { + resolved = flb_utils_resolve_config_path(ctx->script, config->conf_path, + path, sizeof(path)); + if (!resolved) { + return FLB_PROCESSOR_FAILURE; + } + if (resolved != ctx->script) { + ctx->resolved_script = flb_strdup(resolved); + if (!ctx->resolved_script) { + return FLB_PROCESSOR_FAILURE; + } + } + } ctx->vm = flb_luajit_create(config); if (!ctx->vm) { From 86ded843bb56f441fa7490ac7ebcd23baba09796 Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Thu, 29 Oct 2026 15:26:58 +0900 Subject: [PATCH 05/11] config_format: prefer configuration-relative includes Signed-off-by: Hiroshi Hatake --- src/config_format/flb_cf_fluentbit.c | 27 +++++++++++---------------- 1 file changed, 11 insertions(+), 16 deletions(-) diff --git a/src/config_format/flb_cf_fluentbit.c b/src/config_format/flb_cf_fluentbit.c index 8f3ee566161..22cddaa38db 100644 --- a/src/config_format/flb_cf_fluentbit.c +++ b/src/config_format/flb_cf_fluentbit.c @@ -24,6 +24,7 @@ #include #include #include +#include #include @@ -438,27 +439,21 @@ static int read_config(struct flb_cf *cf, struct local_ctx *ctx, return -1; } - /* Check if the path exists (relative cases for included files) */ #ifndef FLB_HAVE_STATIC_CONF if (ctx->level >= 0) { - ret = stat(cfg_file, &st); - if (ret == -1 && errno == ENOENT) { - /* Try to resolve the real path (if exists) */ - if (cfg_file[0] == '/') { - return -1; - } - - if (ctx->root_path) { - snprintf(tmp, PATH_MAX, "%s/%s", ctx->root_path, cfg_file); - cfg_file = tmp; - } - /* stat again */ - ret = stat(cfg_file, &st); - if (ret < 0) { - flb_errno(); + /* Keep the main file as supplied; resolve only included files. */ + if (ctx->level > 0) { + cfg_file = (char *) flb_utils_resolve_config_path(cfg_file, ctx->root_path, + tmp, sizeof(tmp)); + if (!cfg_file) { return -1; } } + ret = stat(cfg_file, &st); + if (ret < 0) { + flb_errno(); + return -1; + } #ifndef _WIN32 /* check if readed file */ for (i=0; i<*ino_num; i++) { From 42a83a874c836f70bbac01e354ffaf4c2ff2a8d6 Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Thu, 29 Oct 2026 15:26:58 +0900 Subject: [PATCH 06/11] lib: prefer configuration-relative auxiliary files Signed-off-by: Hiroshi Hatake --- src/flb_lib.c | 25 +++++-------------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/src/flb_lib.c b/src/flb_lib.c index f4dab73948c..298e0ce7ee5 100644 --- a/src/flb_lib.c +++ b/src/flb_lib.c @@ -710,27 +710,12 @@ int flb_lib_config_file(struct flb_lib_ctx *ctx, const char *path) char *cfg = NULL; char *end; char *real_path; - struct stat st; - - /* Check if file exists and resolve path */ - ret = stat(path, &st); - if (ret == -1 && errno == ENOENT) { - /* Try to resolve the real path (if exists) */ - if (path[0] == '/') { - fprintf(stderr, "Error: configuration file not found: %s\n", path); - return -1; - } - if (ctx->config->conf_path) { - snprintf(tmp, PATH_MAX, "%s%s", ctx->config->conf_path, path); - cfg = tmp; - } - else { - cfg = (char *) path; - } - } - else { - cfg = (char *) path; + cfg = (char *) flb_utils_resolve_config_path(path, ctx->config->conf_path, + tmp, sizeof(tmp)); + if (!cfg) { + fprintf(stderr, "Error: configuration file path is too long: %s\n", path); + return -1; } if (access(cfg, R_OK) != 0) { From 43baa601a5b3ed0265d275cdd5e24ff89014bfe3 Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Thu, 29 Oct 2026 15:26:59 +0900 Subject: [PATCH 07/11] parser: prefer configuration-relative parser files Signed-off-by: Hiroshi Hatake --- src/flb_parser.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/src/flb_parser.c b/src/flb_parser.c index 15a77442937..9162f9e36ac 100644 --- a/src/flb_parser.c +++ b/src/flb_parser.c @@ -1689,25 +1689,22 @@ int flb_parser_load_multiline_parser_definitions(const char *cfg, struct flb_cf int flb_parser_conf_file_stat(const char *file, struct flb_config *config) { int ret; + char tmp[PATH_MAX + 1]; + const char *cfg; struct stat st; - ret = stat(file, &st); - if (ret == -1 && errno == ENOENT) { - /* Try to resolve the real path (if exists) */ - if (file[0] == '/') { - flb_utils_error(FLB_ERR_CFG_PARSER_FILE); - return -1; - } - - if (config->conf_path) { - /* Handle as special case here. */ - return -2; - } + cfg = flb_utils_resolve_config_path(file, config->conf_path, tmp, sizeof(tmp)); + if (!cfg) { + return -1; + } + ret = stat(cfg, &st); + if (ret == -1) { + flb_utils_error(FLB_ERR_CFG_PARSER_FILE); return -1; } - return 0; + return cfg == file ? 0 : -2; } /* Load parsers from a configuration file */ @@ -1724,7 +1721,7 @@ int flb_parser_conf_file(const char *file, struct flb_config *config) return -1; } else if (ret == -2) { - snprintf(tmp, PATH_MAX, "%s%s", config->conf_path, file); + snprintf(tmp, sizeof(tmp), "%s%s", config->conf_path, file); cfg = tmp; } else { From c4e597456cd92340ab52e48315ed09ca0ef23fb7 Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Thu, 29 Oct 2026 15:27:00 +0900 Subject: [PATCH 08/11] plugin: prefer configuration-relative plugin files Signed-off-by: Hiroshi Hatake --- src/flb_plugin.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/src/flb_plugin.c b/src/flb_plugin.c index 327a968afcc..a8919553810 100644 --- a/src/flb_plugin.c +++ b/src/flb_plugin.c @@ -388,27 +388,16 @@ int flb_plugin_load_config_file(const char *file, struct flb_config *config) char *cfg = NULL; struct mk_list *head; struct cfl_list *head_e; - struct stat st; struct flb_cf *cf; struct flb_cf_section *section; struct cfl_kvpair *entry; #ifndef FLB_HAVE_STATIC_CONF - ret = stat(file, &st); - if (ret == -1 && errno == ENOENT) { - /* Try to resolve the real path (if exists) */ - if (file[0] == '/') { - flb_utils_error(FLB_ERR_CFG_PLUGIN_FILE); - return -1; - } - - if (config->conf_path) { - snprintf(tmp, PATH_MAX, "%s%s", config->conf_path, file); - cfg = tmp; - } - } - else { - cfg = (char *) file; + cfg = (char *) flb_utils_resolve_config_path(file, config->conf_path, + tmp, sizeof(tmp)); + if (!cfg) { + flb_utils_error(FLB_ERR_CFG_PLUGIN_FILE); + return -1; } flb_debug("[plugin] opening configuration file %s", cfg); From 5cbbb8cb26ea59f41b68435377567ec37d52871e Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Thu, 29 Oct 2026 15:27:01 +0900 Subject: [PATCH 09/11] upstream_ha: prefer configuration-relative upstream files Signed-off-by: Hiroshi Hatake --- src/flb_upstream_ha.c | 18 +++--------------- 1 file changed, 3 insertions(+), 15 deletions(-) diff --git a/src/flb_upstream_ha.c b/src/flb_upstream_ha.c index 7c372893225..0206a9efd22 100644 --- a/src/flb_upstream_ha.c +++ b/src/flb_upstream_ha.c @@ -361,7 +361,6 @@ struct flb_upstream_ha *flb_upstream_ha_from_file(const char *file, const char *cfg = NULL; char *tmp; char path[PATH_MAX + 1]; - struct stat st; struct mk_list *head; struct mk_list *g_head; struct flb_upstream_ha *ups; @@ -372,20 +371,9 @@ struct flb_upstream_ha *flb_upstream_ha_from_file(const char *file, struct flb_cf_section *node_section; #ifndef FLB_HAVE_STATIC_CONF - ret = stat(file, &st); - if (ret == -1 && errno == ENOENT) { - /* Try to resolve the real path (if exists) */ - if (file[0] == '/') { - return NULL; - } - - if (config->conf_path) { - snprintf(path, PATH_MAX, "%s%s", config->conf_path, file); - cfg = path; - } - } - else { - cfg = file; + cfg = flb_utils_resolve_config_path(file, config->conf_path, path, sizeof(path)); + if (!cfg) { + return NULL; } flb_debug("[upstream_ha] opening file %s", cfg); cf = flb_cf_create_from_file(NULL, (char *) cfg); From 4128d8ba8664cae411070b6e28e3f35e54e9a6fc Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Thu, 29 Oct 2026 15:27:02 +0900 Subject: [PATCH 10/11] stream_processor: prefer configuration-relative task files Signed-off-by: Hiroshi Hatake --- src/stream_processor/flb_sp.c | 21 +++++---------------- 1 file changed, 5 insertions(+), 16 deletions(-) diff --git a/src/stream_processor/flb_sp.c b/src/stream_processor/flb_sp.c index 855f2861c22..ec41e148c35 100644 --- a/src/stream_processor/flb_sp.c +++ b/src/stream_processor/flb_sp.c @@ -63,28 +63,17 @@ static int sp_config_file(struct flb_config *config, struct flb_sp *sp, flb_sds_t exec; char *cfg = NULL; char tmp[PATH_MAX + 1]; - struct stat st; struct mk_list *head; struct flb_sp_task *task; struct flb_cf *cf; struct flb_cf_section *section; #ifndef FLB_HAVE_STATIC_CONF - ret = stat(file, &st); - if (ret == -1 && errno == ENOENT) { - /* Try to resolve the real path (if exists) */ - if (file[0] == '/') { - flb_error("[sp] cannot open configuration file: %s", file); - return -1; - } - - if (config->conf_path) { - snprintf(tmp, PATH_MAX, "%s%s", config->conf_path, file); - cfg = tmp; - } - } - else { - cfg = (char *) file; + cfg = (char *) flb_utils_resolve_config_path(file, config->conf_path, + tmp, sizeof(tmp)); + if (!cfg) { + flb_error("[sp] configuration file path is too long: %s", file); + return -1; } cf = flb_cf_create_from_file(NULL, cfg); From 8e5db7283694e26a9b4a6dc839dea1a3fde979b1 Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Thu, 29 Oct 2026 15:27:02 +0900 Subject: [PATCH 11/11] tests: integration: cover configuration path precedence Signed-off-by: Hiroshi Hatake --- .../tests/test_config_classic_includes.py | 63 +++++++++++++++++++ .../filter_lua/tests/test_filter_lua_001.py | 42 +++++++++++++ .../scenarios/processor_fts/tests/test_fts.py | 25 ++++++++ 3 files changed, 130 insertions(+) create mode 100644 tests/integration/scenarios/config_yaml/tests/test_config_classic_includes.py diff --git a/tests/integration/scenarios/config_yaml/tests/test_config_classic_includes.py b/tests/integration/scenarios/config_yaml/tests/test_config_classic_includes.py new file mode 100644 index 00000000000..8e6dfac2136 --- /dev/null +++ b/tests/integration/scenarios/config_yaml/tests/test_config_classic_includes.py @@ -0,0 +1,63 @@ +"""Classic includes must prefer the main configuration directory.""" + +from pathlib import Path + +from utils.test_service import FluentBitTestService + + +def test_classic_include_prefers_config_directory(tmp_path, monkeypatch): + config_dir = tmp_path / "config" + working_dir = tmp_path / "working" + config_dir.mkdir() + working_dir.mkdir() + (config_dir / "input.conf").write_text( + '[INPUT]\n Name dummy\n Tag include.test\n' + ' Dummy {"message":"config-selected"}\n Samples 1\n') + (working_dir / "input.conf").write_text( + '[INPUT]\n Name dummy\n Tag include.test\n' + ' Dummy {"message":"working-selected"}\n Samples 1\n') + config = config_dir / "fluent-bit.conf" + config.write_text( + '[SERVICE]\n Flush 0.2\n Grace 1\n HTTP_Server On\n' + ' HTTP_Port ${FLUENT_BIT_HTTP_MONITORING_PORT}\n' + '@INCLUDE input.conf\n' + '[OUTPUT]\n Name stdout\n Match *\n Format json_lines\n') + + monkeypatch.chdir(working_dir) + service = FluentBitTestService(str(config)) + try: + service.start() + service.wait_for_condition( + lambda: "config-selected" in Path(service.flb.log_file).read_text(), + timeout=15, + ) + assert "working-selected" not in Path(service.flb.log_file).read_text() + finally: + service.stop() + + +def test_classic_relative_main_config_is_not_resolved_again(tmp_path, monkeypatch): + config_dir = tmp_path / "config" + nested_dir = config_dir / "config" + nested_dir.mkdir(parents=True) + (config_dir / "main.conf").write_text( + '[SERVICE]\n Flush 0.2\n Grace 1\n HTTP_Server On\n' + ' HTTP_Port ${FLUENT_BIT_HTTP_MONITORING_PORT}\n' + '@INCLUDE input.conf\n' + '[OUTPUT]\n Name stdout\n Match *\n Format json_lines\n') + (config_dir / "input.conf").write_text( + '[INPUT]\n Name dummy\n Tag include.test\n' + ' Dummy {"message":"requested-main-selected"}\n Samples 1\n') + # Re-resolving config/main.conf against its own directory selects this file. + (nested_dir / "main.conf").write_text('[INPUT]\n Name nonexistent_shadow_plugin\n') + + monkeypatch.chdir(tmp_path) + service = FluentBitTestService(str(Path("config") / "main.conf")) + try: + service.start() + service.wait_for_condition( + lambda: "requested-main-selected" in Path(service.flb.log_file).read_text(), + timeout=15, + ) + finally: + service.stop() diff --git a/tests/integration/scenarios/filter_lua/tests/test_filter_lua_001.py b/tests/integration/scenarios/filter_lua/tests/test_filter_lua_001.py index 3448ad2c8c4..a7431681cad 100644 --- a/tests/integration/scenarios/filter_lua/tests/test_filter_lua_001.py +++ b/tests/integration/scenarios/filter_lua/tests/test_filter_lua_001.py @@ -93,3 +93,45 @@ def records(): record["values"] == values and record["optional"] is None for record in output) finally: service.stop() + + +@pytest.mark.parametrize("context", ["filter", "processor"]) +def test_script_prefers_config_directory(tmp_path, monkeypatch, context): + config_dir = tmp_path / "config" + working_dir = tmp_path / "working" + config_dir.mkdir() + working_dir.mkdir() + (config_dir / "policy.lua").write_text( + 'function enrich(tag, timestamp, record) record.source = "config"; ' + 'return 2, timestamp, record end\n', encoding="utf-8") + (working_dir / "policy.lua").write_text( + 'function enrich(tag, timestamp, record) record.source = "working"; ' + 'return 2, timestamp, record end\n', encoding="utf-8") + + lua_filter = {"name": "lua", "script": "policy.lua", "call": "enrich"} + dummy = {"name": "dummy", "tag": "lua.test", "dummy": '{"message":"lua-test"}'} + pipeline = {"inputs": [dummy], + "outputs": [{"name": "stdout", "match": "*", "format": "json_lines"}]} + if context == "processor": + dummy["processors"] = {"logs": [lua_filter]} + else: + lua_filter["match"] = "*" + pipeline["filters"] = [lua_filter] + config = config_dir / "fluent-bit.yaml" + config.write_text(yaml.safe_dump({ + "service": {"flush": 0.2, "grace": 1, "http_server": True, + "http_port": "${FLUENT_BIT_HTTP_MONITORING_PORT}"}, + "pipeline": pipeline, + })) + + monkeypatch.chdir(working_dir) + service = FluentBitTestService(str(config)) + try: + service.start() + service.wait_for_condition( + lambda: '"source":"config"' in Path(service.flb.log_file).read_text(), + timeout=15, + ) + assert '"source":"working"' not in Path(service.flb.log_file).read_text() + finally: + service.stop() diff --git a/tests/integration/scenarios/processor_fts/tests/test_fts.py b/tests/integration/scenarios/processor_fts/tests/test_fts.py index 578303900e0..ac2ee809b99 100644 --- a/tests/integration/scenarios/processor_fts/tests/test_fts.py +++ b/tests/integration/scenarios/processor_fts/tests/test_fts.py @@ -272,6 +272,31 @@ def test_script_file_and_default_callback(tmp_path): service.stop() +def test_script_prefers_config_directory(tmp_path, monkeypatch): + working_dir = tmp_path / "working" + working_dir.mkdir() + (tmp_path / "policy.lua").write_text( + 'function process(log) log.body:set("message", "config") end') + (working_dir / "policy.lua").write_text( + 'function process(log) log.body:set("message", "working") end') + service = make_service(tmp_path, "unused") + config = tmp_path / "typed.yaml" + document = yaml.safe_load(config.read_text()) + processor = document["pipeline"]["inputs"][0]["processors"]["logs"][0] + processor.pop("call") + processor.pop("code") + processor["script"] = "policy.lua" + config.write_text(yaml.safe_dump(document)) + + monkeypatch.chdir(working_dir) + try: + service.start() + output = service.wait_for_condition(lambda: records(service), timeout=30) + assert all(log["message"] == "config" for log in output) + finally: + service.stop() + + @pytest.mark.parametrize("signal", ["profiles"]) def test_unsupported_signals_fail_startup(tmp_path, signal): service = make_service(tmp_path, "function process_log(log) end")