mirror of
https://github.com/netdata/netdata.git
synced 2025-04-27 14:16:20 +00:00
DYNCFG: call the interceptor when a test is made on a new job (#17052)
* 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:
parent
751e80476f
commit
bc3ff3fabe
3 changed files with 41 additions and 9 deletions
src/daemon/config
|
@ -180,7 +180,7 @@ static int dyncfg_intercept_early_error(struct rrd_function_execute *rfe, int 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];
|
||||
memcpy(id_copy, job_id, sizeof(id_copy));
|
||||
|
||||
|
|
|
@ -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);
|
||||
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);
|
||||
|
||||
RRDHOST *dyncfg_rrdhost_by_uuid(UUID *uuid);
|
||||
|
|
|
@ -204,31 +204,57 @@ static int dyncfg_config_execute_cb(struct rrd_function_execute *rfe, void *data
|
|||
action = path;
|
||||
path = NULL;
|
||||
|
||||
if(id && *id && dyncfg_cmds2id(action) == DYNCFG_CMD_REMOVE) {
|
||||
const DICTIONARY_ITEM *item = dictionary_get_and_acquire_item(dyncfg_globals.nodes, id);
|
||||
if(item) {
|
||||
DYNCFG *df = dictionary_acquired_item_value(item);
|
||||
DYNCFG_CMDS cmd = dyncfg_cmds2id(action);
|
||||
const DICTIONARY_ITEM *item = dictionary_get_and_acquire_item(dyncfg_globals.nodes, id);
|
||||
if(!item)
|
||||
item = dyncfg_get_template_of_new_job(id);
|
||||
|
||||
if(!rrd_function_available(host, string2str(df->function)))
|
||||
df->current.status = DYNCFG_STATUS_ORPHAN;
|
||||
if(item) {
|
||||
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);
|
||||
dictionary_acquired_item_release(dyncfg_globals.nodes, item);
|
||||
item = NULL;
|
||||
|
||||
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);
|
||||
dyncfg_file_delete(id);
|
||||
code = dyncfg_default_response(rfe->result.wb, 200, "");
|
||||
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;
|
||||
nd_log(NDLS_DAEMON, NDLP_ERR,
|
||||
"DYNCFG: unknown config id '%s' in call: '%s'. "
|
||||
"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(
|
||||
rfe->result.wb,
|
||||
|
@ -248,7 +274,11 @@ cleanup:
|
|||
// for which there is no id overloaded.
|
||||
|
||||
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,
|
||||
1000, "Dynamic configuration", "config", HTTP_ACCESS_ANONYMOUS_DATA,
|
||||
true, dyncfg_config_execute_cb, host);
|
||||
false, dyncfg_config_execute_cb, host);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue