diff --git a/include/fluent-bit/flb_api.h b/include/fluent-bit/flb_api.h index cfef53e7160..69a0cab153c 100644 --- a/include/fluent-bit/flb_api.h +++ b/include/fluent-bit/flb_api.h @@ -39,6 +39,9 @@ struct flb_api { * input/output definitions. */ const char *(*custom_get_property) (const char *, struct flb_custom_instance *); int (*custom_log_check) (struct flb_custom_instance *, int); + + struct flb_kv **(*output_get_all_properties) (struct flb_output_instance *, int *); + struct flb_kv **(*input_get_all_properties) (struct flb_input_instance *, int *); }; #ifdef FLB_CORE diff --git a/include/fluent-bit/flb_config.h b/include/fluent-bit/flb_config.h index d171ef08167..34a53f5e655 100644 --- a/include/fluent-bit/flb_config.h +++ b/include/fluent-bit/flb_config.h @@ -32,6 +32,7 @@ #include struct flb_router; +struct flb_kv; #define FLB_CONFIG_FLUSH_SECS 1 #define FLB_CONFIG_HTTP_LISTEN "0.0.0.0" @@ -341,6 +342,7 @@ struct flb_config { struct flb_config *flb_config_init(); void flb_config_exit(struct flb_config *config); const char *flb_config_prop_get(const char *key, struct mk_list *list); +struct flb_kv **flb_config_prop_get_all(struct mk_list *list, int *out_count); int flb_config_set_property(struct flb_config *config, const char *k, const char *v); int flb_config_set_program_name(struct flb_config *config, char *name); diff --git a/include/fluent-bit/flb_input.h b/include/fluent-bit/flb_input.h index c2ca41bd75e..0b95868d389 100644 --- a/include/fluent-bit/flb_input.h +++ b/include/fluent-bit/flb_input.h @@ -795,6 +795,8 @@ int flb_input_set_property(struct flb_input_instance *ins, const char *k, const char *v); const char *flb_input_get_property(const char *key, struct flb_input_instance *ins); +struct flb_kv **flb_input_get_all_properties(struct flb_input_instance *ins, + int *out_count); #ifdef FLB_HAVE_METRICS void *flb_input_get_cmt_instance(struct flb_input_instance *ins); #endif diff --git a/include/fluent-bit/flb_kv.h b/include/fluent-bit/flb_kv.h index 0c4ad82ce1f..17213186d51 100644 --- a/include/fluent-bit/flb_kv.h +++ b/include/fluent-bit/flb_kv.h @@ -41,5 +41,6 @@ struct flb_kv *flb_kv_item_set(struct mk_list *list, void flb_kv_item_destroy(struct flb_kv *kv); void flb_kv_release(struct mk_list *list); const char *flb_kv_get_key_value(const char *key, struct mk_list *list); +struct flb_kv **flb_kv_get_all_key_values(struct mk_list *list, int *out_count); #endif diff --git a/include/fluent-bit/flb_output.h b/include/fluent-bit/flb_output.h index 8e2b8fc3512..df2b8b84466 100644 --- a/include/fluent-bit/flb_output.h +++ b/include/fluent-bit/flb_output.h @@ -1405,6 +1405,8 @@ const char *flb_output_name(struct flb_output_instance *in); int flb_output_set_property(struct flb_output_instance *out, const char *k, const char *v); const char *flb_output_get_property(const char *key, struct flb_output_instance *ins); +struct flb_kv **flb_output_get_all_properties(struct flb_output_instance *ins, + int *out_count); #ifdef FLB_HAVE_METRICS void *flb_output_get_cmt_instance(struct flb_output_instance *ins); #endif diff --git a/src/flb_api.c b/src/flb_api.c index 0390a005350..e2408cc7738 100644 --- a/src/flb_api.c +++ b/src/flb_api.c @@ -50,6 +50,9 @@ struct flb_api *flb_api_create() api->output_log_check = flb_output_log_check; api->custom_log_check = flb_custom_log_check; + api->output_get_all_properties = flb_output_get_all_properties; + api->input_get_all_properties = flb_input_get_all_properties; + return api; } diff --git a/src/flb_config.c b/src/flb_config.c index 06c76ca78c3..025e42d06bf 100644 --- a/src/flb_config.c +++ b/src/flb_config.c @@ -676,6 +676,18 @@ const char *flb_config_prop_get(const char *key, struct mk_list *list) return flb_kv_get_key_value(key, list); } +/* + * Return a heap-allocated array of pointers to every property in 'list'. + * The caller must release the array with flb_free(); the individual entries + * remain owned by the property list. 'out_count' (optional) receives the + * number of entries. Returns NULL on empty list, NULL input, or allocation + * failure. See flb_kv_get_all_key_values() for the full contract. + */ +struct flb_kv **flb_config_prop_get_all(struct mk_list *list, int *out_count) +{ + return flb_kv_get_all_key_values(list, out_count); +} + static inline int prop_key_check(const char *key, const char *kv, int k_len) { size_t len; diff --git a/src/flb_input.c b/src/flb_input.c index e990eee238c..e4e3a0008ab 100644 --- a/src/flb_input.c +++ b/src/flb_input.c @@ -952,6 +952,19 @@ const char *flb_input_get_property(const char *key, return flb_config_prop_get(key, &ins->properties); } +/* +* Return a heap-allocated array of pointers to every property configured on +* 'ins'. The caller owns the array and must release it with flb_free(); the +* underlying flb_kv entries remain owned by the input instance. 'out_count' +* (optional) receives the number of properties. Returns NULL when the +* instance has no properties or on allocation failure. +*/ +struct flb_kv **flb_input_get_all_properties(struct flb_input_instance *ins, + int *out_count) +{ + return flb_config_prop_get_all(&ins->properties, out_count); +} + #ifdef FLB_HAVE_METRICS void *flb_input_get_cmt_instance(struct flb_input_instance *ins) { diff --git a/src/flb_kv.c b/src/flb_kv.c index fc3c3545fad..5ca2c4fd8e0 100644 --- a/src/flb_kv.c +++ b/src/flb_kv.c @@ -160,3 +160,53 @@ const char *flb_kv_get_key_value(const char *key, struct mk_list *list) return NULL; } + +/* + * Return a heap-allocated array of pointers to every flb_kv entry in 'list', + * preserving insertion order. The array itself is owned by the caller and + * must be released with flb_free(); the flb_kv entries it points to remain + * owned by 'list' and are freed by flb_kv_release()/flb_kv_item_destroy(). + * + * If 'out_count' is non-NULL it receives the number of entries (0 when the + * list is empty or NULL). Returns NULL when the list is empty, NULL, or on + * allocation failure. + */ +struct flb_kv **flb_kv_get_all_key_values(struct mk_list *list, int *out_count) +{ + int count; + int i = 0; + struct mk_list *head; + struct flb_kv *kv; + struct flb_kv **arr; + + if (out_count) { + *out_count = 0; + } + + if (!list) { + return NULL; + } + + count = mk_list_size(list); + if (count == 0) { + return NULL; + } + + arr = flb_calloc(count, sizeof(struct flb_kv *)); + if (!arr) { + flb_errno(); + return NULL; + } + + mk_list_foreach(head, list) { + kv = mk_list_entry(head, struct flb_kv, _head); + arr[i] = kv; + i++; + } + + if (out_count) { + *out_count = count; + } + + return arr; +} diff --git a/src/flb_output.c b/src/flb_output.c index 26f66ad9e36..d8852704e60 100644 --- a/src/flb_output.c +++ b/src/flb_output.c @@ -1179,6 +1179,19 @@ const char *flb_output_get_property(const char *key, struct flb_output_instance return flb_config_prop_get(key, &ins->properties); } +/* + * Return a heap-allocated array of pointers to every property configured on + * 'ins'. The caller owns the array and must release it with flb_free(); the + * underlying flb_kv entries remain owned by the output instance. 'out_count' + * (optional) receives the number of properties. Returns NULL when the + * instance has no properties or on allocation failure. + */ +struct flb_kv **flb_output_get_all_properties(struct flb_output_instance *ins, + int *out_count) +{ + return flb_config_prop_get_all(&ins->properties, out_count); +} + #ifdef FLB_HAVE_METRICS void *flb_output_get_cmt_instance(struct flb_output_instance *ins) { diff --git a/tests/internal/kv.c b/tests/internal/kv.c index e20d5184692..f630fc5dee0 100644 --- a/tests/internal/kv.c +++ b/tests/internal/kv.c @@ -1,6 +1,7 @@ /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ #include +#include #include "flb_tests_internal.h" static void test_kv_item_set_duplicate() @@ -28,7 +29,46 @@ static void test_kv_item_set_duplicate() flb_kv_release(&list); } +static void test_kv_get_all_key_values() +{ + struct mk_list list; + struct flb_kv **pairs; + int count = -1; + + flb_kv_init(&list); + + pairs = flb_kv_get_all_key_values(&list, &count); + TEST_CHECK(pairs == NULL); + TEST_CHECK(count == 0); + + flb_kv_item_set(&list, "host", "localhost"); + flb_kv_item_set(&list, "port", "8080"); + flb_kv_item_set(&list, "path", "/api"); + + pairs = flb_kv_get_all_key_values(&list, &count); + TEST_CHECK(pairs != NULL); + TEST_CHECK(count == 3); + + if (pairs && count == 3) { + TEST_CHECK(pairs[0] != NULL); + TEST_CHECK(strcmp(pairs[0]->key, "host") == 0); + TEST_CHECK(strcmp(pairs[0]->val, "localhost") == 0); + + TEST_CHECK(pairs[1] != NULL); + TEST_CHECK(strcmp(pairs[1]->key, "port") == 0); + TEST_CHECK(strcmp(pairs[1]->val, "8080") == 0); + + TEST_CHECK(pairs[2] != NULL); + TEST_CHECK(strcmp(pairs[2]->key, "path") == 0); + TEST_CHECK(strcmp(pairs[2]->val, "/api") == 0); + } + + flb_kv_release(&list); + flb_free(pairs); +} + TEST_LIST = { {"kv_item_set_duplicate", test_kv_item_set_duplicate}, + {"kv_get_all_key_values", test_kv_get_all_key_values}, {0} };