blob: fd41d86e7d3232e33b192c7ff0383cf500239855 [file] [log] [blame]
Ales Komarek3f044b22016-10-30 00:27:24 +02001# -*- coding: utf-8 -*-
2'''
3Manage Grafana v3.0 data sources
4
5.. versionadded:: 2016.3.0
6
7Token auth setup
8
9.. code-block:: yaml
10
Guillaume Thouveninab102342016-11-03 10:40:29 +010011 grafana_version: 3
Ales Komarek3f044b22016-10-30 00:27:24 +020012 grafana:
Ales Komarek3f044b22016-10-30 00:27:24 +020013 grafana_timeout: 5
14 grafana_token: qwertyuiop
15 grafana_url: 'https://url.com'
16
17Basic auth setup
18
19.. code-block:: yaml
20
Guillaume Thouveninab102342016-11-03 10:40:29 +010021 grafana_version: 3
Ales Komarek3f044b22016-10-30 00:27:24 +020022 grafana:
Ales Komarek3f044b22016-10-30 00:27:24 +020023 grafana_timeout: 5
24 grafana_user: grafana
25 grafana_password: qwertyuiop
26 grafana_url: 'https://url.com'
27
28.. code-block:: yaml
29
30 Ensure influxdb data source is present:
31 grafana_datasource.present:
32 - name: influxdb
33 - type: influxdb
34 - url: http://localhost:8086
35 - access: proxy
36 - basic_auth: true
37 - basic_auth_user: myuser
38 - basic_auth_password: mypass
39 - is_default: true
40'''
41from __future__ import absolute_import
42
43import requests
44
45from salt.ext.six import string_types
46
47
48def __virtual__():
49 '''Only load if grafana v3.0 is configured.'''
50 return __salt__['config.get']('grafana_version', 1) == 3
51
52
53def present(name,
54 type,
55 url,
56 access='proxy',
57 user='',
58 password='',
59 database='',
60 basic_auth=False,
61 basic_auth_user='',
62 basic_auth_password='',
63 is_default=False,
Ales Komarek3f044b22016-10-30 00:27:24 +020064 profile='grafana'):
65 '''
66 Ensure that a data source is present.
67
68 name
69 Name of the data source.
70
71 type
72 Which type of data source it is ('graphite', 'influxdb' etc.).
73
Guillaume Thouveninab102342016-11-03 10:40:29 +010074 access
75 Use proxy or direct. Default: proxy
76
Ales Komarek3f044b22016-10-30 00:27:24 +020077 url
78 The URL to the data source API.
79
80 user
81 Optional - user to authenticate with the data source
82
83 password
84 Optional - password to authenticate with the data source
85
Guillaume Thouveninab102342016-11-03 10:40:29 +010086 database
87 Optional - database to use with the data source
88
Ales Komarek3f044b22016-10-30 00:27:24 +020089 basic_auth
90 Optional - set to True to use HTTP basic auth to authenticate with the
91 data source.
92
93 basic_auth_user
94 Optional - HTTP basic auth username.
95
96 basic_auth_password
97 Optional - HTTP basic auth password.
98
99 is_default
Guillaume Thouveninab102342016-11-03 10:40:29 +0100100 Optional - Set data source as default. Default: False
Ales Komarek3f044b22016-10-30 00:27:24 +0200101 '''
102 if isinstance(profile, string_types):
103 profile = __salt__['config.option'](profile)
104
105 ret = {'name': name, 'result': None, 'comment': None, 'changes': None}
106 datasource = _get_datasource(profile, name)
Guillaume Thouveninab102342016-11-03 10:40:29 +0100107 data = _get_json_data(name, type, url,
108 access=access,
109 user=user,
110 password=password,
111 database=database,
112 basic_auth=basic_auth,
113 basic_auth_user=basic_auth_user,
114 basic_auth_password=basic_auth_password,
115 is_default=is_default)
Ales Komarek3f044b22016-10-30 00:27:24 +0200116
117 if datasource:
118 if profile.get('grafana_token', False):
119 requests.put(
120 _get_url(profile, datasource['id']),
121 data,
122 headers=_get_headers(profile),
123 timeout=profile.get('grafana_timeout', 3),
124 )
125 else:
126 requests.put(
127 _get_url(profile, datasource['id']),
128 data,
129 auth=_get_auth(profile),
130 timeout=profile.get('grafana_timeout', 3),
131 )
132 ret['result'] = True
133 ret['changes'] = _diff(datasource, data)
134 if ret['changes']['new'] or ret['changes']['old']:
135 ret['comment'] = 'Data source {0} updated'.format(name)
136 else:
137 ret['changes'] = None
138 ret['comment'] = 'Data source {0} already up-to-date'.format(name)
139 else:
Guillaume Thouvenin22a78bd2016-11-02 09:04:42 +0100140 if profile.get('grafana_token', False):
141 requests.post(
142 '{0}/api/datasources'.format(profile['grafana_url']),
143 data,
144 headers=_get_headers(profile),
145 timeout=profile.get('grafana_timeout', 3),
146 )
147 else:
Guillaume Thouvenin5bbb9f22016-11-02 15:48:12 +0100148 requests.post(
Guillaume Thouvenin22a78bd2016-11-02 09:04:42 +0100149 '{0}/api/datasources'.format(profile['grafana_url']),
150 data,
151 auth=_get_auth(profile),
152 timeout=profile.get('grafana_timeout', 3),
153 )
Ales Komarek3f044b22016-10-30 00:27:24 +0200154 ret['result'] = True
155 ret['comment'] = 'New data source {0} added'.format(name)
156 ret['changes'] = data
157
158 return ret
159
160
161def absent(name, profile='grafana'):
162 '''
163 Ensure that a data source is present.
164
165 name
166 Name of the data source to remove.
167 '''
168 if isinstance(profile, string_types):
169 profile = __salt__['config.option'](profile)
170
171 ret = {'result': None, 'comment': None, 'changes': None}
172 datasource = _get_datasource(profile, name)
173
174 if not datasource:
175 ret['result'] = True
176 ret['comment'] = 'Data source {0} already absent'.format(name)
177 return ret
178
179 if profile.get('grafana_token', False):
180 requests.delete(
181 _get_url(profile, datasource['id']),
182 headers=_get_headers(profile),
183 timeout=profile.get('grafana_timeout', 3),
184 )
185 else:
186 requests.delete(
187 _get_url(profile, datasource['id']),
188 auth=_get_auth(profile),
189 timeout=profile.get('grafana_timeout', 3),
190 )
191
192 ret['result'] = True
193 ret['comment'] = 'Data source {0} was deleted'.format(name)
194
195 return ret
196
197
198def _get_url(profile, datasource_id):
199 return '{0}/api/datasources/{1}'.format(
200 profile['grafana_url'],
201 datasource_id
202 )
203
204
205def _get_datasource(profile, name):
206 if profile.get('grafana_token', False):
207 response = requests.get(
208 '{0}/api/datasources'.format(profile['grafana_url']),
209 headers=_get_headers(profile),
210 timeout=profile.get('grafana_timeout', 3),
211 )
212 else:
213 response = requests.get(
214 '{0}/api/datasources'.format(profile['grafana_url']),
215 auth=_get_auth(profile),
216 timeout=profile.get('grafana_timeout', 3),
217 )
218 data = response.json()
219 for datasource in data:
220 if datasource['name'] == name:
221 return datasource
222 return None
223
224
225def _get_headers(profile):
226 return {
227 'Accept': 'application/json',
228 'Authorization': 'Bearer {0}'.format(profile['grafana_token'])
229 }
230
231
232def _get_auth(profile):
233 return requests.auth.HTTPBasicAuth(
234 profile['grafana_user'],
235 profile['grafana_password']
236 )
237
238
239def _get_json_data(name,
240 type,
241 url,
242 access='proxy',
243 user='',
244 password='',
245 database='',
246 basic_auth=False,
247 basic_auth_user='',
248 basic_auth_password='',
249 is_default=False,
Guillaume Thouveninab102342016-11-03 10:40:29 +0100250 type_logo_url='public/app/plugins/datasource/influxdb/img/influxdb_logo.svg',
251 with_credentials=False):
Ales Komarek3f044b22016-10-30 00:27:24 +0200252 return {
253 'name': name,
254 'type': type,
255 'url': url,
256 'access': access,
257 'user': user,
258 'password': password,
259 'database': database,
260 'basicAuth': basic_auth,
261 'basicAuthUser': basic_auth_user,
262 'basicAuthPassword': basic_auth_password,
263 'isDefault': is_default,
264 'typeLogoUrl': type_logo_url,
265 'withCredentials': with_credentials,
Ales Komarek3f044b22016-10-30 00:27:24 +0200266 }
267
268
269def _diff(old, new):
270 old_keys = old.keys()
271 old = old.copy()
272 new = new.copy()
273 for key in old_keys:
274 if key == 'id' or key == 'orgId':
275 del old[key]
276 elif old[key] == new[key]:
277 del old[key]
278 del new[key]
279 return {'old': old, 'new': new}