summaryrefslogtreecommitdiffstats
path: root/fluent-bit/src/flb_config.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-03-09 13:19:48 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-03-09 13:20:02 +0000
commit58daab21cd043e1dc37024a7f99b396788372918 (patch)
tree96771e43bb69f7c1c2b0b4f7374cb74d7866d0cb /fluent-bit/src/flb_config.c
parentReleasing debian version 1.43.2-1. (diff)
downloadnetdata-58daab21cd043e1dc37024a7f99b396788372918.tar.xz
netdata-58daab21cd043e1dc37024a7f99b396788372918.zip
Merging upstream version 1.44.3.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'fluent-bit/src/flb_config.c')
-rw-r--r--fluent-bit/src/flb_config.c942
1 files changed, 942 insertions, 0 deletions
diff --git a/fluent-bit/src/flb_config.c b/fluent-bit/src/flb_config.c
new file mode 100644
index 00000000..882a93c7
--- /dev/null
+++ b/fluent-bit/src/flb_config.c
@@ -0,0 +1,942 @@
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+
+/* Fluent Bit
+ * ==========
+ * Copyright (C) 2015-2022 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 <stdio.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <stddef.h>
+
+#include <monkey/mk_core.h>
+#include <fluent-bit/flb_info.h>
+#include <fluent-bit/flb_mem.h>
+#include <fluent-bit/flb_str.h>
+#include <fluent-bit/flb_kv.h>
+#include <fluent-bit/flb_env.h>
+#include <fluent-bit/flb_meta.h>
+#include <fluent-bit/flb_macros.h>
+#include <fluent-bit/flb_config.h>
+#include <fluent-bit/flb_parser.h>
+#include <fluent-bit/flb_plugin.h>
+#include <fluent-bit/flb_plugins.h>
+#include <fluent-bit/flb_slist.h>
+#include <fluent-bit/flb_kernel.h>
+#include <fluent-bit/flb_worker.h>
+#include <fluent-bit/flb_scheduler.h>
+#include <fluent-bit/flb_http_server.h>
+#include <fluent-bit/flb_plugin.h>
+#include <fluent-bit/flb_utils.h>
+#include <fluent-bit/flb_config_format.h>
+#include <fluent-bit/multiline/flb_ml.h>
+#include <fluent-bit/flb_bucket_queue.h>
+
+const char *FLB_CONF_ENV_LOGLEVEL = "FLB_LOG_LEVEL";
+
+int flb_regex_init();
+
+struct flb_service_config service_configs[] = {
+ {FLB_CONF_STR_FLUSH,
+ FLB_CONF_TYPE_DOUBLE,
+ offsetof(struct flb_config, flush)},
+
+ {FLB_CONF_STR_GRACE,
+ FLB_CONF_TYPE_INT,
+ offsetof(struct flb_config, grace)},
+
+ {FLB_CONF_STR_CONV_NAN,
+ FLB_CONF_TYPE_BOOL,
+ offsetof(struct flb_config, convert_nan_to_null)},
+
+ {FLB_CONF_STR_DAEMON,
+ FLB_CONF_TYPE_BOOL,
+ offsetof(struct flb_config, daemon)},
+
+ {FLB_CONF_STR_LOGFILE,
+ FLB_CONF_TYPE_STR,
+ offsetof(struct flb_config, log_file)},
+
+ {FLB_CONF_STR_PARSERS_FILE,
+ FLB_CONF_TYPE_STR,
+ offsetof(struct flb_config, parsers_file)},
+
+ {FLB_CONF_STR_PLUGINS_FILE,
+ FLB_CONF_TYPE_STR,
+ offsetof(struct flb_config, plugins_file)},
+
+ {FLB_CONF_STR_LOGLEVEL,
+ FLB_CONF_TYPE_STR,
+ offsetof(struct flb_config, log)},
+
+#ifdef FLB_HAVE_HTTP_SERVER
+ {FLB_CONF_STR_HTTP_SERVER,
+ FLB_CONF_TYPE_BOOL,
+ offsetof(struct flb_config, http_server)},
+
+ {FLB_CONF_STR_HTTP_LISTEN,
+ FLB_CONF_TYPE_STR,
+ offsetof(struct flb_config, http_listen)},
+
+ {FLB_CONF_STR_HTTP_PORT,
+ FLB_CONF_TYPE_STR,
+ offsetof(struct flb_config, http_port)},
+
+ {FLB_CONF_STR_HEALTH_CHECK,
+ FLB_CONF_TYPE_BOOL,
+ offsetof(struct flb_config, health_check)},
+
+ {FLB_CONF_STR_HC_ERRORS_COUNT,
+ FLB_CONF_TYPE_INT,
+ offsetof(struct flb_config, hc_errors_count)},
+
+ {FLB_CONF_STR_HC_RETRIES_FAILURE_COUNT,
+ FLB_CONF_TYPE_INT,
+ offsetof(struct flb_config, hc_retry_failure_count)},
+
+ {FLB_CONF_STR_HC_PERIOD,
+ FLB_CONF_TYPE_INT,
+ offsetof(struct flb_config, health_check_period)},
+
+#endif
+ /* DNS*/
+ {FLB_CONF_DNS_MODE,
+ FLB_CONF_TYPE_STR,
+ offsetof(struct flb_config, dns_mode)},
+
+ {FLB_CONF_DNS_RESOLVER,
+ FLB_CONF_TYPE_STR,
+ offsetof(struct flb_config, dns_resolver)},
+
+ {FLB_CONF_DNS_PREFER_IPV4,
+ FLB_CONF_TYPE_BOOL,
+ offsetof(struct flb_config, dns_prefer_ipv4)},
+
+ /* Storage */
+ {FLB_CONF_STORAGE_PATH,
+ FLB_CONF_TYPE_STR,
+ offsetof(struct flb_config, storage_path)},
+ {FLB_CONF_STORAGE_SYNC,
+ FLB_CONF_TYPE_STR,
+ offsetof(struct flb_config, storage_sync)},
+ {FLB_CONF_STORAGE_METRICS,
+ FLB_CONF_TYPE_BOOL,
+ offsetof(struct flb_config, storage_metrics)},
+ {FLB_CONF_STORAGE_CHECKSUM,
+ FLB_CONF_TYPE_BOOL,
+ offsetof(struct flb_config, storage_checksum)},
+ {FLB_CONF_STORAGE_BL_MEM_LIMIT,
+ FLB_CONF_TYPE_STR,
+ offsetof(struct flb_config, storage_bl_mem_limit)},
+ {FLB_CONF_STORAGE_MAX_CHUNKS_UP,
+ FLB_CONF_TYPE_INT,
+ offsetof(struct flb_config, storage_max_chunks_up)},
+ {FLB_CONF_STORAGE_DELETE_IRRECOVERABLE_CHUNKS,
+ FLB_CONF_TYPE_BOOL,
+ offsetof(struct flb_config, storage_del_bad_chunks)},
+ {FLB_CONF_STORAGE_TRIM_FILES,
+ FLB_CONF_TYPE_BOOL,
+ offsetof(struct flb_config, storage_trim_files)},
+
+ /* Coroutines */
+ {FLB_CONF_STR_CORO_STACK_SIZE,
+ FLB_CONF_TYPE_INT,
+ offsetof(struct flb_config, coro_stack_size)},
+
+ /* Scheduler */
+ {FLB_CONF_STR_SCHED_CAP,
+ FLB_CONF_TYPE_INT,
+ offsetof(struct flb_config, sched_cap)},
+ {FLB_CONF_STR_SCHED_BASE,
+ FLB_CONF_TYPE_INT,
+ offsetof(struct flb_config, sched_base)},
+
+#ifdef FLB_HAVE_STREAM_PROCESSOR
+ {FLB_CONF_STR_STREAMS_FILE,
+ FLB_CONF_TYPE_STR,
+ offsetof(struct flb_config, stream_processor_file)},
+ {FLB_CONF_STR_STREAMS_STR_CONV,
+ FLB_CONF_TYPE_BOOL,
+ offsetof(struct flb_config, stream_processor_str_conv)},
+#endif
+
+#ifdef FLB_HAVE_CHUNK_TRACE
+ {FLB_CONF_STR_ENABLE_CHUNK_TRACE,
+ FLB_CONF_TYPE_BOOL,
+ offsetof(struct flb_config, enable_chunk_trace)},
+#endif
+
+ {FLB_CONF_STR_HOT_RELOAD,
+ FLB_CONF_TYPE_BOOL,
+ offsetof(struct flb_config, enable_hot_reload)},
+
+ {FLB_CONF_STR_HOT_RELOAD_ENSURE_THREAD_SAFETY,
+ FLB_CONF_TYPE_BOOL,
+ offsetof(struct flb_config, ensure_thread_safety_on_hot_reloading)},
+
+ {NULL, FLB_CONF_TYPE_OTHER, 0} /* end of array */
+};
+
+
+struct flb_config *flb_config_init()
+{
+ int ret;
+ struct flb_config *config;
+ struct flb_cf *cf;
+ struct flb_cf_section *section;
+
+ config = flb_calloc(1, sizeof(struct flb_config));
+ if (!config) {
+ flb_errno();
+ return NULL;
+ }
+
+ MK_EVENT_ZERO(&config->ch_event);
+ MK_EVENT_ZERO(&config->event_flush);
+ MK_EVENT_ZERO(&config->event_shutdown);
+
+ /* is data ingestion active ? */
+ config->is_ingestion_active = FLB_TRUE;
+
+ /* Is the engine (event loop) actively running ? */
+ config->is_running = FLB_TRUE;
+
+ /* Initialize config_format context */
+ cf = flb_cf_create();
+ if (!cf) {
+ flb_free(config);
+ return NULL;
+ }
+ config->cf_main = cf;
+
+ section = flb_cf_section_create(cf, "service", 0);
+ if (!section) {
+ flb_cf_destroy(cf);
+ flb_free(config);
+ return NULL;
+ }
+
+ /* Flush */
+ config->flush = FLB_CONFIG_FLUSH_SECS;
+ config->daemon = FLB_FALSE;
+ config->init_time = time(NULL);
+ config->kernel = flb_kernel_info();
+ config->verbose = 3;
+ config->grace = 5;
+ config->grace_count = 0;
+ config->exit_status_code = 0;
+
+ /* json */
+ config->convert_nan_to_null = FLB_FALSE;
+
+#ifdef FLB_HAVE_HTTP_SERVER
+ config->http_ctx = NULL;
+ config->http_server = FLB_FALSE;
+ config->http_listen = flb_strdup(FLB_CONFIG_HTTP_LISTEN);
+ config->http_port = flb_strdup(FLB_CONFIG_HTTP_PORT);
+ config->health_check = FLB_FALSE;
+ config->hc_errors_count = HC_ERRORS_COUNT_DEFAULT;
+ config->hc_retry_failure_count = HC_RETRY_FAILURE_COUNTS_DEFAULT;
+ config->health_check_period = HEALTH_CHECK_PERIOD;
+#endif
+
+ config->http_proxy = getenv("HTTP_PROXY");
+ if (flb_str_emptyval(config->http_proxy) == FLB_TRUE) {
+ config->http_proxy = getenv("http_proxy");
+ if (flb_str_emptyval(config->http_proxy) == FLB_TRUE) {
+ /* Proxy should not be set when `HTTP_PROXY` or `http_proxy` are set to "" */
+ config->http_proxy = NULL;
+ }
+ }
+ config->no_proxy = getenv("NO_PROXY");
+ if (flb_str_emptyval(config->no_proxy) == FLB_TRUE || config->http_proxy == NULL) {
+ config->no_proxy = getenv("no_proxy");
+ if (flb_str_emptyval(config->no_proxy) == FLB_TRUE || config->http_proxy == NULL) {
+ /* NoProxy should not be set when `NO_PROXY` or `no_proxy` are set to "" or there is no Proxy. */
+ config->no_proxy = NULL;
+ }
+ }
+
+ config->cio = NULL;
+ config->storage_path = NULL;
+ config->storage_input_plugin = NULL;
+ config->storage_metrics = FLB_TRUE;
+
+ config->sched_cap = FLB_SCHED_CAP;
+ config->sched_base = FLB_SCHED_BASE;
+
+ /* reload */
+ config->ensure_thread_safety_on_hot_reloading = FLB_TRUE;
+ config->hot_reloaded_count = 0;
+
+#ifdef FLB_HAVE_SQLDB
+ mk_list_init(&config->sqldb_list);
+#endif
+
+#ifdef FLB_HAVE_LUAJIT
+ mk_list_init(&config->luajit_list);
+#endif
+
+#ifdef FLB_HAVE_STREAM_PROCESSOR
+ flb_slist_create(&config->stream_processor_tasks);
+ config->stream_processor_str_conv = FLB_TRUE;
+#endif
+
+ flb_slist_create(&config->external_plugins);
+
+ /* Set default coroutines stack size */
+ config->coro_stack_size = FLB_CORO_STACK_SIZE_BYTE;
+ if (config->coro_stack_size < getpagesize()) {
+ flb_info("[config] changing coro_stack_size from %u to %u bytes",
+ config->coro_stack_size, getpagesize());
+ config->coro_stack_size = (unsigned int)getpagesize();
+ }
+
+ /* collectors */
+ pthread_mutex_init(&config->collectors_mutex, NULL);
+
+ /* Initialize linked lists */
+ mk_list_init(&config->processor_plugins);
+ mk_list_init(&config->custom_plugins);
+ mk_list_init(&config->in_plugins);
+ mk_list_init(&config->parser_plugins);
+ mk_list_init(&config->filter_plugins);
+ mk_list_init(&config->out_plugins);
+ mk_list_init(&config->customs);
+ mk_list_init(&config->inputs);
+ mk_list_init(&config->parsers);
+ mk_list_init(&config->filters);
+ mk_list_init(&config->outputs);
+ mk_list_init(&config->proxies);
+ mk_list_init(&config->workers);
+ mk_list_init(&config->upstreams);
+ mk_list_init(&config->downstreams);
+ mk_list_init(&config->cmetrics);
+ mk_list_init(&config->cf_parsers_list);
+
+ memset(&config->tasks_map, '\0', sizeof(config->tasks_map));
+
+ /* Initialize multiline-parser list. We need this here, because from now
+ * on we use flb_config_exit to cleanup the config, which requires
+ * the config->multiline_parsers list to be initialized. */
+ mk_list_init(&config->multiline_parsers);
+
+ /* Environment */
+ config->env = flb_env_create();
+ if (config->env == NULL) {
+ flb_error("[config] environment creation failed");
+ flb_config_exit(config);
+ return NULL;
+ }
+
+ /* Multiline core */
+ ret = flb_ml_init(config);
+ if (ret == -1) {
+ flb_error("[config] multiline core initialization failed");
+ flb_config_exit(config);
+ return NULL;
+ }
+
+ /* Register static plugins */
+ ret = flb_plugins_register(config);
+ if (ret == -1) {
+ flb_error("[config] plugins registration failed");
+ flb_config_exit(config);
+ return NULL;
+ }
+
+ /* Create environment for dynamic plugins */
+ config->dso_plugins = flb_plugin_create();
+
+ /* Ignoring SIGPIPE on Windows (scary) */
+#ifndef _WIN32
+ /* Ignore SIGPIPE */
+ signal(SIGPIPE, SIG_IGN);
+#endif
+
+ /* Prepare worker interface */
+ flb_worker_init(config);
+
+#ifdef FLB_HAVE_REGEX
+ /* Regex support */
+ flb_regex_init();
+#endif
+
+ return config;
+}
+
+void flb_config_exit(struct flb_config *config)
+{
+ struct mk_list *tmp;
+ struct mk_list *head;
+ struct flb_cf *cf;
+
+ if (config->log_file) {
+ flb_free(config->log_file);
+ }
+
+ if (config->log) {
+ flb_log_destroy(config->log, config);
+ }
+
+ if (config->parsers_file) {
+ flb_free(config->parsers_file);
+ }
+
+ if (config->plugins_file) {
+ flb_free(config->plugins_file);
+ }
+
+ if (config->kernel) {
+ flb_kernel_destroy(config->kernel);
+ }
+
+ /* release resources */
+ if (config->ch_event.fd) {
+ mk_event_closesocket(config->ch_event.fd);
+ }
+
+ /* Pipe */
+ if (config->ch_data[0]) {
+ mk_event_closesocket(config->ch_data[0]);
+ mk_event_closesocket(config->ch_data[1]);
+ }
+
+ /* Channel manager */
+ if (config->ch_manager[0] > 0) {
+ mk_event_closesocket(config->ch_manager[0]);
+ if (config->ch_manager[0] != config->ch_manager[1]) {
+ mk_event_closesocket(config->ch_manager[1]);
+ }
+ }
+
+ /* Channel notifications */
+ if (config->ch_notif[0] > 0) {
+ mk_event_closesocket(config->ch_notif[0]);
+ if (config->ch_notif[0] != config->ch_notif[1]) {
+ mk_event_closesocket(config->ch_notif[1]);
+ }
+ }
+
+ if (config->env) {
+ flb_env_destroy(config->env);
+ }
+
+ /* Program name */
+ if (config->program_name) {
+ flb_sds_destroy(config->program_name);
+ }
+
+ /* Conf path */
+ if (config->conf_path) {
+ flb_free(config->conf_path);
+ }
+
+ /* conf path file (file system config path) */
+ if (config->conf_path_file) {
+ flb_sds_destroy(config->conf_path_file);
+ }
+
+ /* Working directory */
+ if (config->workdir) {
+ flb_free(config->workdir);
+ }
+
+ /* Destroy any DSO context */
+ if (config->dso_plugins) {
+ flb_plugin_destroy(config->dso_plugins);
+ }
+
+ /* Workers */
+ flb_worker_exit(config);
+
+ /* Event flush */
+ if (config->evl) {
+ if (config->event_flush.status != MK_EVENT_NONE) {
+ mk_event_timeout_destroy(config->evl, &config->event_flush);
+ }
+ }
+
+ /* Release scheduler */
+ if (config->sched) {
+ flb_sched_destroy(config->sched);
+ }
+
+#ifdef FLB_HAVE_HTTP_SERVER
+ if (config->http_listen) {
+ flb_free(config->http_listen);
+ }
+
+ if (config->http_port) {
+ flb_free(config->http_port);
+ }
+#endif
+
+#ifdef FLB_HAVE_PARSER
+ /* parsers */
+ flb_parser_exit(config);
+#endif
+
+ if (config->dns_mode) {
+ flb_free(config->dns_mode);
+ }
+ if (config->dns_resolver) {
+ flb_free(config->dns_resolver);
+ }
+
+ if (config->storage_path) {
+ flb_free(config->storage_path);
+ }
+ if (config->storage_sync) {
+ flb_free(config->storage_sync);
+ }
+ if (config->storage_bl_mem_limit) {
+ flb_free(config->storage_bl_mem_limit);
+ }
+
+#ifdef FLB_HAVE_STREAM_PROCESSOR
+ if (config->stream_processor_file) {
+ flb_free(config->stream_processor_file);
+ }
+
+ flb_slist_destroy(&config->stream_processor_tasks);
+#endif
+
+ flb_slist_destroy(&config->external_plugins);
+
+ if (config->evl) {
+ mk_event_loop_destroy(config->evl);
+ }
+ if (config->evl_bktq) {
+ flb_bucket_queue_destroy(config->evl_bktq);
+ }
+
+ flb_plugins_unregister(config);
+
+ if (config->cf_main) {
+ flb_cf_destroy(config->cf_main);
+ }
+
+ /* cf_opts' lifetime should differ from config's lifetime.
+ * This member should be storing just for the cf_opts reference.
+ * Don't destroy it here.
+ */
+
+ /* remove parsers */
+ mk_list_foreach_safe(head, tmp, &config->cf_parsers_list) {
+ cf = mk_list_entry(head, struct flb_cf, _head);
+ mk_list_del(&cf->_head);
+ flb_cf_destroy(cf);
+ }
+
+ flb_free(config);
+}
+
+const char *flb_config_prop_get(const char *key, struct mk_list *list)
+{
+ return flb_kv_get_key_value(key, list);
+}
+
+static inline int prop_key_check(const char *key, const char *kv, int k_len)
+{
+ size_t len;
+
+ len = strnlen(key,256);
+ if (strncasecmp(key, kv, k_len) == 0 && len == k_len) {
+ return 0;
+ }
+ return -1;
+}
+
+static int set_log_level(struct flb_config *config, const char *v_str)
+{
+ if (v_str != NULL) {
+ if (strcasecmp(v_str, "error") == 0) {
+ config->verbose = 1;
+ }
+ else if (strcasecmp(v_str, "warn") == 0 ||
+ strcasecmp(v_str, "warning") == 0) {
+ config->verbose = 2;
+ }
+ else if (strcasecmp(v_str, "info") == 0) {
+ config->verbose = 3;
+ }
+ else if (strcasecmp(v_str, "debug") == 0) {
+ config->verbose = 4;
+ }
+ else if (strcasecmp(v_str, "trace") == 0) {
+ config->verbose = 5;
+ }
+ else if (strcasecmp(v_str, "off") == 0) {
+ config->verbose = FLB_LOG_OFF;
+ }
+ else {
+ return -1;
+ }
+ }
+ else if (config->log) {
+ config->verbose = 3;
+ }
+ return 0;
+}
+
+int set_log_level_from_env(struct flb_config *config)
+{
+ const char *val = NULL;
+ val = flb_env_get(config->env, FLB_CONF_ENV_LOGLEVEL);
+ if (val) {
+ return set_log_level(config, val);
+ }
+ return -1;
+}
+
+int flb_config_set_property(struct flb_config *config,
+ const char *k, const char *v)
+{
+ int i=0;
+ int ret = -1;
+ int *i_val;
+ double *d_val;
+ char **s_val;
+ size_t len = strnlen(k, 256);
+ char *key = service_configs[0].key;
+ flb_sds_t tmp = NULL;
+
+ while (key != NULL) {
+ if (prop_key_check(key, k,len) == 0) {
+ if (!strncasecmp(key, FLB_CONF_STR_LOGLEVEL, 256)) {
+ #ifndef FLB_HAVE_STATIC_CONF
+ if (set_log_level_from_env(config) < 0) {
+ #endif
+ tmp = flb_env_var_translate(config->env, v);
+ if (tmp) {
+ ret = set_log_level(config, tmp);
+ flb_sds_destroy(tmp);
+ tmp = NULL;
+ }
+ else {
+ ret = set_log_level(config, v);
+ }
+ #ifndef FLB_HAVE_STATIC_CONF
+ }
+ #endif
+ }
+ else if (!strncasecmp(key, FLB_CONF_STR_PARSERS_FILE, 32)) {
+#ifdef FLB_HAVE_PARSER
+ tmp = flb_env_var_translate(config->env, v);
+ ret = flb_parser_conf_file(tmp, config);
+ flb_sds_destroy(tmp);
+ tmp = NULL;
+#endif
+ }
+ else if (!strncasecmp(key, FLB_CONF_STR_PLUGINS_FILE, 32)) {
+ tmp = flb_env_var_translate(config->env, v);
+ ret = flb_plugin_load_config_file(tmp, config);
+ flb_sds_destroy(tmp);
+ tmp = NULL;
+ }
+ else {
+ ret = 0;
+ tmp = flb_env_var_translate(config->env, v);
+ switch(service_configs[i].type) {
+ case FLB_CONF_TYPE_INT:
+ i_val = (int*)((char*)config + service_configs[i].offset);
+ *i_val = atoi(tmp);
+ flb_sds_destroy(tmp);
+ break;
+ case FLB_CONF_TYPE_DOUBLE:
+ d_val = (double*)((char*)config + service_configs[i].offset);
+ *d_val = atof(tmp);
+ flb_sds_destroy(tmp);
+ break;
+ case FLB_CONF_TYPE_BOOL:
+ i_val = (int*)((char*)config+service_configs[i].offset);
+ *i_val = flb_utils_bool(tmp);
+ flb_sds_destroy(tmp);
+ break;
+ case FLB_CONF_TYPE_STR:
+ s_val = (char**)((char*)config+service_configs[i].offset);
+ if ( *s_val != NULL ) {
+ flb_free(*s_val); /* release before overwriting */
+ }
+
+ *s_val = flb_strdup(tmp);
+ flb_sds_destroy(tmp);
+ break;
+ default:
+ ret = -1;
+ }
+ }
+
+ if (ret < 0) {
+ if (tmp) {
+ flb_sds_destroy(tmp);
+ }
+ return -1;
+ }
+ return 0;
+ }
+ key = service_configs[++i].key;
+ }
+ return 0;
+}
+
+int flb_config_set_program_name(struct flb_config *config, char *name)
+{
+ config->program_name = flb_sds_create(name);
+
+ if (!config->program_name) {
+ return -1;
+ }
+
+ return 0;
+}
+
+static int configure_plugins_type(struct flb_config *config, struct flb_cf *cf, enum section_type type)
+{
+ int ret;
+ char *tmp;
+ char *name;
+ char *s_type;
+ struct mk_list *list;
+ struct mk_list *head;
+ struct cfl_list *h_prop;
+ struct cfl_kvpair *kv;
+ struct cfl_variant *val;
+ struct flb_cf_section *s;
+ struct flb_cf_group *processors = NULL;
+ int i;
+ void *ins;
+
+ if (type == FLB_CF_CUSTOM) {
+ s_type = "custom";
+ list = &cf->customs;
+ }
+ else if (type == FLB_CF_INPUT) {
+ s_type = "input";
+ list = &cf->inputs;
+ }
+ else if (type == FLB_CF_FILTER) {
+ s_type = "filter";
+ list = &cf->filters;
+ }
+ else if (type == FLB_CF_OUTPUT) {
+ s_type = "output";
+ list = &cf->outputs;
+ }
+ else {
+ return -1;
+ }
+
+ mk_list_foreach(head, list) {
+ s = mk_list_entry(head, struct flb_cf_section, _head_section);
+ name = flb_cf_section_property_get_string(cf, s, "name");
+ if (!name) {
+ flb_error("[config] section '%s' is missing the 'name' property",
+ s_type);
+ return -1;
+ }
+
+ /* translate the variable */
+ tmp = flb_env_var_translate(config->env, name);
+
+ /* create an instance of the plugin */
+ ins = NULL;
+ if (type == FLB_CF_CUSTOM) {
+ ins = flb_custom_new(config, tmp, NULL);
+ }
+ else if (type == FLB_CF_INPUT) {
+ ins = flb_input_new(config, tmp, NULL, FLB_TRUE);
+ }
+ else if (type == FLB_CF_FILTER) {
+ ins = flb_filter_new(config, tmp, NULL);
+ }
+ else if (type == FLB_CF_OUTPUT) {
+ ins = flb_output_new(config, tmp, NULL, FLB_TRUE);
+ }
+ flb_sds_destroy(tmp);
+
+ /* validate the instance creation */
+ if (!ins) {
+ flb_error("[config] section '%s' tried to instance a plugin name "
+ "that don't exists", name);
+ flb_sds_destroy(name);
+ return -1;
+ }
+ flb_sds_destroy(name);
+
+ /*
+ * iterate section properties and populate instance by using specific
+ * api function.
+ */
+ cfl_list_foreach(h_prop, &s->properties->list) {
+ kv = cfl_list_entry(h_prop, struct cfl_kvpair, _head);
+ if (strcasecmp(kv->key, "name") == 0) {
+ continue;
+ }
+
+ /* set ret to -1 to ensure that we treat any unhandled plugin or
+ * value types as errors.
+ */
+ ret = -1;
+
+ if (type == FLB_CF_CUSTOM) {
+ if (kv->val->type == CFL_VARIANT_STRING) {
+ ret = flb_custom_set_property(ins, kv->key, kv->val->data.as_string);
+ } else if (kv->val->type == CFL_VARIANT_ARRAY) {
+ for (i = 0; i < kv->val->data.as_array->entry_count; i++) {
+ val = kv->val->data.as_array->entries[i];
+ ret = flb_custom_set_property(ins, kv->key, val->data.as_string);
+ }
+ }
+ }
+ else if (type == FLB_CF_INPUT) {
+ if (kv->val->type == CFL_VARIANT_STRING) {
+ ret = flb_input_set_property(ins, kv->key, kv->val->data.as_string);
+ } else if (kv->val->type == CFL_VARIANT_ARRAY) {
+ for (i = 0; i < kv->val->data.as_array->entry_count; i++) {
+ val = kv->val->data.as_array->entries[i];
+ ret = flb_input_set_property(ins, kv->key, val->data.as_string);
+ }
+ }
+ }
+ else if (type == FLB_CF_FILTER) {
+ if (kv->val->type == CFL_VARIANT_STRING) {
+ ret = flb_filter_set_property(ins, kv->key, kv->val->data.as_string);
+ } else if (kv->val->type == CFL_VARIANT_ARRAY) {
+ for (i = 0; i < kv->val->data.as_array->entry_count; i++) {
+ val = kv->val->data.as_array->entries[i];
+ ret = flb_filter_set_property(ins, kv->key, val->data.as_string);
+ }
+ }
+ }
+ else if (type == FLB_CF_OUTPUT) {
+ if (kv->val->type == CFL_VARIANT_STRING) {
+ ret = flb_output_set_property(ins, kv->key, kv->val->data.as_string);
+ } else if (kv->val->type == CFL_VARIANT_ARRAY) {
+ for (i = 0; i < kv->val->data.as_array->entry_count; i++) {
+ val = kv->val->data.as_array->entries[i];
+ ret = flb_output_set_property(ins, kv->key, val->data.as_string);
+ }
+ }
+ }
+
+ if (ret == -1) {
+ flb_error("[config] could not configure property '%s' on "
+ "%s plugin with section name '%s'",
+ kv->key, s_type, name);
+ }
+ }
+
+ /* Processors */
+ processors = flb_cf_group_get(cf, s, "processors");
+ if (processors) {
+ if (type == FLB_CF_INPUT) {
+ flb_processors_load_from_config_format_group(((struct flb_input_instance *) ins)->processor, processors);
+ }
+ else if (type == FLB_CF_OUTPUT) {
+ flb_processors_load_from_config_format_group(((struct flb_output_instance *) ins)->processor, processors);
+ }
+ else {
+ flb_error("[config] section '%s' does not support processors", s_type);
+ }
+ }
+ }
+
+ return 0;
+}
+/* Load a struct flb_config_format context into a flb_config instance */
+int flb_config_load_config_format(struct flb_config *config, struct flb_cf *cf)
+{
+ int ret;
+ struct flb_kv *kv;
+ struct mk_list *head;
+ struct cfl_kvpair *ckv;
+ struct cfl_list *chead;
+ struct flb_cf_section *s;
+
+ /* Process config environment vars */
+ mk_list_foreach(head, &cf->env) {
+ kv = mk_list_entry(head, struct flb_kv, _head);
+ ret = flb_env_set(config->env, kv->key, kv->val);
+ if (ret == -1) {
+ flb_error("could not set config environment variable '%s'", kv->key);
+ return -1;
+ }
+ }
+
+ /* Process all meta commands */
+ mk_list_foreach(head, &cf->metas) {
+ kv = mk_list_entry(head, struct flb_kv, _head);
+ flb_meta_run(config, kv->key, kv->val);
+ }
+
+ /* Validate sections */
+ mk_list_foreach(head, &cf->sections) {
+ s = mk_list_entry(head, struct flb_cf_section, _head);
+
+ if (strcasecmp(s->name, "env") == 0 ||
+ strcasecmp(s->name, "service") == 0 ||
+ strcasecmp(s->name, "custom") == 0 ||
+ strcasecmp(s->name, "input") == 0 ||
+ strcasecmp(s->name, "filter") == 0 ||
+ strcasecmp(s->name, "output") == 0) {
+
+ /* continue on valid sections */
+ continue;
+ }
+
+ /* Extra sanity checks */
+ if (strcasecmp(s->name, "parser") == 0 ||
+ strcasecmp(s->name, "multiline_parser") == 0) {
+ fprintf(stderr,
+ "Sections 'multiline_parser' and 'parser' are not valid in "
+ "the main configuration file. It belongs to \n"
+ "the 'parsers_file' configuration files.\n");
+ return -1;
+ }
+ }
+
+ /* Read main 'service' section */
+ s = cf->service;
+ if (s) {
+ /* Iterate properties */
+ cfl_list_foreach(chead, &s->properties->list) {
+ ckv = cfl_list_entry(chead, struct cfl_kvpair, _head);
+ flb_config_set_property(config, ckv->key, ckv->val->data.as_string);
+ }
+ }
+
+ ret = configure_plugins_type(config, cf, FLB_CF_CUSTOM);
+ if (ret == -1) {
+ return -1;
+ }
+
+ ret = configure_plugins_type(config, cf, FLB_CF_INPUT);
+ if (ret == -1) {
+ return -1;
+ }
+ ret = configure_plugins_type(config, cf, FLB_CF_FILTER);
+ if (ret == -1) {
+ return -1;
+ }
+ ret = configure_plugins_type(config, cf, FLB_CF_OUTPUT);
+ if (ret == -1) {
+ return -1;
+ }
+
+ return 0;
+}