grafana 0.8.5 → 1.1.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 (49) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +8 -3
  3. data/lib/_logging.rb_ +55 -0
  4. data/lib/grafana.rb +1 -1
  5. data/lib/grafana/admin.rb +2 -1
  6. data/lib/grafana/alerts.rb +338 -14
  7. data/lib/grafana/annotations.rb +284 -9
  8. data/lib/grafana/auth.rb +150 -0
  9. data/lib/grafana/client.rb +81 -5
  10. data/lib/grafana/dashboard.rb +99 -7
  11. data/lib/grafana/dashboard_permissions.rb +132 -0
  12. data/lib/grafana/dashboard_versions.rb +101 -5
  13. data/lib/grafana/datasource.rb +34 -38
  14. data/lib/grafana/folder.rb +198 -0
  15. data/lib/grafana/folder_and_dashboard_search.rb +57 -0
  16. data/lib/grafana/folder_permissions.rb +155 -0
  17. data/lib/grafana/logging.rb +55 -0
  18. data/lib/grafana/login.rb +93 -49
  19. data/lib/grafana/network.rb +130 -101
  20. data/lib/grafana/organization.rb +2 -1
  21. data/lib/grafana/organizations.rb +15 -6
  22. data/lib/grafana/playlist.rb +594 -0
  23. data/lib/grafana/preferences.rb +122 -0
  24. data/lib/grafana/tags.rb +16 -0
  25. data/lib/grafana/teams.rb +364 -0
  26. data/lib/grafana/tools.rb +42 -9
  27. data/lib/grafana/user.rb +6 -2
  28. data/lib/grafana/users.rb +19 -11
  29. data/lib/grafana/validator.rb +47 -2
  30. data/lib/grafana/version.rb +3 -3
  31. metadata +16 -39
  32. data/doc/Array.html +0 -200
  33. data/doc/Boolean.html +0 -122
  34. data/doc/FalseClass.html +0 -132
  35. data/doc/Grafana.html +0 -172
  36. data/doc/Hash.html +0 -212
  37. data/doc/Logging.html +0 -326
  38. data/doc/Object.html +0 -286
  39. data/doc/Time.html +0 -200
  40. data/doc/TrueClass.html +0 -132
  41. data/doc/_index.html +0 -380
  42. data/doc/class_list.html +0 -51
  43. data/doc/file.README.html +0 -117
  44. data/doc/file_list.html +0 -56
  45. data/doc/frames.html +0 -17
  46. data/doc/index.html +0 -117
  47. data/doc/method_list.html +0 -747
  48. data/doc/top-level-namespace.html +0 -112
  49. data/lib/logging.rb +0 -35
@@ -5,21 +5,31 @@ require 'rest-client'
5
5
  require 'json'
6
6
  require 'timeout'
7
7
 
8
+ require_relative 'logging'
8
9
  require_relative 'version'
10
+ require_relative 'auth'
9
11
  require_relative 'validator'
10
12
  require_relative 'login'
11
13
  require_relative 'network'
12
14
  require_relative 'tools'
13
15
  require_relative 'admin'
14
16
  require_relative 'annotations'
17
+ require_relative 'preferences'
15
18
  require_relative 'user'
16
19
  require_relative 'users'
20
+ require_relative 'teams'
17
21
  require_relative 'datasource'
18
22
  require_relative 'organization'
19
23
  require_relative 'organizations'
20
24
  require_relative 'dashboard'
21
25
  require_relative 'dashboard_versions'
26
+ require_relative 'dashboard_permissions'
22
27
  require_relative 'snapshot'
28
+ require_relative 'alerts'
29
+ require_relative 'folder'
30
+ require_relative 'folder_permissions'
31
+ require_relative 'folder_and_dashboard_search'
32
+ require_relative 'playlist'
23
33
 
24
34
  # -------------------------------------------------------------------------------------------------------------------
25
35
  #
@@ -40,20 +50,29 @@ module Grafana
40
50
  include Logging
41
51
 
42
52
  include Grafana::Version
53
+ include Grafana::Auth
43
54
  include Grafana::Validator
44
55
  include Grafana::Login
45
56
  include Grafana::Network
46
57
  include Grafana::Tools
47
58
  include Grafana::Admin
48
59
  include Grafana::Annotations
60
+ include Grafana::Preferences
49
61
  include Grafana::User
50
62
  include Grafana::Users
63
+ include Grafana::Teams
51
64
  include Grafana::Datasource
52
65
  include Grafana::Organization
53
66
  include Grafana::Organizations
54
67
  include Grafana::Dashboard
55
68
  include Grafana::DashboardVersions
69
+ include Grafana::DashboardPermissions
56
70
  include Grafana::Snapshot
71
+ include Grafana::Alerts
72
+ include Grafana::Folder
73
+ include Grafana::FolderPermissions
74
+ include Grafana::FolderSearch
75
+ include Grafana::Playlist
57
76
 
58
77
  attr_accessor :debug
59
78
 
@@ -95,8 +114,17 @@ module Grafana
95
114
  ssl = settings.dig(:grafana, :ssl) || false
96
115
  @timeout = settings.dig(:grafana, :timeout) || 5
97
116
  @open_timeout = settings.dig(:grafana, :open_timeout) || 5
98
- @http_headers = settings.dig(:grafana, :http_headers) || {}
117
+ @api_user = settings.dig(:grafana, :api, :user) || 'admin'
118
+ @api_password = settings.dig(:grafana, :api, :password)
119
+ @http_headers = settings.dig(:grafana, :http_headers) || { 'Content-Type' => 'application/json', 'Accept' => 'application/json' }
99
120
  @debug = settings.dig(:debug) || false
121
+ @debug = false
122
+ @headers = {}
123
+
124
+ # Token Support for Grafana 6
125
+ @api_key = nil
126
+ @api_token_name = settings.dig(:grafana, :api, :token, :name ) || (0..10).to_a.map{|_a| rand(16).to_s(16)}.join
127
+ @api_token_lifetime = settings.dig(:grafana, :api, :token, :lifetime ) || 0
100
128
 
101
129
  raise ArgumentError.new('missing \'host\'') if( host.nil? )
102
130
 
@@ -111,14 +139,62 @@ module Grafana
111
139
  @url = format( '%s://%s:%d%s', protocoll, host, port, url_path )
112
140
  end
113
141
 
114
- def self.logger
115
- @@logger ||= defined?(Logging) ? Logging.logger : Logger.new(STDOUT)
142
+
143
+ def create_instance
144
+
145
+ logger.debug( "create_instance" )
146
+ logger.debug( "@api_key: #{@api_key} #{@api_key.class}" )
147
+
148
+ params = { timeout: @timeout.to_i, open_timeout: @open_timeout.to_i, headers: @http_headers, verify_ssl: false }
149
+ params = { timeout: @timeout.to_i, open_timeout: @open_timeout.to_i, headers: @http_headers, verify_ssl: false, user: @api_user, password: @api_password } if( @api_key.nil? )
150
+
151
+ logger.debug( "url : #{@url}" )
152
+ logger.debug( "params: #{params}" )
153
+
154
+ begin
155
+ RestClient::Resource.new( @url, params )
156
+ rescue => error
157
+ logger.error( error ) # if @debug
158
+ logger.debug( e.backtrace.join("\n") ) #if @debug
159
+ false
160
+ end
116
161
  end
117
162
 
118
- def self.logger=(logger)
119
- @@logger = logger
163
+
164
+ # Get Settings
165
+ #
166
+ # http://docs.grafana.org/http_api/other/#get-settings
167
+ #
168
+ def settings
169
+ endpoint = '/api/frontend/settings'
170
+ @logger.debug("Getting all settings (GET #{endpoint})") if @debug
171
+ get(endpoint)
120
172
  end
121
173
 
174
+
175
+ def version
176
+ s = settings
177
+
178
+ status = s.dig('status')
179
+ if( status.to_i == 200 )
180
+ @version = s.dig('buildInfo','version')
181
+ @major_version = @version.split('.').first.to_i
182
+
183
+ { version: @version, major_version: @major_version }
184
+ else
185
+ s
186
+ end
187
+ end
188
+
189
+
190
+ # def self.logger
191
+ # @@logger ||= defined?(Logging) ? Logging.logger : Logger.new(STDOUT)
192
+ # end
193
+ #
194
+ # def self.logger=(logger)
195
+ # @@logger = logger
196
+ # end
197
+
122
198
  end
123
199
 
124
200
  end
@@ -2,12 +2,36 @@
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
+ #
11
35
  # @example
12
36
  # dashboard('dashboard for many foo')
13
37
  #
@@ -18,23 +42,70 @@ module Grafana
18
42
  raise ArgumentError.new(format('wrong type. \'name\' must be an String, given \'%s\'', name.class.to_s)) unless( name.is_a?(String) )
19
43
  raise ArgumentError.new('missing name') if( name.size.zero? )
20
44
 
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
52
+
21
53
  endpoint = format( '/api/dashboards/db/%s', slug(name) )
54
+ @logger.debug( "Attempting to get dashboard (GET #{endpoint})" ) if @debug
55
+
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? )
22
79
 
23
- @logger.debug( "Attempting to get dashboard (GET /api/dashboards/db/#{name})" ) if @debug
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
24
87
 
25
88
  get( endpoint )
26
89
  end
27
90
 
28
91
  # Create / Update dashboard
29
92
  #
93
+ # Creates a new dashboard or updates an existing dashboard.
94
+ #
30
95
  # @param [Hash] params
31
- # @option params [Hash] dashboard
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.
32
102
  # @option params [Boolean] overwrite (true)
33
103
  #
34
104
  # @example
35
105
  # params = {
36
106
  # dashboard: {
37
107
  # id: null,
108
+ # uid: null,
38
109
  # title: 'Production Overview',
39
110
  # tags: [ 'templated' ],
40
111
  # timezone": 'browser',
@@ -45,7 +116,9 @@ module Grafana
45
116
  # 'schemaVersion': 6,
46
117
  # 'version': 0
47
118
  # },
48
- # overwrite: false
119
+ # folderId: 0,
120
+ # overwrite: false,
121
+ # message: 'created by foo'
49
122
  # }
50
123
  # create_dashboard( params )
51
124
  #
@@ -57,19 +130,33 @@ module Grafana
57
130
  raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
58
131
  raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
59
132
 
60
- dashboard = validate( params, required: true, var: 'dashboard', type: Hash )
133
+ dashboard = validate( params, required: true , var: 'dashboard', type: Hash )
61
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 )
62
137
 
63
138
  dashboard = regenerate_template_ids( dashboard )
64
139
 
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')
145
+ end
146
+
65
147
  db = JSON.parse( dashboard ) if( dashboard.is_a?(String) )
66
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 )
67
152
 
68
153
  endpoint = '/api/dashboards/db'
69
154
 
70
155
  payload = {
71
156
  dashboard: db.dig('dashboard'),
72
- overwrite: overwrite
157
+ overwrite: overwrite,
158
+ folderId: folder_id,
159
+ message: message
73
160
  }
74
161
  payload.reject!{ |_k, v| v.nil? }
75
162
 
@@ -78,7 +165,12 @@ module Grafana
78
165
  post( endpoint, payload.to_json )
79
166
  end
80
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
+ #
81
172
  # Delete dashboard
173
+ # Will delete the dashboard given the specified slug. Slug is the url friendly version of the dashboard title.
82
174
  #
83
175
  # @example
84
176
  # delete_dashboard('dashboard for many foo')
@@ -149,7 +241,7 @@ module Grafana
149
241
  tags = validate( params, required: false, var: 'tags' )
150
242
 
151
243
  api = []
152
- api << format( 'query=%s', CGI.escape( query ) ) unless query.nil?
244
+ api << format( 'query=%s', CGI.escape( query ) ) unless( query.nil? )
153
245
  api << format( 'starred=%s', starred ? 'true' : 'false' ) unless( starred.nil? )
154
246
 
155
247
  unless( tags.nil? )
