blob: dbb331284a548000603a570c8528ce295ccb7486 [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
11 grafana:
12 grafana_version: 3
13 grafana_timeout: 5
14 grafana_token: qwertyuiop
15 grafana_url: 'https://url.com'
16
17Basic auth setup
18
19.. code-block:: yaml
20
21 grafana:
22 grafana_version: 3
23 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,
64 type_logo_url='public/app/plugins/datasource/graphite/img/graphite_logo.png',
65 with_credentials=False,
66 json_data=None,
67 profile='grafana'):
68 '''
69 Ensure that a data source is present.
70
71 name
72 Name of the data source.
73
74 type
75 Which type of data source it is ('graphite', 'influxdb' etc.).
76
77 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
86 basic_auth
87 Optional - set to True to use HTTP basic auth to authenticate with the
88 data source.
89
90 basic_auth_user
91 Optional - HTTP basic auth username.
92
93 basic_auth_password
94 Optional - HTTP basic auth password.
95
96 is_default
97 Default: False
98 '''
99 if isinstance(profile, string_types):
100 profile = __salt__['config.option'](profile)
101
102 ret = {'name': name, 'result': None, 'comment': None, 'changes': None}
103 datasource = _get_datasource(profile, name)
104 data = _get_json_data(name, type, url, access, user, password, database,
105 basic_auth, basic_auth_user, basic_auth_password, is_default, json_data)
106
107 if datasource:
108 if profile.get('grafana_token', False):
109 requests.put(
110 _get_url(profile, datasource['id']),
111 data,
112 headers=_get_headers(profile),
113 timeout=profile.get('grafana_timeout', 3),
114 )
115 else:
116 requests.put(
117 _get_url(profile, datasource['id']),
118 data,
119 auth=_get_auth(profile),
120 timeout=profile.get('grafana_timeout', 3),
121 )
122 ret['result'] = True
123 ret['changes'] = _diff(datasource, data)
124 if ret['changes']['new'] or ret['changes']['old']:
125 ret['comment'] = 'Data source {0} updated'.format(name)
126 else:
127 ret['changes'] = None
128 ret['comment'] = 'Data source {0} already up-to-date'.format(name)
129 else:
Guillaume Thouvenin22a78bd2016-11-02 09:04:42 +0100130 if profile.get('grafana_token', False):
131 requests.post(
132 '{0}/api/datasources'.format(profile['grafana_url']),
133 data,
134 headers=_get_headers(profile),
135 timeout=profile.get('grafana_timeout', 3),
136 )
137 else:
138 requests.put(
139 '{0}/api/datasources'.format(profile['grafana_url']),
140 data,
141 auth=_get_auth(profile),
142 timeout=profile.get('grafana_timeout', 3),
143 )
Ales Komarek3f044b22016-10-30 00:27:24 +0200144 ret['result'] = True
145 ret['comment'] = 'New data source {0} added'.format(name)
146 ret['changes'] = data
147
148 return ret
149
150
151def absent(name, profile='grafana'):
152 '''
153 Ensure that a data source is present.
154
155 name
156 Name of the data source to remove.
157 '''
158 if isinstance(profile, string_types):
159 profile = __salt__['config.option'](profile)
160
161 ret = {'result': None, 'comment': None, 'changes': None}
162 datasource = _get_datasource(profile, name)
163
164 if not datasource:
165 ret['result'] = True
166 ret['comment'] = 'Data source {0} already absent'.format(name)
167 return ret
168
169 if profile.get('grafana_token', False):
170 requests.delete(
171 _get_url(profile, datasource['id']),
172 headers=_get_headers(profile),
173 timeout=profile.get('grafana_timeout', 3),
174 )
175 else:
176 requests.delete(
177 _get_url(profile, datasource['id']),
178 auth=_get_auth(profile),
179 timeout=profile.get('grafana_timeout', 3),
180 )
181
182 ret['result'] = True
183 ret['comment'] = 'Data source {0} was deleted'.format(name)
184
185 return ret
186
187
188def _get_url(profile, datasource_id):
189 return '{0}/api/datasources/{1}'.format(
190 profile['grafana_url'],
191 datasource_id
192 )
193
194
195def _get_datasource(profile, name):
196 if profile.get('grafana_token', False):
197 response = requests.get(
198 '{0}/api/datasources'.format(profile['grafana_url']),
199 headers=_get_headers(profile),
200 timeout=profile.get('grafana_timeout', 3),
201 )
202 else:
203 response = requests.get(
204 '{0}/api/datasources'.format(profile['grafana_url']),
205 auth=_get_auth(profile),
206 timeout=profile.get('grafana_timeout', 3),
207 )
208 data = response.json()
209 for datasource in data:
210 if datasource['name'] == name:
211 return datasource
212 return None
213
214
215def _get_headers(profile):
216 return {
217 'Accept': 'application/json',
218 'Authorization': 'Bearer {0}'.format(profile['grafana_token'])
219 }
220
221
222def _get_auth(profile):
223 return requests.auth.HTTPBasicAuth(
224 profile['grafana_user'],
225 profile['grafana_password']
226 )
227
228
229def _get_json_data(name,
230 type,
231 url,
232 access='proxy',
233 user='',
234 password='',
235 database='',
236 basic_auth=False,
237 basic_auth_user='',
238 basic_auth_password='',
239 is_default=False,
240 type_logo_url='public/app/plugins/datasource/graphite/img/graphite_logo.png',
241 with_credentials=False,
242 json_data=None):
243 return {
244 'name': name,
245 'type': type,
246 'url': url,
247 'access': access,
248 'user': user,
249 'password': password,
250 'database': database,
251 'basicAuth': basic_auth,
252 'basicAuthUser': basic_auth_user,
253 'basicAuthPassword': basic_auth_password,
254 'isDefault': is_default,
255 'typeLogoUrl': type_logo_url,
256 'withCredentials': with_credentials,
257 'jsonData': json_data,
258 }
259
260
261def _diff(old, new):
262 old_keys = old.keys()
263 old = old.copy()
264 new = new.copy()
265 for key in old_keys:
266 if key == 'id' or key == 'orgId':
267 del old[key]
268 elif old[key] == new[key]:
269 del old[key]
270 del new[key]
271 return {'old': old, 'new': new}