1
0
Fork 0

Merge pull request #11 from thouveng/use-json-dashboards

Add support for JSON dashboards
This commit is contained in:
thouveng 2016-11-15 09:27:28 +01:00 committed by GitHub
commit 13574258bc
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
@ -202,7 +204,7 @@ The default format of Grafana dashboards with lists for rows, panels and targets
span: 6 span: 6
editable: false editable: false
type: graph type: graph
targets: targets:
- refId: A - refId: A
target: "support_prd.cfg01_iot_tcpcloud_eu.cpu.0.idle" target: "support_prd.cfg01_iot_tcpcloud_eu.cpu.0.idle"
datasource: graphite01 datasource: graphite01

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,18 +460,12 @@ 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(
response = requests.delete( request_url,
request_url, auth=_get_auth(profile),
headers=_get_headers(profile), headers=_get_headers(profile),
timeout=profile.get('grafana_timeout'), timeout=profile.get('grafana_timeout'),
) )
else:
response = requests.delete(
request_url,
auth=_get_auth(profile),
timeout=profile.get('grafana_timeout'),
)
data = response.json() data = response.json()
return data return data
@ -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')) response = requests.post(
if profile.get('grafana_token', False): "{0}/api/dashboards/db".format(profile.get('grafana_url')),
response = requests.post( auth=_get_auth(profile),
request_url, headers=_get_headers(profile),
headers=_get_headers(profile), json=payload
json=payload )
)
else:
response = requests.post(
request_url,
auth=_get_auth(profile),
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']
@ -568,4 +581,4 @@ def _stripped(d):
for k, v in six.iteritems(d): for k, v in six.iteritems(d):
if v: if v:
ret[k] = v ret[k] = v
return ret return ret

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