grafana 0.9.0 → 0.10.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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