1
1
#!/usr/bin/env python3
2
- import json
3
2
import argparse
3
+ import json
4
4
import os
5
- from glob import glob
6
- from functools import partial
7
- import subprocess
8
- from urllib .request import urlopen , Request
9
- from urllib .parse import urlencode
10
- from urllib .error import HTTPError
11
- from copy import deepcopy
12
5
import re
13
6
import ssl
7
+ import subprocess
8
+ from copy import deepcopy
9
+ from functools import partial
10
+ from glob import glob
11
+ from urllib .error import HTTPError
12
+ from urllib .parse import urlencode
13
+ from urllib .request import Request , urlopen
14
14
15
15
# UID for the folder under which our dashboards will be setup
16
16
DEFAULT_FOLDER_UID = '70E5EE84-1217-4021-A89E-1E3DE0566D93'
17
17
18
18
19
19
def grafana_request (endpoint , token , path , data = None , no_tls_verify = False ):
20
- headers = {
21
- 'Authorization' : f'Bearer { token } ' ,
22
- 'Content-Type' : 'application/json'
23
- }
20
+ headers = {'Authorization' : f'Bearer { token } ' , 'Content-Type' : 'application/json' }
24
21
method = 'GET' if data is None else 'POST'
25
22
req = Request (f'{ endpoint } /api{ path } ' , headers = headers , method = method )
26
23
@@ -44,28 +41,30 @@ def ensure_folder(name, uid, api):
44
41
except HTTPError as e :
45
42
if e .code == 404 :
46
43
# We got a 404 in
47
- folder = {
48
- 'uid' : uid ,
49
- 'title' : name
50
- }
44
+ folder = {'uid' : uid , 'title' : name }
51
45
return api ('/folders' , folder )
52
46
else :
53
47
raise
54
48
55
49
56
50
def build_dashboard (dashboard_path , api , global_dash = False ):
57
-
58
51
datasources = api ("/datasources" )
59
52
datasources_names = [ds ["name" ] for ds in datasources ]
60
53
61
54
# We pass the list of all datasources because the global dashboards
62
55
# use this information to show info about all datasources in the same panel
63
- return json .loads (subprocess .check_output (
64
- [
65
- "jsonnet" , "-J" , "vendor" , dashboard_path ,
66
- "--tla-code" , f"datasources={ datasources_names } "
67
- ]
68
- ).decode ())
56
+ return json .loads (
57
+ subprocess .check_output (
58
+ [
59
+ "jsonnet" ,
60
+ "-J" ,
61
+ "vendor" ,
62
+ dashboard_path ,
63
+ "--tla-code" ,
64
+ f"datasources={ datasources_names } " ,
65
+ ]
66
+ ).decode ()
67
+ )
69
68
70
69
71
70
def layout_dashboard (dashboard ):
@@ -108,11 +107,7 @@ def deploy_dashboard(dashboard_path, folder_uid, api, global_dash=False):
108
107
db = layout_dashboard (db )
109
108
db = populate_template_variables (api , db )
110
109
111
- data = {
112
- 'dashboard' : db ,
113
- 'folderId' : folder_uid ,
114
- 'overwrite' : True
115
- }
110
+ data = {'dashboard' : db , 'folderId' : folder_uid , 'overwrite' : True }
116
111
api ('/dashboards/db' , data )
117
112
118
113
@@ -125,7 +120,9 @@ def get_label_values(api, ds_id, template_query):
125
120
in a dashboard
126
121
"""
127
122
# re.DOTALL allows the query to be multi-line
128
- match = re .match (r'label_values\((?P<query>.*),\s*(?P<label>.*)\)' , template_query , re .DOTALL )
123
+ match = re .match (
124
+ r'label_values\((?P<query>.*),\s*(?P<label>.*)\)' , template_query , re .DOTALL
125
+ )
129
126
query = match .group ('query' )
130
127
label = match .group ('label' )
131
128
query = {'match[]' : query }
@@ -151,7 +148,9 @@ def populate_template_variables(api, db):
151
148
for var in db .get ('templating' , {}).get ('list' , []):
152
149
datasources = api ("/datasources" )
153
150
if var ["type" ] == "datasource" :
154
- var ["options" ] = [{"text" : ds ["name" ], "value" : ds ["name" ]} for ds in datasources ]
151
+ var ["options" ] = [
152
+ {"text" : ds ["name" ], "value" : ds ["name" ]} for ds in datasources
153
+ ]
155
154
156
155
# default selection: first datasource in list
157
156
if datasources and not var .get ("current" ):
@@ -188,17 +187,38 @@ def populate_template_variables(api, db):
188
187
def main ():
189
188
parser = argparse .ArgumentParser ()
190
189
parser .add_argument ('grafana_url' , help = 'Grafana endpoint to deploy dashboards to' )
191
- parser .add_argument ('--dashboards-dir' , default = "dashboards" , help = 'Directory of jsonnet dashboards to deploy' )
192
- parser .add_argument ('--folder-name' , default = 'JupyterHub Default Dashboards' , help = 'Name of Folder to deploy to' )
193
- parser .add_argument ('--folder-uid' , default = DEFAULT_FOLDER_UID , help = 'UID of grafana folder to deploy to' )
194
- parser .add_argument ('--no-tls-verify' , action = 'store_true' , default = False ,
195
- help = 'Whether or not to skip TLS certificate validation' )
190
+ parser .add_argument (
191
+ '--dashboards-dir' ,
192
+ default = "dashboards" ,
193
+ help = 'Directory of jsonnet dashboards to deploy' ,
194
+ )
195
+ parser .add_argument (
196
+ '--folder-name' ,
197
+ default = 'JupyterHub Default Dashboards' ,
198
+ help = 'Name of Folder to deploy to' ,
199
+ )
200
+ parser .add_argument (
201
+ '--folder-uid' ,
202
+ default = DEFAULT_FOLDER_UID ,
203
+ help = 'UID of grafana folder to deploy to' ,
204
+ )
205
+ parser .add_argument (
206
+ '--no-tls-verify' ,
207
+ action = 'store_true' ,
208
+ default = False ,
209
+ help = 'Whether or not to skip TLS certificate validation' ,
210
+ )
196
211
197
212
args = parser .parse_args ()
198
213
199
214
grafana_token = os .environ ['GRAFANA_TOKEN' ]
200
215
201
- api = partial (grafana_request , args .grafana_url , grafana_token , no_tls_verify = args .no_tls_verify )
216
+ api = partial (
217
+ grafana_request ,
218
+ args .grafana_url ,
219
+ grafana_token ,
220
+ no_tls_verify = args .no_tls_verify ,
221
+ )
202
222
folder = ensure_folder (args .folder_name , args .folder_uid , api )
203
223
204
224
for dashboard in glob (f'{ args .dashboards_dir } /*.jsonnet' ):
0 commit comments