1
0
Fork 0
mirror of synced 2024-11-05 01:08:57 -05:00
formula-grafana/_states/grafana3_datasource.py
Michal Kobus 2f77faae7f Add Gnocchi datasource for Grafana
Change-Id: I7a48be1b447b84f672e4462fde29cbe044613acd
Closes-bug: PROD-21747
2018-09-10 14:32:09 +02:00

291 lines
7.7 KiB
Python

# -*- coding: utf-8 -*-
'''
Manage Grafana v3.0 data sources
.. versionadded:: 2016.3.0
Token auth setup
.. code-block:: yaml
grafana_version: 3
grafana:
grafana_timeout: 5
grafana_token: qwertyuiop
grafana_url: 'https://url.com'
Basic auth setup
.. code-block:: yaml
grafana_version: 3
grafana:
grafana_timeout: 5
grafana_user: grafana
grafana_password: qwertyuiop
grafana_url: 'https://url.com'
.. code-block:: yaml
Ensure influxdb data source is present:
grafana_datasource.present:
- name: influxdb
- type: influxdb
- url: http://localhost:8086
- access: proxy
- basic_auth: true
- basic_auth_user: myuser
- basic_auth_password: mypass
- is_default: true
'''
from __future__ import absolute_import
import json
import requests
from salt.ext.six import string_types
def __virtual__():
'''Only load if grafana v3.0 is configured.'''
return __salt__['config.get']('grafana_version', 1) == 3
def present(name,
type,
url,
access='proxy',
user='',
password='',
database='',
basic_auth=False,
basic_auth_user='',
basic_auth_password='',
mode=None,
domain='default',
project=None,
is_default=False,
profile='grafana'):
'''
Ensure that a data source is present.
name
Name of the data source.
type
Which type of data source it is ('graphite', 'influxdb' etc.).
access
Use proxy or direct. Default: proxy
url
The URL to the data source API.
user
Optional - user to authenticate with the data source
password
Optional - password to authenticate with the data source
database
Optional - database to use with the data source
basic_auth
Optional - set to True to use HTTP basic auth to authenticate with the
data source.
basic_auth_user
Optional - HTTP basic auth username.
basic_auth_password
Optional - HTTP basic auth password.
mode
Optional - Gnocchi authentication mode.
domain
Optional - Gnocchi domain, defaults to "default".
project
Optional - Keystone user for Gnocchi.
is_default
Optional - Set data source as default. Default: False
'''
if isinstance(profile, string_types):
profile = __salt__['config.option'](profile)
ret = {'name': name, 'result': None, 'comment': None, 'changes': None}
datasource = _get_datasource(profile, name)
data = _get_json_data(name, type, url,
access=access,
user=user,
password=password,
database=database,
basic_auth=basic_auth,
basic_auth_user=basic_auth_user,
basic_auth_password=basic_auth_password,
mode=mode,
domain=domain,
project=project,
is_default=is_default)
if datasource:
requests.put(
_get_url(profile, datasource['id']),
data=json.dumps(data),
auth=_get_auth(profile),
headers=_get_headers(profile),
timeout=profile.get('grafana_timeout', 3),
)
ret['result'] = True
ret['changes'] = _diff(datasource, data)
if ret['changes']['new'] or ret['changes']['old']:
ret['comment'] = 'Data source {0} updated'.format(name)
else:
ret['changes'] = None
ret['comment'] = 'Data source {0} already up-to-date'.format(name)
else:
requests.post(
'{0}/api/datasources'.format(profile['grafana_url']),
data=json.dumps(data),
auth=_get_auth(profile),
headers=_get_headers(profile),
timeout=profile.get('grafana_timeout', 3),
)
ret['result'] = True
ret['comment'] = 'New data source {0} added'.format(name)
ret['changes'] = data
return ret
def absent(name, profile='grafana'):
'''
Ensure that a data source is present.
name
Name of the data source to remove.
'''
if isinstance(profile, string_types):
profile = __salt__['config.option'](profile)
ret = {'result': None, 'comment': None, 'changes': None}
datasource = _get_datasource(profile, name)
if not datasource:
ret['result'] = True
ret['comment'] = 'Data source {0} already absent'.format(name)
return ret
requests.delete(
_get_url(profile, datasource['id']),
auth=_get_auth(profile),
headers=_get_headers(profile),
timeout=profile.get('grafana_timeout', 3),
)
ret['result'] = True
ret['comment'] = 'Data source {0} was deleted'.format(name)
return ret
def _get_url(profile, datasource_id):
return '{0}/api/datasources/{1}'.format(
profile['grafana_url'],
datasource_id
)
def _get_datasource(profile, name):
response = requests.get(
'{0}/api/datasources'.format(profile['grafana_url']),
auth=_get_auth(profile),
headers=_get_headers(profile),
timeout=profile.get('grafana_timeout', 3),
)
data = response.json()
for datasource in data:
if datasource['name'] == name:
return datasource
def _get_headers(profile):
headers = {'Content-type': 'application/json'}
if profile.get('grafana_token'):
headers['Authorization'] = 'Bearer {0}'.format(profile['grafana_token'])
return headers
def _get_auth(profile):
if profile.get('grafana_token'):
return None
return requests.auth.HTTPBasicAuth(
profile['grafana_user'],
profile['grafana_password']
)
def _get_json_data(name,
type,
url,
access='proxy',
user='',
password='',
database='',
basic_auth=False,
basic_auth_user='',
basic_auth_password='',
mode=None,
domain=None,
project=None,
is_default=False,
type_logo_url='public/app/plugins/datasource/influxdb/img/influxdb_logo.svg',
with_credentials=False):
data = {
'name': name,
'type': type,
'url': url,
'access': access,
'user': user,
'password': password,
'database': database,
'basicAuth': basic_auth,
'basicAuthUser': basic_auth_user,
'basicAuthPassword': basic_auth_password,
'isDefault': is_default,
'typeLogoUrl': type_logo_url,
'withCredentials': with_credentials,
}
if data['type'] == 'gnocchixyz-gnocchi-datasource':
json_data = {}
for special in ['mode', 'domain', 'project', 'user', 'password']:
value = locals().get(special)
if value is not None:
if special == 'user':
json_data['username'] = value
else:
json_data[special] = value
if json_data:
data['jsonData'] = json_data
return data
def _diff(old, new):
old_keys = old.keys()
old = old.copy()
new = new.copy()
for key in old_keys:
if key in ['id', 'orgId']:
del old[key]
# New versions of Grafana can introduce new keys that are not present
# in _get_json_data.
elif key in new and old[key] == new[key]:
del old[key]
del new[key]
return {'old': old, 'new': new}