-
Bjarke Madsen authoredBjarke Madsen authored
dashboard.py 5.54 KiB
"""
Grafana Dashhboard API endpoints wrapper functions.
"""
import logging
import os
import json
from typing import Dict
from requests.models import HTTPError
from brian_dashboard_manager.grafana.utils.request import TokenRequest
logger = logging.getLogger(__name__)
# Returns dictionary for each dashboard JSON definition in supplied directory
def get_dashboard_definitions(dir=None): # pragma: no cover
dashboard_dir = dir or os.path.join(
os.path.dirname(__file__), '../dashboards/')
for (dirpath, _, filenames) in os.walk(dashboard_dir):
for file in filenames:
if file.endswith('.json'):
filename = os.path.join(dirpath, file)
dashboard = json.load(open(filename, 'r'))
yield dashboard
def delete_dashboard(request: TokenRequest, dashboard, folder_id=None):
try:
r = None
uid = dashboard.get('uid')
if uid:
return _delete_dashboard(request, uid)
elif dashboard.get('title'):
# if a folder ID is not supplied,
# dashboard title should be globally unique
dash = _search_dashboard(request, dashboard, folder_id)
if dash is None:
return True
_delete_dashboard(request, dash.get(
'dashboard', {}).get('uid', ''))
logger.info(f'Deleted dashboard: {dashboard.get("title")}')
return r is not None
except HTTPError:
dump = json.dumps(dashboard, indent=2)
logger.exception(
f'Error when deleting dashboard:\n{dump}')
return None
# Deletes a single dashboard for the organization
# the API token is registered to.
def _delete_dashboard(request: TokenRequest, uid: int):
try:
r = request.delete(f'api/dashboards/uid/{uid}')
if r and 'deleted' in r.get('message', ''):
return True
except HTTPError as e:
if e.response is not None and e.response.status_code == 404:
return True
logger.exception(f'Error when deleting dashboard with UID #{uid}')
return False
# Deletes all dashboards for the organization
# the API token is registered to.
def delete_dashboards(request: TokenRequest):
r = request.get('api/search')
if r and len(r) > 0:
for dash in r:
_delete_dashboard(request, dash['uid'])
return True
# Searches for a dashboard with given title
def find_dashboard(request: TokenRequest, title=None):
param = {
**({'query': title} if title else {}),
'type': 'dash-db',
'limit': 5000,
'page': 1
}
r = request.get('api/search', params=param)
if r and len(r) > 0:
if title:
return r[0]
else:
while True:
param['page'] += 1
page = request.get('api/search', params=param)
if len(page) > 0:
r.extend(page)
else:
break
return r
return None
# Searches Grafana for a dashboard
# matching the title of the provided dashboard.
def _search_dashboard(request: TokenRequest, dashboard: Dict, folder_id=None):
try:
r = request.get('api/search', params={
'query': dashboard["title"]
})
if r and isinstance(r, list):
if len(r) >= 1:
for dash in r:
if folder_id:
if folder_id != dash.get('folderId'):
continue
if dash['title'] == dashboard['title']:
definition = _get_dashboard(request, dash['uid'])
return definition
return None
except HTTPError:
return None
# Fetches dashboard with given UID for the token's organization.
def _get_dashboard(request: TokenRequest, uid: int):
try:
r = request.get(f'api/dashboards/uid/{uid}')
except HTTPError:
return None
return r
# Creates or updates (if exists) given dashboard for the token's organization.
# supplied dashboards are JSON blobs exported from GUI with a UID.
def create_dashboard(request: TokenRequest, dashboard: Dict, folder_id=None):
title = dashboard['title']
existing_dashboard = None
has_uid = dashboard.get('uid') is not None
if has_uid:
existing_dashboard = _get_dashboard(request, uid=dashboard['uid'])
# The title might not match the one that's provisioned with that UID.
# Try to find it by searching for the title instead.
if existing_dashboard is not None:
grafana_title = existing_dashboard['dashboard']['title']
different = grafana_title != title
else:
different = False
if existing_dashboard is None or different:
existing_dashboard = _search_dashboard(request, dashboard, folder_id)
if existing_dashboard:
dashboard['uid'] = existing_dashboard['dashboard']['uid']
dashboard['id'] = existing_dashboard['dashboard']['id']
dashboard['version'] = existing_dashboard['dashboard']['version']
else:
# We are creating a new dashboard, delete ID if it exists.
del dashboard['id']
payload = {
'dashboard': dashboard,
'overwrite': False
}
if folder_id:
payload['folderId'] = folder_id
try:
# action = "Updating" if existing_dashboard else "Creating"
# logger.info(f'{action} dashboard: {title}')
r = request.post('api/dashboards/db', json=payload)
return r
except HTTPError:
logger.exception(f'Error when provisioning dashboard {title}')
return None