Grafana dashboards backup python script using both API and username authentication
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
from __future__ import print_function
import argparse
import base64
import getpass
import json
import re
import urllib2 as urllib
class GrafanaExporter(object):
"""
Exports dashboards from Grafana api to *.json files
"""
def __init__(self, **kwargs):
self.__grafana_host = kwargs.get('host', '127.0.0.1')
self.__grafana_path_to_save = kwargs.get('path_to_save', '/tmp').rstrip('/')
self.__grafana_port = kwargs.get('port', 80)
self.__grafana_headers_set = {
'Content-Type': 'application/json',
'Accept': 'application/json',
}
if kwargs.get('api_key'):
self.__grafana_headers_set.setdefault('Authorization',
'Bearer {api_key}'.format(api_key=kwargs.get('api_key', '')))
elif kwargs.get('user'):
self.__grafana_headers_set.setdefault('Authorization',
'Basic {basic}'.format(basic=base64.b64encode('{}:{}'.format(
kwargs.get('user'), kwargs.get('password', '')
))))
def __get_dashboards(self):
__dashboards = list()
__dashboards_url = "http{s}://{host}{port}/api/search".format(
s='s' if self.__grafana_port == 443 else '',
host=self.__grafana_host,
port=':{}'.format(self.__grafana_port) if (self.__grafana_port != 80 and self.__grafana_port != 443)
else '')
print('Downloading dashboards from: {}'.format(__dashboards_url))
__request_object = urllib.Request(__dashboards_url, headers=self.__grafana_headers_set)
__response = urllib.urlopen(__request_object)
__data = json.loads(__response.read())
for item in __data:
__dashboards.append(item.get('uri'))
return __dashboards
def export_dashboards(self):
"""
main method to export dashboards
"""
__dashboards = self.__get_dashboards()
for dashboard in __dashboards:
__dashboards_url = "http{s}://{host}{port}/api/dashboards/{dashboard}".format(
s='s' if self.__grafana_port == 443 else '',
host=self.__grafana_host,
port=':{}'.format(self.__grafana_port) if (self.__grafana_port != 80 or self.__grafana_port != 443)
else '',
dashboard=dashboard)
__request_object = urllib.Request(__dashboards_url, headers=self.__grafana_headers_set)
__response = urllib.urlopen(__request_object)
__data = json.loads(__response.read())
__dashboard_info = __data.get('dashboard')
__dashboard_file_name = self.__compose_file_name(__dashboard_info.get('title'))
__data['dashboard']['id'] = 'null'
with open('{path}/{file}'.format(path=self.__grafana_path_to_save, file=__dashboard_file_name), 'w') as outfile:
json.dump(__data, outfile)
print('Dashboard "{name}" was saved as: {path}/{file}'.format(
name=__dashboard_info.get('title'),
path=self.__grafana_path_to_save,
file=__dashboard_file_name))
@staticmethod
def __compose_file_name(name):
name = '{}.json'.format(re.sub(r'[/ :()\'"]', '_', name))
name = re.sub(r'_{2,}', '_', name)
return name
def run_export():
"""
run exporter with script params
"""
parser = argparse.ArgumentParser(description='Exports Grafana dashboards from specified instance to given path.')
parser.add_argument('--key', '-k', help='Api - key for Grafana api', type=str)
parser.add_argument('--user', '-u', help='Grafana authentication user', type=str)
parser.add_argument('--pass', '-p', help='Authenticate grafana with password', dest='password', action='store_true')
parser.add_argument('--host', '-H', help='Grafana host / IP, without protocol (default: 127.0.0.1)', default='127.0.0.1',
type=str)
parser.add_argument('--port', '-P', help='Port for Grafana (default: 80)', default=80, type=int)
parser.add_argument('--output', '-o', help='Path to save dashboards (default: /tmp)', default='/tmp', type=str)
args = parser.parse_args()
if args.password:
password = getpass.getpass()
else:
password = None
exporter = GrafanaExporter(host=args.host,
api_key=args.key,
user=args.user,
password=password,
path_to_save=args.output,
port=args.port)
exporter.export_dashboards()
if __name__ == '__main__':
run_export()