@@ -0,0 +1,132 @@
1
+
2
+ module Grafana
3
+
4
+ # http://docs.grafana.org/http_api/dashboard_permissions/#dashboard-permissions-api
5
+ #
6
+ # This API can be used to update/get the permissions for a dashboard.
7
+ # Permissions with dashboardId=-1 are the default permissions for users with the Viewer and Editor roles.
8
+ # Permissions can be set for a user, a team or a role (Viewer or Editor).
9
+ # Permissions cannot be set for Admins - they always have access to everything.
10
+ #
11
+ # The permission levels for the permission field:
12
+ #
13
+ # 1 = View
14
+ # 2 = Edit
15
+ # 4 = Admin
16
+ #
17
+ module DashboardPermissions
18
+
19
+ # http://docs.grafana.org/http_api/dashboard_permissions/#get-permissions-for-a-dashboard
20
+ #
21
+ # GET /api/dashboards/id/:dashboardId/permissions
22
+ #
23
+ # Gets all existing permissions for the dashboard with the given dashboardId.
24
+ #
25
+ def dashboard_permissions(uid)
26
+
27
+ if( uid.is_a?(String) && uid.is_a?(Integer) )
28
+ 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))
29
+ end
30
+ raise ArgumentError.new('missing \'uid\'') if( uid.size.zero? )
31
+
32
+ endpoint = format( '/api/dashboards/id/%s/permissions', uid )
33
+ @logger.debug( "Attempting to get dashboard permissions (GET #{endpoint})" ) if @debug
34
+
35
+ r = get( endpoint )
36
+ r['message'] = format('dashboard \'%s\' not found', uid) if(r.dig('status') == 404)
37
+ r
38
+ end
39
+
40
+ # http://docs.grafana.org/http_api/dashboard_permissions/#update-permissions-for-a-dashboard
41
+ #
42
+ # POST /api/dashboards/id/:dashboardId/permissions
43
+ #
44
+ # Updates permissions for a dashboard.
45
+ # This operation will remove existing permissions if they're not included in the request.
46
+ #
47
+ #
48
+ def update_dashboad_permissions(params)
49
+
50
+ raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
51
+ raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
52
+
53
+ v, mv = version.values
54
+ return { 'status' => 404, 'message' => format( 'folder has been supported in Grafana since version 5. you use version %s', v) } if(mv < 5)
55
+
56
+ dashboard_id = validate( params, required: true, var: 'dashboard_id', type: Integer )
57
+ permissions = validate( params, required: true, var: 'permissions' , type: Hash )
58
+
59
+ return { 'status' => 404, 'message' => 'no permissions given' } if( permissions.size.zero? )
60
+
61
+ valid_roles = %w[View Edit Admin]
62
+
63
+ c_team = permissions.dig('team')
64
+ c_user = permissions.dig('user')
65
+ team = []
66
+ user = []
67
+
68
+ unless(c_team.nil?)
69
+ check_keys = []
70
+
71
+ c_team.uniq.each do |x|
72
+ k = x.keys.first
73
+ v = x.values.first
74
+ r = validate_hash( v, valid_roles )
75
+
76
+ f_team = team(k)
77
+ team_id = f_team.dig('id')
78
+
79
+ next unless(( f_team.dig('status') == 200) && !check_keys.include?(team_id) && r == true )
80
+
81
+ check_keys << team_id
82
+
83
+ role_id = valid_roles.index(v)
84
+ role_id += 1
85
+ role_id += 1 if(v == 'Admin')
86
+
87
+ team << {
88
+ teamId: team_id,
89
+ permission: role_id
90
+ }
91
+ end
92
+ end
93
+
94
+ unless(c_user.nil?)
95
+ check_keys = []
96
+
97
+ c_user.uniq.each do |x|
98
+ k = x.keys.first
99
+ v = x.values.first
100
+ r = validate_hash( v, valid_roles )
101
+
102
+ f_user = user(k)
103
+ user_id = f_user.dig('id')
104
+
105
+ next unless(( f_user.dig('status') == 200) && !check_keys.include?(user_id) && r == true )
106
+
107
+ check_keys << user_id
108
+
109
+ role_id = valid_roles.index(v)
110
+ role_id += 1
111
+ role_id += 1 if(v == 'Admin')
112
+
113
+ user << {
114
+ userId: user_id,
115
+ permission: role_id
116
+ }
117
+ end
118
+ end
119
+
120
+ payload = {
121
+ items: team + user
122
+ }
123
+ payload.reject!{ |_, y| y.nil? }
124
+
125
+
126
+ endpoint = format('/api/dashboards/id/%s/permissions', dashboard_id)
127
+ post(endpoint, payload.to_json)
128
+ end
129
+
130
+ end
131
+
132
+ end