0
0
Fork 0
mirror of https://github.com/netdata/netdata.git synced 2025-04-16 10:31:07 +00:00

DYNCFG support deleting orphan configurations ()

* dyncfg: allow deleting orphan configs

* restore applied text

* make the dyncfg applied text more descriptive
This commit is contained in:
Costa Tsaousis 2024-02-16 16:39:00 +02:00 committed by GitHub
parent 23e9e990ba
commit 81cb35dcca
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 73 additions and 28 deletions

View file

@ -225,38 +225,44 @@ int dyncfg_function_intercept_cb(struct rrd_function_execute *rfe, void *data __
char *cmd_str = get_word(words, num_words, i++);
if(!config || !*config || strcmp(config, PLUGINSD_FUNCTION_CONFIG) != 0)
return dyncfg_intercept_early_error(rfe, HTTP_RESP_BAD_REQUEST,
"dyncfg functions intercept: this is not a dyncfg request");
return dyncfg_intercept_early_error(
rfe, HTTP_RESP_BAD_REQUEST,
"dyncfg functions intercept: this is not a dyncfg request");
cmd = dyncfg_cmds2id(cmd_str);
if(cmd == DYNCFG_CMD_NONE)
return dyncfg_intercept_early_error(rfe, HTTP_RESP_BAD_REQUEST,
"dyncfg functions intercept: invalid command received");
return dyncfg_intercept_early_error(
rfe, HTTP_RESP_BAD_REQUEST,
"dyncfg functions intercept: invalid command received");
if(cmd == DYNCFG_CMD_ADD) {
add_name = get_word(words, num_words, i++);
if(!add_name || !*add_name)
return dyncfg_intercept_early_error(rfe, HTTP_RESP_BAD_REQUEST,
"dyncfg functions intercept: this action requires a name");
return dyncfg_intercept_early_error(
rfe, HTTP_RESP_BAD_REQUEST,
"dyncfg functions intercept: this action requires a name");
if(!called_from_dyncfg_echo) {
char nid[strlen(id) + strlen(add_name) + 2];
snprintfz(nid, sizeof(nid), "%s:%s", id, add_name);
if (dictionary_get(dyncfg_globals.nodes, nid))
return dyncfg_intercept_early_error(rfe, HTTP_RESP_BAD_REQUEST,
"dyncfg functions intercept: a configuration with this name already exists");
return dyncfg_intercept_early_error(
rfe, HTTP_RESP_BAD_REQUEST,
"dyncfg functions intercept: a configuration with this name already exists");
}
}
if((cmd == DYNCFG_CMD_ADD || cmd == DYNCFG_CMD_UPDATE || cmd == DYNCFG_CMD_TEST) && !has_payload)
return dyncfg_intercept_early_error(rfe, HTTP_RESP_BAD_REQUEST,
"dyncfg functions intercept: this action requires a payload");
return dyncfg_intercept_early_error(
rfe, HTTP_RESP_BAD_REQUEST,
"dyncfg functions intercept: this action requires a payload");
if((cmd != DYNCFG_CMD_ADD && cmd != DYNCFG_CMD_UPDATE && cmd != DYNCFG_CMD_TEST) && has_payload)
return dyncfg_intercept_early_error(rfe, HTTP_RESP_BAD_REQUEST,
"dyncfg functions intercept: this action does not require a payload");
return dyncfg_intercept_early_error(
rfe, HTTP_RESP_BAD_REQUEST,
"dyncfg functions intercept: this action does not require a payload");
item = dictionary_get_and_acquire_item(dyncfg_globals.nodes, id);
if(!item) {
@ -266,7 +272,9 @@ int dyncfg_function_intercept_cb(struct rrd_function_execute *rfe, void *data __
}
if(!item)
return dyncfg_intercept_early_error(rfe, HTTP_RESP_NOT_FOUND, "dyncfg functions intercept: id is not found");
return dyncfg_intercept_early_error(
rfe, HTTP_RESP_NOT_FOUND,
"dyncfg functions intercept: id is not found");
}
DYNCFG *df = dictionary_acquired_item_value(item);
@ -278,8 +286,9 @@ int dyncfg_function_intercept_cb(struct rrd_function_execute *rfe, void *data __
case DYNCFG_CMD_SCHEMA:
if(!http_access_user_has_enough_access_level_for_endpoint(rfe->user_access, df->view_access)) {
make_the_call_to_plugin = false;
rc = dyncfg_default_response(rfe->result.wb, HTTP_RESP_FORBIDDEN,
"dyncfg: you don't have enough view permissions to execute this command");
rc = dyncfg_default_response(
rfe->result.wb, HTTP_RESP_FORBIDDEN,
"dyncfg: you don't have enough view permissions to execute this command");
}
break;
@ -292,15 +301,17 @@ int dyncfg_function_intercept_cb(struct rrd_function_execute *rfe, void *data __
case DYNCFG_CMD_RESTART:
if(!http_access_user_has_enough_access_level_for_endpoint(rfe->user_access, df->edit_access)) {
make_the_call_to_plugin = false;
rc = dyncfg_default_response(rfe->result.wb, HTTP_RESP_FORBIDDEN,
"dyncfg: you don't have enough edit permissions to execute this command");
rc = dyncfg_default_response(
rfe->result.wb, HTTP_RESP_FORBIDDEN,
"dyncfg: you don't have enough edit permissions to execute this command");
}
break;
default: {
make_the_call_to_plugin = false;
rc = dyncfg_default_response(rfe->result.wb, HTTP_RESP_INTERNAL_SERVER_ERROR,
"dyncfg: permissions for this command are not set");
rc = dyncfg_default_response(
rfe->result.wb, HTTP_RESP_INTERNAL_SERVER_ERROR,
"dyncfg: permissions for this command are not set");
}
break;
}
@ -320,8 +331,9 @@ int dyncfg_function_intercept_cb(struct rrd_function_execute *rfe, void *data __
else if (cmd == DYNCFG_CMD_ADD) {
if (df->type != DYNCFG_TYPE_TEMPLATE) {
make_the_call_to_plugin = false;
rc = dyncfg_default_response(rfe->result.wb, HTTP_RESP_BAD_REQUEST,
"dyncfg functions intercept: add command is only allowed in templates");
rc = dyncfg_default_response(
rfe->result.wb, HTTP_RESP_BAD_REQUEST,
"dyncfg functions intercept: add command is only allowed in templates");
nd_log(NDLS_DAEMON, NDLP_ERR,
"DYNCFG: add command can only be applied on templates, not %s: %s",
@ -331,11 +343,14 @@ int dyncfg_function_intercept_cb(struct rrd_function_execute *rfe, void *data __
else if (
cmd == DYNCFG_CMD_ENABLE && df->type == DYNCFG_TYPE_JOB &&
dyncfg_is_user_disabled(string2str(df->template))) {
nd_log(NDLS_DAEMON, NDLP_ERR, "DYNCFG: cannot enable a job of a disabled template: %s", rfe->function);
nd_log(NDLS_DAEMON, NDLP_ERR,
"DYNCFG: cannot enable a job of a disabled template: %s",
rfe->function);
make_the_call_to_plugin = false;
rc = dyncfg_default_response(rfe->result.wb, HTTP_RESP_BAD_REQUEST,
"dyncfg functions intercept: this job belongs to disabled template");
rc = dyncfg_default_response(
rfe->result.wb, HTTP_RESP_BAD_REQUEST,
"dyncfg functions intercept: this job belongs to disabled template");
}
}
@ -356,7 +371,7 @@ int dyncfg_function_intercept_cb(struct rrd_function_execute *rfe, void *data __
dyncfg_apply_action_on_all_template_jobs(rfe, id, cmd);
rc = dyncfg_default_response(rfe->result.wb, HTTP_RESP_OK, "applied");
rc = dyncfg_default_response(rfe->result.wb, HTTP_RESP_OK, "applied to all template job");
make_the_call_to_plugin = false;
}
else if (cmd == DYNCFG_CMD_SCHEMA) {

View file

@ -26,7 +26,7 @@ static void dyncfg_to_json(DYNCFG *df, const char *id, BUFFER *wb) {
buffer_json_member_add_string(wb, "template", string2str(df->template));
buffer_json_member_add_string(wb, "status", dyncfg_id2status(df->current.status));
dyncfg_cmds2json_array(df->cmds, "cmds", wb);
dyncfg_cmds2json_array(df->current.status == DYNCFG_STATUS_ORPHAN ? DYNCFG_CMD_REMOVE : df->cmds, "cmds", wb);
buffer_json_member_add_object(wb, "access");
{
http_access2buffer_json_array(wb, "view", df->view_access);
@ -200,9 +200,39 @@ static int dyncfg_config_execute_cb(struct rrd_function_execute *rfe, void *data
dyncfg_tree_for_host(host, rfe->result.wb, path, id);
}
else {
id = action;
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);
if(!rrd_function_available(host, string2str(df->function)))
df->current.status = DYNCFG_STATUS_ORPHAN;
bool delete = (df->current.status == DYNCFG_STATUS_ORPHAN);
dictionary_acquired_item_release(dyncfg_globals.nodes, item);
if(delete) {
dictionary_del(dyncfg_globals.nodes, id);
dyncfg_file_delete(id);
code = dyncfg_default_response(rfe->result.wb, 200, "");
goto cleanup;
}
}
}
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);
rrd_call_function_error(rfe->result.wb, "unknown config id given", code);
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);
rrd_call_function_error(
rfe->result.wb,
"unknown config id given", code);
}
cleanup: