Created
June 29, 2017 16:34
-
-
Save AndreLouisCaron/138f9b3447208a79345e9cb6f9d9b3e8 to your computer and use it in GitHub Desktop.
Grafana dashboard exchange
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# -*- coding: utf-8 -*- | |
from __future__ import print_function | |
import errno | |
import glob | |
import json | |
import os | |
import requests | |
import sys | |
import time | |
from urlparse import urljoin | |
# Settings. | |
GRAFANA_URL = sys.argv[1] | |
GRAFANA_USERNAME = 'admin' | |
GRAFANA_PASSWORD = 'admin' | |
def get_json(url): | |
rep = requests.get( | |
urljoin(GRAFANA_URL, url), | |
auth=(GRAFANA_USERNAME, GRAFANA_PASSWORD), | |
) | |
rep.raise_for_status() | |
return rep.json() | |
def post_json(url, document, serialize=json.dumps): | |
rep = requests.post( | |
urljoin(GRAFANA_URL, url), | |
auth=(GRAFANA_USERNAME, GRAFANA_PASSWORD), | |
headers={ | |
'Content-Type': 'application/json', | |
}, | |
data=serialize(document), | |
) | |
rep.raise_for_status() | |
return rep.json() | |
def put_json(url, document, serialize=json.dumps): | |
rep = requests.put( | |
urljoin(GRAFANA_URL, url), | |
auth=(GRAFANA_USERNAME, GRAFANA_PASSWORD), | |
headers={ | |
'Content-Type': 'application/json', | |
}, | |
data=serialize(document), | |
) | |
rep.raise_for_status() | |
return rep.json() | |
def json_pp(doc): | |
"""Render JSON in normalized format.""" | |
return json.dumps(doc, indent=2, sort_keys=True, separators=(',', ': ')) | |
def ensure_dir(path): | |
"""Create a folder if it doesn't already exist.""" | |
try: | |
os.mkdir(path) | |
except OSError as error: | |
if error.errno != errno.EEXIST: | |
raise | |
return path | |
def pull(): | |
"""Pull Grafana configuration to disk.""" | |
# Fetch all data sources. | |
ensure_dir('datasources') | |
for document in get_json('api/datasources'): | |
slug = document['name'] | |
path = os.path.join('datasources', '%s.json' % (slug,)) | |
print(path) | |
with open(path, 'wb') as stream: | |
stream.write(json_pp(document).encode('utf-8')) | |
stream.write(b'\n') | |
# Fetch all dashboards (except Home, which we can't edit). | |
ensure_dir('dashboards') | |
for document in get_json('api/search'): | |
if document['type'] != 'dash-db': | |
continue | |
slug = document['uri'].split('/', 1)[1] | |
dashboard = get_json('api/dashboards/db/%s' % (slug,)) | |
path = os.path.join('dashboards', '%s.json' % (slug,)) | |
print(path) | |
with open(path, 'wb') as stream: | |
stream.write(json_pp(dashboard).encode('utf-8')) | |
stream.write(b'\n') | |
def push(): | |
"""Push on-disk configuration to Grafana.""" | |
# Create/update data sources. | |
datasources = { | |
document['name']: document['id'] | |
for document in get_json('api/datasources') | |
} | |
for path in glob.iglob(os.path.join('datasources', '*.json')): | |
print(path) | |
with open(path, 'rb') as stream: | |
document = json.loads(stream.read().decode('utf-8')) | |
# Create or update depending on whether it already exists. | |
document['id'] = datasources.get(document['name'], None) | |
if document['id']: | |
print('Updating data source "%s" with ID #%s.' % ( | |
document['name'], | |
document['id'], | |
)) | |
put_json( | |
'api/datasources/%s' % (document['id'],), | |
document, | |
) | |
else: | |
rep = post_json( | |
'api/datasources', | |
document, | |
) | |
print('Created data source "%s" with ID #%d.' % ( | |
document['name'], | |
rep['id'], | |
)) | |
print() | |
print('---') | |
# Create/update dashboards. | |
dashboards = { | |
document['uri'].split('/', 1)[1]: document['id'] | |
for document in get_json('api/search') | |
} | |
for path in glob.iglob(os.path.join('dashboards', '*.json')): | |
print(path) | |
with open(path, 'rb') as stream: | |
document = json.loads(stream.read().decode('utf-8')) | |
slug = document['meta']['slug'] | |
del document['meta'] | |
document['dashboard']['id'] = dashboards.get(slug, None) | |
if 'id' in document: | |
print('Updating dashboard "%s" with slug "%s" and ID #%d.' % ( | |
document['dashboard']['title'], | |
slug, | |
document['id'], | |
)) | |
else: | |
print('Updating dashboard "%s" with slug "%s".' % ( | |
document['dashboard']['title'], | |
slug, | |
)) | |
try: | |
post_json( | |
'api/dashboards/db', | |
document, | |
) | |
except requests.exceptions.HTTPError as error: | |
# We'll get a version-mismatch error if Grafana already has the | |
# latest version (or a newer version). | |
if error.response.status_code != 412: | |
raise | |
print(error.response.json()['message']) | |
print() | |
def wait_until_responsive(): | |
"""Poll Grafana until its API is repsonsive.""" | |
while True: | |
print('Pinging Grafana...') | |
try: | |
rep = requests.get( | |
urljoin(GRAFANA_URL, 'api/admin/stats'), | |
auth=(GRAFANA_USERNAME, GRAFANA_PASSWORD), | |
) | |
except requests.exceptions.ConnectionError: | |
print(' not ready, retrying in 1 second...') | |
time.sleep(1.0) | |
continue | |
rep.raise_for_status() | |
print(' ready!') | |
break | |
if __name__ == '__main__': | |
wait_until_responsive() | |
#push() | |
pull() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment