
Экспорт дашбордов из grafana в Unix/Linux
У меня на работе, установлена grafana и ее активно используют коллеги для снятия различных метрик по дашбордам. Как у нас частенько бывает — ложатся сервера и если нет бэкапов, то все печально! Руками бэкапить дашборды с графаны — это нормально, но я люблю автоматизацию. И решил написать скрипт для экспорта всех дашбордов из grafana себе на компьютер. Я совсем не много пишу на питон и по этому — хотел написать на нем (так и будет немного позже)….. но на скорую руку пришелся — bash.
Полезное чтиво:
Установка grafana в Unix/Linux
-=== СПОСОБ 1 — Использование BASH===-
Предположим, скрипт у меня лежит прям в текущей директории:
# cat get_grafana_dashes.sh
Собственно, вот сие чудо:
#!/bin/bash -x # # Vitaliy Natarov # # Set some colors for status OK, FAIL and titles SETCOLOR_SUCCESS="echo -en \\033[1;32m" SETCOLOR_FAILURE="echo -en \\033[1;31m" SETCOLOR_NORMAL="echo -en \\033[0;39m" SETCOLOR_TITLE="echo -en \\033[1;36m" #Fuscia SETCOLOR_TITLE_GREEN="echo -en \\033[0;32m" #green SETCOLOR_TITLE_PURPLE="echo -en \\033[0;35m" #purple SETCOLOR_NUMBERS="echo -en \\033[0;34m" #BLUE KEY="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX" HOST="http://graffana-server.local" DASH_DIR="/home/captain/Grafana/dashboards" if [ ! -d "$DASH_DIR" ]; then mkdir -p dashboards else $SETCOLOR_TITLE_PURPLE echo "|-------------------------------------------------------------------------------|"; echo "| A $DASH_DIR directory is already exist! |"; echo "|-------------------------------------------------------------------------------|"; $SETCOLOR_NORMAL fi #curl -sS -k -H "Authorization: Bearer $KEY" $HOST/api/search\?query\=\& |tr ']{' '\n'| cut -d ':' -f4| cut -d ',' -f1| cut -d '"' -f2 | grep -Ev "(^$|\[)"| cut -c 4- for dash in $(curl -sS -k -H "Authorization: Bearer $KEY" $HOST/api/search\?query\=\& |tr ']{' '\n'| cut -d ':' -f4| cut -d ',' -f1| cut -d '"' -f2 | grep -Ev "(^$|\[)"| cut -c 4-); do curl -sS -k -H "Authorization: Bearer $KEY" $HOST/api/dashboards/db/$dash > dashboards/$dash.json $SETCOLOR_TITLE_GREEN echo "The [ $dash ] dashboard has been exported" $SETCOLOR_NORMAL done $SETCOLOR_TITLE echo "|-------------------------------------------------------------------------------|"; echo "|----------------------------------FINISHED-------------------------------------|"; echo "|-------------------------------------------------------------------------------|"; $SETCOLOR_NORMAL
Где:
- KEY=»XXXXXXXXXXXXXXXXXXXXXXXX» — Ключ для использования API. Можно сгенерировать в админ-панеле самой графаны.
- HOST=»http://graffana-server.local» — УРЛ где находится графана-сервер.
- DASH_DIR=»/home/captain/Grafana/dashboards» — Путь где будут лежать все шаблоны (дашборды) после экспорта.
Запускаем:
$ bash Get_grafana_dashes.sh
Получаем:

