2
2
# (c) 2019-2021 Andreas Motl <[email protected] >
3
3
# License: GNU Affero General Public License, Version 3
4
4
import asyncio
5
+ import dataclasses
5
6
import json
6
7
import logging
7
8
from collections import OrderedDict
18
19
DashboardDetails ,
19
20
DashboardExplorationItem ,
20
21
DatasourceExplorationItem ,
22
+ DatasourceItem ,
21
23
GrafanaDataModel ,
22
24
)
23
25
from grafana_wtf .monkey import monkeypatch_grafana_api
@@ -390,9 +392,10 @@ def explore_datasources(self):
390
392
# Compute list of exploration items, associating datasources with the dashboards that use them.
391
393
results_used = []
392
394
results_unused = []
393
- for name in sorted (ix .datasource_by_name ):
394
- datasource = ix .datasource_by_name [name ]
395
- dashboard_uids = ix .datasource_dashboard_index .get (name , [])
395
+ for ds_identifier in sorted (ix .datasource_by_ident ):
396
+
397
+ datasource = ix .datasource_by_ident [ds_identifier ]
398
+ dashboard_uids = ix .datasource_dashboard_index .get (ds_identifier , [])
396
399
dashboards = list (map (ix .dashboard_by_uid .get , dashboard_uids ))
397
400
item = DatasourceExplorationItem (datasource = datasource , used_in = dashboards , grafana_url = self .grafana_url )
398
401
@@ -404,6 +407,9 @@ def explore_datasources(self):
404
407
else :
405
408
results_unused .append (result )
406
409
410
+ results_used = sorted (results_used , key = lambda x : x ["datasource" ]["uid" ] or x ["datasource" ]["name" ])
411
+ results_unused = sorted (results_unused , key = lambda x : x ["datasource" ]["uid" ] or x ["datasource" ]["name" ])
412
+
407
413
response = OrderedDict (
408
414
used = results_used ,
409
415
unused = results_unused ,
@@ -422,18 +428,20 @@ def explore_dashboards(self):
422
428
for uid in sorted (ix .dashboard_by_uid ):
423
429
424
430
dashboard = ix .dashboard_by_uid [uid ]
425
- datasource_names = ix .dashboard_datasource_index [uid ]
431
+ datasource_items = ix .dashboard_datasource_index [uid ]
426
432
427
433
datasources_existing = []
428
- datasource_names_missing = []
429
- for datasource_name in datasource_names :
430
- if datasource_name == "-- Grafana --" :
434
+ datasources_missing = []
435
+ for datasource_item in datasource_items :
436
+ if datasource_item . name == "-- Grafana --" :
431
437
continue
432
- datasource = ix .datasource_by_name .get (datasource_name )
438
+ datasource_by_uid = ix .datasource_by_uid .get (datasource_item .uid )
439
+ datasource_by_name = ix .datasource_by_name .get (datasource_item .name )
440
+ datasource = datasource_by_uid or datasource_by_name
433
441
if datasource :
434
442
datasources_existing .append (datasource )
435
443
else :
436
- datasource_names_missing .append ({ "name" : datasource_name } )
444
+ datasources_missing .append (dataclasses . asdict ( datasource_item ) )
437
445
item = DashboardExplorationItem (
438
446
dashboard = dashboard , datasources = datasources_existing , grafana_url = self .grafana_url
439
447
)
@@ -442,8 +450,8 @@ def explore_dashboards(self):
442
450
result = item .format_compact ()
443
451
444
452
# Add information about missing data sources.
445
- if datasource_names_missing :
446
- result ["datasources_missing" ] = datasource_names_missing
453
+ if datasources_missing :
454
+ result ["datasources_missing" ] = datasources_missing
447
455
448
456
results .append (result )
449
457
@@ -456,6 +464,8 @@ def __init__(self, engine: GrafanaWtf):
456
464
457
465
# Prepare index data structures.
458
466
self .dashboard_by_uid = {}
467
+ self .datasource_by_ident = {}
468
+ self .datasource_by_uid = {}
459
469
self .datasource_by_name = {}
460
470
self .dashboard_datasource_index = {}
461
471
self .datasource_dashboard_index = {}
@@ -472,12 +482,16 @@ def index(self):
472
482
self .index_datasources ()
473
483
474
484
@staticmethod
475
- def collect_datasource_names (element ):
476
- names = []
485
+ def collect_datasource_items (element ):
486
+ items = []
477
487
for node in element :
478
488
if "datasource" in node and node ["datasource" ]:
479
- names .append (node .datasource )
480
- return list (sorted (set (names )))
489
+ ds = node .datasource
490
+ if isinstance (ds , Munch ):
491
+ ds = dict (ds )
492
+ if ds not in items :
493
+ items .append (ds )
494
+ return sorted (items )
481
495
482
496
def index_dashboards (self ):
483
497
@@ -496,21 +510,36 @@ def index_dashboards(self):
496
510
self .dashboard_by_uid [uid ] = dashboard
497
511
498
512
# Map to data source names.
499
- ds_panels = self .collect_datasource_names (dbdetails .panels )
500
- ds_annotations = self .collect_datasource_names (dbdetails .annotations )
501
- ds_templating = self .collect_datasource_names (dbdetails .templating )
502
- self .dashboard_datasource_index [uid ] = list (sorted (set (ds_panels + ds_annotations + ds_templating )))
513
+ ds_panels = self .collect_datasource_items (dbdetails .panels )
514
+ ds_annotations = self .collect_datasource_items (dbdetails .annotations )
515
+ ds_templating = self .collect_datasource_items (dbdetails .templating )
516
+
517
+ results = []
518
+ for bucket in ds_panels , ds_annotations , ds_templating :
519
+ for item in bucket :
520
+ item = DatasourceItem .from_payload (item )
521
+ if item not in results :
522
+ results .append (item )
523
+ self .dashboard_datasource_index [uid ] = results
503
524
504
525
def index_datasources (self ):
505
526
527
+ self .datasource_by_ident = {}
528
+ self .datasource_by_uid = {}
506
529
self .datasource_by_name = {}
507
530
self .datasource_dashboard_index = {}
508
531
509
532
for datasource in self .datasources :
510
- name = datasource .name
511
- self .datasource_by_name [name ] = datasource
512
-
513
- for dashboard_uid , datasource_names in self .dashboard_datasource_index .items ():
514
- for datasource_name in datasource_names :
515
- self .datasource_dashboard_index .setdefault (datasource_name , [])
516
- self .datasource_dashboard_index [datasource_name ].append (dashboard_uid )
533
+ datasource_name_or_uid = datasource .uid or datasource .name
534
+ self .datasource_by_ident [datasource_name_or_uid ] = datasource
535
+ self .datasource_by_uid [datasource .uid ] = datasource
536
+ self .datasource_by_name [datasource .name ] = datasource
537
+
538
+ for dashboard_uid , datasource_items in self .dashboard_datasource_index .items ():
539
+ datasource_item : DatasourceItem
540
+ for datasource_item in datasource_items :
541
+ datasource_name_or_uid = datasource_item .uid or datasource_item .name
542
+ if datasource_name_or_uid in self .datasource_by_name :
543
+ datasource_name_or_uid = self .datasource_by_name [datasource_name_or_uid ].uid
544
+ self .datasource_dashboard_index .setdefault (datasource_name_or_uid , [])
545
+ self .datasource_dashboard_index [datasource_name_or_uid ].append (dashboard_uid )
0 commit comments