Merge "Add import of json files"
This commit is contained in:
commit
39d8bd1d84
@ -52,6 +52,11 @@ For example, here is a minimal dashboard specification
|
||||
environments. Users can specify their dashboards via a normal review
|
||||
process and tests can validate their correctness.
|
||||
|
||||
The tool can also take JSON manually exported from the Grafana
|
||||
interface and load it as a dashboard. This allows keeping dashboards
|
||||
that have been edited with the inbuilt editor externally version
|
||||
controlled.
|
||||
|
||||
A large number of examples are available in the OpenStack
|
||||
`project-config
|
||||
<https://git.openstack.org/cgit/openstack-infra/project-config/tree/grafana>`__
|
||||
|
@ -38,7 +38,8 @@ Update Command
|
||||
|
||||
``grafana-dashboard`` [options] update <path>
|
||||
|
||||
Updates each specified dashboard to the lastest layout from parsed yaml files.
|
||||
Updates each specified dashboard to the lastest layout from parsed
|
||||
yaml or json files.
|
||||
|
||||
FILES
|
||||
=====
|
||||
|
@ -51,7 +51,8 @@ class Builder(object):
|
||||
files_to_process.extend([os.path.join(path, f)
|
||||
for f in os.listdir(path)
|
||||
if (f.endswith('.yaml')
|
||||
or f.endswith('.yml'))])
|
||||
or f.endswith('.yml')
|
||||
or f.endswith('.json'))])
|
||||
else:
|
||||
files_to_process.append(path)
|
||||
|
||||
|
@ -50,21 +50,29 @@ class YamlParser(object):
|
||||
|
||||
def parse_fp(self, fp):
|
||||
data = yaml.safe_load(fp)
|
||||
result = self.validate(data)
|
||||
for item in result.items():
|
||||
group = self.data.get(item[0], {})
|
||||
# Create slug to make it easier to find dashboards.
|
||||
if item[0] == 'dashboard':
|
||||
name = item[1]['title']
|
||||
else:
|
||||
name = item[1]['name']
|
||||
slug = slugify(name)
|
||||
if slug in group:
|
||||
raise Exception(
|
||||
"Duplicate {0} found in '{1}: '{2}' "
|
||||
"already defined".format(item[0], fp.name, name))
|
||||
group[slug] = item[1]
|
||||
self.data[item[0]] = group
|
||||
# Since a json file is valid YAML, we just pass through
|
||||
# any JSON files
|
||||
if fp.name.endswith('.json'):
|
||||
slug = slugify(data['title'])
|
||||
if not self.data.get('dashboard'):
|
||||
self.data['dashboard'] = {}
|
||||
self.data['dashboard'][slug] = data
|
||||
else:
|
||||
result = self.validate(data)
|
||||
for item in result.items():
|
||||
group = self.data.get(item[0], {})
|
||||
# Create slug to make it easier to find dashboards.
|
||||
if item[0] == 'dashboard':
|
||||
name = item[1]['title']
|
||||
else:
|
||||
name = item[1]['name']
|
||||
slug = slugify(name)
|
||||
if slug in group:
|
||||
raise Exception(
|
||||
"Duplicate {0} found in '{1}: '{2}' "
|
||||
"already defined".format(item[0], fp.name, name))
|
||||
group[slug] = item[1]
|
||||
self.data[item[0]] = group
|
||||
|
||||
def validate(self, data):
|
||||
schema = Schema()
|
||||
|
141
tests/fixtures/parser/json-dashboard-0001.json
vendored
Normal file
141
tests/fixtures/parser/json-dashboard-0001.json
vendored
Normal file
@ -0,0 +1,141 @@
|
||||
{
|
||||
"annotations": {
|
||||
"list": [
|
||||
{
|
||||
"builtIn": 1,
|
||||
"datasource": "-- Grafana --",
|
||||
"enable": true,
|
||||
"hide": true,
|
||||
"iconColor": "rgba(0, 211, 255, 1)",
|
||||
"name": "Annotations & Alerts",
|
||||
"type": "dashboard"
|
||||
}
|
||||
]
|
||||
},
|
||||
"editable": true,
|
||||
"gnetId": null,
|
||||
"graphTooltip": 0,
|
||||
"id": 38,
|
||||
"links": [],
|
||||
"panels": [
|
||||
{
|
||||
"aliasColors": {},
|
||||
"bars": false,
|
||||
"dashLength": 10,
|
||||
"dashes": false,
|
||||
"datasource": null,
|
||||
"fieldConfig": {
|
||||
"defaults": {
|
||||
"custom": {}
|
||||
},
|
||||
"overrides": []
|
||||
},
|
||||
"fill": 1,
|
||||
"fillGradient": 0,
|
||||
"gridPos": {
|
||||
"h": 9,
|
||||
"w": 12,
|
||||
"x": 0,
|
||||
"y": 0
|
||||
},
|
||||
"hiddenSeries": false,
|
||||
"id": 2,
|
||||
"legend": {
|
||||
"avg": false,
|
||||
"current": false,
|
||||
"max": false,
|
||||
"min": false,
|
||||
"show": true,
|
||||
"total": false,
|
||||
"values": false
|
||||
},
|
||||
"lines": true,
|
||||
"linewidth": 1,
|
||||
"nullPointMode": "null",
|
||||
"options": {
|
||||
"dataLinks": []
|
||||
},
|
||||
"percentage": false,
|
||||
"pointradius": 2,
|
||||
"points": false,
|
||||
"renderer": "flot",
|
||||
"seriesOverrides": [],
|
||||
"spaceLength": 10,
|
||||
"stack": false,
|
||||
"steppedLine": false,
|
||||
"targets": [
|
||||
{
|
||||
"refId": "A",
|
||||
"target": "stats.haproxy.balance_git_http.gitea01.opendev.org.bout"
|
||||
}
|
||||
],
|
||||
"thresholds": [],
|
||||
"timeFrom": null,
|
||||
"timeRegions": [],
|
||||
"timeShift": null,
|
||||
"title": "Fresh update",
|
||||
"tooltip": {
|
||||
"shared": true,
|
||||
"sort": 0,
|
||||
"value_type": "individual"
|
||||
},
|
||||
"type": "graph",
|
||||
"xaxis": {
|
||||
"buckets": null,
|
||||
"mode": "time",
|
||||
"name": null,
|
||||
"show": true,
|
||||
"values": []
|
||||
},
|
||||
"yaxes": [
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
},
|
||||
{
|
||||
"format": "short",
|
||||
"label": null,
|
||||
"logBase": 1,
|
||||
"max": null,
|
||||
"min": null,
|
||||
"show": true
|
||||
}
|
||||
],
|
||||
"yaxis": {
|
||||
"align": false,
|
||||
"alignLevel": null
|
||||
}
|
||||
}
|
||||
],
|
||||
"schemaVersion": 25,
|
||||
"style": "dark",
|
||||
"tags": [],
|
||||
"templating": {
|
||||
"list": []
|
||||
},
|
||||
"time": {
|
||||
"from": "now-6h",
|
||||
"to": "now"
|
||||
},
|
||||
"timepicker": {
|
||||
"refresh_intervals": [
|
||||
"10s",
|
||||
"30s",
|
||||
"1m",
|
||||
"5m",
|
||||
"15m",
|
||||
"30m",
|
||||
"1h",
|
||||
"2h",
|
||||
"1d"
|
||||
]
|
||||
},
|
||||
"timezone": "",
|
||||
"title": "test json",
|
||||
"uid": "M-GEcyWMk",
|
||||
"version": 1
|
||||
}
|
@ -100,3 +100,12 @@ class TestCaseParser(TestCase):
|
||||
def _get_empty_dashboard(self, name):
|
||||
res, md5 = self.parser.get_dashboard(name)
|
||||
self.assertEqual(res, None)
|
||||
|
||||
def test_parse_json(self):
|
||||
path = os.path.join(
|
||||
os.path.dirname(__file__),
|
||||
'fixtures/parser/json-dashboard-0001.json')
|
||||
self.parser.parse(path)
|
||||
# Get parsed dashboard
|
||||
res, md5 = self.parser.get_dashboard('test-json')
|
||||
self.assertEqual(res['title'], 'test json')
|
||||
|
Loading…
x
Reference in New Issue
Block a user