summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCosta Tsaousis <costa@netdata.cloud>2024-01-12 03:09:05 +0200
committerGitHub <noreply@github.com>2024-01-12 01:09:05 +0000
commit7fce3dcd9cb9eb87509a9cec80e51fefd0a971ff (patch)
tree7d77b663a540429d2da81bfafc392f7549cac24a
parent1474b502b871325e520f08af40c34036df017117 (diff)
/api/v1/config tree improvements and swagger documentation (#16764)
-rw-r--r--daemon/config/dyncfg-tree.c20
-rw-r--r--web/api/netdata-swagger.json355
-rw-r--r--web/api/netdata-swagger.yaml225
-rw-r--r--web/api/web_api_v1.c3
4 files changed, 591 insertions, 12 deletions
diff --git a/daemon/config/dyncfg-tree.c b/daemon/config/dyncfg-tree.c
index 2155e4a771..086b1f13a3 100644
--- a/daemon/config/dyncfg-tree.c
+++ b/daemon/config/dyncfg-tree.c
@@ -21,6 +21,10 @@ static void dyncfg_to_json(DYNCFG *df, const char *id, BUFFER *wb) {
buffer_json_member_add_object(wb, id);
{
buffer_json_member_add_string(wb, "type", dyncfg_id2type(df->type));
+
+ if(df->type == DYNCFG_TYPE_JOB)
+ buffer_json_member_add_string(wb, "template", string2str(df->template));
+
buffer_json_member_add_string(wb, "status", dyncfg_id2status(df->status));
dyncfg_cmds2json_array(df->cmds, "cmds", wb);
buffer_json_member_add_string(wb, "source_type", dyncfg_id2source_type(df->source_type));
@@ -46,13 +50,17 @@ static void dyncfg_to_json(DYNCFG *df, const char *id, BUFFER *wb) {
buffer_json_object_close(wb);
}
-static void dyncfg_tree_for_host(RRDHOST *host, BUFFER *wb, const char *parent, const char *id __maybe_unused) {
+static void dyncfg_tree_for_host(RRDHOST *host, BUFFER *wb, const char *path, const char *id) {
size_t entries = dictionary_entries(dyncfg_globals.nodes);
size_t used = 0;
const DICTIONARY_ITEM *items[entries];
size_t restart_required = 0, plugin_rejected = 0, status_incomplete = 0, status_failed = 0;
- size_t parent_len = strlen(parent);
+ STRING *template = NULL;
+ if(id && *id)
+ template = string_strdupz(id);
+
+ size_t path_len = strlen(path);
DYNCFG *df;
dfe_start_read(dyncfg_globals.nodes, df) {
if(!df->host) {
@@ -60,17 +68,21 @@ static void dyncfg_tree_for_host(RRDHOST *host, BUFFER *wb, const char *parent,
df->host = host;
}
- if(df->host != host || strncmp(string2str(df->path), parent, parent_len) != 0)
+ if(df->host != host || strncmp(string2str(df->path), path, path_len) != 0)
continue;
if(!rrd_function_available(host, string2str(df->function)))
df->status = DYNCFG_STATUS_ORPHAN;
+ if((id && strcmp(id, df_dfe.name) != 0) || (template && df->template != template))
+ continue;
+
items[used++] = dictionary_acquired_item_dup(dyncfg_globals.nodes, df_dfe.item);
}
dfe_done(df);
- qsort(items, used, sizeof(const DICTIONARY_ITEM *), dyncfg_tree_compar);
+ if(used > 1)
+ qsort(items, used, sizeof(const DICTIONARY_ITEM *), dyncfg_tree_compar);
buffer_flush(wb);
buffer_json_initialize(wb, "\"", "\"", 0, true, BUFFER_JSON_OPTIONS_MINIFY);
diff --git a/web/api/netdata-swagger.json b/web/api/netdata-swagger.json
index 6ed3e08b8c..eee8af3306 100644
--- a/web/api/netdata-swagger.json
+++ b/web/api/netdata-swagger.json
@@ -373,6 +373,201 @@
}
}
},
+ "/api/v1/config": {
+ "get": {
+ "operationId": "getConfig",
+ "tags": [
+ "dyncfg"
+ ],
+ "description": "Get dynamic configuration information.\n",
+ "parameters": [
+ {
+ "name": "action",
+ "in": "query",
+ "description": "The type of information required",
+ "schema": {
+ "type": "string",
+ "enum": [
+ "tree",
+ "schema",
+ "get",
+ "enable",
+ "disable",
+ "restart"
+ ],
+ "default": "tree"
+ }
+ },
+ {
+ "name": "id",
+ "in": "query",
+ "description": "The ID of the dynamic configuration entity",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "path",
+ "in": "query",
+ "description": "Top level path of the configuration entities, used with action 'tree'",
+ "schema": {
+ "type": "string",
+ "default": "/"
+ }
+ },
+ {
+ "name": "timeout",
+ "in": "query",
+ "description": "The timeout in seconds",
+ "schema": {
+ "type": "number",
+ "default": 120
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "The call was successful.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "oneOf": [
+ {
+ "$ref": "#/components/schemas/config_default_response"
+ },
+ {
+ "$ref": "#/components/schemas/config_tree"
+ },
+ {
+ "$ref": "#/components/schemas/config_schema"
+ }
+ ]
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Something is wrong with the request.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/config_default_response"
+ }
+ }
+ }
+ },
+ "404": {
+ "description": "The configurable entity requests is not found.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/config_default_response"
+ }
+ }
+ }
+ }
+ }
+ },
+ "post": {
+ "operationId": "postConfig",
+ "tags": [
+ "dyncfg"
+ ],
+ "description": "Post dynamic configuration to Netdata.\n",
+ "parameters": [
+ {
+ "name": "action",
+ "in": "query",
+ "description": "The type of action required.",
+ "schema": {
+ "type": "string",
+ "enum": [
+ "add",
+ "test",
+ "update"
+ ]
+ }
+ },
+ {
+ "name": "id",
+ "in": "query",
+ "description": "The ID of the dynamic configuration entity to configure.",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "name",
+ "in": "query",
+ "description": "Name of the dynamic configuration entity, used with action 'add'",
+ "schema": {
+ "type": "string"
+ }
+ },
+ {
+ "name": "timeout",
+ "in": "query",
+ "description": "The timeout in seconds",
+ "schema": {
+ "type": "number",
+ "default": 120
+ }
+ }
+ ],
+ "responses": {
+ "200": {
+ "description": "The call was successful. This also means the configuration is currently running.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/config_default_response"
+ }
+ }
+ }
+ },
+ "202": {
+ "description": "The call was successful. The configuration has been accepted, but its status is not yet known.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/config_default_response"
+ }
+ }
+ }
+ },
+ "299": {
+ "description": "The call was successful. The configuration has been accepted, but a restart is required to apply it.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/config_default_response"
+ }
+ }
+ }
+ },
+ "400": {
+ "description": "Something is wrong with the request.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/config_default_response"
+ }
+ }
+ }
+ },
+ "404": {
+ "description": "The configurable entity requests is not found.",
+ "content": {
+ "application/json": {
+ "schema": {
+ "$ref": "#/components/schemas/config_default_response"
+ }
+ }
+ }
+ }
+ }
+ }
+ },
"/api/v2/data": {
"get": {
"operationId": "dataQuery2",
@@ -385,7 +580,7 @@
{
"name": "group_by",
"in": "query",
- "description": "A comma separated list of the groupings required.\nAll possible values can be combined together, except `selected`. If `selected` is given in the list, all others are ignored.\nThe order they are placed in the list is currently ignored.\n",
+ "description": "A comma separated list of the groupings required.\nAll possible values can be combined together, except `selected`. If `selected` is given in the list, all others are ignored.\nThe order they are placed in the list is currently ignored.\nThis parameter is also accepted as `group_by[0]` and `group_by[1]` when multiple grouping passes are required.\n",
"required": false,
"schema": {
"type": "array",
@@ -410,7 +605,7 @@
{
"name": "group_by_label",
"in": "query",
- "description": "A comma separated list of the label keys to group by their values. The order of the labels in the list is respected.\n",
+ "description": "A comma separated list of the label keys to group by their values. The order of the labels in the list is respected.\nThis parameter is also accepted as `group_by_label[0]` and `group_by_label[1]` when multiple grouping passes are required.\n",
"required": false,
"schema": {
"type": "string",
@@ -421,7 +616,7 @@
{
"name": "aggregation",
"in": "query",
- "description": "The aggregation function to apply when grouping metrics together.\nWhen option `raw` is given, `average` and `avg` behave like `sum` and the caller is expected to calculate the average.\n",
+ "description": "The aggregation function to apply when grouping metrics together.\nWhen option `raw` is given, `average` and `avg` behave like `sum` and the caller is expected to calculate the average.\nThis parameter is also accepted as `aggregation[0]` and `aggregation[1]` when multiple grouping passes are required.\n",
"required": false,
"schema": {
"type": "string",
@@ -430,7 +625,8 @@
"max",
"avg",
"average",
- "sum"
+ "sum",
+ "percentage"
],
"default": "average"
}
@@ -3689,8 +3885,11 @@
"type": "integer"
},
"count": {
- "description": "The number of metrics aggregated into this point. This exists only when the option `raw` is given to the query.\n",
+ "description": "The number of metrics aggregated into this point.\nThis exists only when the option `raw` is given to the query and the final aggregation point is NOT `percentage`.\n",
"type": "integer"
+ },
+ "hidden": {
+ "description": "The sum of the non-selected dimensions aggregated for this group item point.\nThis exists only when the option `raw` is given to the query and the final aggregation method is `percentage`.\n"
}
}
},
@@ -4415,7 +4614,151 @@
},
"weighted_dimension": {
"type": "number"
+ },
+ "config_schema": {
+ "type": "object",
+ "properties": {
+ "jsonSchema": {
+ "type": "object",
+ "description": "Standard JSON Schema object describing the schema of each configurable entity."
+ },
+ "uiSchema": {
+ "type": "object",
+ "description": "Schema for react-json-schema-form to drive the UI. Provides additional UI-specific configuration."
+ }
+ }
+ },
+ "config_tree": {
+ "type": "object",
+ "properties": {
+ "version": {
+ "type": "integer",
+ "description": "The version of dynamic configuration supported by the Netdata agent."
+ },
+ "tree": {
+ "type": "object",
+ "description": "A map of configuration entity paths, each containing one or more configurable entities.",
+ "additionalProperties": {
+ "type": "object",
+ "additionalProperties": {
+ "$ref": "#/components/schemas/config_entity"
+ }
+ }
+ },
+ "attention": {
+ "$ref": "#/components/schemas/config_attention"
+ }
+ }
+ },
+ "config_entity": {
+ "type": "object",
+ "properties": {
+ "type": {
+ "type": "string",
+ "description": "Can be 'single' for entities appearing once, 'template' for entities supporting multiple instances, or 'job' for jobs belonging to a template."
+ },
+ "status": {
+ "type": "string",
+ "description": "The current status of the entity. Values include 'accepted', 'running', 'failed', 'disabled', 'incomplete', or 'orphan'."
+ },
+ "cmds": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "An array of the possible actions supported by this entity."
+ },
+ "source_type": {
+ "type": "string",
+ "description": "The source type of the configuration (e.g., 'internal', 'stock', 'user', 'discovered', 'dyncfg')."
+ },
+ "source": {
+ "type": "string",
+ "description": "Additional information about the source, formatted as comma-separated name-value pairs."
+ },
+ "sync": {
+ "type": "boolean",
+ "description": "Indicates if this is an internal module (true) or an external plugin (false)."
+ },
+ "user_disabled": {
+ "type": "boolean",
+ "description": "True if the entity is disabled by the user."
+ },
+ "restart_required": {
+ "type": "boolean",
+ "description": "True if the entity requires a restart after addition or update."
+ },
+ "plugin_rejected": {
+ "type": "boolean",
+ "description": "True if a previously saved configuration failed to apply after a restart."
+ },
+ "payload": {
+ "type": "object",
+ "description": "Object containing at least an 'available' boolean indicating if there's a saved configuration for this entity.",
+ "properties": {
+ "available": {
+ "type": "boolean"
+ }
+ }
+ },
+ "saves": {
+ "type": "integer",
+ "description": "The number of times this configuration has been saved to disk by the dynamic configuration manager."
+ },
+ "created_ut": {
+ "type": "integer",
+ "format": "int64",
+ "description": "The timestamp in microseconds when this dynamic configuration was first created."
+ },
+ "modified_ut": {
+ "type": "integer",
+ "format": "int64",
+ "description": "The timestamp in microseconds when this dynamic configuration was last modified."
+ },
+ "template": {
+ "type": "string",
+ "description": "Shows the template the job belongs to, applicable when type is 'job'."
+ }
+ }
+ },
+ "config_attention": {
+ "type": "object",
+ "properties": {
+ "degraded": {
+ "type": "boolean"
+ },
+ "restart_required": {
+ "type": "integer"
+ },
+ "plugin_rejected": {
+ "type": "integer"
+ },
+ "status_failed": {
+ "type": "integer"
+ },
+ "status_incomplete": {
+ "type": "integer"
+ }
+ }
+ },
+ "config_default_response": {
+ "type": "object",
+ "properties": {
+ "status": {
+ "type": "integer",
+ "description": "The HTTP status code of the response."
+ },
+ "message": {
+ "type": "string",
+ "description": "A descriptive message about the response or the action taken."
+ },
+ "data": {
+ "type": "object",
+ "description": "The data payload of the response, contents vary depending on the specific request and action.",
+ "additionalProperties": true
+ }
+ }
}
}
}
-}
+} \ No newline at end of file
diff --git a/web/api/netdata-swagger.yaml b/web/api/netdata-swagger.yaml
index 7fa852f4a3..5107bbe673 100644
--- a/web/api/netdata-swagger.yaml
+++ b/web/api/netdata-swagger.yaml
@@ -226,6 +226,129 @@ paths:
description: No context id was supplied in the request.
"404":
description: No context with the given id is found.
+ /api/v1/config:
+ get:
+ operationId: getConfig
+ tags:
+ - dyncfg
+ description: |
+ Get dynamic configuration information.
+ parameters:
+ - name: action
+ in: query
+ description: The type of information required
+ schema:
+ type: string
+ enum:
+ - tree
+ - schema
+ - get
+ - enable
+ - disable
+ - restart
+ default: tree
+ - name: id
+ in: query
+ description: The ID of the dynamic configuration entity
+ schema:
+ type: string
+ - name: path
+ in: query
+ description: Top level path of the configuration entities, used with action 'tree'
+ schema:
+ type: string
+ default: '/'
+ - name: timeout
+ in: query
+ description: The timeout in seconds
+ schema:
+ type: number
+ default: 120
+ responses:
+ "200":
+ description: The call was successful.
+ content:
+ application/json:
+ schema:
+ oneOf:
+ - $ref: '#/components/schemas/config_default_response'
+ - $ref: '#/components/schemas/config_tree'
+ - $ref: "#/components/schemas/config_schema"
+ "400":
+ description: Something is wrong with the request.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/config_default_response'
+ "404":
+ description: The configurable entity requests is not found.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/config_default_response'
+ post:
+ operationId: postConfig
+ tags:
+ - dyncfg
+ description: |
+ Post dynamic configuration to Netdata.
+ parameters:
+ - name: action
+ in: query
+ description: The type of action required.
+ schema:
+ type: string
+ enum:
+ - add
+ - test
+ - update
+ - name: id
+ in: query
+ description: The ID of the dynamic configuration entity to configure.
+ schema:
+ type: string
+ - name: name
+ in: query
+ description: Name of the dynamic configuration entity, used with action 'add'
+ schema:
+ type: string
+ - name: timeout
+ in: query
+ description: The timeout in seconds
+ schema:
+ type: number
+ default: 120
+ responses:
+ "200":
+ description: The call was successful. This also means the configuration is currently running.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/config_default_response'
+ "202":
+ description: The call was successful. The configuration has been accepted, but its status is not yet known.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/config_default_response'
+ "299":
+ description: The call was successful. The configuration has been accepted, but a restart is required to apply it.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/config_default_response'
+ "400":
+ description: Something is wrong with the request.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/config_default_response'
+ "404":
+ description: The configurable entity requests is not found.
+ content:
+ application/json:
+ schema:
+ $ref: '#/components/schemas/config_default_response'
/api/v2/data:
get:
operationId: dataQuery2
@@ -3259,3 +3382,105 @@ components:
$ref: '#/components/schemas/weighted_dimension'
weighted_dimension:
type: number
+ config_schema:
+ type: object
+ properties:
+ jsonSchema:
+ type: object
+ description: Standard JSON Schema object describing the schema of each configurable entity.
+ uiSchema:
+ type: object
+ description: Schema for react-json-schema-form to drive the UI. Provides additional UI-specific configuration.
+ config_tree:
+ type: object
+ properties:
+ version:
+ type: integer
+ description: The version of dynamic configuration supported by the Netdata agent.
+ tree:
+ type: object
+ description: A map of configuration entity paths, each containing one or more configurable entities.
+ additionalProperties:
+ type: object
+ additionalProperties:
+ $ref: '#/components/schemas/config_entity'
+ attention:
+ $ref: '#/components/schemas/config_attention'
+ config_entity:
+ type: object
+ properties:
+ type:
+ type: string
+ description: Can be 'single' for entities appearing once, 'template' for entities supporting multiple instances, or 'job' for jobs belonging to a template.
+ status:
+ type: string
+ description: The current status of the entity. Values include 'accepted', 'running', 'failed', 'disabled', 'incomplete', or 'orphan'.
+ cmds:
+ type: array
+ items:
+ type: string
+ description: An array of the possible actions supported by this entity.
+ source_type:
+ type: string
+ description: The source type of the configuration (e.g., 'internal', 'stock', 'user', 'discovered', 'dyncfg').
+ source:
+ type: string
+ description: Additional information about the source, formatted as comma-separated name-value pairs.
+ sync:
+ type: boolean
+ description: Indicates if this is an internal module (true) or an external plugin (false).
+ user_disabled:
+ type: boolean
+ description: True if the entity is disabled by the user.
+ restart_required:
+ type: boolean
+ description: True if the entity requires a restart after addition or update.
+ plugin_rejected:
+ type: boolean
+ description: True if a previously saved configuration failed to apply after a restart.
+ payload:
+ type: object
+ description: Object containing at least an 'available' boolean indicating if there's a saved configuration for this entity.
+ properties:
+ available:
+ type: boolean
+ saves:
+ type: integer
+ description: The number of times this configuration has been saved to disk by the dynamic configuration manager.
+ created_ut:
+ type: integer
+ format: int64
+ description: The timestamp in microseconds when this dynamic configuration was first created.
+ modified_ut:
+ type: integer
+ format: int64
+ description: The timestamp in microseconds when this dynamic configuration was last modified.
+ template:
+ type: string
+ description: Shows the template the job belongs to, applicable when type is 'job'.
+ config_attention:
+ type: object
+ properties:
+ degraded:
+ type: boolean
+ restart_required:
+ type: integer
+ plugin_rejected:
+ type: integer
+ status_failed:
+ type: integer
+ status_incomplete:
+ type: integer
+ config_default_response:
+ type: object
+ properties:
+ status:
+ type: integer
+ description: The HTTP status code of the response.
+ message:
+ type: string
+ description: A descriptive message about the response or the action taken.
+ data:
+ type: object
+ description: The data payload of the response, contents vary depending on the specific request and action.
+ additionalProperties: true
diff --git a/web/api/web_api_v1.c b/web/api/web_api_v1.c
index 59c04df10e..5033002d74 100644
--- a/web/api/web_api_v1.c
+++ b/web/api/web_api_v1.c
@@ -1548,8 +1548,7 @@ static int web_client_api_request_v1_config(RRDHOST *host, struct web_client *w,
NULL, NULL,
web_client_progress_functions_update, w,
web_client_interrupt_callback, w,
- w->payload,
- buffer_tostring(source));
+ w->payload, buffer_tostring(source));
return code;
}