11#!/usr/bin/env python3
2+
23import argparse
34import json
45import sqlite3
6+ import urllib .request as rq
57
68
79def cli_options ():
810 parser = argparse .ArgumentParser (description = "Grafana JSON Model updater" )
911
10- parser .add_argument ("json_file " , help = "File exported from Grafana Dashboard " )
12+ parser .add_argument ("-db " , "--db-file" , help = "Grafana sqlite database " )
1113 parser .add_argument (
1214 "-o" , "--datasource-old" , help = "Name of the OLD Grafana Connector Version 1.x"
1315 )
@@ -28,12 +30,12 @@ def nested_set(target, keys, value):
2830 target [keys [- 1 ]] = value
2931
3032
31- def config_set (target , keys , value ):
33+ def config_set (target , keys , value , label = "" ):
3234 nested_set (target , keys , value )
3335 nested_set (
3436 target ,
3537 ["params" , "selections" ] + keys ,
36- {"value" : value , "label" : value , "isDisabled" : False },
38+ {"value" : value , "label" : label or value , "isDisabled" : False },
3739 )
3840
3941
@@ -47,18 +49,103 @@ def update_host_tags(target):
4749 if value := target .pop (key ):
4850 new_key = f"host_tag_{ nr } _{ host_tag_obj [obj ]} "
4951 config_set (target , ["context" , "host_tags" , new_key ], value )
52+ if all (x .endswith ("op" ) for x in target ["context" ]["host_tags" ].keys ()):
53+ del target ["context" ]["host_tags" ]
54+ del target ["params" ]["selections" ]["context" ]["host_tags" ]
55+
56+
57+ def update_context (target ):
58+ update_host_tags (target )
59+ target .pop ("format" , None )
60+ target .pop ("usehostregex" , None )
61+ if host := target .pop ("host" , None ):
62+ config_set (target , ["context" , "host" , "host" ], host )
63+ if host := target .pop ("hostregex" , None ):
64+ nested_set (target , ["context" , "hostregex" , "host_regex" ], host )
65+
66+ if service := target .pop ("service" , None ):
67+ config_set (target , ["context" , "service" , "service" ], service )
68+ if service := target .pop ("serviceregex" , None ):
69+ nested_set (target , ["context" , "serviceregex" , "service_regex" ], service )
70+
71+ if site := target .pop ("site" , None ):
72+ config_set (target , ["context" , "siteopt" , "site" ], site )
73+
74+
75+ def extract_single_info (context ):
76+ return {
77+ "site" : context .get ("siteopt" , {}).get ("site" , "" ),
78+ "host_name" : context .get ("host" , {}).get ("host" , "" ),
79+ "service_description" : context .get ("service" , {}).get ("service" , "" ),
80+ }
81+
82+
83+ def update_graph (query_graph , target ):
84+ mode = target .pop ("mode" , "" )
85+ metric_id = [int (x ) for x in target .pop ("metric" , "" ).split ("." ) if x ]
86+ graph_idx = target .pop ("graph" , 0 )
87+ presentation = target .pop ("presentiation" , "lines" )
88+ if combined_graph_name := target .pop ("combinedgraph" , None ):
89+ config_set (target , ["params" , "graph_name" ], combined_graph_name )
90+ target ["params" ]["presentation" ] = presentation
91+ return
92+
93+ graph = query_graph (target ["context" ])
94+ if mode == "graph" and graph_idx < len (graph ):
95+ graph_name = graph [graph_idx ]["specification" ][1 ]["graph_id" ]
96+ graph_title = graph [graph_idx ]["title" ]
97+ config_set (target , ["params" , "graph_name" ], graph_name , graph_title )
98+ elif mode == "metric" and len (metric_id ) == 2 :
99+ graph_idx , metric_idx = metric_id
100+ if graph_idx < len (graph ) and metric_idx < len (graph [graph_idx ]["metrics" ]):
101+ metric = graph [graph_idx ]["metrics" ][metric_idx ]
102+ expression = metric ["expression" ]
103+ if expression [0 ] == "rrd" :
104+ nested_set (target , ["params" , "graphMode" ], "metric" )
105+ config_set (
106+ target , ["params" , "graph_name" ], expression [4 ], metric ["title" ]
107+ )
108+ else :
109+ config_set (target , ["params" , "graph_name" ], "" , "Not available" )
110+
111+
112+ def get_datasource_configs (cursor ):
113+ for ds , name , json_data in cursor .execute (
114+ "select type, name, json_data from data_source"
115+ ):
116+ if ds in ["checkmk-datasource" , "tribe-29-grafana-checkmk-datasource" ]:
117+ yield name , {** json .loads (json_data ), "name" : name , "ds" : ds }
118+
119+
120+ def query (conf ):
121+ def _query (context ):
122+ req = rq .Request (
123+ conf ["url" ]
124+ + "/check_mk/webapi.py?_username=%s&_secret=%s&action=get_graph_recipes"
125+ % (conf ["username" ], conf ["secret" ])
126+ )
127+ spec = {"specification" : ["template" , extract_single_info (context )]}
128+ response = rq .urlopen (req , ("request=%s" % json .dumps (spec )).encode ("utf-8" ))
129+ if response .status == 200 :
130+ return json .loads (response .read ())["result" ]
131+ return []
132+
133+ return _query
50134
51135
52136def main ():
53137 args = cli_options ().parse_args ()
54- con = sqlite3 .connect (args .json_file )
138+ con = sqlite3 .connect (args .db_file )
55139 cur = con .cursor ()
140+ datasource_config = dict (get_datasource_configs (cur ))
141+ query_graph = query (datasource_config [args .datasource_old ])
142+
56143 row = list (cur .execute ("select data from dashboard where slug = 'cmk'" ))
57144 dash = json .loads (row [0 ][0 ])
58145
59- # if title := args.new_dashboard_title:
60- # dash["title"] = title
61- # else:
146+ # # if title := args.new_dashboard_title:
147+ # # dash["title"] = title
148+ # # else:
62149 dash ["title" ] += " NEW"
63150 dash ["uid" ] += "1"
64151
@@ -67,46 +154,16 @@ def main():
67154 panel ["datasource" ] = args .datasource_new
68155
69156 for target in panel ["targets" ]:
70- update_host_tags (target )
71-
72- if host := target .pop ("host" , None ):
73- config_set (target , ["context" , "host" , "host" ], host )
74- if host := target .pop ("hostregex" , None ):
75- nested_set (target , ["context" , "hostregex" , "host_regex" ], host )
76-
77- if service := target .pop ("service" , None ):
78- config_set (target , ["context" , "service" , "service" ], service )
79- if service := target .pop ("serviceregex" , None ):
80- nested_set (
81- target , ["context" , "serviceregex" , "service_regex" ], service
82- )
83-
84- if site := target .pop ("site" , None ):
85- config_set (target , ["context" , "siteopt" , "site" ], site )
86-
87- mode = target .pop ("mode" , "" )
88- metric_id = target .pop ("metric" , "" )
89- graph_id = str (target .pop ("graph" , "0" ))
90- combined_graph_name = target .pop ("combinedgraph" , None )
91- if mode == "metric" :
92- nested_set (target , ["params" , "graphMode" ], "metric" )
93- nested_set (target , ["params" , "graph_name" ], metric_id )
94- elif mode == "graph" :
95- nested_set (target , ["params" , "graph_name" ], graph_id )
96- elif combined_graph_name :
97- config_set (target , ["params" , "graph_name" ], combined_graph_name )
98-
99- if presentation := target .pop ("presentiation" , None ):
100- target ["params" ]["presentation" ] = presentation
157+ update_context (target )
158+ update_graph (query_graph , target )
101159
160+ print (json .dumps (dash ))
102161 cur .execute (
103162 "update dashboard set data = '%s' where slug = 'cmk-new'" % json .dumps (dash )
104163 )
105164 con .commit ()
106165 con .close ()
107166
108- print (json .dumps (dash ))
109-
110167
111168if __name__ == "__main__" :
112169 main ()
0 commit comments