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.
- checksums.yaml +5 -5
- data/README.md +8 -3
- data/lib/grafana/admin.rb +39 -65
- data/lib/grafana/alerts.rb +334 -14
- data/lib/grafana/annotations.rb +284 -9
- data/lib/grafana/client.rb +38 -1
- data/lib/grafana/dashboard.rb +182 -39
- data/lib/grafana/dashboard_permissions.rb +132 -0
- data/lib/grafana/dashboard_versions.rb +101 -5
- data/lib/grafana/datasource.rb +93 -49
- data/lib/grafana/folder.rb +198 -0
- data/lib/grafana/folder_and_dashboard_search.rb +57 -0
- data/lib/grafana/folder_permissions.rb +155 -0
- data/lib/grafana/login.rb +41 -35
- data/lib/grafana/network.rb +128 -91
- data/lib/grafana/organization.rb +65 -34
- data/lib/grafana/organizations.rb +119 -175
- data/lib/grafana/playlist.rb +599 -0
- data/lib/grafana/preferences.rb +122 -0
- data/lib/grafana/tags.rb +19 -8
- data/lib/grafana/teams.rb +364 -0
- data/lib/grafana/tools.rb +44 -12
- data/lib/grafana/user.rb +78 -39
- data/lib/grafana/users.rb +104 -53
- data/lib/grafana/validator.rb +47 -2
- data/lib/grafana/version.rb +3 -3
- metadata +13 -38
- data/doc/Array.html +0 -200
- data/doc/Boolean.html +0 -122
- data/doc/FalseClass.html +0 -132
- data/doc/Grafana.html +0 -172
- data/doc/Hash.html +0 -212
- data/doc/Logging.html +0 -326
- data/doc/Object.html +0 -286
- data/doc/Time.html +0 -200
- data/doc/TrueClass.html +0 -132
- data/doc/_index.html +0 -380
- data/doc/class_list.html +0 -51
- data/doc/file.README.html +0 -117
- data/doc/file_list.html +0 -56
- data/doc/frames.html +0 -17
- data/doc/index.html +0 -117
- data/doc/method_list.html +0 -771
- data/doc/top-level-namespace.html +0 -112
data/lib/grafana/annotations.rb
CHANGED
@@ -1,39 +1,314 @@
|
|
1
1
|
|
2
2
|
module Grafana
|
3
3
|
|
4
|
-
#
|
4
|
+
# This is the API documentation for the new Grafana Annotations feature released in Grafana 4.6.
|
5
|
+
# Annotations are saved in the Grafana database (sqlite, mysql or postgres).
|
6
|
+
#
|
7
|
+
# Annotations can be global annotations that can be shown on any dashboard by configuring an annotation
|
8
|
+
# data source - they are filtered by tags.
|
9
|
+
#
|
10
|
+
# Or they can be tied to a panel on a dashboard and are then only shown on that panel.
|
11
|
+
#
|
12
|
+
# original API Documentation can be found under: http://docs.grafana.org/http_api/annotations/
|
5
13
|
#
|
6
14
|
module Annotations
|
7
15
|
|
8
16
|
# Find Annotations
|
9
17
|
# http://docs.grafana.org/http_api/annotations/#find-annotations
|
10
|
-
#
|
11
|
-
|
18
|
+
#
|
19
|
+
# @param [Hash] params
|
20
|
+
# @option params [Integer] from: epoch datetime in milliseconds. Optional.
|
21
|
+
# @option params [Integer] to: epoch datetime in milliseconds. Optional.
|
22
|
+
# @option params [Integer] limit: number. Optional - default is 10. Max limit for results returned.
|
23
|
+
# @option params [Integer] alert_id: number. Optional. Find annotations for a specified alert.
|
24
|
+
# @option params [Mixed] dashboard: number. Optional. Find annotations that are scoped to a specific dashboard
|
25
|
+
# @option params [Integer] panel_id: number. Optional. Find annotations that are scoped to a specific panel
|
26
|
+
# @option params [Array] tags: Optional. Use this to filter global annotations.
|
27
|
+
# Global annotations are annotations from an annotation data source that are not connected specifically to a dashboard or panel.
|
28
|
+
# To do an "AND" filtering with multiple tags, specify the tags parameter multiple times e.g.
|
29
|
+
#
|
30
|
+
# @example
|
31
|
+
# params = {
|
32
|
+
# limit: 5,
|
33
|
+
# tags: [ 'spec', 'test' ]
|
34
|
+
# }
|
35
|
+
# find_annotation( params )
|
36
|
+
#
|
37
|
+
# @return [Array]
|
38
|
+
#
|
39
|
+
def find_annotation( params )
|
40
|
+
|
41
|
+
raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
|
42
|
+
raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
|
43
|
+
|
44
|
+
dashboard = validate( params, required: false, var: 'dashboard' )
|
45
|
+
from = validate( params, required: false, var: 'from', type: Integer )
|
46
|
+
to = validate( params, required: false, var: 'to', type: Integer )
|
47
|
+
limit = validate( params, required: false, var: 'limit', type: Integer ) || 10
|
48
|
+
alert_id = validate( params, required: false, var: 'alert_id', type: Integer )
|
49
|
+
panel_id = validate( params, required: false, var: 'panel_id', type: Integer )
|
50
|
+
tags = validate( params, required: false, var: 'tags', type: Array )
|
51
|
+
|
52
|
+
if( dashboard.is_a?(String) )
|
53
|
+
|
54
|
+
dashboard = search_dashboards( query: dashboard )
|
55
|
+
|
56
|
+
return { 'status' => 404, 'message' => format( 'No Dashboard \'%s\' found', dashboard) } if( dashboard.nil? || dashboard.dig('status').to_i != 200 )
|
57
|
+
|
58
|
+
dashboard = dashboard.dig('message').first unless( dashboard.nil? && dashboard.dig('status').to_i == 200 )
|
59
|
+
dashboard = dashboard.dig('id') unless( dashboard.nil? )
|
60
|
+
|
61
|
+
return { 'status' => 404, 'message' => format( 'No Dashboard \'%s\' found', dashboard) } if( dashboard.nil? )
|
62
|
+
end
|
63
|
+
|
64
|
+
api = []
|
65
|
+
api << format( 'from=%s', from ) unless( from.nil? )
|
66
|
+
api << format( 'to=%s', to ) unless( to.nil? )
|
67
|
+
api << format( 'limit=%s', limit ) unless( limit.nil? )
|
68
|
+
api << format( 'alertId=%s', alert_id ) unless( alert_id.nil? )
|
69
|
+
api << format( 'panelId=%s', panel_id ) unless( panel_id.nil? )
|
70
|
+
api << format( 'dashboardId=%s', dashboard ) unless( dashboard.nil? )
|
71
|
+
|
72
|
+
unless( tags.nil? )
|
73
|
+
tags = tags.join( '&tags=' ) if( tags.is_a?( Array ) )
|
74
|
+
api << format( 'tags=%s', tags )
|
75
|
+
end
|
76
|
+
api = api.join( '&' )
|
77
|
+
|
78
|
+
endpoint = format( '/api/annotations/?%s' , api )
|
79
|
+
|
80
|
+
@logger.debug("Attempting to search for annotations (GET #{endpoint})") if @debug
|
81
|
+
|
82
|
+
get( endpoint )
|
83
|
+
end
|
12
84
|
|
13
85
|
# Create Annotation
|
86
|
+
#
|
87
|
+
# Creates an annotation in the Grafana database.
|
88
|
+
# The dashboard_id and panel_id fields are optional.
|
89
|
+
# If they are not specified then a global annotation is created and can be queried in any dashboard that adds
|
90
|
+
# the Grafana annotations data source.
|
91
|
+
#
|
92
|
+
# When creating a region annotation the response will include both id and endId, if not only id.
|
93
|
+
#
|
14
94
|
# http://docs.grafana.org/http_api/annotations/#create-annotation
|
15
95
|
# POST /api/annotations
|
16
|
-
|
96
|
+
#
|
97
|
+
#
|
98
|
+
# @param [Hash] params
|
99
|
+
# @option params [Mixed] dashboard
|
100
|
+
# @option params [Integer] panel_id
|
101
|
+
# @option params [Integer] time:
|
102
|
+
# @option params [Integer] time_end:
|
103
|
+
# @option params [Boolean] region:
|
104
|
+
# @option params [Array] tags:
|
105
|
+
# @option params [String] text:
|
106
|
+
#
|
107
|
+
# @example
|
108
|
+
# params = {
|
109
|
+
# time: Time.now.to_i,
|
110
|
+
# tags: [ 'spec', 'test' ],
|
111
|
+
# text: 'test annotation'
|
112
|
+
# }
|
113
|
+
# create_annotation( params )
|
114
|
+
#
|
115
|
+
# @return [Hash]
|
116
|
+
#
|
117
|
+
def create_annotation( params )
|
118
|
+
|
119
|
+
raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
|
120
|
+
raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
|
121
|
+
|
122
|
+
dashboard = validate( params, required: false, var: 'dashboard' )
|
123
|
+
panel_id = validate( params, required: false, var: 'panel_id', type: Integer )
|
124
|
+
time = validate( params, required: false, var: 'time', type: Integer ) || Time.now.to_i
|
125
|
+
time_end = validate( params, required: false, var: 'time_end', type: Integer )
|
126
|
+
region = validate( params, required: false, var: 'region', type: Boolean )
|
127
|
+
tags = validate( params, required: true, var: 'tags', type: Array )
|
128
|
+
text = validate( params, required: true, var: 'text', type: String )
|
129
|
+
|
130
|
+
if( dashboard.is_a?(String) )
|
131
|
+
|
132
|
+
dashboard = search_dashboards( query: dashboard )
|
133
|
+
|
134
|
+
return { 'status' => 404, 'message' => format( 'No Dashboard \'%s\' found', dashboard) } if( dashboard.nil? || dashboard.dig('status').to_i != 200 )
|
135
|
+
|
136
|
+
dashboard = dashboard.dig('message').first unless( dashboard.nil? && dashboard.dig('status').to_i == 200 )
|
137
|
+
dashboard = dashboard.dig('id') unless( dashboard.nil? )
|
138
|
+
|
139
|
+
return { 'status' => 404, 'message' => format( 'No Dashboard \'%s\' found', dashboard) } if( dashboard.nil? )
|
140
|
+
end
|
141
|
+
|
142
|
+
unless( time_end.nil? )
|
143
|
+
return { 'status' => 404, 'message' => format( '\'end_time\' can\'t be lower then \'time\'' ) } if( time_end < time )
|
144
|
+
end
|
145
|
+
|
146
|
+
endpoint = '/api/annotations'
|
147
|
+
payload = {
|
148
|
+
dashboardId: dashboard,
|
149
|
+
panelId: panel_id,
|
150
|
+
time: time,
|
151
|
+
timeEnd: time_end,
|
152
|
+
isRegion: region,
|
153
|
+
tags: tags,
|
154
|
+
text: text
|
155
|
+
}
|
156
|
+
payload.reject!{ |_k, v| v.nil? }
|
157
|
+
|
158
|
+
post(endpoint, payload.to_json)
|
159
|
+
end
|
17
160
|
|
18
161
|
# Create Annotation in Graphite format
|
162
|
+
#
|
163
|
+
# Creates an annotation by using Graphite-compatible event format.
|
164
|
+
# The when and data fields are optional.
|
165
|
+
# If when is not specified then the current time will be used as annotation's timestamp.
|
166
|
+
# The tags field can also be in prior to Graphite 0.10.0 format (string with multiple tags being separated by a space).
|
167
|
+
#
|
19
168
|
# http://docs.grafana.org/http_api/annotations/#create-annotation-in-graphite-format
|
20
169
|
# POST /api/annotations/graphite
|
21
|
-
|
170
|
+
#
|
171
|
+
# @param [Hash] params
|
172
|
+
# @option params [Integer] what
|
173
|
+
# @option params [Integer] when
|
174
|
+
# @option params [Array] tags
|
175
|
+
# @option params [String] data
|
176
|
+
#
|
177
|
+
# @example
|
178
|
+
# params = {
|
179
|
+
# what: 'spec test graphite annotation',
|
180
|
+
# when: Time.now.to_i,
|
181
|
+
# tags: [ 'spec', 'test' ],
|
182
|
+
# data: 'test annotation'
|
183
|
+
# }
|
184
|
+
# create_annotation_graphite( params )
|
185
|
+
#
|
186
|
+
# @return [Hash]
|
187
|
+
#
|
188
|
+
def create_annotation_graphite( params )
|
189
|
+
|
190
|
+
raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
|
191
|
+
raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
|
192
|
+
|
193
|
+
what = validate( params, required: true , var: 'what', type: String )
|
194
|
+
time_when = validate( params, required: false, var: 'when', type: Integer ) || Time.now.to_i
|
195
|
+
tags = validate( params, required: true , var: 'tags', type: Array )
|
196
|
+
data = validate( params, required: false, var: 'data', type: String )
|
197
|
+
|
198
|
+
endpoint = '/api/annotations/graphite'
|
199
|
+
payload = {
|
200
|
+
what: what,
|
201
|
+
when: time_when,
|
202
|
+
tags: tags,
|
203
|
+
data: data
|
204
|
+
}
|
205
|
+
payload.reject!{ |_k, v| v.nil? }
|
206
|
+
|
207
|
+
post(endpoint, payload.to_json)
|
208
|
+
end
|
22
209
|
|
23
210
|
# Update Annotation
|
211
|
+
#
|
24
212
|
# http://docs.grafana.org/http_api/annotations/#update-annotation
|
25
|
-
#
|
26
|
-
|
213
|
+
#
|
214
|
+
# @param [Hash] params
|
215
|
+
# @option params [Integer] annotation
|
216
|
+
# @option params [Integer] time
|
217
|
+
# @option params [Integer] time_end
|
218
|
+
# @option params [Boolean] region
|
219
|
+
# @option params [Array] tags
|
220
|
+
# @option params [String] text
|
221
|
+
#
|
222
|
+
# @example
|
223
|
+
# params = {
|
224
|
+
# annotation: 1,
|
225
|
+
# tags: [ 'deployment' ],
|
226
|
+
# text: 'git tag #1234'
|
227
|
+
# }
|
228
|
+
# update_annotation( params )
|
229
|
+
#
|
230
|
+
# @return [Hash]
|
231
|
+
#
|
232
|
+
def update_annotation( params )
|
233
|
+
|
234
|
+
raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
|
235
|
+
raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
|
236
|
+
|
237
|
+
annotation_id = validate( params, required: true, var: 'annotation', type: Integer )
|
238
|
+
time = validate( params, required: false, var: 'time', type: Integer )
|
239
|
+
time_end = validate( params, required: false, var: 'time_end', type: Integer )
|
240
|
+
region = validate( params, required: false, var: 'region', type: Boolean )
|
241
|
+
tags = validate( params, required: false, var: 'tags', type: Array )
|
242
|
+
text = validate( params, required: false, var: 'text', type: String )
|
243
|
+
|
244
|
+
unless( time_end.nil? )
|
245
|
+
return { 'status' => 404, 'message' => format( '\'end_time\' can\'t be lower then \'time\'' ) } if( time_end < time )
|
246
|
+
end
|
247
|
+
|
248
|
+
endpoint = format( '/api/annotations/%d', annotation_id)
|
249
|
+
payload = {
|
250
|
+
time: time,
|
251
|
+
timeEnd: time_end,
|
252
|
+
isRegion: region,
|
253
|
+
text: text,
|
254
|
+
tags: tags
|
255
|
+
}
|
256
|
+
payload.reject!{ |_k, v| v.nil? }
|
257
|
+
|
258
|
+
put(endpoint, payload.to_json)
|
259
|
+
end
|
27
260
|
|
28
261
|
# Delete Annotation By Id
|
262
|
+
#
|
263
|
+
# Deletes the annotation that matches the specified id.
|
264
|
+
#
|
29
265
|
# http://docs.grafana.org/http_api/annotations/#delete-annotation-by-id
|
30
266
|
# DELETE /api/annotation/:id
|
31
|
-
|
267
|
+
#
|
268
|
+
# @param [Integer] annotation_id
|
269
|
+
#
|
270
|
+
# @example
|
271
|
+
# delete_annotation( 1 )
|
272
|
+
#
|
273
|
+
# @return [Hash]
|
274
|
+
#
|
275
|
+
def delete_annotation( annotation_id )
|
276
|
+
|
277
|
+
raise ArgumentError.new(format('wrong type. user \'annotation_id\' must be an Integer, given \'%s\'', annotation_id.class.to_s)) unless( annotation_id.is_a?(Integer) )
|
278
|
+
raise ArgumentError.new('missing \'annotation_id\'') if( annotation_id.size.zero? )
|
279
|
+
raise ArgumentError.new('\'annotation_id\' can not be 0') if( annotation_id.zero? )
|
280
|
+
|
281
|
+
endpoint = format( '/api/annotation/%d', annotation_id )
|
282
|
+
|
283
|
+
delete(endpoint)
|
284
|
+
end
|
32
285
|
|
33
286
|
# Delete Annotation By RegionId
|
287
|
+
#
|
288
|
+
# Deletes the annotation that matches the specified region id.
|
289
|
+
# A region is an annotation that covers a timerange and has a start and end time.
|
290
|
+
# In the Grafana database, this is a stored as two annotations connected by a region id.
|
291
|
+
#
|
34
292
|
# http://docs.grafana.org/http_api/annotations/#delete-annotation-by-regionid
|
35
293
|
# DELETE /api/annotation/region/:id
|
36
|
-
|
294
|
+
#
|
295
|
+
# @param [Integer] region_id
|
296
|
+
#
|
297
|
+
# @example
|
298
|
+
# delete_annotation_by_region( 1 )
|
299
|
+
#
|
300
|
+
# @return [Hash]
|
301
|
+
#
|
302
|
+
def delete_annotation_by_region( region_id )
|
303
|
+
|
304
|
+
raise ArgumentError.new(format('wrong type. user \'region_id\' must be an Integer, given \'%s\'', region_id.class.to_s)) unless( region_id.is_a?(Integer) )
|
305
|
+
raise ArgumentError.new('missing \'region_id\'') if( region_id.size.zero? )
|
306
|
+
# raise ArgumentError.new('\'region_id\' can not be 0') if( region_id.zero? )
|
307
|
+
|
308
|
+
endpoint = format( '/api/annotation/region/%d', region_id )
|
309
|
+
|
310
|
+
delete(endpoint)
|
311
|
+
end
|
37
312
|
|
38
313
|
end
|
39
314
|
|
data/lib/grafana/client.rb
CHANGED
@@ -12,14 +12,22 @@ require_relative 'network'
|
|
12
12
|
require_relative 'tools'
|
13
13
|
require_relative 'admin'
|
14
14
|
require_relative 'annotations'
|
15
|
+
require_relative 'preferences'
|
15
16
|
require_relative 'user'
|
16
17
|
require_relative 'users'
|
18
|
+
require_relative 'teams'
|
17
19
|
require_relative 'datasource'
|
18
20
|
require_relative 'organization'
|
19
21
|
require_relative 'organizations'
|
20
22
|
require_relative 'dashboard'
|
21
23
|
require_relative 'dashboard_versions'
|
24
|
+
require_relative 'dashboard_permissions'
|
22
25
|
require_relative 'snapshot'
|
26
|
+
require_relative 'alerts'
|
27
|
+
require_relative 'folder'
|
28
|
+
require_relative 'folder_permissions'
|
29
|
+
require_relative 'folder_and_dashboard_search'
|
30
|
+
require_relative 'playlist'
|
23
31
|
|
24
32
|
# -------------------------------------------------------------------------------------------------------------------
|
25
33
|
#
|
@@ -46,14 +54,22 @@ module Grafana
|
|
46
54
|
include Grafana::Tools
|
47
55
|
include Grafana::Admin
|
48
56
|
include Grafana::Annotations
|
57
|
+
include Grafana::Preferences
|
49
58
|
include Grafana::User
|
50
59
|
include Grafana::Users
|
60
|
+
include Grafana::Teams
|
51
61
|
include Grafana::Datasource
|
52
62
|
include Grafana::Organization
|
53
63
|
include Grafana::Organizations
|
54
64
|
include Grafana::Dashboard
|
55
65
|
include Grafana::DashboardVersions
|
66
|
+
include Grafana::DashboardPermissions
|
56
67
|
include Grafana::Snapshot
|
68
|
+
include Grafana::Alerts
|
69
|
+
include Grafana::Folder
|
70
|
+
include Grafana::FolderPermissions
|
71
|
+
include Grafana::FolderSearch
|
72
|
+
include Grafana::Playlist
|
57
73
|
|
58
74
|
attr_accessor :debug
|
59
75
|
|
@@ -98,6 +114,8 @@ module Grafana
|
|
98
114
|
@http_headers = settings.dig(:grafana, :http_headers) || {}
|
99
115
|
@debug = settings.dig(:debug) || false
|
100
116
|
|
117
|
+
@headers = {}
|
118
|
+
|
101
119
|
raise ArgumentError.new('missing \'host\'') if( host.nil? )
|
102
120
|
|
103
121
|
raise ArgumentError.new(format('wrong type. \'port\' must be an Integer, given \'%s\'', port.class.to_s)) unless( port.is_a?(Integer) )
|
@@ -107,11 +125,30 @@ module Grafana
|
|
107
125
|
raise ArgumentError.new(format('wrong type. \'open_timeout\' must be an Integer, given \'%s\'', @open_timeout.class.to_s)) unless( @open_timeout.is_a?(Integer) )
|
108
126
|
|
109
127
|
protocoll = ssl == true ? 'https' : 'http'
|
110
|
-
raise ArgumentError.new(format('wrong \'protocoll\'. only \'http\' or \'https\' allowed, given \'%s\'', protocoll)) if( %w[http https].include?(protocoll.downcase) == false )
|
111
128
|
|
112
129
|
@url = format( '%s://%s:%d%s', protocoll, host, port, url_path )
|
113
130
|
end
|
114
131
|
|
132
|
+
# Get Settings
|
133
|
+
#
|
134
|
+
# http://docs.grafana.org/http_api/other/#get-settings
|
135
|
+
#
|
136
|
+
def settings
|
137
|
+
endpoint = '/api/frontend/settings'
|
138
|
+
@logger.debug("Getting all settings (GET #{endpoint})") if @debug
|
139
|
+
get(endpoint)
|
140
|
+
end
|
141
|
+
|
142
|
+
|
143
|
+
def version
|
144
|
+
s = settings
|
145
|
+
@version = s.dig('buildInfo','version')
|
146
|
+
@major_version = @version.split('.').first.to_i
|
147
|
+
|
148
|
+
{version: @version, major_version: @major_version}
|
149
|
+
end
|
150
|
+
|
151
|
+
|
115
152
|
def self.logger
|
116
153
|
@@logger ||= defined?(Logging) ? Logging.logger : Logger.new(STDOUT)
|
117
154
|
end
|
data/lib/grafana/dashboard.rb
CHANGED
@@ -2,59 +2,186 @@
|
|
2
2
|
module Grafana
|
3
3
|
|
4
4
|
# http://docs.grafana.org/http_api/dashboard/
|
5
|
+
|
6
|
+
# The identifier (id) of a dashboard is an auto-incrementing numeric value and is only unique per Grafana install.
|
7
|
+
#
|
8
|
+
# The unique identifier (uid) of a dashboard can be used for uniquely identify a dashboard between multiple Grafana installs.
|
9
|
+
# It's automatically generated if not provided when creating a dashboard. The uid allows having consistent URL's for
|
10
|
+
# accessing dashboards and when syncing dashboards between multiple Grafana installs, see dashboard provisioning for
|
11
|
+
# more information. This means that changing the title of a dashboard will not break any bookmarked links to that dashboard.
|
12
|
+
#
|
13
|
+
# The uid can have a maximum length of 40 characters.
|
14
|
+
#
|
15
|
+
# Deprecated resources
|
16
|
+
# Please note that these resource have been deprecated and will be removed in a future release.
|
17
|
+
#
|
18
|
+
# - Get dashboard by slug
|
19
|
+
# - Delete dashboard by slug
|
20
|
+
#
|
21
|
+
#
|
5
22
|
#
|
6
23
|
module Dashboard
|
7
24
|
|
8
|
-
|
25
|
+
# http://docs.grafana.org/http_api/dashboard/#get-dashboard-by-slug
|
26
|
+
# - Deprecated starting from Grafana v5.0.
|
27
|
+
# Please update to use the new Get dashboard by uid resource instead
|
28
|
+
#
|
9
29
|
# Get dashboard
|
10
|
-
#
|
30
|
+
#
|
31
|
+
# Will return the dashboard given the dashboard slug.
|
32
|
+
# Slug is the url friendly version of the dashboard title.
|
33
|
+
# If there exists multiple dashboards with the same slug, one of them will be returned in the response.
|
34
|
+
#
|
35
|
+
# @example
|
36
|
+
# dashboard('dashboard for many foo')
|
37
|
+
#
|
38
|
+
# @return [String]
|
39
|
+
#
|
11
40
|
def dashboard( name )
|
12
41
|
|
13
42
|
raise ArgumentError.new(format('wrong type. \'name\' must be an String, given \'%s\'', name.class.to_s)) unless( name.is_a?(String) )
|
14
43
|
raise ArgumentError.new('missing name') if( name.size.zero? )
|
15
44
|
|
16
|
-
#
|
45
|
+
# v, mv = version.values
|
46
|
+
#
|
47
|
+
# if( mv == 5)
|
48
|
+
# puts 'DEPRICATION WARNING'
|
49
|
+
# puts 'Grafana v5.0 use a new interal id/uid handling'
|
50
|
+
# puts 'This function works well with Grafana v4.x'
|
51
|
+
# end
|
17
52
|
|
18
53
|
endpoint = format( '/api/dashboards/db/%s', slug(name) )
|
54
|
+
@logger.debug( "Attempting to get dashboard (GET #{endpoint})" ) if @debug
|
19
55
|
|
20
|
-
|
56
|
+
get( endpoint )
|
57
|
+
end
|
58
|
+
|
59
|
+
# http://docs.grafana.org/http_api/dashboard/#get-dashboard-by-uid
|
60
|
+
#
|
61
|
+
# GET /api/dashboards/uid/:uid
|
62
|
+
# Will return the dashboard given the dashboard unique identifier (uid).
|
63
|
+
#
|
64
|
+
# Get dashboard
|
65
|
+
#
|
66
|
+
# Will return the dashboard given the dashboard unique identifier (uid).
|
67
|
+
#
|
68
|
+
# @example
|
69
|
+
# dashboard('L42r6NWiz')
|
70
|
+
#
|
71
|
+
# @return [String]
|
72
|
+
#
|
73
|
+
def dashboard_by_uid( uid )
|
74
|
+
|
75
|
+
if( uid.is_a?(String) && uid.is_a?(Integer) )
|
76
|
+
raise ArgumentError.new(format('wrong type. dashboard \'uid\' must be an String (for an title name) or an Integer (for an Datasource Id), given \'%s\'', uid.class.to_s))
|
77
|
+
end
|
78
|
+
raise ArgumentError.new('missing \'uid\'') if( uid.size.zero? )
|
79
|
+
|
80
|
+
v, mv = version.values
|
81
|
+
return { 'status' => 404, 'message' => format( 'uid has been supported in Grafana since version 5. you use version %s', v) } if(mv < 5)
|
82
|
+
|
83
|
+
return { 'status' => 404, 'message' => format( 'The uid can have a maximum length of 40 characters, but it is %s characters long', uid.length) } if( uid.length > 40 )
|
84
|
+
|
85
|
+
endpoint = format( '/api/dashboards/uid/%s', uid )
|
86
|
+
@logger.debug( "Attempting to get dashboard (GET #{endpoint})" ) if @debug
|
21
87
|
|
22
88
|
get( endpoint )
|
23
89
|
end
|
24
90
|
|
25
91
|
# Create / Update dashboard
|
92
|
+
#
|
93
|
+
# Creates a new dashboard or updates an existing dashboard.
|
94
|
+
#
|
95
|
+
# @param [Hash] params
|
96
|
+
# @option params [Hash] dashboard The complete dashboard model
|
97
|
+
# - dashboard.id - id = null to create a new dashboard.
|
98
|
+
# - dashboard.uid - Optional unique identifier when creating a dashboard. uid = null will generate a new uid.
|
99
|
+
# - folderId - The id of the folder to save the dashboard in.
|
100
|
+
# - overwrite - Set to true if you want to overwrite existing dashboard with newer version, same dashboard title in folder or same dashboard uid.
|
101
|
+
# - message - Set a commit message for the version history.
|
102
|
+
# @option params [Boolean] overwrite (true)
|
103
|
+
#
|
104
|
+
# @example
|
105
|
+
# params = {
|
106
|
+
# dashboard: {
|
107
|
+
# id: null,
|
108
|
+
# uid: null,
|
109
|
+
# title: 'Production Overview',
|
110
|
+
# tags: [ 'templated' ],
|
111
|
+
# timezone": 'browser',
|
112
|
+
# rows: [
|
113
|
+
# {
|
114
|
+
# }
|
115
|
+
# ],
|
116
|
+
# 'schemaVersion': 6,
|
117
|
+
# 'version': 0
|
118
|
+
# },
|
119
|
+
# folderId: 0,
|
120
|
+
# overwrite: false,
|
121
|
+
# message: 'created by foo'
|
122
|
+
# }
|
123
|
+
# create_dashboard( params )
|
124
|
+
#
|
125
|
+
# @return [Hash]
|
126
|
+
#
|
26
127
|
# POST /api/dashboards/db
|
27
128
|
def create_dashboard( params )
|
28
129
|
|
29
|
-
raise ArgumentError.new(format('wrong type. params must be an Hash, given %s', params.class.to_s
|
30
|
-
|
31
|
-
title = params.dig(:title)
|
32
|
-
dashboard = params.dig(:dashboard)
|
130
|
+
raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
|
131
|
+
raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
|
33
132
|
|
34
|
-
|
35
|
-
|
36
|
-
|
133
|
+
dashboard = validate( params, required: true , var: 'dashboard', type: Hash )
|
134
|
+
overwrite = validate( params, required: false, var: 'overwrite', type: Boolean ) || true
|
135
|
+
folder_id = validate( params, required: false, var: 'folderId' )
|
136
|
+
message = validate( params, required: false, var: 'message', type: String )
|
37
137
|
|
38
|
-
endpoint = '/api/dashboards/db'
|
39
|
-
# title = slug(title)
|
40
|
-
|
41
|
-
# dashboard = JSON.parse( dashboard ) if( dashboard.is_a?(String) )
|
42
138
|
dashboard = regenerate_template_ids( dashboard )
|
43
139
|
|
44
|
-
|
45
|
-
|
46
|
-
|
140
|
+
unless(folder_id.nil?)
|
141
|
+
f_folder = folder(folder_id)
|
142
|
+
return { 'status' => 404, 'message' => format( 'No Folder \'%s\' found', folder_id) } if( f_folder.dig('status') != 200 )
|
143
|
+
|
144
|
+
folder_id = f_folder.dig('id')
|
47
145
|
end
|
48
146
|
|
147
|
+
db = JSON.parse( dashboard ) if( dashboard.is_a?(String) )
|
148
|
+
title = db.dig('dashboard','title')
|
149
|
+
uid = db.dig('dashboard','uid')
|
150
|
+
|
151
|
+
return { 'status' => 404, 'message' => format( 'The template \'%s\' can\'t be create. The uid can have a maximum length of 40 characters, but it is %s characters long', title, uid.length) } if( ! uid.nil? && uid.length > 40 )
|
152
|
+
|
153
|
+
endpoint = '/api/dashboards/db'
|
154
|
+
|
155
|
+
payload = {
|
156
|
+
dashboard: db.dig('dashboard'),
|
157
|
+
overwrite: overwrite,
|
158
|
+
folderId: folder_id,
|
159
|
+
message: message
|
160
|
+
}
|
161
|
+
payload.reject!{ |_k, v| v.nil? }
|
162
|
+
|
49
163
|
@logger.debug("Creating dashboard: #{title} (POST /api/dashboards/db)") if @debug
|
50
164
|
|
51
|
-
post( endpoint,
|
165
|
+
post( endpoint, payload.to_json )
|
52
166
|
end
|
53
167
|
|
168
|
+
# http://docs.grafana.org/http_api/dashboard/#delete-dashboard-by-slug
|
169
|
+
# - Deprecated starting from Grafana v5.0.
|
170
|
+
# Please update to use the new Get dashboard by uid resource instead
|
171
|
+
#
|
54
172
|
# Delete dashboard
|
55
|
-
#
|
173
|
+
# Will delete the dashboard given the specified slug. Slug is the url friendly version of the dashboard title.
|
174
|
+
#
|
175
|
+
# @example
|
176
|
+
# delete_dashboard('dashboard for many foo')
|
177
|
+
#
|
178
|
+
# @return [Hash]
|
179
|
+
#
|
56
180
|
def delete_dashboard( name )
|
57
181
|
|
182
|
+
raise ArgumentError.new(format('wrong type. \'name\' must be an String, given \'%s\'', name.class.to_s)) unless( name.is_a?(String) )
|
183
|
+
raise ArgumentError.new('missing name') if( name.size.zero? )
|
184
|
+
|
58
185
|
endpoint = format( '/api/dashboards/db/%s', slug(name) )
|
59
186
|
|
60
187
|
@logger.debug("Deleting dashboard #{slug(name)} (DELETE #{endpoint})") if @debug
|
@@ -63,7 +190,12 @@ module Grafana
|
|
63
190
|
end
|
64
191
|
|
65
192
|
# Gets the home dashboard
|
66
|
-
#
|
193
|
+
#
|
194
|
+
# @example
|
195
|
+
# home_dashboard
|
196
|
+
#
|
197
|
+
# @return [Hash]
|
198
|
+
#
|
67
199
|
def home_dashboard
|
68
200
|
|
69
201
|
endpoint = '/api/dashboards/home'
|
@@ -74,7 +206,12 @@ module Grafana
|
|
74
206
|
end
|
75
207
|
|
76
208
|
# Tags for Dashboard
|
77
|
-
#
|
209
|
+
#
|
210
|
+
# @example
|
211
|
+
# dashboard_tags
|
212
|
+
#
|
213
|
+
# @return [Hash]
|
214
|
+
#
|
78
215
|
def dashboard_tags
|
79
216
|
|
80
217
|
endpoint = '/api/dashboards/tags'
|
@@ -85,29 +222,30 @@ module Grafana
|
|
85
222
|
end
|
86
223
|
|
87
224
|
# Search Dashboards
|
88
|
-
# GET /api/search/
|
89
225
|
#
|
90
|
-
#
|
91
|
-
# searchDashboards(
|
92
|
-
# searchDashboards(
|
93
|
-
# searchDashboards(
|
94
|
-
# searchDashboards(
|
95
|
-
|
226
|
+
# @example
|
227
|
+
# searchDashboards( tags: host )
|
228
|
+
# searchDashboards( tags: [ host, 'tag1' ] )
|
229
|
+
# searchDashboards( tags: [ 'tag2' ] )
|
230
|
+
# searchDashboards( query: title )
|
231
|
+
# searchDashboards( starred: true )
|
232
|
+
#
|
233
|
+
# @return [Hash]
|
234
|
+
#
|
235
|
+
def search_dashboards( params )
|
96
236
|
|
97
237
|
raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
|
98
238
|
|
99
|
-
query = params
|
100
|
-
starred = params
|
101
|
-
tags = params
|
102
|
-
api = []
|
239
|
+
query = validate( params, required: false, var: 'query', type: String )
|
240
|
+
starred = validate( params, required: false, var: 'starred', type: Boolean )
|
241
|
+
tags = validate( params, required: false, var: 'tags' )
|
103
242
|
|
104
|
-
api
|
243
|
+
api = []
|
244
|
+
api << format( 'query=%s', CGI.escape( query ) ) unless( query.nil? )
|
105
245
|
api << format( 'starred=%s', starred ? 'true' : 'false' ) unless( starred.nil? )
|
106
246
|
|
107
247
|
unless( tags.nil? )
|
108
|
-
|
109
248
|
tags = tags.join( '&tag=' ) if( tags.is_a?( Array ) )
|
110
|
-
|
111
249
|
api << format( 'tag=%s', tags )
|
112
250
|
end
|
113
251
|
|
@@ -120,7 +258,13 @@ module Grafana
|
|
120
258
|
get( endpoint )
|
121
259
|
end
|
122
260
|
|
123
|
-
|
261
|
+
# import Dashboards from directory
|
262
|
+
#
|
263
|
+
# @example
|
264
|
+
# import_dashboards_from_directory( '/tmp/dashboards' )
|
265
|
+
#
|
266
|
+
# @return [Hash]
|
267
|
+
#
|
124
268
|
def import_dashboards_from_directory( directory )
|
125
269
|
|
126
270
|
raise ArgumentError.new('directory must be an String') unless( directory.is_a?(String) )
|
@@ -135,10 +279,9 @@ module Grafana
|
|
135
279
|
|
136
280
|
dashboard = File.read( f )
|
137
281
|
dashboard = JSON.parse( dashboard )
|
138
|
-
title = dashboard.dig('dashboard','title') || f
|
139
282
|
|
140
283
|
result[f.to_s] ||= {}
|
141
|
-
result[f.to_s] = create_dashboard(
|
284
|
+
result[f.to_s] = create_dashboard( dashboard: dashboard )
|
142
285
|
end
|
143
286
|
|
144
287
|
result
|