@cryptotaxi247 / netdata-1 / commits / 7fce3dcd9

/api/v1/config tree improvements and swagger documentation (#16764)

Costa Tsaousis committed Jan 12, 2024 at 03:09 UTC 7fce3dcd9cb9eb87509a9cec80e51fefd0a971ff
4 files changed +591 -12
daemon/config/dyncfg-tree.c
+16 -4
@@ -21,6 +21,10 @@ static void dyncfg_to_json(DYNCFG *df, const char *id, BUFFER *wb) {
21 buffer_json_member_add_object(wb, id);
22 {
23 buffer_json_member_add_string(wb, "type", dyncfg_id2type(df->type));
24 +
25 + if(df->type == DYNCFG_TYPE_JOB)
26 + buffer_json_member_add_string(wb, "template", string2str(df->template));
27 +
28 buffer_json_member_add_string(wb, "status", dyncfg_id2status(df->status));
29 dyncfg_cmds2json_array(df->cmds, "cmds", wb);
30 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) {
50 buffer_json_object_close(wb);
51 }
52
49 -static void dyncfg_tree_for_host(RRDHOST *host, BUFFER *wb, const char *parent, const char *id __maybe_unused) {
53 +static void dyncfg_tree_for_host(RRDHOST *host, BUFFER *wb, const char *path, const char *id) {
54 size_t entries = dictionary_entries(dyncfg_globals.nodes);
55 size_t used = 0;
56 const DICTIONARY_ITEM *items[entries];
57 size_t restart_required = 0, plugin_rejected = 0, status_incomplete = 0, status_failed = 0;
58
55 - size_t parent_len = strlen(parent);
59 + STRING *template = NULL;
60 + if(id && *id)
61 + template = string_strdupz(id);
62 +
63 + size_t path_len = strlen(path);
64 DYNCFG *df;
65 dfe_start_read(dyncfg_globals.nodes, df) {
66 if(!df->host) {
@@ -60,17 +68,21 @@ static void dyncfg_tree_for_host(RRDHOST *host, BUFFER *wb, const char *parent,
68 df->host = host;
69 }
70
63 - if(df->host != host || strncmp(string2str(df->path), parent, parent_len) != 0)
71 + if(df->host != host || strncmp(string2str(df->path), path, path_len) != 0)
72 continue;
73
74 if(!rrd_function_available(host, string2str(df->function)))
75 df->status = DYNCFG_STATUS_ORPHAN;
76
77 + if((id && strcmp(id, df_dfe.name) != 0) || (template && df->template != template))
78 + continue;
79 +
80 items[used++] = dictionary_acquired_item_dup(dyncfg_globals.nodes, df_dfe.item);
81 }
82 dfe_done(df);
83
73 - qsort(items, used, sizeof(const DICTIONARY_ITEM *), dyncfg_tree_compar);
84 + if(used > 1)
85 + qsort(items, used, sizeof(const DICTIONARY_ITEM *), dyncfg_tree_compar);
86
87 buffer_flush(wb);
88 buffer_json_initialize(wb, "\"", "\"", 0, true, BUFFER_JSON_OPTIONS_MINIFY);
web/api/netdata-swagger.json
+349 -6
@@ -373,6 +373,201 @@
373 }
374 }
375 },
376 + "/api/v1/config": {
377 + "get": {
378 + "operationId": "getConfig",
379 + "tags": [
380 + "dyncfg"
381 + ],
382 + "description": "Get dynamic configuration information.\n",
383 + "parameters": [
384 + {
385 + "name": "action",
386 + "in": "query",
387 + "description": "The type of information required",
388 + "schema": {
389 + "type": "string",
390 + "enum": [
391 + "tree",
392 + "schema",
393 + "get",
394 + "enable",
395 + "disable",
396 + "restart"
397 + ],
398 + "default": "tree"
399 + }
400 + },
401 + {
402 + "name": "id",
403 + "in": "query",
404 + "description": "The ID of the dynamic configuration entity",
405 + "schema": {
406 + "type": "string"
407 + }
408 + },
409 + {
410 + "name": "path",
411 + "in": "query",
412 + "description": "Top level path of the configuration entities, used with action 'tree'",
413 + "schema": {
414 + "type": "string",
415 + "default": "/"
416 + }
417 + },
418 + {
419 + "name": "timeout",
420 + "in": "query",
421 + "description": "The timeout in seconds",
422 + "schema": {
423 + "type": "number",
424 + "default": 120
425 + }
426 + }
427 + ],
428 + "responses": {
429 + "200": {
430 + "description": "The call was successful.",
431 + "content": {
432 + "application/json": {
433 + "schema": {
434 + "oneOf": [
435 + {
436 + "$ref": "#/components/schemas/config_default_response"
437 + },
438 + {
439 + "$ref": "#/components/schemas/config_tree"
440 + },
441 + {
442 + "$ref": "#/components/schemas/config_schema"
443 + }
444 + ]
445 + }
446 + }
447 + }
448 + },
449 + "400": {
450 + "description": "Something is wrong with the request.",
451 + "content": {
452 + "application/json": {
453 + "schema": {
454 + "$ref": "#/components/schemas/config_default_response"
455 + }
456 + }
457 + }
458 + },
459 + "404": {
460 + "description": "The configurable entity requests is not found.",
461 + "content": {
462 + "application/json": {
463 + "schema": {
464 + "$ref": "#/components/schemas/config_default_response"
465 + }
466 + }
467 + }
468 + }
469 + }
470 + },
471 + "post": {
472 + "operationId": "postConfig",
473 + "tags": [
474 + "dyncfg"
475 + ],
476 + "description": "Post dynamic configuration to Netdata.\n",
477 + "parameters": [
478 + {
479 + "name": "action",
480 + "in": "query",
481 + "description": "The type of action required.",
482 + "schema": {
483 + "type": "string",
484 + "enum": [
485 + "add",
486 + "test",
487 + "update"
488 + ]
489 + }
490 + },
491 + {
492 + "name": "id",
493 + "in": "query",
494 + "description": "The ID of the dynamic configuration entity to configure.",
495 + "schema": {
496 + "type": "string"
497 + }
498 + },
499 + {
500 + "name": "name",
501 + "in": "query",
502 + "description": "Name of the dynamic configuration entity, used with action 'add'",
503 + "schema": {
504 + "type": "string"
505 + }
506 + },
507 + {
508 + "name": "timeout",
509 + "in": "query",
510 + "description": "The timeout in seconds",
511 + "schema": {
512 + "type": "number",
513 + "default": 120
514 + }
515 + }
516 + ],
517 + "responses": {
518 + "200": {
519 + "description": "The call was successful. This also means the configuration is currently running.",
520 + "content": {
521 + "application/json": {
522 + "schema": {
523 + "$ref": "#/components/schemas/config_default_response"
524 + }
525 + }
526 + }
527 + },
528 + "202": {
529 + "description": "The call was successful. The configuration has been accepted, but its status is not yet known.",
530 + "content": {
531 + "application/json": {
532 + "schema": {
533 + "$ref": "#/components/schemas/config_default_response"
534 + }
535 + }
536 + }
537 + },
538 + "299": {
539 + "description": "The call was successful. The configuration has been accepted, but a restart is required to apply it.",
540 + "content": {
541 + "application/json": {
542 + "schema": {
543 + "$ref": "#/components/schemas/config_default_response"
544 + }
545 + }
546 + }
547 + },
548 + "400": {
549 + "description": "Something is wrong with the request.",
550 + "content": {
551 + "application/json": {
552 + "schema": {
553 + "$ref": "#/components/schemas/config_default_response"
554 + }
555 + }
556 + }
557 + },
558 + "404": {
559 + "description": "The configurable entity requests is not found.",
560 + "content": {
561 + "application/json": {
562 + "schema": {
563 + "$ref": "#/components/schemas/config_default_response"
564 + }
565 + }
566 + }
567 + }
568 + }
569 + }
570 + },
571 "/api/v2/data": {
572 "get": {
573 "operationId": "dataQuery2",
@@ -385,7 +580,7 @@
580 {
581 "name": "group_by",
582 "in": "query",
388 - "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",
583 + "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",
584 "required": false,
585 "schema": {
586 "type": "array",
@@ -410,7 +605,7 @@
605 {
606 "name": "group_by_label",
607 "in": "query",
413 - "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",
608 + "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",
609 "required": false,
610 "schema": {
611 "type": "string",
@@ -421,7 +616,7 @@
616 {
617 "name": "aggregation",
618 "in": "query",
424 - "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",
619 + "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",
620 "required": false,
621 "schema": {
622 "type": "string",
@@ -430,7 +625,8 @@
625 "max",
626 "avg",
627 "average",
433 - "sum"
628 + "sum",
629 + "percentage"
630 ],
631 "default": "average"
632 }
@@ -3689,8 +3885,11 @@
3885 "type": "integer"
3886 },
3887 "count": {
3692 - "description": "The number of metrics aggregated into this point. This exists only when the option `raw` is given to the query.\n",
3888 + "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",
3889 "type": "integer"
3890 + },
3891 + "hidden": {
3892 + "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"
3893 }
3894 }
3895 },
@@ -4415,7 +4614,151 @@
4614 },
4615 "weighted_dimension": {
4616 "type": "number"
4617 + },
4618 + "config_schema": {
4619 + "type": "object",
4620 + "properties": {
4621 + "jsonSchema": {
4622 + "type": "object",
4623 + "description": "Standard JSON Schema object describing the schema of each configurable entity."
4624 + },
4625 + "uiSchema": {
4626 + "type": "object",
4627 + "description": "Schema for react-json-schema-form to drive the UI. Provides additional UI-specific configuration."
4628 + }
4629 + }
4630 + },
4631 + "config_tree": {
4632 + "type": "object",
4633 + "properties": {
4634 + "version": {
4635 + "type": "integer",
4636 + "description": "The version of dynamic configuration supported by the Netdata agent."
4637 + },
4638 + "tree": {
4639 + "type": "object",
4640 + "description": "A map of configuration entity paths, each containing one or more configurable entities.",
4641 + "additionalProperties": {
4642 + "type": "object",
4643 + "additionalProperties": {
4644 + "$ref": "#/components/schemas/config_entity"
4645 + }
4646 + }
4647 + },
4648 + "attention": {
4649 + "$ref": "#/components/schemas/config_attention"
4650 + }
4651 + }
4652 + },
4653 + "config_entity": {
4654 + "type": "object",
4655 + "properties": {
4656 + "type": {
4657 + "type": "string",
4658 + "description": "Can be 'single' for entities appearing once, 'template' for entities supporting multiple instances, or 'job' for jobs belonging to a template."
4659 + },
4660 + "status": {
4661 + "type": "string",
4662 + "description": "The current status of the entity. Values include 'accepted', 'running', 'failed', 'disabled', 'incomplete', or 'orphan'."
4663 + },
4664 + "cmds": {
4665 + "type": "array",
4666 + "items": {
4667 + "type": "string"
4668 + },
4669 + "description": "An array of the possible actions supported by this entity."
4670 + },
4671 + "source_type": {
4672 + "type": "string",
4673 + "description": "The source type of the configuration (e.g., 'internal', 'stock', 'user', 'discovered', 'dyncfg')."
4674 + },
4675 + "source": {
4676 + "type": "string",
4677 + "description": "Additional information about the source, formatted as comma-separated name-value pairs."
4678 + },
4679 + "sync": {
4680 + "type": "boolean",
4681 + "description": "Indicates if this is an internal module (true) or an external plugin (false)."
4682 + },
4683 + "user_disabled": {
4684 + "type": "boolean",
4685 + "description": "True if the entity is disabled by the user."
4686 + },
4687 + "restart_required": {
4688 + "type": "boolean",
4689 + "description": "True if the entity requires a restart after addition or update."
4690 + },
4691 + "plugin_rejected": {
4692 + "type": "boolean",
4693 + "description": "True if a previously saved configuration failed to apply after a restart."
4694 + },
4695 + "payload": {
4696 + "type": "object",
4697 + "description": "Object containing at least an 'available' boolean indicating if there's a saved configuration for this entity.",
4698 + "properties": {
4699 + "available": {
4700 + "type": "boolean"
4701 + }
4702 + }
4703 + },
4704 + "saves": {
4705 + "type": "integer",
4706 + "description": "The number of times this configuration has been saved to disk by the dynamic configuration manager."
4707 + },
4708 + "created_ut": {
4709 + "type": "integer",
4710 + "format": "int64",
4711 + "description": "The timestamp in microseconds when this dynamic configuration was first created."
4712 + },
4713 + "modified_ut": {
4714 + "type": "integer",
4715 + "format": "int64",
4716 + "description": "The timestamp in microseconds when this dynamic configuration was last modified."
4717 + },
4718 + "template": {
4719 + "type": "string",
4720 + "description": "Shows the template the job belongs to, applicable when type is 'job'."
4721 + }
4722 + }
4723 + },
4724 + "config_attention": {
4725 + "type": "object",
4726 + "properties": {
4727 + "degraded": {
4728 + "type": "boolean"
4729 + },
4730 + "restart_required": {
4731 + "type": "integer"
4732 + },
4733 + "plugin_rejected": {
4734 + "type": "integer"
4735 + },
4736 + "status_failed": {
4737 + "type": "integer"
4738 + },
4739 + "status_incomplete": {
4740 + "type": "integer"
4741 + }
4742 + }
4743 + },
4744 + "config_default_response": {
4745 + "type": "object",
4746 + "properties": {
4747 + "status": {
4748 + "type": "integer",
4749 + "description": "The HTTP status code of the response."
4750 + },
4751 + "message": {
4752 + "type": "string",
4753 + "description": "A descriptive message about the response or the action taken."
4754 + },
4755 + "data": {
4756 + "type": "object",
4757 + "description": "The data payload of the response, contents vary depending on the specific request and action.",
4758 + "additionalProperties": true
4759 + }
4760 + }
4761 }
4762 }
4763 }
4421 -}
4764 +}
\ No newline at end of file
web/api/netdata-swagger.yaml
+225
@@ -226,6 +226,129 @@ paths:
226 description: No context id was supplied in the request.
227 "404":
228 description: No context with the given id is found.
229 + /api/v1/config:
230 + get:
231 + operationId: getConfig
232 + tags:
233 + - dyncfg
234 + description: |
235 + Get dynamic configuration information.
236 + parameters:
237 + - name: action
238 + in: query
239 + description: The type of information required
240 + schema:
241 + type: string
242 + enum:
243 + - tree
244 + - schema
245 + - get
246 + - enable
247 + - disable
248 + - restart
249 + default: tree
250 + - name: id
251 + in: query
252 + description: The ID of the dynamic configuration entity
253 + schema:
254 + type: string
255 + - name: path
256 + in: query
257 + description: Top level path of the configuration entities, used with action 'tree'
258 + schema:
259 + type: string
260 + default: '/'
261 + - name: timeout
262 + in: query
263 + description: The timeout in seconds
264 + schema:
265 + type: number
266 + default: 120
267 + responses:
268 + "200":
269 + description: The call was successful.
270 + content:
271 + application/json:
272 + schema:
273 + oneOf:
274 + - $ref: '#/components/schemas/config_default_response'
275 + - $ref: '#/components/schemas/config_tree'
276 + - $ref: "#/components/schemas/config_schema"
277 + "400":
278 + description: Something is wrong with the request.
279 + content:
280 + application/json:
281 + schema:
282 + $ref: '#/components/schemas/config_default_response'
283 + "404":
284 + description: The configurable entity requests is not found.
285 + content:
286 + application/json:
287 + schema:
288 + $ref: '#/components/schemas/config_default_response'
289 + post:
290 + operationId: postConfig
291 + tags:
292 + - dyncfg
293 + description: |
294 + Post dynamic configuration to Netdata.
295 + parameters:
296 + - name: action
297 + in: query
298 + description: The type of action required.
299 + schema:
300 + type: string
301 + enum:
302 + - add
303 + - test
304 + - update
305 + - name: id
306 + in: query
307 + description: The ID of the dynamic configuration entity to configure.
308 + schema:
309 + type: string
310 + - name: name
311 + in: query
312 + description: Name of the dynamic configuration entity, used with action 'add'
313 + schema:
314 + type: string
315 + - name: timeout
316 + in: query
317 + description: The timeout in seconds
318 + schema:
319 + type: number
320 + default: 120
321 + responses:
322 + "200":
323 + description: The call was successful. This also means the configuration is currently running.
324 + content:
325 + application/json:
326 + schema:
327 + $ref: '#/components/schemas/config_default_response'
328 + "202":
329 + description: The call was successful. The configuration has been accepted, but its status is not yet known.
330 + content:
331 + application/json:
332 + schema:
333 + $ref: '#/components/schemas/config_default_response'
334 + "299":
335 + description: The call was successful. The configuration has been accepted, but a restart is required to apply it.
336 + content:
337 + application/json:
338 + schema:
339 + $ref: '#/components/schemas/config_default_response'
340 + "400":
341 + description: Something is wrong with the request.
342 + content:
343 + application/json:
344 + schema:
345 + $ref: '#/components/schemas/config_default_response'
346 + "404":
347 + description: The configurable entity requests is not found.
348 + content:
349 + application/json:
350 + schema:
351 + $ref: '#/components/schemas/config_default_response'
352 /api/v2/data:
353 get:
354 operationId: dataQuery2
@@ -3259,3 +3382,105 @@ components:
3382 $ref: '#/components/schemas/weighted_dimension'
3383 weighted_dimension:
3384 type: number
3385 + config_schema:
3386 + type: object
3387 + properties:
3388 + jsonSchema:
3389 + type: object
3390 + description: Standard JSON Schema object describing the schema of each configurable entity.
3391 + uiSchema:
3392 + type: object
3393 + description: Schema for react-json-schema-form to drive the UI. Provides additional UI-specific configuration.
3394 + config_tree:
3395 + type: object
3396 + properties:
3397 + version:
3398 + type: integer
3399 + description: The version of dynamic configuration supported by the Netdata agent.
3400 + tree:
3401 + type: object
3402 + description: A map of configuration entity paths, each containing one or more configurable entities.
3403 + additionalProperties:
3404 + type: object
3405 + additionalProperties:
3406 + $ref: '#/components/schemas/config_entity'
3407 + attention:
3408 + $ref: '#/components/schemas/config_attention'
3409 + config_entity:
3410 + type: object
3411 + properties:
3412 + type:
3413 + type: string
3414 + description: Can be 'single' for entities appearing once, 'template' for entities supporting multiple instances, or 'job' for jobs belonging to a template.
3415 + status:
3416 + type: string
3417 + description: The current status of the entity. Values include 'accepted', 'running', 'failed', 'disabled', 'incomplete', or 'orphan'.
3418 + cmds:
3419 + type: array
3420 + items:
3421 + type: string
3422 + description: An array of the possible actions supported by this entity.
3423 + source_type:
3424 + type: string
3425 + description: The source type of the configuration (e.g., 'internal', 'stock', 'user', 'discovered', 'dyncfg').
3426 + source:
3427 + type: string
3428 + description: Additional information about the source, formatted as comma-separated name-value pairs.
3429 + sync:
3430 + type: boolean
3431 + description: Indicates if this is an internal module (true) or an external plugin (false).
3432 + user_disabled:
3433 + type: boolean
3434 + description: True if the entity is disabled by the user.
3435 + restart_required:
3436 + type: boolean
3437 + description: True if the entity requires a restart after addition or update.
3438 + plugin_rejected:
3439 + type: boolean
3440 + description: True if a previously saved configuration failed to apply after a restart.
3441 + payload:
3442 + type: object
3443 + description: Object containing at least an 'available' boolean indicating if there's a saved configuration for this entity.
3444 + properties:
3445 + available:
3446 + type: boolean
3447 + saves:
3448 + type: integer
3449 + description: The number of times this configuration has been saved to disk by the dynamic configuration manager.
3450 + created_ut:
3451 + type: integer
3452 + format: int64
3453 + description: The timestamp in microseconds when this dynamic configuration was first created.
3454 + modified_ut:
3455 + type: integer
3456 + format: int64
3457 + description: The timestamp in microseconds when this dynamic configuration was last modified.
3458 + template:
3459 + type: string
3460 + description: Shows the template the job belongs to, applicable when type is 'job'.
3461 + config_attention:
3462 + type: object
3463 + properties:
3464 + degraded:
3465 + type: boolean
3466 + restart_required:
3467 + type: integer
3468 + plugin_rejected:
3469 + type: integer
3470 + status_failed:
3471 + type: integer
3472 + status_incomplete:
3473 + type: integer
3474 + config_default_response:
3475 + type: object
3476 + properties:
3477 + status:
3478 + type: integer
3479 + description: The HTTP status code of the response.
3480 + message:
3481 + type: string
3482 + description: A descriptive message about the response or the action taken.
3483 + data:
3484 + type: object
3485 + description: The data payload of the response, contents vary depending on the specific request and action.
3486 + additionalProperties: true
web/api/web_api_v1.c
+1 -2
@@ -1548,8 +1548,7 @@ static int web_client_api_request_v1_config(RRDHOST *host, struct web_client *w,
1548 NULL, NULL,
1549 web_client_progress_functions_update, w,
1550 web_client_interrupt_callback, w,
1551 - w->payload,
1552 - buffer_tostring(source));
1551 + w->payload, buffer_tostring(source));
1552
1553 return code;
1554 }