inthuriel
4/24/2018 - 10:16 AM

Grafana dashboards backup

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()