]> git.proxmox.com Git - ceph.git/blame - ceph/src/pybind/mgr/dashboard/ci/check_grafana_uids.py
import new upstream nautilus stable release 14.2.8
[ceph.git] / ceph / src / pybind / mgr / dashboard / ci / check_grafana_uids.py
CommitLineData
92f5a8d4
TL
1# -*- coding: utf-8 -*-
2# pylint: disable=F0401
3"""
4This script does:
5* Scan through Angular html templates and extract <cd-grafana> tags
6* Check if every tag has a corresponding Grafana dashboard by `uid`
7
8Usage:
9 python <script> <angular_app_dir> <grafana_dashboard_dir>
10
11e.g.
12 cd /ceph/src/pybind/mgr/dashboard
13 python ci/<script> frontend/src/app /ceph/monitoring/grafana/dashboards
14"""
15import argparse
16import codecs
17import copy
18import json
19import os
20
21import six
22from six.moves.html_parser import HTMLParser
23
24
25class TemplateParser(HTMLParser):
26
27 def __init__(self, _file, search_tag):
28 if six.PY3:
29 super(TemplateParser, self).__init__()
30 else:
31 # HTMLParser is not a new-style class in py2
32 HTMLParser.__init__(self)
33 self.search_tag = search_tag
34 self.file = _file
35 self.parsed_data = []
36
37 def parse(self):
38 with codecs.open(self.file, encoding='UTF-8') as f:
39 self.feed(f.read())
40
41 def handle_starttag(self, tag, attrs):
42 if tag != self.search_tag:
43 return
44 tag_data = {
45 'file': self.file,
46 'attrs': dict(attrs),
47 'line': self.getpos()[0]
48 }
49 self.parsed_data.append(tag_data)
50
51 def error(self, message):
52 error_msg = 'fail to parse file {} (@{}): {}'.\
53 format(self.file, self.getpos(), message)
54 exit(error_msg)
55
56
57def stdout(msg):
58 six.print_(msg)
59
60
61def get_files(base_dir, file_ext):
62 result = []
63 for root, _, files in os.walk(base_dir):
64 for _file in files:
65 if _file.endswith('.{}'.format(file_ext)):
66 result.append(os.path.join(root, _file))
67 return result
68
69
70def get_tags(base_dir, tag='cd-grafana'):
71 templates = get_files(base_dir, 'html')
72 tags = []
73 for templ in templates:
74 parser = TemplateParser(templ, tag)
75 parser.parse()
76 if parser.parsed_data:
77 tags.extend(parser.parsed_data)
78 return tags
79
80
81def get_grafana_dashboards(base_dir):
82 json_files = get_files(base_dir, 'json')
83 dashboards = {}
84 for json_file in json_files:
85 with open(json_file) as f:
86 dashboard_config = json.load(f)
87 uid = dashboard_config.get('uid')
88 if not uid:
89 continue
90 if uid in dashboards:
91 # duplicated uids
92 error_msg = 'Duplicated UID {} found, already defined in {}'.\
93 format(uid, dashboards[uid]['file'])
94 exit(error_msg)
95 dashboards[uid] = {
96 'file': json_file,
97 'title': dashboard_config['title']
98 }
99 return dashboards
100
101
102def parse_args():
103 long_desc = ('Check every <cd-grafana> component in Angular template has a'
104 ' mapped Grafana dashboard.')
105 parser = argparse.ArgumentParser(description=long_desc)
106 parser.add_argument('angular_app_dir', type=str,
107 help='Angular app base directory')
108 parser.add_argument('grafana_dash_dir', type=str,
109 help='Directory contains Grafana dashboard JSON files')
110 parser.add_argument('--verbose', action='store_true',
111 help='Display verbose mapping information.')
112 return parser.parse_args()
113
114
115def main():
116 args = parse_args()
117 tags = get_tags(args.angular_app_dir)
118 grafana_dashboards = get_grafana_dashboards(args.grafana_dash_dir)
119 verbose = args.verbose
120
121 if not tags:
122 error_msg = 'Can not find any cd-grafana component under {}'.\
123 format(args.angular_app_dir)
124 exit(error_msg)
125
126 if verbose:
127 stdout('Found mappings:')
128 no_dashboard_tags = []
129 for tag in tags:
130 uid = tag['attrs']['uid']
131 if uid not in grafana_dashboards:
132 no_dashboard_tags.append(copy.copy(tag))
133 continue
134 if verbose:
135 msg = '{} ({}:{}) \n\t-> {} ({})'.\
136 format(uid, tag['file'], tag['line'],
137 grafana_dashboards[uid]['title'],
138 grafana_dashboards[uid]['file'])
139 stdout(msg)
140
141 if no_dashboard_tags:
142 title = ('Checking Grafana dashboards UIDs: ERROR\n'
143 'Components that have no mapped Grafana dashboards:\n')
144 lines = ('{} ({}:{})'.format(tag['attrs']['uid'],
145 tag['file'],
146 tag['line'])
147 for tag in no_dashboard_tags)
148 error_msg = title + '\n'.join(lines)
149 exit(error_msg)
150 else:
151 stdout('Checking Grafana dashboards UIDs: OK')
152
153
154if __name__ == '__main__':
155 main()