1
0
Fork 0
mirror of synced 2024-11-22 08:55:35 -05:00

Add support for JSON dashboards

This patch adds the support for JSON dashboards and also provides the
support for remote dashboards.
This commit is contained in:
Guillaume Thouvenin 2016-11-08 11:55:55 +01:00
parent c4ddb9ebda
commit 2958bda057
5 changed files with 92 additions and 65 deletions

View file

@ -44,7 +44,9 @@ Server installed with PostgreSQL database
user: grafana user: grafana
password: passwd password: passwd
Server installed with default StackLight JSON dashboards Server installed with default StackLight JSON dashboards. This will
be replaced by the possibility for a service to provide its own dashboard
using salt-mine.
.. code-block:: yaml .. code-block:: yaml

View file

@ -65,6 +65,7 @@ def present(name,
base_panels_from_pillar=None, base_panels_from_pillar=None,
base_rows_from_pillar=None, base_rows_from_pillar=None,
dashboard=None, dashboard=None,
dashboard_format='yaml',
profile='grafana'): profile='grafana'):
''' '''
Ensure the grafana dashboard exists and is managed. Ensure the grafana dashboard exists and is managed.
@ -84,19 +85,39 @@ def present(name,
dashboard dashboard
A dict that defines a dashboard that should be managed. A dict that defines a dashboard that should be managed.
dashboard_format
You can use two formats for dashboards. You can use the JSON format
if you provide a complete dashboard in raw JSON or you can use the YAML
format (this is the default) and provide a description of the
dashboard in YAML.
profile profile
A pillar key or dict that contains grafana information A pillar key or dict that contains grafana information
''' '''
ret = {'name': name, 'result': True, 'comment': '', 'changes': {}} ret = {'name': name, 'result': True, 'comment': '', 'changes': {}}
base_dashboards_from_pillar = base_dashboards_from_pillar or []
base_panels_from_pillar = base_panels_from_pillar or []
base_rows_from_pillar = base_rows_from_pillar or []
dashboard = dashboard or {} dashboard = dashboard or {}
if isinstance(profile, six.string_types): if isinstance(profile, six.string_types):
profile = __salt__['config.option'](profile) profile = __salt__['config.option'](profile)
if dashboard_format == 'json':
# In this case, a raw JSON of the full dashboard is provided.
response = _update(dashboard, profile)
if response.get('status') == 'success':
ret['comment'] = 'Dashboard {0} created.'.format(name)
ret['changes']['new'] = 'Dashboard {0} created.'.format(name)
else:
ret['result'] = False
ret['comment'] = ("Failed to create dashboard {0}, "
"response={1}").format(name, response)
return ret
base_dashboards_from_pillar = base_dashboards_from_pillar or []
base_panels_from_pillar = base_panels_from_pillar or []
base_rows_from_pillar = base_rows_from_pillar or []
# Add pillar keys for default configuration # Add pillar keys for default configuration
base_dashboards_from_pillar = ([_DEFAULT_DASHBOARD_PILLAR] + base_dashboards_from_pillar = ([_DEFAULT_DASHBOARD_PILLAR] +
base_dashboards_from_pillar) base_dashboards_from_pillar)
@ -439,16 +460,10 @@ def _delete(url, profile):
'''Delete a specific dashboard.''' '''Delete a specific dashboard.'''
request_url = "{0}/api/dashboards/{1}".format(profile.get('grafana_url'), request_url = "{0}/api/dashboards/{1}".format(profile.get('grafana_url'),
url) url)
if profile.get('grafana_token', False):
response = requests.delete(
request_url,
headers=_get_headers(profile),
timeout=profile.get('grafana_timeout'),
)
else:
response = requests.delete( response = requests.delete(
request_url, request_url,
auth=_get_auth(profile), auth=_get_auth(profile),
headers=_get_headers(profile),
timeout=profile.get('grafana_timeout'), timeout=profile.get('grafana_timeout'),
) )
data = response.json() data = response.json()
@ -461,30 +476,28 @@ def _update(dashboard, profile):
'dashboard': dashboard, 'dashboard': dashboard,
'overwrite': True 'overwrite': True
} }
request_url = "{0}/api/dashboards/db".format(profile.get('grafana_url'))
if profile.get('grafana_token', False):
response = requests.post( response = requests.post(
request_url, "{0}/api/dashboards/db".format(profile.get('grafana_url')),
headers=_get_headers(profile),
json=payload
)
else:
response = requests.post(
request_url,
auth=_get_auth(profile), auth=_get_auth(profile),
headers=_get_headers(profile),
json=payload json=payload
) )
return response.json() return response.json()
def _get_headers(profile): def _get_headers(profile):
return { headers = {'Content-type': 'application/json'}
'Accept': 'application/json',
'Authorization': 'Bearer {0}'.format(profile['grafana_token']) if profile.get('grafana_token', False):
} headers['Authorization'] = 'Bearer {0}'.format(profile['grafana_token'])
return headers
def _get_auth(profile): def _get_auth(profile):
if profile.get('grafana_token', False):
return None
return requests.auth.HTTPBasicAuth( return requests.auth.HTTPBasicAuth(
profile['grafana_user'], profile['grafana_user'],
profile['grafana_password'] profile['grafana_password']

View file

@ -36,52 +36,56 @@ grafana_client_datasource_{{ datasource_name }}:
{%- if client.remote_data.engine == 'salt_mine' %} {%- if client.remote_data.engine == 'salt_mine' %}
{%- for node_name, node_grains in salt['mine.get']('*', 'grains.items').iteritems() %} {%- for node_name, node_grains in salt['mine.get']('*', 'grains.items').iteritems() %}
{%- if node_grains.grafana is defined %} {%- if node_grains.grafana is defined %}
{%- set raw_dict = salt['grains.filter_by']({'default': raw_dict}, merge=node_grains.grafana.get('dashboard', {})) %} {%- set raw_dict = salt['grains.filter_by']({'default': raw_dict}, merge=node_grains.grafana.get('dashboard', {})) %}
{%- endif %} {%- endif %}
{%- endfor %} {%- endfor %}
{%- endif %} {%- endif %}
{%- if client.dashboard is defined %} {%- if client.dashboard is defined %}
{%- set raw_dict = salt['grains.filter_by']({'default': raw_dict}, merge=client.dashboard) %} {%- set raw_dict = salt['grains.filter_by']({'default': raw_dict}, merge=client.dashboard) %}
{%- endif %} {%- endif %}
{%- for dashboard_name, dashboard in raw_dict.iteritems() %} {%- for dashboard_name, dashboard in raw_dict.iteritems() %}
{%- set rows = [] %} {%- if dashboard.get('format', 'yaml')|lower == 'yaml' %}
{%- for row_name, row in dashboard.get('row', {}).iteritems() %} # Dashboards in JSON format are considered as blob
{%- set panels = [] %} {%- set rows = [] %}
{%- for panel_name, panel in row.get('panel', {}).iteritems() %} {%- for row_name, row in dashboard.get('row', {}).iteritems() %}
{%- set targets = [] %} {%- set panels = [] %}
{%- for target_name, target in panel.get('target', {}).iteritems() %} {%- for panel_name, panel in row.get('panel', {}).iteritems() %}
{%- do targets.extend([target]) %} {%- set targets = [] %}
{%- endfor %} {%- for target_name, target in panel.get('target', {}).iteritems() %}
{%- do panel.update({'targets': targets}) %} {%- do targets.extend([target]) %}
{%- do panels.extend([panel]) %} {%- endfor %}
{%- endfor %} {%- do panel.update({'targets': targets}) %}
{%- do row.update({'panels': panels}) %} {%- do panels.extend([panel]) %}
{%- do rows.extend([row]) %} {%- endfor %}
{%- endfor %} {%- do row.update({'panels': panels}) %}
{%- do dashboard.update({'rows': rows}) %} {%- do rows.extend([row]) %}
{%- do final_dict.update({dashboard_name: dashboard}) %} {%- endfor %}
{%- do dashboard.update({'rows': rows}) %}
{%- endif %}
{%- do final_dict.update({dashboard_name: dashboard}) %}
{%- endfor %} {%- endfor %}
{%- for dashboard_name, dashboard in final_dict.iteritems() %} {%- for dashboard_name, dashboard in final_dict.iteritems() %}
{%- if dashboard.get('enabled', True) %}
{%- if dashboard.get('enabled', True) %}
grafana_client_dashboard_{{ dashboard_name }}: grafana_client_dashboard_{{ dashboard_name }}:
grafana3_dashboard.present: grafana3_dashboard.present:
- name: {{ dashboard_name }} - name: {{ dashboard_name }}
{%- if dashboard.get('format', 'yaml')|lower == 'json' %}
{%- import_json dashboard.template as dash %}
- dashboard: {{ dash|json }}
- dashboard_format: json
{%- else %}
- dashboard: {{ dashboard }} - dashboard: {{ dashboard }}
{%- endif %}
{%- else %} {%- else %}
grafana_client_dashboard_{{ dashboard_name }}: grafana_client_dashboard_{{ dashboard_name }}:
grafana3_dashboard.absent: grafana3_dashboard.absent:
- name: {{ dashboard_name }} - name: {{ dashboard_name }}
{%- endif %}
{%- endif %}
{%- endfor %} {%- endfor %}
{%- endif %} {%- endif %}

View file

@ -13,6 +13,7 @@ grafana_grains_dir:
{# Loading the other service support metadata for localhost #} {# Loading the other service support metadata for localhost #}
{%- for service_name, service in pillar.iteritems() %} {%- for service_name, service in pillar.iteritems() %}
{%- if service.get('_support', {}).get('grafana', {}).get('enabled', False) %}
{%- macro load_grains_file(grains_fragment_file) %}{% include grains_fragment_file ignore missing %}{% endmacro %} {%- macro load_grains_file(grains_fragment_file) %}{% include grains_fragment_file ignore missing %}{% endmacro %}
@ -20,6 +21,7 @@ grafana_grains_dir:
{%- set grains_yaml = load_grains_file(grains_fragment_file)|load_yaml %} {%- set grains_yaml = load_grains_file(grains_fragment_file)|load_yaml %}
{%- set service_grains = salt['grains.filter_by']({'default': service_grains}, merge=grains_yaml) %} {%- set service_grains = salt['grains.filter_by']({'default': service_grains}, merge=grains_yaml) %}
{%- endif %}
{%- endfor %} {%- endfor %}
grafana_grain: grafana_grain:

View file

@ -0,0 +1,6 @@
applications:
- grafana
parameters:
grafana:
collector:
enabled: true