grafana 0.9.0 → 0.10.1

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.
@@ -102,7 +102,7 @@
102
102
  </div>
103
103
 
104
104
  <div id="footer">
105
- Generated on Wed Dec 13 06:51:14 2017 by
105
+ Generated on Thu Dec 14 05:45:14 2017 by
106
106
  <a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
107
107
  0.9.11 (ruby-2.2.8).
108
108
  </div>
data/lib/grafana/admin.rb CHANGED
@@ -142,7 +142,8 @@ module Grafana
142
142
  #
143
143
  def delete_user( user_id )
144
144
 
145
- raise ArgumentError.new(format('wrong type. user \'user_id\' must be an String (for an User name) or an Integer (for an User Id), given \'%s\'', user_id.class.to_s)) if( user_id.is_a?(String) && user_id.is_a?(Integer) )
145
+ raise ArgumentError.new(format('wrong type. user \'user_id\' must be an String (for an User name) or an Integer (for an User Id), given \'%s\'', user_id.class.to_s)) \
146
+ if( user_id.is_a?(String) && user_id.is_a?(Integer) )
146
147
  raise ArgumentError.new('missing \'user_id\'') if( user_id.size.zero? )
147
148
 
148
149
  if(user_id.is_a?(String))
@@ -1,38 +1,358 @@
1
1
 
2
2
  module Grafana
3
3
 
4
- # http://docs.grafana.org/http_api/alerting/
4
+ # You can use the Alerting API to get information about alerts and their states but this API cannot be used to modify the alert.
5
+ # To create new alerts or modify them you need to update the dashboard json that contains the alerts.
6
+ #
7
+ # This API can also be used to create, update and delete alert notifications.
8
+ #
9
+ # original API Documentation can be found under: http://docs.grafana.org/http_api/alerting/
5
10
  #
6
11
  module Alerts
7
12
 
8
13
  # Get alerts
14
+ #
15
+ # These parameters are used as querystring parameters. For example:
16
+ #
17
+ # @param [Hash] params
18
+ # @option params [Mixed] dashboard_id alerts for a specified dashboard.
19
+ # @option params [Integer] panel_id alerts for a specified panel on a dashboard.
20
+ # @option params [Integer] limit (10) response to x number of alerts.
21
+ # @option params [Integer] state (ALL,no_data, paused, alerting, ok, pending)
22
+ # @option params [Array] alerts with one or more of the following alert states: 'ALL', 'no_data', 'paused', 'alerting', 'ok', 'pending'.
23
+ ## To specify multiple states use the following format: ?state=paused&state=alerting
24
+ #
25
+ # @return [Array]
9
26
  # GET /api/alerts/
27
+ # curl -H 'Content-Type: application/json;charset=UTF-8' 'http://admin:admin@127.0.0.1:3030/api/alerts'
10
28
  #
29
+ def alerts( params )
30
+
31
+ raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
32
+ # raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
33
+
34
+ dashboard_id = validate( params, required: false, var: 'dashboard_id' )
35
+ panel_id = validate( params, required: false, var: 'panel_id', type: Integer )
36
+ limit = validate( params, required: false, var: 'limit', type: Integer )
37
+ alert_array = validate( params, required: false, var: 'alerts', type: Array )
38
+ valid_alerts = %w[ALL no_data paused alerting ok pending].sort
39
+
40
+ unless( alert_array.nil? )
41
+ alert_array = alert_array.sort
42
+ # valid = alert_array & valid_alerts
43
+ invalid = alert_array - valid_alerts
44
+
45
+ raise ArgumentError.new(format('wrong alerts type. only %s allowed, given \'%s\'', valid_alerts.join(', '), alert_array.join(', '))) if( invalid.count != 0 )
46
+ end
47
+
48
+ if( dashboard_id.is_a?(String) )
49
+
50
+ dashboard = search_dashboards( query: dashboard_id )
51
+
52
+ return { 'status' => 404, 'message' => format( 'No Dashboard \'%s\' found', dashboard_id) } if( dashboard.nil? || dashboard.dig('status').to_i != 200 )
53
+
54
+ dashboard = dashboard.dig('message').first unless( dashboard.nil? && dashboard.dig('status').to_i == 200 )
55
+ dashboard_id = dashboard.dig('id') unless( dashboard.nil? )
56
+
57
+ return { 'status' => 404, 'message' => format( 'No Dashboard \'%s\' found', dashboard_id) } if( dashboard_id.nil? )
58
+ end
59
+
60
+ api = []
61
+ api << format( 'dashboardId=%s', dashboard_id ) unless( dashboard_id.nil? )
62
+ api << format( 'panelId=%s', panel_id ) unless( panel_id.nil? )
63
+ api << format( 'limit=%s', limit ) unless( limit.nil? )
64
+
65
+ unless( alert_array.nil? )
66
+ alert_array = alert_array.join( '&state=' ) if( alert_array.is_a?( Array ) )
67
+ api << format( 'state=%s', alert_array )
68
+ end
69
+ api = api.join( '&' )
70
+
71
+ endpoint = format( '/api/alerts/?%s' , api )
72
+
73
+ @logger.debug("Attempting to search for alerts (GET #{endpoint})") if @debug
74
+
75
+ get( endpoint )
76
+ end
77
+
11
78
  # Get one alert
12
- # GET /api/alerts/:id
13
79
  #
14
- def alerts( id = nil ); end
80
+ # @param [Mixed] alert_id Alertname (String) or Alertid (Integer)
81
+ #
82
+ # @example
83
+ # alert( 1 )
84
+ # alert( 'foo' )
85
+ #
86
+ # @return [Hash]
87
+ #
88
+ # curl -H 'Content-Type: application/json;charset=UTF-8' 'http://admin:admin@127.0.0.1:3030/api/alerts/1'
89
+ #
90
+ def alert( alert_id )
15
91
 
16
- # Pause alert
17
- # POST /api/alerts/:id/pause
18
- def alert_pause( id ); end
92
+ if( alert_id.is_a?(String) && alert_id.is_a?(Integer) )
93
+ raise ArgumentError.new(format('wrong type. \'alert_id\' must be an String (for an Alert name) or an Integer (for an Alert Id), given \'%s\'', alert_id.class.to_s))
94
+ end
95
+ raise ArgumentError.new('missing \'alert_id\'') if( alert_id.size.zero? )
96
+
97
+ # if(alert_id.is_a?(String))
98
+ # data = alerts( alerts: 'all' ).select { |_k,v| v['name'] == alert_id }
99
+ # alert_id = data.keys.first if( data )
100
+ # end
101
+
102
+ # puts alert_id
103
+ # GET /api/alerts/:id
104
+
105
+
106
+ endpoint = format( '/api/alerts/%d' , alert_id )
107
+
108
+ # puts endpoint
109
+
110
+ @logger.debug("Attempting get alert id #{alert_id} (GET #{endpoint})") if @debug
111
+
112
+ get( endpoint )
113
+ end
114
+
115
+
116
+ # Pause single alert
117
+ #
118
+ # @param [Mixed] alert_id Alertname (String) or Alertid (Integer)
119
+ #
120
+ # @example
121
+ # alert_pause( 1 )
122
+ # alert_pause( 'foo' )
123
+ #
124
+ # @return [Hash]
125
+ #
126
+ def alert_pause( alert_id )
127
+
128
+ if( alert_id.is_a?(String) && alert_id.is_a?(Integer) )
129
+ raise ArgumentError.new(format('wrong type. \'alert_id\' must be an String (for an Alert name) or an Integer (for an Alert Id), given \'%s\'', alert_id.class.to_s))
130
+ end
131
+ raise ArgumentError.new('missing \'alert_id\'') if( alert_id.size.zero? )
132
+
133
+ if(alert_id.is_a?(String))
134
+ data = alerts( alerts: 'all' ).select { |_k,v| v['name'] == alert_id }
135
+ alert_id = data.keys.first if( data )
136
+ end
137
+
138
+ # POST /api/alerts/:id/pause
139
+ # puts alert_id
140
+ end
19
141
 
20
142
  # Get alert notifications
21
- # GET /api/alert-notifications
22
- def alert_notifications; end
143
+ #
144
+ # @example
145
+ # alert_notifications
146
+ #
147
+ # @return [Hash]
148
+ #
149
+ def alert_notifications
150
+ logger.debug('Getting alert notifications') if @debug
151
+ get('/api/alert-notifications')
152
+ end
153
+
154
+
155
+
156
+
157
+
23
158
 
24
159
  # Create alert notification
25
- # POST /api/alert-notifications
26
- def create_alert_notification( oarams ); end
160
+ #
161
+ # @param [Hash] params
162
+ # @option params [String] name short description - required
163
+ # @option params [String] type one of 'slack', 'pagerduty','email','webhook','kafka','hipchat',
164
+ # 'victorops','sensu','opsgenie','threema','pushover','telegram','line','prometheus-alertmanager' - required
165
+ # @option params [Boolean] default (false)
166
+ # @option params [Hash] settings
167
+ #
168
+ # @example
169
+ # params = {
170
+ # name: 'new alert notification',
171
+ # type: 'email',
172
+ # default: false,
173
+ # settings: {
174
+ # addresses: 'carl@grafana.com;dev@grafana.com'
175
+ # }
176
+ # }
177
+ # create_alert_notification( params )
178
+ #
179
+ # @return [Hash]
180
+ #
181
+ def create_alert_notification( params )
182
+
183
+ raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
184
+ raise ArgumentError.new('missing params') if( params.size.zero? )
185
+
186
+ # TODO
187
+ # type are 'email'
188
+ # and the other possible values?
189
+ name = validate( params, required: true, var: 'name', type: String )
190
+ type = validate( params, required: true, var: 'type', type: String ) || 'email'
191
+ default = validate( params, required: false, var: 'default', type: Boolean ) || false
192
+ settings = validate( params, required: false, var: 'settings', type: Hash )
193
+
194
+ unless( type.nil? )
195
+ valid_types = %w[slack pagerduty email webhook kafka hipchat victorops sensu opsgenie threema pushover telegram line prometheus-alertmanager]
196
+ raise ArgumentError.new(format('wrong notification type. only %s allowed, given \%s\'', valid_types.join(', '), type)) if( valid_types.include?(type.downcase) == false )
197
+ end
198
+
199
+ # TODO
200
+ # check if the alert 'name' already created
201
+ return { 'status' => 404, 'message' => format( 'alert notification \'%s\' alread exists', name) } if( alert_notification?(name) )
202
+
203
+ # data = alert_notifications
204
+ # data = data.dig('message').first unless( data.nil? && data.dig('status').to_i == 200 )
205
+ # data = data.select { |k| k['name'] == name }
206
+ # return { 'status' => 404, 'message' => format( 'alert notification \'%s\' alread exists', name) } if( data )
207
+
208
+ payload = {
209
+ name: name,
210
+ type: type,
211
+ isDefault: default,
212
+ settings: settings
213
+ }
214
+ payload.reject!{ |_k, v| v.nil? }
215
+
216
+ endpoint = '/api/alert-notifications'
217
+
218
+ # puts endpoint
219
+ # puts payload
220
+
221
+ post(endpoint, payload.to_json)
222
+ end
27
223
 
28
224
  # Update alert notification
29
- # PUT /api/alert-notifications/1
30
- def update_alert_notification( params ); end
225
+ #
226
+ # @param [Hash] params
227
+ # @param [Mixed] alert_id Alertname (String) or Alertid (Integer) to change
228
+ # @option params [String] name short description - required
229
+ # @option params [String] type ('email') - required
230
+ # @option params [Boolean] default (false)
231
+ # @option params [Hash] settings
232
+ #
233
+ # @example
234
+ # params = {
235
+ # alert_id: 1
236
+ # name: 'new alert notification',
237
+ # type: 'email',
238
+ # default: false,
239
+ # settings: {
240
+ # addresses: 'carl@grafana.com;dev@grafana.com'
241
+ # }
242
+ # }
243
+ # update_alert_notification( params )
244
+ #
245
+ # params = {
246
+ # alert_id: 'new alert notification'
247
+ # name: 'new alert notification',
248
+ # type: 'email',
249
+ # default: false,
250
+ # settings: {
251
+ # addresses: 'carl@grafana.com;dev@grafana.com'
252
+ # }
253
+ # }
254
+ # update_alert_notification( params )
255
+ #
256
+ # @return [Hash]
257
+ #
258
+ def update_alert_notification( params )
259
+
260
+ raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
261
+ raise ArgumentError.new('missing params') if( params.size.zero? )
262
+
263
+ # TODO
264
+ # type are 'email'
265
+ # and the other possible values?
266
+ alert_id = validate( params, required: true, var: 'alert_id' )
267
+ name = validate( params, required: true, var: 'name', type: String )
268
+ type = validate( params, required: true, var: 'type', type: String ) || 'email'
269
+ default = validate( params, required: false, var: 'default', type: Boolean ) || false
270
+ settings = validate( params, required: false, var: 'settings', type: Hash )
271
+
272
+ unless( type.nil? )
273
+ valid_types = %w[slack pagerduty email webhook kafka hipchat victorops sensu opsgenie threema pushover telegram line prometheus-alertmanager]
274
+ raise ArgumentError.new(format('wrong notification type. only %s allowed, given \%s\'', valid_types.join(', '), type)) if( valid_types.include?(type.downcase) == false )
275
+ end
276
+
277
+ if( alert_id.is_a?(String) && alert_id.is_a?(Integer) )
278
+ raise ArgumentError.new(format('wrong type. user \'alert_id\' must be an String (for an Alertname) or an Integer (for an Alert Id), given \'%s\'', alert_id.class.to_s))
279
+ end
280
+
281
+ alert_id = alert_notification_id(alert_id)
282
+ return { 'status' => 404, 'message' => format( 'alert notification \'%s\' not exists', name) } if( alert_id.nil? )
283
+
284
+ payload = {
285
+ id: alert_id,
286
+ name: name,
287
+ type: type,
288
+ isDefault: default,
289
+ settings: settings
290
+ }
291
+ payload.reject!{ |_k, v| v.nil? }
292
+
293
+ endpoint = format( '/api/alert-notifications/%d', alert_id )
294
+
295
+ put(endpoint, payload.to_json)
296
+ end
31
297
 
32
298
  # Delete alert notification
33
- # DELETE /api/alert-notifications/:notificationId
34
- def delete_alert_notification( id ); end
299
+ #
300
+ # @param [Mixed] alert_id Alertname (String) or Alertid (Integer)
301
+ #
302
+ # @example
303
+ # delete_alert_notification( 1 )
304
+ # delete_alert_notification( 'foo' )
305
+ #
306
+ # @return [Hash]
307
+ #
308
+ def delete_alert_notification( alert_id )
309
+
310
+ if( alert_id.is_a?(String) && alert_id.is_a?(Integer) )
311
+ raise ArgumentError.new(format('wrong type. user \'alert_id\' must be an String (for an Alert name) or an Integer (for an Alert Id), given \'%s\'', alert_id.class.to_s))
312
+ end
313
+ raise ArgumentError.new('missing \'alert_id\'') if( alert_id.size.zero? )
314
+
315
+ id = alert_notification_id(alert_id)
316
+ return { 'status' => 404, 'message' => format( 'alert notification \'%s\' not exists', alert_id) } if( id.nil? )
317
+
318
+ endpoint = format('/api/alert-notifications/%d', alert_id )
319
+ logger.debug( "Deleting alert id #{alert_id} (DELETE #{endpoint})" ) if @debug
320
+
321
+ delete( endpoint )
322
+ end
323
+
324
+
325
+ private
326
+ def alert_notification?( alert_id )
327
+
328
+ id = alert_notification_id(alert_id)
329
+
330
+ return true unless( id.nil? )
331
+
332
+ false
333
+ end
334
+
335
+ def alert_notification_id( alert_id )
336
+
337
+ data = alert_notifications
338
+ data = data.dig('message') unless( data.nil? && data.dig('status').to_i == 200 )
339
+
340
+ map = {}
341
+ data.each do |d|
342
+ map[d.dig('id')] = d.dig('name').downcase.split.join('_')
343
+ end
344
+
345
+ id = map.select { |key,_value| key == alert_id } if( map && alert_id.is_a?(Integer) )
346
+ id = map.select { |_key,value| value == alert_id.downcase.split.join('_') } if( map && alert_id.is_a?(String) )
347
+
348
+ id = id.keys.first unless(id.nil?)
349
+
350
+ return id if( id.is_a?(Integer) )
351
+
352
+ nil
353
+ end
35
354
 
36
355
  end
37
356
 
38
357
  end
358
+
@@ -20,10 +20,12 @@ module Grafana
20
20
  # @option params [Integer] from: epoch datetime in milliseconds. Optional.
21
21
  # @option params [Integer] to: epoch datetime in milliseconds. Optional.
22
22
  # @option params [Integer] limit: number. Optional - default is 10. Max limit for results returned.
23
- # @option params [Integer] alertId: number. Optional. Find annotations for a specified alert.
23
+ # @option params [Integer] alert_id: number. Optional. Find annotations for a specified alert.
24
24
  # @option params [Mixed] dashboard: number. Optional. Find annotations that are scoped to a specific dashboard
25
25
  # @option params [Integer] panel_id: number. Optional. Find annotations that are scoped to a specific panel
26
- # @option params [Array] tags: string. Optional. Use this to filter global annotations. Global annotations are annotations from an annotation data source that are not connected specifically to a dashboard or panel. To do an “AND” filtering with multiple tags, specify the tags parameter multiple times e.g.
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.
27
29
  #
