0
0
Fork 0
mirror of https://github.com/netdata/netdata.git synced 2025-05-02 08:20:10 +00:00

DYNCFG: call the interceptor when a test is made on a new job ()

* call the interceptor when a test is made on a new job

* unify exception handling

* dont shadow variable

* the config tree function, that is also the catch all for all config commands, is now marked async, to allow calling async functions
This commit is contained in:
Costa Tsaousis 2024-02-25 03:36:39 +02:00 committed by GitHub
parent 751e80476f
commit bc3ff3fabe
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 41 additions and 9 deletions

View file

@ -180,7 +180,7 @@ static int dyncfg_intercept_early_error(struct rrd_function_execute *rfe, int rc
return rc; return rc;
} }
static const DICTIONARY_ITEM *dyncfg_get_template_of_new_job(const char *job_id) { const DICTIONARY_ITEM *dyncfg_get_template_of_new_job(const char *job_id) {
char id_copy[strlen(job_id) + 1]; char id_copy[strlen(job_id) + 1];
memcpy(id_copy, job_id, sizeof(id_copy)); memcpy(id_copy, job_id, sizeof(id_copy));

View file

@ -76,6 +76,8 @@ const DICTIONARY_ITEM *dyncfg_add_internal(RRDHOST *host, const char *id, const
int dyncfg_function_intercept_cb(struct rrd_function_execute *rfe, void *data); int dyncfg_function_intercept_cb(struct rrd_function_execute *rfe, void *data);
void dyncfg_cleanup(DYNCFG *v); void dyncfg_cleanup(DYNCFG *v);
const DICTIONARY_ITEM *dyncfg_get_template_of_new_job(const char *job_id);
bool dyncfg_is_user_disabled(const char *id); bool dyncfg_is_user_disabled(const char *id);
RRDHOST *dyncfg_rrdhost_by_uuid(UUID *uuid); RRDHOST *dyncfg_rrdhost_by_uuid(UUID *uuid);

View file

@ -204,31 +204,57 @@ static int dyncfg_config_execute_cb(struct rrd_function_execute *rfe, void *data
action = path; action = path;
path = NULL; path = NULL;
if(id && *id && dyncfg_cmds2id(action) == DYNCFG_CMD_REMOVE) { DYNCFG_CMDS cmd = dyncfg_cmds2id(action);
const DICTIONARY_ITEM *item = dictionary_get_and_acquire_item(dyncfg_globals.nodes, id); const DICTIONARY_ITEM *item = dictionary_get_and_acquire_item(dyncfg_globals.nodes, id);
if(item) { if(!item)
DYNCFG *df = dictionary_acquired_item_value(item); item = dyncfg_get_template_of_new_job(id);
if(!rrd_function_available(host, string2str(df->function))) if(item) {
df->current.status = DYNCFG_STATUS_ORPHAN; DYNCFG *df = dictionary_acquired_item_value(item);
if(!rrd_function_available(host, string2str(df->function)))
df->current.status = DYNCFG_STATUS_ORPHAN;
if(cmd == DYNCFG_CMD_REMOVE) {
bool delete = (df->current.status == DYNCFG_STATUS_ORPHAN); bool delete = (df->current.status == DYNCFG_STATUS_ORPHAN);
dictionary_acquired_item_release(dyncfg_globals.nodes, item); dictionary_acquired_item_release(dyncfg_globals.nodes, item);
item = NULL;
if(delete) { if(delete) {
if(!http_access_user_has_enough_access_level_for_endpoint(rfe->user_access, df->edit_access)) {
code = dyncfg_default_response(
rfe->result.wb, HTTP_RESP_FORBIDDEN,
"dyncfg: you don't have enough edit permissions to execute this command");
goto cleanup;
}
dictionary_del(dyncfg_globals.nodes, id); dictionary_del(dyncfg_globals.nodes, id);
dyncfg_file_delete(id); dyncfg_file_delete(id);
code = dyncfg_default_response(rfe->result.wb, 200, ""); code = dyncfg_default_response(rfe->result.wb, 200, "");
goto cleanup; goto cleanup;
} }
} }
else if(cmd == DYNCFG_CMD_TEST && df->type == DYNCFG_TYPE_TEMPLATE && df->current.status != DYNCFG_STATUS_ORPHAN) {
const char *old_rfe_function = rfe->function;
char buf2[2048];
snprintfz(buf2, sizeof(buf2), "config %s %s", dictionary_acquired_item_name(item), action);
rfe->function = buf2;
dictionary_acquired_item_release(dyncfg_globals.nodes, item);
item = NULL;
code = dyncfg_function_intercept_cb(rfe, data);
rfe->function = old_rfe_function;
return code;
}
if(item)
dictionary_acquired_item_release(dyncfg_globals.nodes, item);
} }
code = HTTP_RESP_NOT_FOUND; code = HTTP_RESP_NOT_FOUND;
nd_log(NDLS_DAEMON, NDLP_ERR, nd_log(NDLS_DAEMON, NDLP_ERR,
"DYNCFG: unknown config id '%s' in call: '%s'. " "DYNCFG: unknown config id '%s' in call: '%s'. "
"This can happen if the plugin that registered the dynamic configuration is not running now.", "This can happen if the plugin that registered the dynamic configuration is not running now.",
action, rfe->function); id, rfe->function);
rrd_call_function_error( rrd_call_function_error(
rfe->result.wb, rfe->result.wb,
@ -248,7 +274,11 @@ cleanup:
// for which there is no id overloaded. // for which there is no id overloaded.
void dyncfg_host_init(RRDHOST *host) { void dyncfg_host_init(RRDHOST *host) {
// IMPORTANT:
// This function needs to be async, although it is internal.
// The reason is that it can call by itself another function that may or may not be internal (sync).
rrd_function_add(host, NULL, PLUGINSD_FUNCTION_CONFIG, 120, rrd_function_add(host, NULL, PLUGINSD_FUNCTION_CONFIG, 120,
1000, "Dynamic configuration", "config", HTTP_ACCESS_ANONYMOUS_DATA, 1000, "Dynamic configuration", "config", HTTP_ACCESS_ANONYMOUS_DATA,
true, dyncfg_config_execute_cb, host); false, dyncfg_config_execute_cb, host);
} }