diff --git a/include/fluent-bit/flb_plugin_alias.h b/include/fluent-bit/flb_plugin_alias.h new file mode 100644 index 00000000000..bd4746b2e3a --- /dev/null +++ b/include/fluent-bit/flb_plugin_alias.h @@ -0,0 +1,58 @@ +/* -*- 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) + +struct flb_plugin_alias_entry { + int plugin_type; + const char *alias_name; + const char *plugin_name; +}; + +/* + * 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); + +void flb_plugin_alias_set_custom_entries( + const struct flb_plugin_alias_entry *entries); +void flb_plugin_alias_reset_custom_entries(void); + +#endif diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index a984ecc6b70..016db1cab2c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -68,6 +68,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_filter.c b/src/flb_filter.c index 79299885065..5e9a5ba17bf 100644 --- a/src/flb_filter.c +++ b/src/flb_filter.c @@ -27,6 +27,8 @@ #include #include #include +#include +#include #include #ifdef FLB_HAVE_CHUNK_TRACE @@ -435,6 +437,8 @@ struct flb_filter_instance *flb_filter_new(struct flb_config *config, const char *filter, void *data) { int id; + const char *alias_target; + const char *effective_filter_name; struct mk_list *head; struct flb_filter_plugin *plugin; struct flb_filter_instance *instance = NULL; @@ -443,14 +447,32 @@ struct flb_filter_instance *flb_filter_new(struct flb_config *config, return NULL; } + effective_filter_name = filter; + mk_list_foreach(head, &config->filter_plugins) { plugin = mk_list_entry(head, struct flb_filter_plugin, _head); - if (strcasecmp(plugin->name, filter) == 0) { + if (strcasecmp(plugin->name, effective_filter_name) == 0) { break; } plugin = NULL; } + if (plugin == NULL) { + alias_target = flb_plugin_alias_get(FLB_PLUGIN_FILTER, filter, + strlen(filter)); + if (alias_target != NULL) { + effective_filter_name = alias_target; + + mk_list_foreach(head, &config->filter_plugins) { + plugin = mk_list_entry(head, struct flb_filter_plugin, _head); + if (strcasecmp(plugin->name, effective_filter_name) == 0) { + break; + } + plugin = NULL; + } + } + } + if (!plugin) { return NULL; } @@ -493,7 +515,6 @@ struct flb_filter_instance *flb_filter_new(struct flb_config *config, mk_list_init(&instance->properties); mk_list_add(&instance->_head, &config->filters); - return instance; } diff --git a/src/flb_input.c b/src/flb_input.c index e990eee238c..3d44c6ffb8c 100644 --- a/src/flb_input.c +++ b/src/flb_input.c @@ -44,6 +44,7 @@ #include #include #include +#include /* input plugin macro helpers */ #include @@ -197,13 +198,21 @@ struct mk_list *flb_input_get_global_config_map(struct flb_config *config) static int check_protocol(const char *prot, const char *output) { int len; + char *separator; - len = strlen(prot); - if (len != strlen(output)) { + separator = strstr(output, "://"); + if (separator != NULL && separator != output) { + len = separator - output; + } + else { + len = strlen(output); + } + + if (strlen(prot) != (size_t) len) { return 0; } - if (protcmp(prot, output) != 0) { + if (strncasecmp(prot, output, len) != 0) { return 0; } @@ -275,8 +284,12 @@ struct flb_input_instance *flb_input_new(struct flb_config *config, int id; int ret; int flags = 0; + size_t input_name_length; + const char *alias_target; + const char *input_name; + const char *separator; struct mk_list *head; - struct flb_input_plugin *plugin; + struct flb_input_plugin *plugin = NULL; struct flb_input_instance *instance = NULL; /* use for locking the use of the chunk trace context. */ @@ -289,9 +302,36 @@ struct flb_input_instance *flb_input_new(struct flb_config *config, return NULL; } + input_name = input; + + /* Prefer an exact registered plugin name over an alias with the same name. */ + mk_list_foreach(head, &config->in_plugins) { + plugin = mk_list_entry(head, struct flb_input_plugin, _head); + if (check_protocol(plugin->name, input_name)) { + break; + } + plugin = NULL; + } + + if (plugin == NULL) { + separator = strstr(input, "://"); + if (separator != NULL && separator != input) { + input_name_length = separator - input; + } + else { + input_name_length = strlen(input); + } + alias_target = flb_plugin_alias_get(FLB_PLUGIN_INPUT, input, + input_name_length); + if (alias_target == NULL) { + return NULL; + } + input_name = alias_target; + } + mk_list_foreach(head, &config->in_plugins) { plugin = mk_list_entry(head, struct flb_input_plugin, _head); - if (!check_protocol(plugin->name, input)) { + if (!check_protocol(plugin->name, input_name)) { plugin = NULL; continue; } @@ -471,7 +511,12 @@ struct flb_input_instance *flb_input_new(struct flb_config *config, /* Plugin use networking */ if (plugin->flags & (FLB_INPUT_NET | FLB_INPUT_NET_SERVER)) { - ret = flb_net_host_set(plugin->name, &instance->host, input); + if (strstr(input, "://") != NULL) { + ret = flb_net_host_set(plugin->name, &instance->host, input); + } + else { + ret = flb_net_host_set(plugin->name, &instance->host, input_name); + } if (ret != 0) { if (instance->ht_log_chunks) { flb_hash_table_destroy(instance->ht_log_chunks); diff --git a/src/flb_network.c b/src/flb_network.c index 13c965bab21..8073ac72e5c 100644 --- a/src/flb_network.c +++ b/src/flb_network.c @@ -161,20 +161,26 @@ 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)); olen = strlen(address); - if (olen == strlen(plugin_name)) { - return 0; + separator = strstr(address, "://"); + if (separator != NULL && separator != address) { + s = separator + 3; } + else { + if (olen == strlen(plugin_name)) { + return 0; + } - len = strlen(plugin_name) + 3; - if (olen < len) { - return -1; + len = strlen(plugin_name) + 3; + if (olen < len) { + return -1; + } + s = address + len; } - - s = address + len; if (*s == '[') { /* IPv6 address (RFC 3986) */ e = strchr(++s, ']'); diff --git a/src/flb_output.c b/src/flb_output.c index 26f66ad9e36..517608dfddf 100644 --- a/src/flb_output.c +++ b/src/flb_output.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include #include @@ -137,12 +138,9 @@ static int check_protocol(const char *prot, const char *output) len = strlen(output); } - if (strlen(prot) != len) { - return 0; - } - /* Output plugin match */ - if (strncasecmp(prot, output, len) == 0) { + if (strlen(prot) == (size_t) len && + strncasecmp(prot, output, len) == 0) { return 1; } @@ -676,17 +674,24 @@ struct flb_output_instance *flb_output_new(struct flb_config *config, { int ret = -1; int flags = 0; + size_t output_name_length; + const char *alias_target; + const char *output_name; + const char *separator; struct mk_list *head; - struct flb_output_plugin *plugin; + struct flb_output_plugin *plugin = NULL; struct flb_output_instance *instance = NULL; if (!output) { return NULL; } + output_name = output; + + /* Prefer an exact registered plugin name over an alias with the same name. */ 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; } @@ -697,6 +702,34 @@ struct flb_output_instance *flb_output_new(struct flb_config *config, break; } + if (plugin == NULL) { + separator = strstr(output, "://"); + if (separator != NULL && separator != output) { + output_name_length = separator - output; + } + else { + output_name_length = strlen(output); + } + alias_target = flb_plugin_alias_get(FLB_PLUGIN_OUTPUT, output, + output_name_length); + if (alias_target != NULL) { + output_name = alias_target; + + mk_list_foreach(head, &config->out_plugins) { + plugin = mk_list_entry(head, struct flb_output_plugin, _head); + if (!check_protocol(plugin->name, output_name)) { + plugin = NULL; + continue; + } + + if (public_only && plugin->flags & FLB_OUTPUT_PRIVATE) { + return NULL; + } + break; + } + } + } + if (!plugin) { return NULL; } @@ -819,11 +852,25 @@ 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); + if (strstr(output, "://") != NULL) { + ret = flb_net_host_set(plugin->name, &instance->host, output); + } + else { + ret = flb_net_host_set(plugin->name, &instance->host, output_name); + } + if (ret != 0) { - if (instance->flags & FLB_OUTPUT_SYNCHRONOUS) { + if ((instance->flags & FLB_OUTPUT_SYNCHRONOUS) && + instance->singleplex_queue != NULL) { flb_task_queue_destroy(instance->singleplex_queue); } + if (instance->callback != NULL) { + flb_callback_destroy(instance->callback); + } + if (plugin->type != FLB_OUTPUT_PLUGIN_CORE && + instance->context != NULL) { + flb_free(instance->context); + } flb_free(instance->http_server_config); flb_free(instance); return NULL; diff --git a/src/flb_plugin_alias.c b/src/flb_plugin_alias.c new file mode 100644 index 00000000000..f32c4ec14f8 --- /dev/null +++ b/src/flb_plugin_alias.c @@ -0,0 +1,180 @@ +/* -*- 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 + +/* + * 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 const struct flb_plugin_alias_entry *custom_plugin_aliases = NULL; +static pthread_mutex_t custom_plugin_aliases_lock = PTHREAD_MUTEX_INITIALIZER; + +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; + const struct flb_plugin_alias_entry *entry; + const struct flb_plugin_alias_entry *aliases; + + if (alias_name == NULL || alias_name_length == 0) { + return NULL; + } + + pthread_mutex_lock(&custom_plugin_aliases_lock); + aliases = custom_plugin_aliases; + if (aliases != NULL) { + for (index = 0; aliases[index].alias_name != NULL; index++) { + entry = &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) { + pthread_mutex_unlock(&custom_plugin_aliases_lock); + return entry->plugin_name; + } + } + } + pthread_mutex_unlock(&custom_plugin_aliases_lock); + + 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; +} + +void flb_plugin_alias_set_custom_entries( + const struct flb_plugin_alias_entry *entries) +{ + pthread_mutex_lock(&custom_plugin_aliases_lock); + custom_plugin_aliases = entries; + pthread_mutex_unlock(&custom_plugin_aliases_lock); +} + +void flb_plugin_alias_reset_custom_entries(void) +{ + pthread_mutex_lock(&custom_plugin_aliases_lock); + custom_plugin_aliases = NULL; + pthread_mutex_unlock(&custom_plugin_aliases_lock); +} + +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; +} diff --git a/src/flb_processor.c b/src/flb_processor.c index 5de6a4e9780..7f04146ff6f 100644 --- a/src/flb_processor.c +++ b/src/flb_processor.c @@ -35,6 +35,7 @@ #include #include #include +#include #include struct flb_config_map processor_global_properties[] = { @@ -618,13 +619,19 @@ struct flb_processor_unit *flb_processor_unit_create(struct flb_processor *proc, char *unit_name) { int result; + int native_plugin_found; struct mk_list *head; int filter_event_type; + const char *alias_target; + const char *effective_unit_name; struct flb_filter_plugin *f = NULL; struct flb_filter_instance *f_ins; struct flb_config *config = proc->config; struct flb_processor_unit *pu = NULL; struct flb_processor_instance *processor_instance; + struct flb_processor_plugin *processor_plugin; + + effective_unit_name = unit_name; /* * Looking the processor unit by using it's name and type, the first list we @@ -641,7 +648,7 @@ struct flb_processor_unit *flb_processor_unit_create(struct flb_processor *proc, /* skip filters which don't handle the required type */ if ((event_type & filter_event_type) != 0) { - if (strcmp(f->name, unit_name) == 0) { + if (strcasecmp(f->name, effective_unit_name) == 0) { break; } } @@ -649,6 +656,51 @@ struct flb_processor_unit *flb_processor_unit_create(struct flb_processor *proc, f = NULL; } + /* A processor unit may be either a filter or a native processor. */ + native_plugin_found = FLB_FALSE; + if (f == NULL) { + mk_list_foreach(head, &config->processor_plugins) { + processor_plugin = mk_list_entry(head, struct flb_processor_plugin, _head); + if (strcasecmp(processor_plugin->name, unit_name) == 0) { + native_plugin_found = FLB_TRUE; + break; + } + } + } + + /* Prefer exact registered names before falling back to aliases. */ + if (f == NULL && native_plugin_found == FLB_FALSE) { + alias_target = flb_plugin_alias_get(FLB_PLUGIN_FILTER, unit_name, + strlen(unit_name)); + if (alias_target != NULL) { + effective_unit_name = alias_target; + + mk_list_foreach(head, &config->filter_plugins) { + f = mk_list_entry(head, struct flb_filter_plugin, _head); + + filter_event_type = f->event_type; + if (filter_event_type == 0) { + filter_event_type = FLB_FILTER_LOGS; + } + + if ((event_type & filter_event_type) != 0 && + strcasecmp(f->name, effective_unit_name) == 0) { + break; + } + f = NULL; + } + } + + if (f == NULL) { + effective_unit_name = unit_name; + alias_target = flb_plugin_alias_get(FLB_PLUGIN_PROCESSOR, unit_name, + strlen(unit_name)); + if (alias_target != NULL) { + effective_unit_name = alias_target; + } + } + } + /* allocate and initialize processor unit context */ pu = flb_calloc(1, sizeof(struct flb_processor_unit)); @@ -659,7 +711,7 @@ struct flb_processor_unit *flb_processor_unit_create(struct flb_processor *proc, pu->parent = proc; pu->event_type = event_type; - pu->name = flb_sds_create(unit_name); + pu->name = flb_sds_create(effective_unit_name); pu->condition = NULL; if (!pu->name) { @@ -673,14 +725,13 @@ struct flb_processor_unit *flb_processor_unit_create(struct flb_processor *proc, if (result != 0) { flb_sds_destroy(pu->name); flb_free(pu); - return NULL; } /* If we matched a pipeline filter, create the speacial processing unit for it */ if (f) { /* create an instance of the filter */ - f_ins = flb_filter_new(config, unit_name, NULL); + f_ins = flb_filter_new(config, effective_unit_name, NULL); if (!f_ins) { pthread_mutex_destroy(&pu->lock); @@ -725,7 +776,7 @@ struct flb_processor_unit *flb_processor_unit_create(struct flb_processor *proc, processor_instance = flb_processor_instance_create(config, pu, pu->event_type, - unit_name, NULL); + (char *) effective_unit_name, NULL); if (processor_instance == NULL) { flb_error("[processor] error creating processor '%s': plugin doesn't exist or failed to initialize", unit_name); diff --git a/tests/internal/CMakeLists.txt b/tests/internal/CMakeLists.txt index 5fd3f1b10e4..724eaa84bad 100644 --- a/tests/internal/CMakeLists.txt +++ b/tests/internal/CMakeLists.txt @@ -56,6 +56,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..f01859567ac --- /dev/null +++ b/tests/internal/plugin_alias.c @@ -0,0 +1,395 @@ +/* -*- 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 +#include + +#include + +#include "flb_tests_internal.h" + +static struct flb_plugin_alias_entry custom_aliases[] = { + { FLB_PLUGIN_INPUT, "tailing", "tail" }, + { FLB_PLUGIN_INPUT, "httping", "http" }, + { FLB_PLUGIN_FILTER, "grepper", "grep" }, + { FLB_PLUGIN_PROCESSOR, "countering", "content_modifier" }, + { FLB_PLUGIN_OUTPUT, "elasticsearch", "es_custom" }, + { 0, NULL, NULL } +}; + +static struct flb_plugin_alias_entry colliding_aliases[] = { + { FLB_PLUGIN_INPUT, "dummy", "tail" }, + { FLB_PLUGIN_FILTER, "grep", "modify" }, + { FLB_PLUGIN_PROCESSOR, "content_modifier", "labels" }, + { FLB_PLUGIN_OUTPUT, "stdout", "null" }, + { 0, NULL, NULL } +}; + +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_custom_map_test() +{ + const char *alias_target; + + flb_plugin_alias_set_custom_entries(custom_aliases); + + alias_target = flb_plugin_alias_get(FLB_PLUGIN_INPUT, "tailing", + strlen("tailing")); + TEST_CHECK(alias_target != NULL); + TEST_CHECK(strcmp(alias_target, "tail") == 0); + + alias_target = flb_plugin_alias_get(FLB_PLUGIN_FILTER, "grepper", + strlen("grepper")); + TEST_CHECK(alias_target != NULL); + TEST_CHECK(strcmp(alias_target, "grep") == 0); + + alias_target = flb_plugin_alias_get(FLB_PLUGIN_OUTPUT, "elasticsearch", + strlen("elasticsearch")); + TEST_CHECK(alias_target != NULL); + TEST_CHECK(strcmp(alias_target, "es_custom") == 0); + + flb_plugin_alias_reset_custom_entries(); + + alias_target = flb_plugin_alias_get(FLB_PLUGIN_OUTPUT, "elasticsearch", + strlen("elasticsearch")); + TEST_CHECK(alias_target != NULL); + TEST_CHECK(strcmp(alias_target, "es") == 0); +} + +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); + if (host.uri != NULL) { + flb_uri_destroy(host.uri); + } + flb_sds_destroy(host.address); + + ret = flb_net_host_set("very_long_original_plugin", &host, + "x://localhost:1234"); + if (!TEST_CHECK(ret == 0)) { + TEST_MSG("could not parse a URI with an alias shorter than its target"); + return; + } + TEST_CHECK(host.name != NULL && strcmp(host.name, "localhost") == 0); + TEST_CHECK(host.port == 1234); + + flb_sds_destroy(host.name); + flb_sds_destroy(host.listen); + if (host.uri != NULL) { + 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://127.0.0.1:9200/test", + 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); + } + TEST_CHECK(instance->host.name != NULL && + strcmp(instance->host.name, "127.0.0.1") == 0); + TEST_CHECK(instance->host.port == 9200); + + flb_output_instance_destroy(instance); + + instance = flb_output_new(config, "es", NULL, FLB_TRUE); + if (!TEST_CHECK(instance != NULL && strcmp(instance->p->name, "es") == 0)) { + TEST_MSG("could not instantiate output plugin by its original name"); + flb_config_exit(config); + return; + } + flb_output_instance_destroy(instance); + flb_config_exit(config); +} + +void input_alias_uri_instantiation_test() +{ + struct flb_config *config; + struct flb_input_instance *alias_instance; + struct flb_input_instance *original_instance; + + alias_instance = NULL; + original_instance = NULL; + flb_plugin_alias_set_custom_entries(custom_aliases); + + config = flb_config_init(); + if (!TEST_CHECK(config != NULL)) { + goto cleanup; + } + + alias_instance = flb_input_new(config, "httping://127.0.0.1:9880", + NULL, FLB_TRUE); + if (!TEST_CHECK(alias_instance != NULL && + strcmp(alias_instance->p->name, "http") == 0)) { + TEST_MSG("could not instantiate URI input through its alias"); + goto cleanup; + } + TEST_CHECK(alias_instance->host.name != NULL && + strcmp(alias_instance->host.name, "127.0.0.1") == 0); + TEST_CHECK(alias_instance->host.port == 9880); + + original_instance = flb_input_new(config, "http://127.0.0.1:9881", + NULL, FLB_TRUE); + if (!TEST_CHECK(original_instance != NULL && + strcmp(original_instance->p->name, "http") == 0)) { + TEST_MSG("could not instantiate URI input through its original name"); + goto cleanup; + } + TEST_CHECK(original_instance->host.name != NULL && + strcmp(original_instance->host.name, "127.0.0.1") == 0); + TEST_CHECK(original_instance->host.port == 9881); + +cleanup: + if (original_instance != NULL) { + flb_input_instance_destroy(original_instance); + } + if (alias_instance != NULL) { + flb_input_instance_destroy(alias_instance); + } + if (config != NULL) { + flb_config_exit(config); + } + flb_plugin_alias_reset_custom_entries(); +} + +void plugin_alias_instance_types_test() +{ + struct flb_config *config; + struct flb_input_instance *input; + struct flb_filter_instance *filter; + struct flb_processor *processor; + struct flb_processor_unit *filter_unit; + struct flb_processor_unit *native_unit; + + input = NULL; + filter = NULL; + processor = NULL; + flb_plugin_alias_set_custom_entries(custom_aliases); + + config = flb_config_init(); + if (!TEST_CHECK(config != NULL)) { + TEST_MSG("could not initialize config context"); + goto cleanup; + } + + input = flb_input_new(config, "tailing", NULL, FLB_TRUE); + if (!TEST_CHECK(input != NULL && strcmp(input->p->name, "tail") == 0)) { + TEST_MSG("could not instantiate an input plugin through its alias"); + goto cleanup; + } + + filter = flb_filter_new(config, "grepper", NULL); + if (!TEST_CHECK(filter != NULL && strcmp(filter->p->name, "grep") == 0)) { + TEST_MSG("could not instantiate a filter plugin through its alias"); + goto cleanup; + } + + processor = flb_processor_create(config, "alias_test", NULL, FLB_PLUGIN_INPUT); + if (!TEST_CHECK(processor != NULL)) { + TEST_MSG("could not create processor context"); + goto cleanup; + } + + filter_unit = flb_processor_unit_create(processor, FLB_PROCESSOR_LOGS, + "grepper"); + if (!TEST_CHECK(filter_unit != NULL && + filter_unit->unit_type == FLB_PROCESSOR_UNIT_FILTER)) { + TEST_MSG("could not instantiate a processor filter through its alias"); + goto cleanup; + } + + native_unit = flb_processor_unit_create(processor, FLB_PROCESSOR_LOGS, + "countering"); + if (!TEST_CHECK(native_unit != NULL && + native_unit->unit_type == FLB_PROCESSOR_UNIT_NATIVE)) { + TEST_MSG("could not instantiate a native processor through its alias"); + } + +cleanup: + if (processor != NULL) { + flb_processor_destroy(processor); + } + if (filter != NULL) { + flb_filter_instance_destroy(filter); + } + if (input != NULL) { + flb_input_instance_destroy(input); + } + if (config != NULL) { + flb_config_exit(config); + } + flb_plugin_alias_reset_custom_entries(); +} + +void plugin_original_name_precedence_test() +{ + struct flb_config *config; + struct flb_input_instance *input; + struct flb_filter_instance *filter; + struct flb_output_instance *output; + struct flb_processor *processor; + struct flb_processor_unit *unit; + + input = NULL; + filter = NULL; + output = NULL; + processor = NULL; + flb_plugin_alias_set_custom_entries(colliding_aliases); + + config = flb_config_init(); + if (!TEST_CHECK(config != NULL)) { + TEST_MSG("could not initialize config context"); + goto cleanup; + } + + input = flb_input_new(config, "dummy", NULL, FLB_TRUE); + TEST_CHECK(input != NULL && strcmp(input->p->name, "dummy") == 0); + + filter = flb_filter_new(config, "grep", NULL); + TEST_CHECK(filter != NULL && strcmp(filter->p->name, "grep") == 0); + + output = flb_output_new(config, "stdout", NULL, FLB_TRUE); + TEST_CHECK(output != NULL && strcmp(output->p->name, "stdout") == 0); + + processor = flb_processor_create(config, "precedence_test", NULL, + FLB_PLUGIN_INPUT); + if (processor != NULL) { + unit = flb_processor_unit_create(processor, FLB_PROCESSOR_LOGS, + "content_modifier"); + TEST_CHECK(unit != NULL && + strcmp(((struct flb_processor_instance *) unit->ctx)->p->name, + "content_modifier") == 0); + } + else { + TEST_CHECK(processor != NULL); + } + +cleanup: + if (processor != NULL) { + flb_processor_destroy(processor); + } + if (output != NULL) { + flb_output_instance_destroy(output); + } + if (filter != NULL) { + flb_filter_instance_destroy(filter); + } + if (input != NULL) { + flb_input_instance_destroy(input); + } + if (config != NULL) { + flb_config_exit(config); + } + flb_plugin_alias_reset_custom_entries(); +} + +TEST_LIST = { + { "plugin_alias_lookup_test", plugin_alias_lookup_test }, + { "plugin_alias_custom_map_test", plugin_alias_custom_map_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 }, + { "input_alias_uri_instantiation_test", input_alias_uri_instantiation_test }, + { "plugin_alias_instance_types_test", plugin_alias_instance_types_test }, + { "plugin_original_name_precedence_test", plugin_original_name_precedence_test }, + { 0 } +};