From b6810abfd074295821c0b6f0b9d8a92c421ca865 Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Thu, 2 Apr 2026 18:06:56 +0900 Subject: [PATCH 1/4] plugin_alias: Implement a mechanism of plugin aliases Signed-off-by: Hiroshi Hatake --- include/fluent-bit/flb_plugin_alias.h | 48 +++++++++ src/CMakeLists.txt | 1 + src/flb_plugin_alias.c | 144 ++++++++++++++++++++++++++ 3 files changed, 193 insertions(+) create mode 100644 include/fluent-bit/flb_plugin_alias.h create mode 100644 src/flb_plugin_alias.c diff --git a/include/fluent-bit/flb_plugin_alias.h b/include/fluent-bit/flb_plugin_alias.h new file mode 100644 index 00000000000..362b815dec5 --- /dev/null +++ b/include/fluent-bit/flb_plugin_alias.h @@ -0,0 +1,48 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Fluent Bit + * ========== + * Copyright (C) 2015-2026 The Fluent Bit Authors + * + * 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 + * + * 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 FLB_PLUGIN_ALIAS_H +#define FLB_PLUGIN_ALIAS_H + +#include + +/* + * Returned by flb_plugin_alias_rewrite() when an alias exists but an internal + * error prevents generating a rewritten string. + */ +#define FLB_PLUGIN_ALIAS_ERR ((char *) -1) + +/* + * Returns the canonical plugin name for alias_name when a mapping exists, + * otherwise returns NULL. + */ +const char *flb_plugin_alias_get(int plugin_type, const char *alias_name, + size_t alias_name_length); + +/* + * Rewrites plugin_reference when it starts with a known alias. + * + * Return values: + * - NULL: no rewrite needed + * - FLB_PLUGIN_ALIAS_ERR: rewrite needed but failed + * - allocated string: rewritten plugin reference (caller must free) + */ +char *flb_plugin_alias_rewrite(int plugin_type, const char *plugin_reference); + +#endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a47a5d9d658..8b0078afbc5 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -67,6 +67,7 @@ set(src flb_crypto.c flb_random.c flb_plugin.c + flb_plugin_alias.c flb_gzip.c flb_snappy.c flb_zstd.c diff --git a/src/flb_plugin_alias.c b/src/flb_plugin_alias.c new file mode 100644 index 00000000000..dcc0d65b3e1 --- /dev/null +++ b/src/flb_plugin_alias.c @@ -0,0 +1,144 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Fluent Bit + * ========== + * Copyright (C) 2015-2026 The Fluent Bit Authors + * + * 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 + * + * 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. + */ + +#include +#include + +#include +#include +#include +#include + +struct flb_plugin_alias_entry { + int plugin_type; + const char *alias_name; + const char *plugin_name; +}; + +/* + * Table that maps user-facing aliases to plugin short names. + * + * Keep this table focused on backwards/forwards compatibility names where the + * historical short name is still used internally by the plugin implementation. + */ +static struct flb_plugin_alias_entry plugin_aliases[] = { + { + FLB_PLUGIN_OUTPUT, + "elasticsearch", + "es" + }, + { + 0, + NULL, + NULL + } +}; + +static size_t protocol_part_length(const char *plugin_reference) +{ + char *separator; + + separator = strstr(plugin_reference, "://"); + if (separator != NULL && separator != plugin_reference) { + return (size_t) (separator - plugin_reference); + } + + return strlen(plugin_reference); +} + +const char *flb_plugin_alias_get(int plugin_type, const char *alias_name, + size_t alias_name_length) +{ + int index; + struct flb_plugin_alias_entry *entry; + + if (alias_name == NULL || alias_name_length == 0) { + return NULL; + } + + for (index = 0; plugin_aliases[index].alias_name != NULL; index++) { + entry = &plugin_aliases[index]; + + if (entry->plugin_type != plugin_type) { + continue; + } + + if (strlen(entry->alias_name) != alias_name_length) { + continue; + } + + if (strncasecmp(entry->alias_name, alias_name, alias_name_length) == 0) { + return entry->plugin_name; + } + } + + return NULL; +} + +char *flb_plugin_alias_rewrite(int plugin_type, const char *plugin_reference) +{ + int ret; + size_t reference_length; + size_t protocol_length; + size_t plugin_name_length; + char *rewritten_reference; + const char *plugin_name; + + if (plugin_reference == NULL) { + return NULL; + } + + protocol_length = protocol_part_length(plugin_reference); + if (protocol_length == 0) { + return NULL; + } + + plugin_name = flb_plugin_alias_get(plugin_type, plugin_reference, + protocol_length); + if (plugin_name == NULL) { + return NULL; + } + + plugin_name_length = strlen(plugin_name); + + if (plugin_name_length == protocol_length && + strncasecmp(plugin_name, plugin_reference, protocol_length) == 0) { + return NULL; + } + + reference_length = strlen(plugin_reference); + rewritten_reference = flb_calloc(1, reference_length - protocol_length + + plugin_name_length + 1); + if (rewritten_reference == NULL) { + flb_errno(); + return FLB_PLUGIN_ALIAS_ERR; + } + + memcpy(rewritten_reference, plugin_name, plugin_name_length); + + ret = snprintf(rewritten_reference + plugin_name_length, + reference_length - protocol_length + 1, + "%s", plugin_reference + protocol_length); + if (ret < 0) { + flb_free(rewritten_reference); + return FLB_PLUGIN_ALIAS_ERR; + } + + return rewritten_reference; +} From 5b199e0c99bdb22f23bd90cbd59a3809abfaf32c Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Thu, 2 Apr 2026 18:08:38 +0900 Subject: [PATCH 2/4] network: Handle network separator correctly Signed-off-by: Hiroshi Hatake --- src/flb_network.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/src/flb_network.c b/src/flb_network.c index 5783d93c50d..2a2c8bcb218 100644 --- a/src/flb_network.c +++ b/src/flb_network.c @@ -161,6 +161,7 @@ int flb_net_host_set(const char *plugin_name, struct flb_net_host *host, const c int len; int olen; const char *s, *e, *u; + const char *separator; memset(host, '\0', sizeof(struct flb_net_host)); @@ -174,7 +175,16 @@ int flb_net_host_set(const char *plugin_name, struct flb_net_host *host, const c return -1; } - s = address + len; + separator = strchr(address, ':'); + if (separator != NULL && + separator != address && + separator[1] == '/' && + separator[2] == '/') { + s = separator + 3; + } + else { + s = address + len; + } if (*s == '[') { /* IPv6 address (RFC 3986) */ e = strchr(++s, ']'); @@ -2344,4 +2354,4 @@ uint64_t flb_net_htonll(uint64_t value) #else return value; #endif -} \ No newline at end of file +} From 09cda72d6957f832138a510cea93ae462476a496 Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Thu, 2 Apr 2026 18:09:05 +0900 Subject: [PATCH 3/4] output: Handle plugin aliases Signed-off-by: Hiroshi Hatake --- src/flb_output.c | 40 ++++++++++++++++++++++++++++++++++------ 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/src/flb_output.c b/src/flb_output.c index ecd9a75a298..aa926a4f61a 100644 --- a/src/flb_output.c +++ b/src/flb_output.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -128,6 +129,7 @@ static int check_protocol(const char *prot, const char *output) { int len; char *p; + const char *alias_target; p = strstr(output, "://"); if (p && p != output) { @@ -137,12 +139,16 @@ static int check_protocol(const char *prot, const char *output) len = strlen(output); } - if (strlen(prot) != len) { - return 0; + /* Output plugin match */ + if (strlen(prot) == (size_t) len && + strncasecmp(prot, output, len) == 0) { + return 1; } - /* Output plugin match */ - if (strncasecmp(prot, output, len) == 0) { + alias_target = flb_plugin_alias_get(FLB_PLUGIN_OUTPUT, output, len); + if (alias_target != NULL && + strlen(alias_target) == strlen(prot) && + strcasecmp(prot, alias_target) == 0) { return 1; } @@ -676,6 +682,8 @@ struct flb_output_instance *flb_output_new(struct flb_config *config, { int ret = -1; int flags = 0; + const char *output_name; + char *output_uri; struct mk_list *head; struct flb_output_plugin *plugin; struct flb_output_instance *instance = NULL; @@ -684,9 +692,12 @@ struct flb_output_instance *flb_output_new(struct flb_config *config, return NULL; } + output_name = output; + output_uri = NULL; + mk_list_foreach(head, &config->out_plugins) { plugin = mk_list_entry(head, struct flb_output_plugin, _head); - if (!check_protocol(plugin->name, output)) { + if (!check_protocol(plugin->name, output_name)) { plugin = NULL; continue; } @@ -818,7 +829,24 @@ struct flb_output_instance *flb_output_new(struct flb_config *config, #endif if (plugin->flags & FLB_OUTPUT_NET) { - ret = flb_net_host_set(plugin->name, &instance->host, output); + output_uri = flb_plugin_alias_rewrite(FLB_PLUGIN_OUTPUT, output_name); + if (output_uri == FLB_PLUGIN_ALIAS_ERR) { + if (instance->flags & FLB_OUTPUT_SYNCHRONOUS) { + flb_task_queue_destroy(instance->singleplex_queue); + } + flb_free(instance->http_server_config); + flb_free(instance); + return NULL; + } + else if (output_uri != NULL) { + output_name = output_uri; + } + + ret = flb_net_host_set(plugin->name, &instance->host, output_name); + if (output_uri != NULL) { + flb_free(output_uri); + } + if (ret != 0) { if (instance->flags & FLB_OUTPUT_SYNCHRONOUS) { flb_task_queue_destroy(instance->singleplex_queue); From e19cc0469fe47087cae3ac123add01ccd1343555 Mon Sep 17 00:00:00 2001 From: Hiroshi Hatake Date: Thu, 2 Apr 2026 18:09:39 +0900 Subject: [PATCH 4/4] tests: Add internal tests for handling plugin aliases Signed-off-by: Hiroshi Hatake --- tests/internal/CMakeLists.txt | 1 + tests/internal/plugin_alias.c | 130 ++++++++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+) create mode 100644 tests/internal/plugin_alias.c diff --git a/tests/internal/CMakeLists.txt b/tests/internal/CMakeLists.txt index 9f01fc93b26..9f4543764fc 100644 --- a/tests/internal/CMakeLists.txt +++ b/tests/internal/CMakeLists.txt @@ -53,6 +53,7 @@ set(UNIT_TESTS_FILES endianness.c task_map.c strptime.c + plugin_alias.c storage_inherit.c unicode.c opentelemetry.c diff --git a/tests/internal/plugin_alias.c b/tests/internal/plugin_alias.c new file mode 100644 index 00000000000..2f9d9306e17 --- /dev/null +++ b/tests/internal/plugin_alias.c @@ -0,0 +1,130 @@ +/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ + +/* Fluent Bit + * ========== + * Copyright (C) 2015-2026 The Fluent Bit Authors + * + * 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 + * + * 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. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "flb_tests_internal.h" + +void plugin_alias_lookup_test() +{ + const char *alias_target; + + alias_target = flb_plugin_alias_get(FLB_PLUGIN_OUTPUT, "elasticsearch", + strlen("elasticsearch")); + if (!TEST_CHECK(alias_target != NULL)) { + TEST_MSG("output plugin alias was not resolved"); + return; + } + + if (!TEST_CHECK(strcmp(alias_target, "es") == 0)) { + TEST_MSG("unexpected alias target: %s", alias_target); + } +} + +void plugin_alias_rewrite_test() +{ + char *rewritten_name; + + rewritten_name = flb_plugin_alias_rewrite(FLB_PLUGIN_OUTPUT, + "elasticsearch://127.0.0.1:9200"); + if (!TEST_CHECK(rewritten_name != FLB_PLUGIN_ALIAS_ERR)) { + TEST_MSG("error while rewriting output plugin alias"); + return; + } + if (!TEST_CHECK(rewritten_name != NULL)) { + TEST_MSG("could not rewrite output plugin alias"); + return; + } + + if (!TEST_CHECK(strcmp(rewritten_name, "es://127.0.0.1:9200") == 0)) { + TEST_MSG("unexpected rewritten output plugin name: %s", rewritten_name); + } + + flb_free(rewritten_name); +} + +void network_alias_address_parse_test() +{ + int ret; + struct flb_net_host host; + + ret = flb_net_host_set("es", &host, "elasticsearch://127.0.0.1:9200/path"); + if (!TEST_CHECK(ret == 0)) { + TEST_MSG("could not parse alias output address"); + return; + } + + if (!TEST_CHECK(strcmp(host.name, "127.0.0.1") == 0)) { + TEST_MSG("unexpected host name parsed from alias output address: %s", + host.name); + } + + if (!TEST_CHECK(host.port == 9200)) { + TEST_MSG("unexpected host port parsed from alias output address: %d", + host.port); + } + + flb_sds_destroy(host.name); + flb_sds_destroy(host.listen); + flb_uri_destroy(host.uri); + flb_sds_destroy(host.address); +} + +void output_alias_instantiation_test() +{ + struct flb_config *config; + struct flb_output_instance *instance; + + config = flb_config_init(); + if (!TEST_CHECK(config != NULL)) { + TEST_MSG("could not initialize config context"); + return; + } + + instance = flb_output_new(config, "elasticsearch", NULL, FLB_TRUE); + if (!TEST_CHECK(instance != NULL)) { + TEST_MSG("could not instantiate aliased output plugin"); + flb_config_exit(config); + return; + } + + if (!TEST_CHECK(strcmp(instance->p->name, "es") == 0)) { + TEST_MSG("unexpected output plugin instantiated for alias: %s", + instance->p->name); + } + + flb_output_instance_destroy(instance); + flb_config_exit(config); +} + +TEST_LIST = { + { "plugin_alias_lookup_test", plugin_alias_lookup_test }, + { "plugin_alias_rewrite_test", plugin_alias_rewrite_test }, + { "network_alias_address_parse_test", network_alias_address_parse_test }, + { "output_alias_instantiation_test", output_alias_instantiation_test }, + { 0 } +};