28
30
  # @example
29
31
  # params = {
@@ -160,7 +162,7 @@ module Grafana
160
162
  #
161
163
  # Creates an annotation by using Graphite-compatible event format.
162
164
  # The when and data fields are optional.
163
- # If when is not specified then the current time will be used as annotations timestamp.
165
+ # If when is not specified then the current time will be used as annotation's timestamp.
164
166
  # The tags field can also be in prior to Graphite 0.10.0 format (string with multiple tags being separated by a space).
165
167
  #
166
168
  # http://docs.grafana.org/http_api/annotations/#create-annotation-in-graphite-format
@@ -177,7 +179,7 @@ module Grafana
177
179
  # what: 'spec test graphite annotation',
178
180
  # when: Time.now.to_i,
179
181
  # tags: [ 'spec', 'test' ],
180
- # text: 'test annotation'
182
+ # data: 'test annotation'
181
183
  # }
182
184
  # create_annotation_graphite( params )
183
185
  #
@@ -188,17 +190,17 @@ module Grafana
188
190
  raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
189
191
  raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
190
192
 
191
- what = validate( params, required: true, var: 'what', type: String )
193
+ what = validate( params, required: true , var: 'what', type: String )
192
194
  time_when = validate( params, required: false, var: 'when', type: Integer ) || Time.now.to_i
193
- tags = validate( params, required: true, var: 'tags', type: Array )
194
- text = validate( params, required: true, var: 'text', type: String )
195
+ tags = validate( params, required: true , var: 'tags', type: Array )
196
+ data = validate( params, required: false, var: 'data', type: String )
195
197
 
196
198
  endpoint = '/api/annotations/graphite'
197
199
  payload = {
198
200
  what: what,
199
201
  when: time_when,
200
202
  tags: tags,
201
- text: text
203
+ data: data
202
204
  }
203
205
  payload.reject!{ |_k, v| v.nil? }
204
206
 
@@ -12,14 +12,21 @@ 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'
23
30
 
24
31
  # -------------------------------------------------------------------------------------------------------------------
25
32
  #
@@ -46,14 +53,21 @@ module Grafana
46
53
  include Grafana::Tools
47
54
  include Grafana::Admin
48
55
  include Grafana::Annotations
56
+ include Grafana::Preferences
49
57
  include Grafana::User
50
58
  include Grafana::Users
59
+ include Grafana::Teams
51
60
  include Grafana::Datasource
52
61
  include Grafana::Organization
53
62
  include Grafana::Organizations
54
63
  include Grafana::Dashboard
55
64
  include Grafana::DashboardVersions
65
+ include Grafana::DashboardPermissions
56
66
  include Grafana::Snapshot
67
+ include Grafana::Alerts
68
+ include Grafana::Folder
69
+ include Grafana::FolderPermissions
70
+ include Grafana::FolderSearch
57
71
 
58
72
  attr_accessor :debug
59
73
 
@@ -98,6 +112,8 @@ module Grafana
98
112
  @http_headers = settings.dig(:grafana, :http_headers) || {}
99
113
  @debug = settings.dig(:debug) || false
100
114
 
115
+ @headers = {}
116
+
101
117
  raise ArgumentError.new('missing \'host\'') if( host.nil? )
102
118
 
103
119
  raise ArgumentError.new(format('wrong type. \'port\' must be an Integer, given \'%s\'', port.class.to_s)) unless( port.is_a?(Integer) )
@@ -111,6 +127,26 @@ module Grafana
111
127
  @url = format( '%s://%s:%d%s', protocoll, host, port, url_path )
112
128
  end
113
129
 
130
+ # Get Settings
131
+ #
132
+ # http://docs.grafana.org/http_api/other/#get-settings
133
+ #
134
+ def settings
135
+ endpoint = '/api/frontend/settings'
136
+ @logger.debug("Getting all settings (GET #{endpoint})") if @debug
137
+ get(endpoint)
138
+ end
139
+
140
+
141
+ def version
142
+ s = settings
143
+ @version = s.dig('buildInfo','version')
144
+ @major_version = @version.split('.').first.to_i
145
+
146
+ {version: @version, major_version: @major_version}
147
+ end
148
+
149
+
114
150
  def self.logger
115
151
  @@logger ||= defined?(Logging) ? Logging.logger : Logger.new(STDOUT)
116
152
  end