grafana 0.8.2 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +8 -3
  3. data/lib/grafana/admin.rb +39 -65
  4. data/lib/grafana/alerts.rb +334 -14
  5. data/lib/grafana/annotations.rb +284 -9
  6. data/lib/grafana/client.rb +38 -1
  7. data/lib/grafana/dashboard.rb +182 -39
  8. data/lib/grafana/dashboard_permissions.rb +132 -0
  9. data/lib/grafana/dashboard_versions.rb +101 -5
  10. data/lib/grafana/datasource.rb +93 -49
  11. data/lib/grafana/folder.rb +198 -0
  12. data/lib/grafana/folder_and_dashboard_search.rb +57 -0
  13. data/lib/grafana/folder_permissions.rb +155 -0
  14. data/lib/grafana/login.rb +41 -35
  15. data/lib/grafana/network.rb +128 -91
  16. data/lib/grafana/organization.rb +65 -34
  17. data/lib/grafana/organizations.rb +119 -175
  18. data/lib/grafana/playlist.rb +599 -0
  19. data/lib/grafana/preferences.rb +122 -0
  20. data/lib/grafana/tags.rb +19 -8
  21. data/lib/grafana/teams.rb +364 -0
  22. data/lib/grafana/tools.rb +44 -12
  23. data/lib/grafana/user.rb +78 -39
  24. data/lib/grafana/users.rb +104 -53
  25. data/lib/grafana/validator.rb +47 -2
  26. data/lib/grafana/version.rb +3 -3
  27. metadata +13 -38
  28. data/doc/Array.html +0 -200
  29. data/doc/Boolean.html +0 -122
  30. data/doc/FalseClass.html +0 -132
  31. data/doc/Grafana.html +0 -172
  32. data/doc/Hash.html +0 -212
  33. data/doc/Logging.html +0 -326
  34. data/doc/Object.html +0 -286
  35. data/doc/Time.html +0 -200
  36. data/doc/TrueClass.html +0 -132
  37. data/doc/_index.html +0 -380
  38. data/doc/class_list.html +0 -51
  39. data/doc/file.README.html +0 -117
  40. data/doc/file_list.html +0 -56
  41. data/doc/frames.html +0 -17
  42. data/doc/index.html +0 -117
  43. data/doc/method_list.html +0 -771
  44. data/doc/top-level-namespace.html +0 -112
@@ -0,0 +1,599 @@
1
+
2
+ module Grafana
3
+
4
+ # +++
5
+ # title = "Playlist HTTP API "
6
+ # description = "Playlist Admin HTTP API"
7
+ # keywords = ["grafana", "http", "documentation", "api", "playlist"]
8
+ # aliases = ["/http_api/playlist/"]
9
+ # type = "docs"
10
+ # [menu.docs]
11
+ # name = "Playlist"
12
+ # parent = "http_api"
13
+ # +++
14
+
15
+ # https://github.com/grafana/grafana/blob/1165d098b0d0ae705955f9d2ea104beea98ca6eb/pkg/api/dtos/playlist.go
16
+
17
+ module Playlist
18
+
19
+ ## Playlist API
20
+ #
21
+ ### Search Playlist
22
+ #
23
+ #`GET /api/playlists`
24
+ #
25
+ #Get all existing playlist for the current organization using pagination
26
+ #
27
+ #**Example Request**:
28
+ #
29
+ #```bash
30
+ #GET /api/playlists HTTP/1.1
31
+ #Accept: application/json
32
+ #Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
33
+ #```
34
+ #
35
+ # Querystring Parameters:
36
+ #
37
+ # These parameters are used as querystring parameters.
38
+ #
39
+ # - **query** - Limit response to playlist having a name like this value.
40
+ # - **limit** - Limit response to *X* number of playlist.
41
+ #
42
+ #**Example Response**:
43
+ #
44
+ #```json
45
+ #HTTP/1.1 200
46
+ #Content-Type: application/json
47
+ #[
48
+ # {
49
+ # "id": 1,
50
+ # "name": "my playlist",
51
+ # "interval": "5m"
52
+ # }
53
+ #]
54
+ #```
55
+ def playlists
56
+
57
+ endpoint = '/api/playlists'
58
+
59
+ @logger.debug("Attempting to get all existing playlists (GET #{endpoint})") if @debug
60
+
61
+ playlists = get( endpoint )
62
+
63
+ return { 'status' => 404, 'message' => 'No Playlists found' } if( playlists.nil? || playlists == false || playlists.dig('status').to_i != 200 )
64
+
65
+ playlists
66
+ end
67
+
68
+ ### Get one playlist
69
+ #
70
+ #`GET /api/playlists/:id`
71
+ #
72
+ #**Example Request**:
73
+ #
74
+ #```bash
75
+ #GET /api/playlists/1 HTTP/1.1
76
+ #Accept: application/json
77
+ #Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
78
+ #```
79
+ #
80
+ #**Example Response**:
81
+ #
82
+ #```json
83
+ #HTTP/1.1 200
84
+ #Content-Type: application/json
85
+ #{
86
+ # "id" : 1,
87
+ # "name": "my playlist",
88
+ # "interval": "5m",
89
+ # "orgId": "my org",
90
+ # "items": [
91
+ # {
92
+ # "id": 1,
93
+ # "playlistId": 1,
94
+ # "type": "dashboard_by_id",
95
+ # "value": "3",
96
+ # "order": 1,
97
+ # "title":"my third dasboard"
98
+ # },
99
+ # {
100
+ # "id": 2,
101
+ # "playlistId": 1,
102
+ # "type": "dashboard_by_tag",
103
+ # "value": "myTag",
104
+ # "order": 2,
105
+ # "title":"my other dasboard"
106
+ # }
107
+ # ]
108
+ #}
109
+ #```
110
+
111
+ def playlist( playlist_id )
112
+
113
+ if( playlist_id.is_a?(String) && playlist_id.is_a?(Integer) )
114
+ raise ArgumentError.new(format('wrong type. \'playlist_id\' must be an String (for an Playlist name) or an Integer (for an Playlist Id), given \'%s\'', playlist_id.class.to_s))
115
+ end
116
+ raise ArgumentError.new('missing \'playlist_id\'') if( playlist_id.size.zero? )
117
+
118
+ if(playlist_id.is_a?(String))
119
+
120
+ data = playlists
121
+ status = data.dig('status')
122
+ d = data.dig('message')
123
+ data = d.select { |k| k['name'] == playlist_id }
124
+
125
+ return { 'status' => 404, 'message' => format( 'No Playlist \'%s\' found', playlist_id) } if( data.size == 0 )
126
+
127
+ if( data.size != 0 )
128
+
129
+ _d = []
130
+ data.each do |k,v|
131
+ _d << playlist( k['id'] )
132
+ end
133
+ return { 'status' => status, 'playlists' => _d }
134
+ end
135
+ # return { 'status' => 200, 'message' => data } if( data.size != 0 )
136
+ end
137
+
138
+ raise format('playlist id can not be 0') if( playlist_id.zero? )
139
+
140
+ endpoint = format('/api/playlists/%d', playlist_id )
141
+
142
+ @logger.debug("Attempting to get existing playlist id #{playlist_id} (GET #{endpoint})") if @debug
143
+
144
+ result = get(endpoint)
145
+
146
+ return { 'status' => 404, 'message' => 'playlist is empty', 'items' => [] } if( result.dig('status') == 404 )
147
+
148
+ return result
149
+ end
150
+
151
+ ### Get Playlist items
152
+
153
+ #`GET /api/playlists/:id/items`
154
+ #
155
+ #**Example Request**:
156
+ #
157
+ #```bash
158
+ #GET /api/playlists/1/items HTTP/1.1
159
+ #Accept: application/json
160
+ #Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
161
+ #```
162
+ #
163
+ #**Example Response**:
164
+ #
165
+ #```json
166
+ #HTTP/1.1 200
167
+ #Content-Type: application/json
168
+ #[
169
+ # {
170
+ # "id": 1,
171
+ # "playlistId": 1,
172
+ # "type": "dashboard_by_id",
173
+ # "value": "3",
174
+ # "order": 1,
175
+ # "title":"my third dasboard"
176
+ # },
177
+ # {
178
+ # "id": 2,
179
+ # "playlistId": 1,
180
+ # "type": "dashboard_by_tag",
181
+ # "value": "myTag",
182
+ # "order": 2,
183
+ # "title":"my other dasboard"
184
+ # }
185
+ #]
186
+ #```
187
+
188
+ def playlist_items( playlist_id, multi_result = false )
189
+
190
+ if( playlist_id.is_a?(String) && playlist_id.is_a?(Integer) )
191
+ raise ArgumentError.new(format('wrong type. \'playlist_id\' must be an String (for an playlist name) or an Integer (for an playlist Id), given \'%s\'', playlist_id.class.to_s))
192
+ end
193
+ raise ArgumentError.new('missing \'playlist_id\'') if( playlist_id.size.zero? )
194
+
195
+ _playlists = playlists
196
+
197
+ begin
198
+ status = _playlists.dig('status')
199
+ message = _playlists.dig('message')
200
+
201
+ if( status == 200 )
202
+
203
+ data = message.select { |k| k['id'] == playlist_id } if( playlist_id.is_a?(Integer) )
204
+ data = message.select { |k| k['name'] == playlist_id } if( playlist_id.is_a?(String) )
205
+
206
+ return { 'status' => 404, 'message' => 'No Playlist found' } if( !data.is_a?(Array) || data.count == 0 || status.to_i != 200 )
207
+ return { 'status' => 404, 'message' => format('found %d playlists with name %s', data.count, playlist_id ) } if( data.count > 1 && multi_result == false )
208
+
209
+ id = data.first.dig('id')
210
+ else
211
+ return _playlists
212
+ end
213
+ rescue
214
+ return { 'status' => 404, 'message' => 'No Playlists found' } if( playlists.nil? || playlists == false || playlists.dig('status').to_i != 200 )
215
+ end
216
+
217
+ endpoint = "/api/playlists/#{id}/items"
218
+
219
+ result = get( endpoint )
220
+
221
+ return { 'status' => 404, 'message' => 'playlist is empty' } if( result.dig('status') == 404 )
222
+
223
+ return result
224
+ end
225
+
226
+ ### Get Playlist dashboards
227
+ #
228
+ #`GET /api/playlists/:id/dashboards`
229
+ #
230
+ #**Example Request**:
231
+ #
232
+ #```bash
233
+ #GET /api/playlists/1/dashboards HTTP/1.1
234
+ #Accept: application/json
235
+ #Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
236
+ #```
237
+ #
238
+ #**Example Response**:
239
+ #
240
+ #```json
241
+ #HTTP/1.1 200
242
+ #Content-Type: application/json
243
+ #[
244
+ # {
245
+ # "id": 3,
246
+ # "title": "my third dasboard",
247
+ # "order": 1,
248
+ # },
249
+ # {
250
+ # "id": 5,
251
+ # "title":"my other dasboard"
252
+ # "order": 2,
253
+ #
254
+ # }
255
+ #]
256
+ #```
257
+
258
+ def playlist_dashboards( playlist_id )
259
+
260
+ raise ArgumentError.new(format('wrong type. \'playlist_id\' must be an Integer, given \'%s\'', playlist_id.class)) unless( playlist_id.is_a?(Integer) )
261
+ raise ArgumentError.new('missing \'playlist_id\'') if( playlist_id.size.zero? )
262
+
263
+ endpoint = format('/api/playlists/%s/dashboards', playlist_id)
264
+
265
+ @logger.debug( "Attempting to get playlist (GET #{endpoint})" ) if @debug
266
+ get(endpoint)
267
+ end
268
+
269
+ # Create a playlist
270
+
271
+ # `POST /api/playlists/`
272
+ #
273
+ #**Example Request**:
274
+ #
275
+ #```bash
276
+ #PUT /api/playlists/1 HTTP/1.1
277
+ #Accept: application/json
278
+ #Content-Type: application/json
279
+ #Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
280
+ # {
281
+ # "name": "my playlist",
282
+ # "interval": "5m",
283
+ # "items": [
284
+ # {
285
+ # "type": "dashboard_by_id",
286
+ # "value": "3",
287
+ # "order": 1,
288
+ # "title":"my third dasboard"
289
+ # },
290
+ # {
291
+ # "type": "dashboard_by_tag",
292
+ # "value": "myTag",
293
+ # "order": 2,
294
+ # "title":"my other dasboard"
295
+ # }
296
+ # ]
297
+ # }
298
+ #```
299
+ #
300
+ #**Example Response**:
301
+ #
302
+ #```json
303
+ #HTTP/1.1 200
304
+ #Content-Type: application/json
305
+ # {
306
+ # "id": 1,
307
+ # "name": "my playlist",
308
+ # "interval": "5m"
309
+ # }
310
+ #```
311
+
312
+ def create_playlist( params )
313
+
314
+ raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
315
+ raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
316
+
317
+ # v, mv = version.values
318
+ # return { 'status' => 404, 'message' => format( 'folder has been supported in Grafana since version 5. you use version %s', v) } if(mv < 5)
319
+
320
+ name = validate( params, required: true , var: 'name' , type: String )
321
+ interval = validate( params, required: true , var: 'interval' , type: String )
322
+ items = validate( params, required: true , var: 'items' , type: Array )
323
+
324
+ return { 'status' => 404, 'message' => 'There are no elements for a playlist' } if(items.count == 0)
325
+
326
+ payload_items = create_playlist_items(items)
327
+
328
+ payload = {
329
+ name: name,
330
+ interval: interval,
331
+ items: payload_items
332
+ }
333
+ payload.reject!{ |_k, v| v.nil? }
334
+
335
+ endpoint = '/api/playlists'
336
+
337
+ post(endpoint, payload.to_json)
338
+ end
339
+
340
+ ### Update a playlist
341
+ #
342
+ #`PUT /api/playlists/:id`
343
+ #
344
+ #**Example Request**:
345
+ #
346
+ #```bash
347
+ #PUT /api/playlists/1 HTTP/1.1
348
+ #Accept: application/json
349
+ #Content-Type: application/json
350
+ #Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
351
+ # {
352
+ # "name": "my playlist",
353
+ # "interval": "5m",
354
+ # "items": [
355
+ # {
356
+ # "playlistId": 1,
357
+ # "type": "dashboard_by_id",
358
+ # "value": "3",
359
+ # "order": 1,
360
+ # "title":"my third dasboard"
361
+ # },
362
+ # {
363
+ # "playlistId": 1,
364
+ # "type": "dashboard_by_tag",
365
+ # "value": "myTag",
366
+ # "order": 2,
367
+ # "title":"my other dasboard"
368
+ # }
369
+ # ]
370
+ # }
371
+ #```
372
+ #
373
+ #**Example Response**:
374
+ #
375
+ #```json
376
+ #HTTP/1.1 200
377
+ #Content-Type: application/json
378
+ #{
379
+ # "id" : 1,
380
+ # "name": "my playlist",
381
+ # "interval": "5m",
382
+ # "orgId": "my org",
383
+ # "items": [
384
+ # {
385
+ # "id": 1,
386
+ # "playlistId": 1,
387
+ # "type": "dashboard_by_id",
388
+ # "value": "3",
389
+ # "order": 1,
390
+ # "title":"my third dasboard"
391
+ # },
392
+ # {
393
+ # "id": 2,
394
+ # "playlistId": 1,
395
+ # "type": "dashboard_by_tag",
396
+ # "value": "myTag",
397
+ # "order": 2,
398
+ # "title":"my other dasboard"
399
+ # }
400
+ # ]
401
+ #}
402
+ #```
403
+
404
+ def update_playlist( params )
405
+
406
+ raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
407
+ raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
408
+
409
+ playlist_id = validate( params, required: true , var: 'playlist' )
410
+ name = validate( params, required: false, var: 'name' )
411
+ interval = validate( params, required: false, var: 'interval', type: String )
412
+ # organisation = validate( params, required: false, var: 'organisation' )
413
+ items = validate( params, required: false, var: 'items', type: Array )
414
+
415
+ _playlists = playlists
416
+
417
+ data = []
418
+
419
+ begin
420
+ status = _playlists.dig('status')
421
+ message = _playlists.dig('message')
422
+
423
+ if( status == 200 )
424
+ data = message.select { |k| k['id'] == playlist_id } if( playlist_id.is_a?(Integer) )
425
+ data = message.select { |k| k['name'] == playlist_id } if( playlist_id.is_a?(String) )
426
+
427
+ return { 'status' => 404, 'message' => 'no playlist found' } if( !data.is_a?(Array) || data.count == 0 || status.to_i != 200 )
428
+ return { 'status' => 404, 'message' => format('found %d playlists with name %s', data.count, playlist_id ) } if( data.count > 1 && multi_result == false )
429
+ else
430
+ return _playlists
431
+ end
432
+ rescue
433
+ return { 'status' => 404, 'message' => 'no playlists found' } if( playlists.nil? || playlists == false || playlists.dig('status').to_i != 200 )
434
+ end
435
+
436
+ playlist_id = data.first.dig('id')
437
+ playlist_name = data.first.dig('name')
438
+ payload_items = create_playlist_items(items, playlist_id)
439
+
440
+ payload = {
441
+ id: playlist_id,
442
+ name: name,
443
+ interval: interval,
444
+ items: payload_items
445
+ }
446
+ payload.reject!{ |_k, v| v.nil? }
447
+
448
+ endpoint = format( '/api/playlists/%d', playlist_id )
449
+
450
+ put( endpoint, payload.to_json )
451
+
452
+ end
453
+
454
+
455
+ ### Delete a playlist
456
+ #
457
+ #`DELETE /api/playlists/:id`
458
+ #
459
+ #**Example Request**:
460
+ #
461
+ #```bash
462
+ #DELETE /api/playlists/1 HTTP/1.1
463
+ #Accept: application/json
464
+ #Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
465
+ #```
466
+ #
467
+ #**Example Response**:
468
+ #
469
+ #```json
470
+ #HTTP/1.1 200
471
+ #Content-Type: application/json
472
+ #{}
473
+ #```
474
+
475
+ def delete_playlist(playlist_id, multi_result = false )
476
+
477
+ if( playlist_id.is_a?(String) && playlist_id.is_a?(Integer) )
478
+ raise ArgumentError.new(format('wrong type. \'playlist_id\' must be an String (for an Playlist name) or an Integer (for an Playlist Id), given \'%s\'', playlist_id.class.to_s))
479
+ end
480
+ raise ArgumentError.new('missing \'playlist_id\'') if( playlist_id.size.zero? )
481
+
482
+ _playlists = playlists
483
+
484
+ data = []
485
+
486
+ begin
487
+ status = _playlists.dig('status')
488
+ message = _playlists.dig('message')
489
+
490
+ if( status == 200 )
491
+
492
+ data = message.select { |k| k['id'] == playlist_id } if( playlist_id.is_a?(Integer) )
493
+ data = message.select { |k| k['name'] == playlist_id } if( playlist_id.is_a?(String) )
494
+
495
+ return { 'status' => 404, 'message' => 'no playlist found' } if( !data.is_a?(Array) || data.count == 0 || status.to_i != 200 )
496
+ return { 'status' => 404, 'message' => format('found %d playlists with name %s', data.count, playlist_id ) } if( data.count > 1 && multi_result == false )
497
+ else
498
+ return _playlists
499
+ end
500
+ rescue
501
+ return { 'status' => 404, 'message' => 'no playlists found' } if( playlists.nil? || playlists == false || playlists.dig('status').to_i != 200 )
502
+ end
503
+
504
+ if( multi_result == true )
505
+
506
+ result = { 'status' => 0, 'message' => 'under development' }
507
+ data.each do |x|
508
+
509
+ endpoint = format( '/api/playlists/%d', x.dig('id') )
510
+
511
+ begin
512
+ result = delete( endpoint )
513
+ rescue => error
514
+ logger.error( "error: #{error}" )
515
+ end
516
+ end
517
+
518
+ return result
519
+ else
520
+
521
+ playlist_id = data.first.dig('id')
522
+
523
+ endpoint = format( '/api/playlists/%d', playlist_id )
524
+
525
+ result = delete( endpoint )
526
+
527
+ if(result.dig('status').to_i == 500)
528
+ # check if the playlist exists
529
+ r = playlist( playlist_id )
530
+ return { 'status' => 200, 'message' => 'playlist deleted' } if(r.dig('status').to_i == 404)
531
+ end
532
+
533
+ return result
534
+ end
535
+
536
+ end
537
+
538
+
539
+ private
540
+ def create_playlist_items( items, playlistId = nil)
541
+
542
+ _items = []
543
+
544
+ items.each do |r|
545
+ _element = {}
546
+
547
+ if( r['name'] )
548
+
549
+ _name = search_dashboards( query: r['name'] )
550
+ _name_status = _name.dig('status')
551
+
552
+ next unless( _name_status == 200 )
553
+
554
+ _name = _name.dig('message')
555
+ _name_id = _name.first.dig('id')
556
+ _name_title = _name.first.dig('title')
557
+
558
+ _element[:type] = 'dashboard_by_id'
559
+ _element[:value] = _name_id.to_s
560
+ _element[:title] = _name_title
561
+ _element[:playlistId] = playlistId unless(playlistId.nil?)
562
+
563
+ elsif( r['id'] )
564
+
565
+ _uid = dashboard_by_uid(r['id'])
566
+ _uid_status = _uid.dig('status')
567
+
568
+ next unless( _uid_status == 200 )
569
+
570
+ _element[:type] = 'dashboard_by_id'
571
+ _element[:value] = r['id']
572
+ _element[:playlistId] = playlistId unless(playlistId.nil?)
573
+
574
+ elsif( r['tag'] )
575
+
576
+ _tags = search_dashboards( tags: r['tag'] )
577
+ _tags_status = _tags.dig('status')
578
+
579
+ next unless( _tags_status == 200 )
580
+
581
+ _element[:type] = 'dashboard_by_tag'
582
+ _element[:value] = r['tag']
583
+ _element[:title] = r['tag']
584
+ _element[:playlistId] = playlistId unless(playlistId.nil?)
585
+
586
+ else
587
+ next
588
+ end
589
+
590
+ _element[:order] = r['order'] if(r['order'])
591
+
592
+ _items << _element if(_element.count >= 4)
593
+ end
594
+
595
+ _items
596
+ end
597
+
598
+ end
599
+ end