grafana 1.0.0 → 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.
- checksums.yaml +4 -4
- data/README.md +2 -2
- data/lib/_logging.rb_ +55 -0
- data/lib/grafana.rb +1 -1
- data/lib/grafana/alerts.rb +6 -2
- data/lib/grafana/annotations.rb +2 -2
- data/lib/grafana/auth.rb +150 -0
- data/lib/grafana/client.rb +50 -12
- data/lib/grafana/folder.rb +1 -1
- data/lib/grafana/logging.rb +55 -0
- data/lib/grafana/login.rb +54 -16
- data/lib/grafana/network.rb +6 -2
- data/lib/grafana/organizations.rb +1 -1
- data/lib/grafana/playlist.rb +72 -77
- data/lib/grafana/preferences.rb +2 -2
- data/lib/grafana/validator.rb +2 -2
- data/lib/grafana/version.rb +1 -1
- metadata +4 -2
- data/lib/logging.rb +0 -35
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ee4ecb6c21184aee321f81b9d5a5681524da6cac47b736756e8b3b1a4c091eed
|
4
|
+
data.tar.gz: 267e82424dad92727eace6b546f2fd436235e51af5b471c806833e4eb3186efe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 97d4a3aa5740c1992cf706fec3deae4690db5c68f05eb334b828dea74d6173fde86fbb3a53c2afe562d5a299e13a2c5450d4e27bcdf7dae96a146a8b3f2cb770
|
7
|
+
data.tar.gz: 5c231dad3f4552d8176b8b0a5653284b3792ec1058c958674a625e99b790d9e51f93eb240ca5f500c94e2cbff23159b2933fac13723cdaa0518b8f808f31176a
|
data/README.md
CHANGED
@@ -33,9 +33,9 @@ You can also run `bin/console` for an interactive prompt that will allow you to
|
|
33
33
|
To install this gem onto your local machine, run `bundle exec rake install`.
|
34
34
|
To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`,
|
35
35
|
which will create a git tag for the version,
|
36
|
-
push git commits and tags and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
36
|
+
push git commits and tags and push the `.gem` file to [rubygems.org](https://rubygems.org/gems/grafana).
|
37
37
|
|
38
38
|
## Contributing
|
39
39
|
|
40
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/
|
40
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/bodsch/grafana.
|
41
41
|
|
data/lib/_logging.rb_
ADDED
@@ -0,0 +1,55 @@
|
|
1
|
+
|
2
|
+
require 'logger'
|
3
|
+
|
4
|
+
# -------------------------------------------------------------------------------------------------
|
5
|
+
|
6
|
+
module Logging
|
7
|
+
|
8
|
+
def logger
|
9
|
+
@logger ||= Logging.logger_for( self.class.name )
|
10
|
+
end
|
11
|
+
|
12
|
+
# Use a hash class-ivar to cache a unique Logger per class:
|
13
|
+
@loggers = {}
|
14
|
+
|
15
|
+
class << self
|
16
|
+
|
17
|
+
def logger_for( classname )
|
18
|
+
@loggers[classname] ||= configure_logger_for( classname )
|
19
|
+
end
|
20
|
+
|
21
|
+
def configure_logger_for( classname )
|
22
|
+
|
23
|
+
log_level = ENV.fetch('LOG_LEVEL', 'INFO' )
|
24
|
+
level = log_level.dup
|
25
|
+
|
26
|
+
# DEBUG < INFO < WARN < ERROR < FATAL < UNKNOWN
|
27
|
+
log_level = case level.upcase
|
28
|
+
when 'DEBUG'
|
29
|
+
Logger::DEBUG # Low-level information for developers.
|
30
|
+
when 'INFO'
|
31
|
+
Logger::INFO # Generic (useful) information about system operation.
|
32
|
+
when 'WARN'
|
33
|
+
Logger::WARN # A warning.
|
34
|
+
when 'ERROR'
|
35
|
+
Logger::ERROR # A handleable error condition.
|
36
|
+
when 'FATAL'
|
37
|
+
Logger::FATAL # An unhandleable error that results in a program crash.
|
38
|
+
else
|
39
|
+
Logger::UNKNOWN # An unknown message that should always be logged.
|
40
|
+
end
|
41
|
+
|
42
|
+
$stdout.sync = true
|
43
|
+
logger = Logger.new($stdout)
|
44
|
+
logger.level = log_level
|
45
|
+
logger.datetime_format = "%Y-%m-%d %H:%M:%S %z"
|
46
|
+
logger.formatter = proc do |severity, datetime, progname, msg|
|
47
|
+
"[#{datetime.strftime( logger.datetime_format )}] #{severity.ljust(5)} #{msg}\n"
|
48
|
+
end
|
49
|
+
|
50
|
+
logger
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# -------------------------------------------------------------------------------------------------
|
data/lib/grafana.rb
CHANGED
data/lib/grafana/alerts.rb
CHANGED
@@ -102,7 +102,6 @@ module Grafana
|
|
102
102
|
# puts alert_id
|
103
103
|
# GET /api/alerts/:id
|
104
104
|
|
105
|
-
|
106
105
|
endpoint = format( '/api/alerts/%d' , alert_id )
|
107
106
|
|
108
107
|
# puts endpoint
|
@@ -130,13 +129,18 @@ module Grafana
|
|
130
129
|
end
|
131
130
|
raise ArgumentError.new('missing \'alert_id\'') if( alert_id.size.zero? )
|
132
131
|
|
133
|
-
if(alert_id.is_a?(String))
|
132
|
+
if( alert_id.is_a?(String) )
|
134
133
|
data = alerts( alerts: 'all' ).select { |_k,v| v['name'] == alert_id }
|
135
134
|
alert_id = data.keys.first if( data )
|
136
135
|
end
|
137
136
|
|
137
|
+
endpoint = format( '/api/alerts/%d/pause', alert_id )
|
138
|
+
|
139
|
+
@logger.debug("Attempting pause alert id #{alert_id} (POST #{endpoint})") if @debug
|
140
|
+
|
138
141
|
# POST /api/alerts/:id/pause
|
139
142
|
# puts alert_id
|
143
|
+
post( endpoint )
|
140
144
|
end
|
141
145
|
|
142
146
|
# Get alert notifications
|
data/lib/grafana/annotations.rb
CHANGED
@@ -124,8 +124,8 @@ module Grafana
|
|
124
124
|
time = validate( params, required: false, var: 'time', type: Integer ) || Time.now.to_i
|
125
125
|
time_end = validate( params, required: false, var: 'time_end', type: Integer )
|
126
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 )
|
127
|
+
tags = validate( params, required: true , var: 'tags', type: Array )
|
128
|
+
text = validate( params, required: true , var: 'text', type: String )
|
129
129
|
|
130
130
|
if( dashboard.is_a?(String) )
|
131
131
|
|
data/lib/grafana/auth.rb
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
|
2
|
+
module Grafana
|
3
|
+
|
4
|
+
# abstract base class for authentication API
|
5
|
+
#
|
6
|
+
# https://grafana.com/docs/grafana/latest/http_api/auth/
|
7
|
+
#
|
8
|
+
# Token
|
9
|
+
# - Currently you can authenticate via an API Token or via a Session cookie (acquired using regular login or oauth).
|
10
|
+
#
|
11
|
+
# Basic Auth
|
12
|
+
# - If basic auth is enabled (it is enabled by default) you can authenticate your HTTP request via standard
|
13
|
+
# basic auth. Basic auth will also authenticate LDAP users.
|
14
|
+
#
|
15
|
+
module Auth
|
16
|
+
|
17
|
+
# Auth HTTP resources / actions
|
18
|
+
# Api Keys
|
19
|
+
#
|
20
|
+
# GET /api/auth/keys
|
21
|
+
def api_keys
|
22
|
+
|
23
|
+
endpoint = '/api/auth/keys'
|
24
|
+
|
25
|
+
@logger.debug("Attempting to get all existing api keys (GET #{endpoint})") if @debug
|
26
|
+
|
27
|
+
get( endpoint )
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
def api_key( api_id )
|
32
|
+
|
33
|
+
if( api_id.is_a?(String) && api_id.is_a?(Integer) )
|
34
|
+
raise ArgumentError.new(format('wrong type. API token \'api_id\' must be an String (for an API name) or an Integer (for an API Id), given \'%s\'', api_id.class.to_s))
|
35
|
+
end
|
36
|
+
raise ArgumentError.new('missing \'api_id\'') if( api_id.size.zero? )
|
37
|
+
|
38
|
+
if(api_id.is_a?(String))
|
39
|
+
keys = api_keys
|
40
|
+
keys = JSON.parse(keys) if(keys.is_a?(String))
|
41
|
+
|
42
|
+
# logger.debug(keys)
|
43
|
+
|
44
|
+
status = keys.dig('status')
|
45
|
+
return keys if( status != 200 )
|
46
|
+
|
47
|
+
u = keys.dig('message').detect { |v| v['id'] == api_id || v['name'] == api_id }
|
48
|
+
|
49
|
+
# logger.debug(u)
|
50
|
+
|
51
|
+
return { 'status' => 404, 'message' => format( 'No API token \'%s\' found', api_id ) } if( u.nil? )
|
52
|
+
|
53
|
+
# api_id = u.dig('id') unless(u.nil?)
|
54
|
+
end
|
55
|
+
|
56
|
+
{ 'status' => 200, 'message' => u }
|
57
|
+
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
# Create API Key
|
62
|
+
#
|
63
|
+
# POST /api/auth/keys
|
64
|
+
# https://grafana.com/docs/grafana/latest/http_api/auth/#create-api-key
|
65
|
+
#
|
66
|
+
# @param [Hash] params
|
67
|
+
# @option params [String] name The key name - (required)
|
68
|
+
# @option params [String] role Sets the access level/Grafana Role for the key. Can be one of the following values: Viewer, Editor or Admin. - (required)
|
69
|
+
# @option params [Integer] seconds_to_live Sets the key expiration in seconds.
|
70
|
+
# It is optional. If it is a positive number an expiration date for the key is set.
|
71
|
+
# If it is null, zero or is omitted completely (unless api_key_max_seconds_to_live configuration option is set) the key will never expire.
|
72
|
+
#
|
73
|
+
#
|
74
|
+
# @return [Hash]
|
75
|
+
#
|
76
|
+
# @example:
|
77
|
+
#
|
78
|
+
def create_api_key( params )
|
79
|
+
|
80
|
+
raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
|
81
|
+
raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
|
82
|
+
|
83
|
+
name = validate( params, required: true, var: 'name' )
|
84
|
+
role = validate( params, required: true, var: 'role' )
|
85
|
+
seconds_to_live = validate( params, required: false, var: 'seconds_to_live', type: Integer )
|
86
|
+
|
87
|
+
valid_roles = %w[Viewer Editor Admin]
|
88
|
+
|
89
|
+
# https://stackoverflow.com/questions/9333952/case-insensitive-arrayinclude?answertab=votes#tab-top
|
90
|
+
# Do this once, or each time the array changes
|
91
|
+
downcased = Set.new valid_roles.map(&:downcase)
|
92
|
+
unless( downcased.include?( role.downcase ) )
|
93
|
+
return {
|
94
|
+
'status' => 404,
|
95
|
+
'login_or_email' => login_or_email,
|
96
|
+
'role' => role,
|
97
|
+
'message' => format( 'wrong role. Role must be one of %s, given \'%s\'', valid_roles.join(', '), role )
|
98
|
+
}
|
99
|
+
end
|
100
|
+
|
101
|
+
seconds_to_live = 86_400 if seconds_to_live.nil?
|
102
|
+
|
103
|
+
endpoint = '/api/auth/keys'
|
104
|
+
|
105
|
+
data = {
|
106
|
+
name: name,
|
107
|
+
role: role,
|
108
|
+
secondsToLive: seconds_to_live
|
109
|
+
}
|
110
|
+
|
111
|
+
data.reject!{ |_k, v| v.nil? }
|
112
|
+
|
113
|
+
payload = data.deep_string_keys
|
114
|
+
# payload = existing_ds.merge(payload).deep_symbolize_keys
|
115
|
+
|
116
|
+
@logger.debug("create API token (POST #{endpoint})") if @debug
|
117
|
+
|
118
|
+
post(endpoint, payload.to_json)
|
119
|
+
|
120
|
+
end
|
121
|
+
|
122
|
+
# Delete API Key
|
123
|
+
#
|
124
|
+
# DELETE /api/auth/keys/:id
|
125
|
+
def delete_api_key( key_id )
|
126
|
+
|
127
|
+
if( key_id.is_a?(String) && key_id.is_a?(Integer) )
|
128
|
+
raise ArgumentError.new(format('wrong type. \'key_id\' must be an String (for an API Key name) or an Integer (for an API Key Id), given \'%s\'', key_id.class.to_s))
|
129
|
+
end
|
130
|
+
raise ArgumentError.new('missing \'key_id\'') if( key_id.size.zero? )
|
131
|
+
|
132
|
+
if(key_id.is_a?(String))
|
133
|
+
data = api_keys.select { |_k,v| v['name'] == key_id }
|
134
|
+
key_id = data.keys.first if( data )
|
135
|
+
end
|
136
|
+
|
137
|
+
return { 'status' => 404, 'message' => format( 'No API key \'%s\' found', key_id) } if( key_id.nil? )
|
138
|
+
|
139
|
+
raise format('API Key can not be 0') if( key_id.zero? )
|
140
|
+
|
141
|
+
endpoint = format('/api/auth/keys/%d', key_id)
|
142
|
+
logger.debug("Deleting API key #{key_id} (DELETE #{endpoint})") if @debug
|
143
|
+
|
144
|
+
delete(endpoint)
|
145
|
+
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|
data/lib/grafana/client.rb
CHANGED
@@ -5,7 +5,9 @@ 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'
|
@@ -48,6 +50,7 @@ module Grafana
|
|
48
50
|
include Logging
|
49
51
|
|
50
52
|
include Grafana::Version
|
53
|
+
include Grafana::Auth
|
51
54
|
include Grafana::Validator
|
52
55
|
include Grafana::Login
|
53
56
|
include Grafana::Network
|
@@ -111,11 +114,18 @@ module Grafana
|
|
111
114
|
ssl = settings.dig(:grafana, :ssl) || false
|
112
115
|
@timeout = settings.dig(:grafana, :timeout) || 5
|
113
116
|
@open_timeout = settings.dig(:grafana, :open_timeout) || 5
|
114
|
-
@
|
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' }
|
115
120
|
@debug = settings.dig(:debug) || false
|
116
|
-
|
121
|
+
@debug = false
|
117
122
|
@headers = {}
|
118
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
|
128
|
+
|
119
129
|
raise ArgumentError.new('missing \'host\'') if( host.nil? )
|
120
130
|
|
121
131
|
raise ArgumentError.new(format('wrong type. \'port\' must be an Integer, given \'%s\'', port.class.to_s)) unless( port.is_a?(Integer) )
|
@@ -129,6 +139,28 @@ module Grafana
|
|
129
139
|
@url = format( '%s://%s:%d%s', protocoll, host, port, url_path )
|
130
140
|
end
|
131
141
|
|
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
|
161
|
+
end
|
162
|
+
|
163
|
+
|
132
164
|
# Get Settings
|
133
165
|
#
|
134
166
|
# http://docs.grafana.org/http_api/other/#get-settings
|
@@ -142,20 +174,26 @@ module Grafana
|
|
142
174
|
|
143
175
|
def version
|
144
176
|
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
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
|
151
182
|
|
152
|
-
|
153
|
-
|
183
|
+
{ version: @version, major_version: @major_version }
|
184
|
+
else
|
185
|
+
s
|
186
|
+
end
|
154
187
|
end
|
155
188
|
|
156
|
-
|
157
|
-
|
158
|
-
|
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
|
159
197
|
|
160
198
|
end
|
161
199
|
|
data/lib/grafana/folder.rb
CHANGED
@@ -99,7 +99,7 @@ module Grafana
|
|
99
99
|
|
100
100
|
endpoint = '/api/folders'
|
101
101
|
|
102
|
-
@logger.debug("create folder#{title} (GET #{endpoint})") if @debug
|
102
|
+
@logger.debug("create folder #{title} (GET #{endpoint})") if @debug
|
103
103
|
logger.debug(payload.to_json) if(@debug)
|
104
104
|
|
105
105
|
post( endpoint, payload.to_json )
|
@@ -0,0 +1,55 @@
|
|
1
|
+
|
2
|
+
require 'logger'
|
3
|
+
|
4
|
+
# -------------------------------------------------------------------------------------------------
|
5
|
+
|
6
|
+
module Logging
|
7
|
+
|
8
|
+
def logger
|
9
|
+
@logger ||= Logging.logger_for( self.class.name )
|
10
|
+
end
|
11
|
+
|
12
|
+
# Use a hash class-ivar to cache a unique Logger per class:
|
13
|
+
@loggers = {}
|
14
|
+
|
15
|
+
class << self
|
16
|
+
|
17
|
+
def logger_for( classname )
|
18
|
+
@loggers[classname] ||= configure_logger_for( classname )
|
19
|
+
end
|
20
|
+
|
21
|
+
def configure_logger_for( classname )
|
22
|
+
|
23
|
+
log_level = ENV.fetch('LOG_LEVEL', 'INFO' )
|
24
|
+
level = log_level.dup
|
25
|
+
|
26
|
+
# DEBUG < INFO < WARN < ERROR < FATAL < UNKNOWN
|
27
|
+
log_level = case level.upcase
|
28
|
+
when 'DEBUG'
|
29
|
+
Logger::DEBUG # Low-level information for developers.
|
30
|
+
when 'INFO'
|
31
|
+
Logger::INFO # Generic (useful) information about system operation.
|
32
|
+
when 'WARN'
|
33
|
+
Logger::WARN # A warning.
|
34
|
+
when 'ERROR'
|
35
|
+
Logger::ERROR # A handleable error condition.
|
36
|
+
when 'FATAL'
|
37
|
+
Logger::FATAL # An unhandleable error that results in a program crash.
|
38
|
+
else
|
39
|
+
Logger::UNKNOWN # An unknown message that should always be logged.
|
40
|
+
end
|
41
|
+
|
42
|
+
$stdout.sync = true
|
43
|
+
logger = Logger.new($stdout)
|
44
|
+
logger.level = log_level
|
45
|
+
logger.datetime_format = "%Y-%m-%d %H:%M:%S %z"
|
46
|
+
logger.formatter = proc do |severity, datetime, progname, msg|
|
47
|
+
"[#{datetime.strftime( logger.datetime_format )}] #{severity.ljust(5)} #{msg}\n"
|
48
|
+
end
|
49
|
+
|
50
|
+
logger
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# -------------------------------------------------------------------------------------------------
|
data/lib/grafana/login.rb
CHANGED
@@ -29,20 +29,27 @@ module Grafana
|
|
29
29
|
max_retries = validate( params, required: false, var: 'max_retries', type: Integer ) || 2
|
30
30
|
sleep_between_retries = validate( params, required: false, var: 'sleep_between_retries', type: Integer ) || 5
|
31
31
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
32
|
+
# raise 'no valid rest instance found' if( @api_instance.nil? )
|
33
|
+
|
34
|
+
# only useful for Grafana version < 6
|
35
|
+
#
|
36
|
+
if( @api_instance.nil? )
|
37
|
+
|
38
|
+
@api_user = username
|
39
|
+
@api_password = password
|
40
|
+
|
41
|
+
@api_instance = create_instance
|
42
|
+
|
43
|
+
return true if(@api_instance)
|
44
|
+
else
|
45
|
+
logger.debug('User session already initiated') if @debug
|
46
|
+
return true
|
44
47
|
end
|
45
48
|
|
49
|
+
logger.debug( "resource: #{@api_instance.inspect}")
|
50
|
+
|
51
|
+
false
|
52
|
+
|
46
53
|
request_data = { 'User' => username, 'Password' => password }
|
47
54
|
|
48
55
|
if( @api_instance )
|
@@ -51,13 +58,15 @@ module Grafana
|
|
51
58
|
@headers = {}
|
52
59
|
|
53
60
|
begin
|
54
|
-
logger.debug('Attempting to establish user session') if @debug
|
61
|
+
logger.debug('Attempting to establish user session') # if @debug
|
55
62
|
|
56
|
-
response = @api_instance['/login'].post(
|
63
|
+
response = @api_instance['/api/login'].post(
|
57
64
|
request_data.to_json,
|
58
65
|
content_type: 'application/json; charset=UTF-8'
|
59
66
|
)
|
60
67
|
|
68
|
+
logger.debug( "response #{response}")
|
69
|
+
|
61
70
|
response_cookies = response.cookies
|
62
71
|
response_code = response.code.to_i
|
63
72
|
|
@@ -131,11 +140,40 @@ module Grafana
|
|
131
140
|
# @return [Hash]
|
132
141
|
#
|
133
142
|
def ping_session
|
134
|
-
logger.debug( "Pinging current session (GET #{endpoint})" ) if @debug
|
135
143
|
endpoint = '/api/login/ping'
|
136
|
-
|
144
|
+
logger.debug( "Pinging current session (GET #{endpoint})" ) if @debug
|
145
|
+
|
146
|
+
begin
|
147
|
+
get( endpoint )
|
148
|
+
rescue => error
|
149
|
+
logger.error(e)
|
150
|
+
end
|
137
151
|
end
|
138
152
|
|
153
|
+
# Returns health information about Grafana
|
154
|
+
#
|
155
|
+
# @example
|
156
|
+
# health
|
157
|
+
#
|
158
|
+
# @return [Hash]
|
159
|
+
#
|
160
|
+
def health
|
161
|
+
endpoint = '/api/health'
|
162
|
+
logger.debug( "get health information (GET #{endpoint})" ) if @debug
|
163
|
+
|
164
|
+
result = get( endpoint )
|
165
|
+
|
166
|
+
if( result.is_a?(Hash) )
|
167
|
+
status = result.dig('status')
|
168
|
+
if( status.to_i == 200 )
|
169
|
+
message = result.dig('message')
|
170
|
+
r = message.gsub('=>', ':').gsub(':nil,', ':null,')
|
171
|
+
return { 'status' => status, 'message' => JSON.parse( r ) }
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
result
|
176
|
+
end
|
139
177
|
|
140
178
|
def headers
|
141
179
|
@headers
|
data/lib/grafana/network.rb
CHANGED
@@ -61,9 +61,11 @@ module Grafana
|
|
61
61
|
#
|
62
62
|
def request( method_type = 'GET', endpoint = '/', data = {} )
|
63
63
|
|
64
|
+
logger.debug( "request( method_type: #{method_type}, endpoint: #{endpoint}, data )" )
|
65
|
+
|
64
66
|
raise 'try first login()' if @api_instance.nil?
|
65
67
|
|
66
|
-
login( username: @username, password: @password )
|
68
|
+
# login( username: @username, password: @password )
|
67
69
|
|
68
70
|
response = nil
|
69
71
|
response_code = 404
|
@@ -103,7 +105,7 @@ module Grafana
|
|
103
105
|
logger.error('422')
|
104
106
|
|
105
107
|
response_body = response_body.first if(response_body.is_a?(Array))
|
106
|
-
message_field_name = response_body.dig('fieldNames')
|
108
|
+
# message_field_name = response_body.dig('fieldNames')
|
107
109
|
|
108
110
|
#status = response_code # response_body.dig('status')
|
109
111
|
message = response_body # .dig('message')
|
@@ -151,6 +153,8 @@ module Grafana
|
|
151
153
|
return false
|
152
154
|
end
|
153
155
|
|
156
|
+
# logger.debug( "response: #{response} (#{response.class})" )
|
157
|
+
|
154
158
|
response_code = response.code.to_i
|
155
159
|
response_body = response.body
|
156
160
|
response_headers = response.headers
|
@@ -317,7 +317,7 @@ module Grafana
|
|
317
317
|
organization = validate( params, required: true, var: 'organization', type: String )
|
318
318
|
login_or_email = validate( params, required: true, var: 'login_or_email', type: String )
|
319
319
|
role = validate( params, required: true, var: 'role', type: String )
|
320
|
-
valid_roles = [
|
320
|
+
valid_roles = %w[Viewer Editor "Read Only Editor" Admin]
|
321
321
|
|
322
322
|
# https://stackoverflow.com/questions/9333952/case-insensitive-arrayinclude?answertab=votes#tab-top
|
323
323
|
# Do this once, or each time the array changes
|
data/lib/grafana/playlist.rb
CHANGED
@@ -122,17 +122,16 @@ module Grafana
|
|
122
122
|
d = data.dig('message')
|
123
123
|
data = d.select { |k| k['name'] == playlist_id }
|
124
124
|
|
125
|
-
return { 'status' => 404, 'message' => format( 'No Playlist \'%s\' found', playlist_id) } if( data.size
|
125
|
+
return { 'status' => 404, 'message' => format( 'No Playlist \'%s\' found', playlist_id) } if( data.size.zero? )
|
126
126
|
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
_d << playlist( k['id'] )
|
127
|
+
unless( data.empty? )
|
128
|
+
playlist_data = []
|
129
|
+
data.each_entry do |k|
|
130
|
+
playlist_data << playlist( k['id'] )
|
132
131
|
end
|
133
|
-
|
132
|
+
|
133
|
+
return { 'status' => status, 'playlists' => playlist_data }
|
134
134
|
end
|
135
|
-
# return { 'status' => 200, 'message' => data } if( data.size != 0 )
|
136
135
|
end
|
137
136
|
|
138
137
|
raise format('playlist id can not be 0') if( playlist_id.zero? )
|
@@ -145,7 +144,7 @@ module Grafana
|
|
145
144
|
|
146
145
|
return { 'status' => 404, 'message' => 'playlist is empty', 'items' => [] } if( result.dig('status') == 404 )
|
147
146
|
|
148
|
-
|
147
|
+
result
|
149
148
|
end
|
150
149
|
|
151
150
|
### Get Playlist items
|
@@ -192,24 +191,22 @@ module Grafana
|
|
192
191
|
end
|
193
192
|
raise ArgumentError.new('missing \'playlist_id\'') if( playlist_id.size.zero? )
|
194
193
|
|
195
|
-
|
194
|
+
tmp_playlists = playlists
|
196
195
|
|
197
196
|
begin
|
198
|
-
status =
|
199
|
-
message =
|
197
|
+
status = tmp_playlists.dig('status').to_i
|
198
|
+
message = tmp_playlists.dig('message')
|
200
199
|
|
201
|
-
if( status
|
200
|
+
return tmp_playlists if( status != 200 )
|
202
201
|
|
203
|
-
|
204
|
-
|
202
|
+
data = message.select { |k| k['id'] == playlist_id } if( playlist_id.is_a?(Integer) )
|
203
|
+
data = message.select { |k| k['name'] == playlist_id } if( playlist_id.is_a?(String) )
|
205
204
|
|
206
|
-
|
207
|
-
|
205
|
+
return { 'status' => 404, 'message' => 'No Playlist found' } if( !data.is_a?(Array) || data.count.zero? || status.to_i != 200 )
|
206
|
+
return { 'status' => 404, 'message' => format('found %d playlists with name %s', data.count, playlist_id ) } if( data.count > 1 && multi_result == false )
|
207
|
+
|
208
|
+
id = data.first.dig('id')
|
208
209
|
|
209
|
-
id = data.first.dig('id')
|
210
|
-
else
|
211
|
-
return _playlists
|
212
|
-
end
|
213
210
|
rescue
|
214
211
|
return { 'status' => 404, 'message' => 'No Playlists found' } if( playlists.nil? || playlists == false || playlists.dig('status').to_i != 200 )
|
215
212
|
end
|
@@ -220,7 +217,7 @@ module Grafana
|
|
220
217
|
|
221
218
|
return { 'status' => 404, 'message' => 'playlist is empty' } if( result.dig('status') == 404 )
|
222
219
|
|
223
|
-
|
220
|
+
result
|
224
221
|
end
|
225
222
|
|
226
223
|
### Get Playlist dashboards
|
@@ -321,7 +318,7 @@ module Grafana
|
|
321
318
|
interval = validate( params, required: true , var: 'interval' , type: String )
|
322
319
|
items = validate( params, required: true , var: 'items' , type: Array )
|
323
320
|
|
324
|
-
return { 'status' => 404, 'message' => 'There are no elements for a playlist' } if(items.count
|
321
|
+
return { 'status' => 404, 'message' => 'There are no elements for a playlist' } if(items.count.zero?)
|
325
322
|
|
326
323
|
payload_items = create_playlist_items(items)
|
327
324
|
|
@@ -412,29 +409,28 @@ module Grafana
|
|
412
409
|
# organisation = validate( params, required: false, var: 'organisation' )
|
413
410
|
items = validate( params, required: false, var: 'items', type: Array )
|
414
411
|
|
415
|
-
|
412
|
+
tmp_playlists = playlists
|
416
413
|
|
417
414
|
data = []
|
418
415
|
|
419
416
|
begin
|
420
|
-
status =
|
421
|
-
message =
|
417
|
+
status = tmp_playlists.dig('status').to_i
|
418
|
+
message = tmp_playlists.dig('message')
|
422
419
|
|
423
|
-
if( status
|
424
|
-
|
425
|
-
|
420
|
+
return tmp_playlists if( status != 200 )
|
421
|
+
|
422
|
+
data = message.select { |k| k['id'] == playlist_id } if( playlist_id.is_a?(Integer) )
|
423
|
+
data = message.select { |k| k['name'] == playlist_id } if( playlist_id.is_a?(String) )
|
424
|
+
|
425
|
+
return { 'status' => 404, 'message' => 'no playlist found' } if( !data.is_a?(Array) || data.count.zero? || status.to_i != 200 )
|
426
|
+
return { 'status' => 404, 'message' => format('found %d playlists with name %s', data.count, playlist_id ) } if( data.count > 1 && multi_result == false )
|
426
427
|
|
427
|
-
return { 'status' => 404, 'message' => 'no playlist found' } if( !data.is_a?(Array) || data.count == 0 || status.to_i != 200 )
|
428
|
-
return { 'status' => 404, 'message' => format('found %d playlists with name %s', data.count, playlist_id ) } if( data.count > 1 && multi_result == false )
|
429
|
-
else
|
430
|
-
return _playlists
|
431
|
-
end
|
432
428
|
rescue
|
433
429
|
return { 'status' => 404, 'message' => 'no playlists found' } if( playlists.nil? || playlists == false || playlists.dig('status').to_i != 200 )
|
434
430
|
end
|
435
431
|
|
436
432
|
playlist_id = data.first.dig('id')
|
437
|
-
playlist_name = data.first.dig('name')
|
433
|
+
# playlist_name = data.first.dig('name')
|
438
434
|
payload_items = create_playlist_items(items, playlist_id)
|
439
435
|
|
440
436
|
payload = {
|
@@ -479,24 +475,22 @@ module Grafana
|
|
479
475
|
end
|
480
476
|
raise ArgumentError.new('missing \'playlist_id\'') if( playlist_id.size.zero? )
|
481
477
|
|
482
|
-
|
478
|
+
tmp_playlists = playlists
|
483
479
|
|
484
480
|
data = []
|
485
481
|
|
486
482
|
begin
|
487
|
-
status =
|
488
|
-
message =
|
483
|
+
status = tmp_playlists.dig('status').to_i
|
484
|
+
message = tmp_playlists.dig('message')
|
489
485
|
|
490
|
-
if( status
|
486
|
+
return tmp_playlists if( status != 200 )
|
491
487
|
|
492
|
-
|
493
|
-
|
488
|
+
data = message.select { |k| k['id'] == playlist_id } if( playlist_id.is_a?(Integer) )
|
489
|
+
data = message.select { |k| k['name'] == playlist_id } if( playlist_id.is_a?(String) )
|
490
|
+
|
491
|
+
return { 'status' => 404, 'message' => 'no playlist found' } if( !data.is_a?(Array) || data.count.zero? || status.to_i != 200 )
|
492
|
+
return { 'status' => 404, 'message' => format('found %d playlists with name %s', data.count, playlist_id ) } if( data.count > 1 && multi_result == false )
|
494
493
|
|
495
|
-
return { 'status' => 404, 'message' => 'no playlist found' } if( !data.is_a?(Array) || data.count == 0 || status.to_i != 200 )
|
496
|
-
return { 'status' => 404, 'message' => format('found %d playlists with name %s', data.count, playlist_id ) } if( data.count > 1 && multi_result == false )
|
497
|
-
else
|
498
|
-
return _playlists
|
499
|
-
end
|
500
494
|
rescue
|
501
495
|
return { 'status' => 404, 'message' => 'no playlists found' } if( playlists.nil? || playlists == false || playlists.dig('status').to_i != 200 )
|
502
496
|
end
|
@@ -515,7 +509,7 @@ module Grafana
|
|
515
509
|
end
|
516
510
|
end
|
517
511
|
|
518
|
-
return result
|
512
|
+
# return result
|
519
513
|
else
|
520
514
|
|
521
515
|
playlist_id = data.first.dig('id')
|
@@ -530,69 +524,70 @@ module Grafana
|
|
530
524
|
return { 'status' => 200, 'message' => 'playlist deleted' } if(r.dig('status').to_i == 404)
|
531
525
|
end
|
532
526
|
|
533
|
-
return result
|
527
|
+
# return result
|
534
528
|
end
|
535
529
|
|
530
|
+
result
|
536
531
|
end
|
537
532
|
|
538
533
|
|
539
534
|
private
|
540
|
-
def create_playlist_items( items,
|
535
|
+
def create_playlist_items( items, playlist_id = nil)
|
541
536
|
|
542
|
-
|
537
|
+
playlist_items = []
|
543
538
|
|
544
539
|
items.each do |r|
|
545
|
-
|
540
|
+
playlist_element = {}
|
546
541
|
|
547
542
|
if( r['name'] )
|
548
543
|
|
549
|
-
|
550
|
-
|
544
|
+
playlist_name = search_dashboards( query: r['name'] )
|
545
|
+
playlist_name_status = playlist_name.dig('status')
|
551
546
|
|
552
|
-
next unless(
|
547
|
+
next unless( playlist_name_status == 200 )
|
553
548
|
|
554
|
-
|
555
|
-
|
556
|
-
|
549
|
+
playlist_name = playlist_name.dig('message')
|
550
|
+
playlist_name_id = playlist_name.first.dig('id')
|
551
|
+
playlist_name_title = playlist_name.first.dig('title')
|
557
552
|
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
553
|
+
playlist_element[:type] = 'dashboard_by_id'
|
554
|
+
playlist_element[:value] = playlist_name_id.to_s
|
555
|
+
playlist_element[:title] = playlist_name_title
|
556
|
+
playlist_element[:playlistId] = playlist_id unless(playlist_id.nil?)
|
562
557
|
|
563
558
|
elsif( r['id'] )
|
564
559
|
|
565
|
-
|
566
|
-
|
560
|
+
uid = dashboard_by_uid(r['id'])
|
561
|
+
uid_status = uid.dig('status')
|
567
562
|
|
568
|
-
next unless(
|
563
|
+
next unless( uid_status == 200 )
|
569
564
|
|
570
|
-
|
571
|
-
|
572
|
-
|
565
|
+
playlist_element[:type] = 'dashboard_by_id'
|
566
|
+
playlist_element[:value] = r['id']
|
567
|
+
playlist_element[:playlistId] = playlist_id unless(playlist_id.nil?)
|
573
568
|
|
574
569
|
elsif( r['tag'] )
|
575
570
|
|
576
|
-
|
577
|
-
|
571
|
+
tags = search_dashboards( tags: r['tag'] )
|
572
|
+
tags_status = tags.dig('status')
|
578
573
|
|
579
|
-
next unless(
|
574
|
+
next unless( tags_status == 200 )
|
580
575
|
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
|
576
|
+
playlist_element[:type] = 'dashboard_by_tag'
|
577
|
+
playlist_element[:value] = r['tag']
|
578
|
+
playlist_element[:title] = r['tag']
|
579
|
+
playlist_element[:playlistId] = playlist_id unless(playlist_id.nil?)
|
585
580
|
|
586
581
|
else
|
587
582
|
next
|
588
583
|
end
|
589
584
|
|
590
|
-
|
585
|
+
playlist_element[:order] = r['order'] if(r['order'])
|
591
586
|
|
592
|
-
|
587
|
+
playlist_items << playlist_element if(playlist_element.count >= 4)
|
593
588
|
end
|
594
589
|
|
595
|
-
|
590
|
+
playlist_items
|
596
591
|
end
|
597
592
|
|
598
593
|
end
|
data/lib/grafana/preferences.rb
CHANGED
@@ -11,7 +11,7 @@ module Grafana
|
|
11
11
|
|
12
12
|
# Get Current User Prefs
|
13
13
|
# GET /api/user/preferences
|
14
|
-
def user_preferences
|
14
|
+
def user_preferences
|
15
15
|
|
16
16
|
v, mv = version.values
|
17
17
|
return { 'status' => 404, 'message' => format( 'folder has been supported in Grafana since version 5. you use version %s', v) } if(mv < 5)
|
@@ -43,7 +43,7 @@ module Grafana
|
|
43
43
|
|
44
44
|
# Get Current Org Prefs
|
45
45
|
# GET /api/org/preferences
|
46
|
-
def org_preferences
|
46
|
+
def org_preferences
|
47
47
|
|
48
48
|
v, mv = version.values
|
49
49
|
return { 'status' => 404, 'message' => format( 'folder has been supported in Grafana since version 5. you use version %s', v) } if(mv < 5)
|
data/lib/grafana/validator.rb
CHANGED
@@ -8,7 +8,7 @@ module Grafana
|
|
8
8
|
#
|
9
9
|
# @param params [Hash]
|
10
10
|
# @param options [Hash]
|
11
|
-
# @option options [Boolean]
|
11
|
+
# @option options [Boolean] required
|
12
12
|
# @option options [String] var
|
13
13
|
# @option options [Class] type
|
14
14
|
#
|
@@ -26,7 +26,7 @@ module Grafana
|
|
26
26
|
params = params.deep_symbolize_keys
|
27
27
|
variable = params.dig(var.to_sym)
|
28
28
|
|
29
|
-
raise ArgumentError.new(format('\'%s\' is
|
29
|
+
raise ArgumentError.new(format('\'%s\' is required and missing!', var)) if(variable.nil? && required == true )
|
30
30
|
|
31
31
|
unless( type.nil? )
|
32
32
|
clazz = Object.const_get(type.to_s)
|
data/lib/grafana/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: grafana
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bodo Schulz
|
@@ -215,10 +215,12 @@ extra_rdoc_files: []
|
|
215
215
|
files:
|
216
216
|
- LICENSE
|
217
217
|
- README.md
|
218
|
+
- lib/_logging.rb_
|
218
219
|
- lib/grafana.rb
|
219
220
|
- lib/grafana/admin.rb
|
220
221
|
- lib/grafana/alerts.rb
|
221
222
|
- lib/grafana/annotations.rb
|
223
|
+
- lib/grafana/auth.rb
|
222
224
|
- lib/grafana/client.rb
|
223
225
|
- lib/grafana/dashboard.rb
|
224
226
|
- lib/grafana/dashboard_permissions.rb
|
@@ -227,6 +229,7 @@ files:
|
|
227
229
|
- lib/grafana/folder.rb
|
228
230
|
- lib/grafana/folder_and_dashboard_search.rb
|
229
231
|
- lib/grafana/folder_permissions.rb
|
232
|
+
- lib/grafana/logging.rb
|
230
233
|
- lib/grafana/login.rb
|
231
234
|
- lib/grafana/network.rb
|
232
235
|
- lib/grafana/organization.rb
|
@@ -241,7 +244,6 @@ files:
|
|
241
244
|
- lib/grafana/users.rb
|
242
245
|
- lib/grafana/validator.rb
|
243
246
|
- lib/grafana/version.rb
|
244
|
-
- lib/logging.rb
|
245
247
|
- lib/monkey_patches.rb
|
246
248
|
homepage: http://github.com/bodsch/ruby-grafana
|
247
249
|
licenses:
|
data/lib/logging.rb
DELETED
@@ -1,35 +0,0 @@
|
|
1
|
-
|
2
|
-
require 'logger'
|
3
|
-
|
4
|
-
# -------------------------------------------------------------------------------------------------
|
5
|
-
|
6
|
-
module Logging
|
7
|
-
|
8
|
-
def logger
|
9
|
-
@logger ||= Logging.logger_for( self.class.name )
|
10
|
-
end
|
11
|
-
|
12
|
-
# Use a hash class-ivar to cache a unique Logger per class:
|
13
|
-
@loggers = {}
|
14
|
-
|
15
|
-
class << self
|
16
|
-
def logger_for( classname )
|
17
|
-
@loggers[classname] ||= configure_logger_for( classname )
|
18
|
-
end
|
19
|
-
|
20
|
-
def configure_logger_for( classname )
|
21
|
-
|
22
|
-
logger = Logger.new(STDOUT)
|
23
|
-
logger.progname = classname
|
24
|
-
logger.level = Logger::DEBUG
|
25
|
-
logger.datetime_format = '%Y-%m-%d %H:%M:%S::%3N'
|
26
|
-
logger.formatter = proc do |severity, datetime, progname, msg|
|
27
|
-
"[#{datetime.strftime( logger.datetime_format )}] #{severity.ljust(5)} : #{progname} - #{msg}\n"
|
28
|
-
end
|
29
|
-
|
30
|
-
logger
|
31
|
-
end
|
32
|
-
end
|
33
|
-
end
|
34
|
-
|
35
|
-
# -------------------------------------------------------------------------------------------------
|