bundlewrap/bundles/grafana/items.py

181 lines
6.2 KiB
Python

assert node.has_bundle('redis')
assert node.has_bundle('postgresql')
from mako.template import Template
from shlex import quote
from copy import deepcopy
from itertools import count
import yaml
import json
svc_systemd['grafana-server'] = {
'needs': [
'pkg_apt:grafana',
],
}
admin_password = node.metadata.get('grafana/config/security/admin_password')
port = node.metadata.get('grafana/config/server/http_port')
actions['reset_grafana_admin_password'] = {
'command': f"grafana-cli admin reset-admin-password {quote(admin_password)}",
'unless': f"sleep 5 && curl http://admin:{quote(admin_password)}@localhost:{port}/api/org --fail",
'needs': [
'svc_systemd:grafana-server',
],
}
directories = {
'/etc/grafana': {},
'/etc/grafana/provisioning': {
'owner': 'grafana',
'group': 'grafana',
},
'/etc/grafana/provisioning/datasources': {
'purge': True,
},
'/etc/grafana/provisioning/dashboards': {
'purge': True,
},
'/var/lib/grafana': {
'owner': 'grafana',
'group': 'grafana',
},
'/var/lib/grafana/dashboards': {
'owner': 'grafana',
'group': 'grafana',
'purge': True,
'triggers': [
'svc_systemd:grafana-server:restart',
],
},
}
files = {
'/etc/grafana/grafana.ini': {
'content': repo.libs.ini.dumps(node.metadata.get('grafana/config')),
'owner': 'grafana',
'group': 'grafana',
'triggers': [
'svc_systemd:grafana-server:restart',
],
},
'/etc/grafana/provisioning/datasources/managed.yaml': {
'content': yaml.dump({
'apiVersion': 1,
'datasources': list(node.metadata.get('grafana/datasources').values()),
}),
'owner': 'grafana',
'group': 'grafana',
'triggers': [
'svc_systemd:grafana-server:restart',
],
},
'/etc/grafana/provisioning/dashboards/managed.yaml': {
'content': yaml.dump({
'apiVersion': 1,
'providers': [{
'name': 'Default',
'folder': 'Generated',
'type': 'file',
'options': {
'path': '/var/lib/grafana/dashboards',
},
}],
}),
'owner': 'grafana',
'group': 'grafana',
'triggers': [
'svc_systemd:grafana-server:restart',
],
},
}
# DASHBOARDS
with open(repo.path.join([f'data/grafana/dashboard.py'])) as file:
dashboard_template = eval(file.read())
with open(repo.path.join([f'data/grafana/panel.py'])) as file:
panel_template = eval(file.read())
with open(repo.path.join([f'data/grafana/flux.mako'])) as file:
flux_template = Template(file.read())
bucket = repo.get_node(node.metadata.get('grafana/influxdb_node')).metadata.get('influxdb/bucket')
monitored_nodes = [
other_node
for other_node in repo.nodes
if other_node.metadata.get('telegraf/influxdb_node', None) == node.metadata.get('grafana/influxdb_node')
]
for dashboard_id, monitored_node in enumerate(monitored_nodes, start=1):
dashboard = deepcopy(dashboard_template)
dashboard['id'] = dashboard_id
dashboard['title'] = monitored_node.name
dashboard['uid'] = monitored_node.metadata.get('id')
panel_id = count(start=1)
for row_id, row_name in enumerate(sorted(monitored_node.metadata.get('grafana_rows')), start=1):
with open(repo.path.join([f'data/grafana/rows/{row_name}.py'])) as file:
row = eval(file.read())
for panel_in_row, (panel_name, panel_config) in enumerate(row.items()):
panel = deepcopy(panel_template)
panel['id'] = next(panel_id)
panel['title'] = f'{row_name} {panel_name}'
panel['gridPos']['w'] = 24 // len(row)
panel['gridPos']['x'] = (24 // len(row)) * panel_in_row
panel['gridPos']['y'] = (row_id - 1) * panel['gridPos']['h']
if 'display_name' in panel_config:
panel['fieldConfig']['defaults']['displayName'] = '${'+panel_config['display_name']+'}'
if panel_config.get('stacked'):
panel['fieldConfig']['defaults']['custom']['stacking']['mode'] = 'normal'
if 'unit' in panel_config:
panel['fieldConfig']['defaults']['unit'] = panel_config['unit']
if 'min' in panel_config:
panel['fieldConfig']['defaults']['min'] = panel_config['min']
if 'max' in panel_config:
panel['fieldConfig']['defaults']['max'] = panel_config['max']
if 'soft_max' in panel_config:
panel['fieldConfig']['defaults']['custom']['axisSoftMax'] = panel_config['soft_max']
if 'legend' in panel_config:
panel['options']['legend'].update(panel_config['legend'])
if 'tooltip' in panel_config:
panel['options']['tooltip']['mode'] = panel_config['tooltip']
if panel_config['tooltip'] == 'multi':
panel['options']['tooltip']['sort'] = 'desc'
for query_name, query_config in panel_config['queries'].items():
panel['targets'].append({
'refId': query_name,
'query': flux_template.render(
bucket=bucket,
host=monitored_node.name,
negative=query_config.get('negative', False),
boolean_to_int=query_config.get('boolean_to_int', False),
minimum=query_config.get('minimum', None),
filters={
'host': monitored_node.name,
**query_config['filters'],
},
exists=query_config.get('exists', []),
function=query_config.get('function', None),
).strip()
})
dashboard['panels'].append(panel)
files[f'/var/lib/grafana/dashboards/{monitored_node.name}.json'] = {
'content': json.dumps(dashboard, indent=4),
'owner': 'grafana',
'group': 'grafana',
'triggers': [
'svc_systemd:grafana-server:restart',
]
}