| 1 | // SPDX-License-Identifier: GPL-3.0-or-later |
| 2 | |
| 3 | #ifndef NETDATA_DYNCFG_INTERNALS_H |
| 4 | #define NETDATA_DYNCFG_INTERNALS_H |
| 5 | |
| 6 | #include "../common.h" |
| 7 | #include "database/rrd.h" |
| 8 | #include "database/rrdfunctions.h" |
| 9 | #include "database/rrdfunctions-internals.h" |
| 10 | #include "database/rrdcollector-internals.h" |
| 11 | |
| 12 | typedef struct dyncfg { |
| 13 | ND_UUID host_uuid; |
| 14 | STRING *function; |
| 15 | STRING *template; |
| 16 | STRING *path; |
| 17 | DYNCFG_CMDS cmds; |
| 18 | DYNCFG_TYPE type; |
| 19 | |
| 20 | HTTP_ACCESS view_access; |
| 21 | HTTP_ACCESS edit_access; |
| 22 | |
| 23 | struct { |
| 24 | DYNCFG_STATUS status; |
| 25 | DYNCFG_SOURCE_TYPE source_type; |
| 26 | STRING *source; |
| 27 | usec_t created_ut; |
| 28 | usec_t modified_ut; |
| 29 | } current; |
| 30 | |
| 31 | struct { |
| 32 | uint32_t saves; |
| 33 | bool restart_required; |
| 34 | bool plugin_rejected; |
| 35 | bool user_disabled; |
| 36 | DYNCFG_STATUS status; |
| 37 | DYNCFG_SOURCE_TYPE source_type; |
| 38 | STRING *source; |
| 39 | BUFFER *payload; |
| 40 | usec_t created_ut; |
| 41 | usec_t modified_ut; |
| 42 | } dyncfg; |
| 43 | |
| 44 | bool sync; |
| 45 | rrd_function_execute_cb_t execute_cb; |
| 46 | void *execute_cb_data; |
| 47 | } DYNCFG; |
| 48 | |
| 49 | struct dyncfg_globals { |
| 50 | const char *dir; |
| 51 | DICTIONARY *nodes; |
| 52 | }; |
| 53 | |
| 54 | extern struct dyncfg_globals dyncfg_globals; |
| 55 | |
| 56 | void dyncfg_load_all(void); |
| 57 | void dyncfg_file_load(const char *filename); |
| 58 | void dyncfg_file_save(const char *id, DYNCFG *df); |
| 59 | void dyncfg_file_delete(const char *id); |
| 60 | |
| 61 | // Returns the canonical command mask a node should advertise given its type |
| 62 | // and current source_type. Idempotent and order-independent: re-run after a |
| 63 | // node's source_type changes (e.g. UPDATE flips an existing job from |
| 64 | // USER/STOCK to DYNCFG-owned) to refresh the mask -- this is what lets |
| 65 | // REMOVE appear on a freshly overridden alert without an Agent restart. |
| 66 | // The full rule table lives in dyncfg.c. |
| 67 | DYNCFG_CMDS dyncfg_sanitize_cmds(DYNCFG_TYPE type, DYNCFG_SOURCE_TYPE source_type, DYNCFG_CMDS cmds); |
| 68 | bool dyncfg_get_schema(const char *id, BUFFER *dst); |
| 69 | |
| 70 | void dyncfg_echo_cb(BUFFER *wb, int code, void *result_cb_data); |
| 71 | void dyncfg_echo(const DICTIONARY_ITEM *item, DYNCFG *df, const char *id, DYNCFG_CMDS cmd); |
| 72 | void dyncfg_echo_update(const DICTIONARY_ITEM *item, DYNCFG *df, const char *id); |
| 73 | void dyncfg_echo_add(const DICTIONARY_ITEM *item_template, const DICTIONARY_ITEM *item_job, DYNCFG *df_template, DYNCFG *df_job, const char *template_id, const char *job_name); |
| 74 | |
| 75 | const DICTIONARY_ITEM *dyncfg_add_internal(RRDHOST *host, const char *id, const char *path, |
| 76 | DYNCFG_STATUS status, DYNCFG_TYPE type, DYNCFG_SOURCE_TYPE source_type, |
| 77 | const char *source, DYNCFG_CMDS cmds, |
| 78 | usec_t created_ut, usec_t modified_ut, |
| 79 | bool sync, HTTP_ACCESS view_access, HTTP_ACCESS edit_access, |
| 80 | rrd_function_execute_cb_t execute_cb, void *execute_cb_data, |
| 81 | bool overwrite_cb); |
| 82 | |
| 83 | int dyncfg_function_intercept_cb(struct rrd_function_execute *rfe, void *data); |
| 84 | void dyncfg_cleanup(DYNCFG *v); |
| 85 | |
| 86 | const DICTIONARY_ITEM *dyncfg_get_template_of_new_job(const char *job_id); |
| 87 | |
| 88 | bool dyncfg_is_user_disabled(const char *id); |
| 89 | |
| 90 | RRDHOST *dyncfg_rrdhost_by_uuid(ND_UUID *uuid); |
| 91 | RRDHOST *dyncfg_rrdhost(DYNCFG *df); |
| 92 | |
| 93 | static inline void dyncfg_copy_dyncfg_source_to_current(DYNCFG *df) { |
| 94 | STRING *old = df->current.source; |
| 95 | df->current.source = string_dup(df->dyncfg.source); |
| 96 | string_freez(old); |
| 97 | } |
| 98 | |
| 99 | static inline void dyncfg_set_dyncfg_source_from_txt(DYNCFG *df, const char *source) { |
| 100 | STRING *old = df->dyncfg.source; |
| 101 | df->dyncfg.source = string_strdupz(source); |
| 102 | string_freez(old); |
| 103 | } |
| 104 | |
| 105 | static inline void dyncfg_set_current_from_dyncfg(DYNCFG *df) { |
| 106 | df->current.status = df->dyncfg.status; |
| 107 | df->current.source_type = df->dyncfg.source_type; |
| 108 | |
| 109 | dyncfg_copy_dyncfg_source_to_current(df); |
| 110 | |
| 111 | if(df->dyncfg.created_ut < df->current.created_ut) |
| 112 | df->current.created_ut = df->dyncfg.created_ut; |
| 113 | |
| 114 | if(df->dyncfg.modified_ut > df->current.modified_ut) |
| 115 | df->current.modified_ut = df->dyncfg.modified_ut; |
| 116 | } |
| 117 | |
| 118 | static inline void dyncfg_update_status_on_successful_add_or_update(DYNCFG *df, int code) { |
| 119 | df->dyncfg.plugin_rejected = false; |
| 120 | |
| 121 | if (code == DYNCFG_RESP_ACCEPTED_RESTART_REQUIRED) |
| 122 | df->dyncfg.restart_required = true; |
| 123 | else |
| 124 | df->dyncfg.restart_required = false; |
| 125 | |
| 126 | dyncfg_set_current_from_dyncfg(df); |
| 127 | } |
| 128 | |
| 129 | static inline DYNCFG_STATUS dyncfg_status_from_successful_response(int code) { |
| 130 | DYNCFG_STATUS status = DYNCFG_STATUS_ACCEPTED; |
| 131 | |
| 132 | switch(code) { |
| 133 | default: |
| 134 | case DYNCFG_RESP_ACCEPTED: |
| 135 | case DYNCFG_RESP_ACCEPTED_RESTART_REQUIRED: |
| 136 | status = DYNCFG_STATUS_ACCEPTED; |
| 137 | break; |
| 138 | |
| 139 | case DYNCFG_RESP_ACCEPTED_DISABLED: |
| 140 | status = DYNCFG_STATUS_DISABLED; |
| 141 | break; |
| 142 | |
| 143 | case DYNCFG_RESP_RUNNING: |
| 144 | status = DYNCFG_STATUS_RUNNING; |
| 145 | break; |
| 146 | |
| 147 | } |
| 148 | |
| 149 | return status; |
| 150 | } |
| 151 | |
| 152 | #endif //NETDATA_DYNCFG_INTERNALS_H |