Экспорт дашбордов из grafana в Unix/Linux
Вроде бы все нормально. Кому режит глаза, могут убрать расскраску 🙂
-=== СПОСОБ 2 — Использование PYTHON===-
Будет скоро, постараюсь написать на днях. Возможно после выходных….
Так вот, прошло несколько дней и мой скрипт — готов.
Открываю его:
$ vim grafana_dashboards.py
Он имеет следующее содержание:
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import requests import time import os import argparse import json import glob # from datetime import datetime from requests.packages.urllib3.exceptions import InsecureRequestWarning class Bgcolors: def __init__(self): self.get = { 'HEADER': '\033[95m', 'OKBLUE': '\033[94m', 'OKGREEN': '\033[92m', 'WARNING': '\033[93m', 'FAIL': '\033[91m', 'ENDC': '\033[0m', 'BOLD': '\033[1m', 'UNDERLINE': '\033[4m' } def get_grafana_dashboards(g_url, g_token): dashboards_array = [] headers = {'Authorization': str('Bearer ' + g_token), 'Content-type': 'application/json'} get_data_req = requests.get(g_url + '/api/search?query=&', headers=headers) pars_json = json.loads(get_data_req.text) for dash in pars_json: # print(dash['uri'][3::]) dashboards_array.append(dash['uri'][3::]) return dashboards_array def export_grafana_dashboards(g_token, g_url, dir_path, e_dash): headers = {'Authorization': str('Bearer ' + g_token), 'Content-type': 'application/json' } if not os.path.exists(dir_path): os.makedirs(dir_path) print(dir_path, 'has been created') dashboard_names = get_grafana_dashboards(g_url, g_token) dash_count = 1 if e_dash == 'all': # print('I will export ALL DASHes!') for d in dashboard_names: dashboard_name_out = dir_path + '/' + d + '.json' get_dashboard = requests.get(g_url + '/api/dashboards/db/' + d, headers=headers) try: f = open(dashboard_name_out, 'w') f.write(json.dumps(get_dashboard.json(), indent=4)) f.close() print('[', dash_count, ']', d) dash_count += 1 except EOFError: print('I cant write to file: ', EOFError) else: # print('I will export %s dashbourd(s)!' % e_dash) for d in dashboard_names: for dd in e_dash: if d == dd: dashboard_name_out = dir_path + '/' + d + '.json' get_dashboard = requests.get(g_url + '/api/dashboards/db/' + d, headers=headers) try: f = open(dashboard_name_out, 'w+') f.write(json.dumps(get_dashboard.json(), indent=4)) f.close() print('[', dash_count, ']', d) dash_count += 1 except ValueError: print('I cant write to file: ', ValueError) # return export_grafana_dashboards def import_grafana_dashboards(g_token, g_url, dir_path, i_dash): headers = {'Authorization': str('Bearer ' + g_token), 'Content-type': 'application/json', 'Accept': 'application/json' } dash_count = 1 if i_dash == 'all': # print('I will import ALL DASHes!') files = glob.glob(dir_path + "/" + "*.json") else: # print('I will import %s dashbourd(s)!' % i_dash) for d in i_dash: files = glob.glob(str(dir_path) + "/" + str(d) + ".json") for f in files: d = f.split('.')[0].split('/')[1] with open(f, 'r') as file: dashboard = file.read() try: print('[%s] Need to create an import to grafana [%s]' % (dash_count, f)) datas = json.loads(dashboard) protocol = g_url.split(':')[0] if protocol == "http": i__dash = requests.post(g_url + '/api/dashboards/db/', headers=headers, json=datas) elif protocol == "https": verify = False if not verify: requests.packages.urllib3.disable_warnings(InsecureRequestWarning) i__dash = requests.post(g_url + '/api/dashboards/db/', headers=headers, json=datas, verify=verify) if i__dash.status_code != 200: print(i__dash.status_code) exit(0) else: print('Incorrect URL! Use url with http|https protocol') exit(0) print(i__dash) except EOFError as e: print(e) dash_count += 1 return import_grafana_dashboards def main(): start__time = time.time() parser = argparse.ArgumentParser(prog='python3 script_name.py -h', usage='python3 script_name.py {ARGS}', add_help=True, prefix_chars='--/', epilog='''created by Vitalii Natarov''') parser.add_argument('--version', action='version', version='v1.0.0') parser.add_argument('--dash', '--dashboard', nargs='+', dest='dashboard', help='Indicate a dashboard(s)', default='all') parser.add_argument('--gtoken', '--token', dest='gtoken', help='Token of grafana server', default=None) parser.add_argument('--gurl', '--url', dest='gurl', help='URL from grafana', default=None) parser.add_argument('--dir', '--directory', dest='dashboards_dir', help='Indicate a folder for dashboard(s)', default='CM-Shared_Grafana', metavar='folder') group = parser.add_mutually_exclusive_group(required=False) group.add_argument('--i', dest='imports', help='Import function', action='store_true') group.add_argument('--import', dest='imports', help='Import function', action='store_true') group2 = parser.add_mutually_exclusive_group(required=False) group2.add_argument('--e', dest='exports', help='Export function', action='store_true', default=argparse.SUPPRESS) group2.add_argument('--export', dest='exports', help='Export function', action='store_true') results = parser.parse_args() dashboards_dir = results.dashboards_dir dashboard = results.dashboard grafana_token = results.gtoken grafana_url = results.gurl if (grafana_token is not None) and (grafana_url is not None): if results.exports: print('EXPORT function!') export_grafana_dashboards(grafana_token, grafana_url, dashboards_dir, dashboard) elif results.imports: print('IMPORT function') import_grafana_dashboards(grafana_token, grafana_url, dashboards_dir, dashboard) else: print('Please add [--gurl] and/or [--gtoken] option(s).Use "--e" to export, "--i" to import dashboards as well') print('For help, use: script_name.py -h') exit(0) end__time = round(time.time() - start__time, 2) print("--- %s seconds ---" % end__time) print( Bgcolors().get['OKGREEN'], "============================================================", Bgcolors().get['ENDC']) print( Bgcolors().get['OKGREEN'], "==========================FINISHED==========================", Bgcolors().get['ENDC']) print( Bgcolors().get['OKGREEN'], "============================================================", Bgcolors().get['ENDC']) if __name__ == '__main__': main()
Для помощи можно использовать:
$ python3 grafana_dashboards.py -h usage: python3 script_name.py {ARGS} optional arguments: -h, --help show this help message and exit --version show program's version number and exit --dash DASHBOARD [DASHBOARD ...], --dashboard DASHBOARD [DASHBOARD ...] Indicate a dashboard(s) --dir folder, --directory folder Indicate a folder for dashboard(s) --i Import function --import Import function --e Export function --export Export function created by Vitalii Natarov
Чтобы выполнить экспорт шалонов, выполняем:
$ python3 grafana_dashboards.py --e --gurl GRAFANA_URL_HERE --gtoken GRAFANA_TOKEN_HERE
Можно указать другую директорию:
$ python3 grafana_dashboards.py --e --dir some_another_dir --gurl GRAFANA_URL_HERE --gtoken GRAFANA_TOKEN_HERE
Или, можно экспортировать не все шаблоны, а только выбранные, — например:
$ python3 grafana_dashboards.py --e --dir --dash some_dashboard --gurl GRAFANA_URL_HERE --gtoken GRAFANA_TOKEN_HERE
Для импортирования, служит другая команда:
$ python3 grafana_dashboards.py --i
-=== СПОСОБ 3 — Использование модуля для grafana===-
Для начала, потребуется python3 + pip3:
Установка pip/setuptools/wheel в Unix/Linux
Ставим нужный пакет:
$ pip3 install grafcli
Теперь создайте конфигурационный файл grafcli.conf. Пока это в вашем рабочем каталоге в порядке:
[grafcli] editor = vim verbose = off [hosts] $GRAFANA_URL = on [$GRAFANA_URL] type = api url = https://$GRAFANA_URL:$PORT ssl = on user = admin password = $GRAFANA_ADMIN_PASSWORD #token = $GRAFANA_TOKEN [resources] data-dir = ~/.grafcli
Если вы используете token, то вам не нужно прописывать user/password. Чтобы проверить, действительно ли ваш файл конфигурации настроен корректно, попробуйте выполнить:
$ grafcli ls remote
Он должен показать URL-адрес Grafana, который вы прописали. Чтобы создать резервную копию всех дашбордов, используйте команду:
$ grafcli backup remote/$GRAFANA_URL/ backup.tgz
Восстановление из резервной копии также простое:
$ grafcli restore backup.tgz remote/$GRAFANA_URL/
Вот и все, статья «Экспорт дашбордов из grafana в Unix/Linux» завершена.
Добавлю свои 5 копеек. В баш скрипте немного проще, плюс архив:
Да, все верно. Но мне нужно было именно на питоне 🙂
Все настройки графаны, в том числе дашборды, храняться в .db файле рядом с местом установки графаны. Конкретно сами дашборды хранятся в таблице main.dashboard. Там в т.ч. хранятся json-шаблоны в поле data. Не проще было бы оттуда доставать?
Коллеги, а как же рассказать про импорт обратно? =)