grafana 0.8.2
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 +7 -0
- data/LICENSE +21 -0
- data/README.md +36 -0
- data/doc/Array.html +200 -0
- data/doc/Boolean.html +122 -0
- data/doc/FalseClass.html +132 -0
- data/doc/Grafana.html +172 -0
- data/doc/Hash.html +212 -0
- data/doc/Logging.html +326 -0
- data/doc/Object.html +286 -0
- data/doc/Time.html +200 -0
- data/doc/TrueClass.html +132 -0
- data/doc/_index.html +380 -0
- data/doc/class_list.html +51 -0
- data/doc/file.README.html +117 -0
- data/doc/file_list.html +56 -0
- data/doc/frames.html +17 -0
- data/doc/index.html +117 -0
- data/doc/method_list.html +771 -0
- data/doc/top-level-namespace.html +112 -0
- data/lib/grafana.rb +7 -0
- data/lib/grafana/admin.rb +310 -0
- data/lib/grafana/alerts.rb +38 -0
- data/lib/grafana/annotations.rb +40 -0
- data/lib/grafana/client.rb +126 -0
- data/lib/grafana/dashboard.rb +149 -0
- data/lib/grafana/dashboard_versions.rb +30 -0
- data/lib/grafana/datasource.rb +271 -0
- data/lib/grafana/login.rb +139 -0
- data/lib/grafana/network.rb +169 -0
- data/lib/grafana/organization.rb +101 -0
- data/lib/grafana/organizations.rb +406 -0
- data/lib/grafana/snapshot.rb +47 -0
- data/lib/grafana/tags.rb +41 -0
- data/lib/grafana/tools.rb +66 -0
- data/lib/grafana/user.rb +116 -0
- data/lib/grafana/users.rb +122 -0
- data/lib/grafana/validator.rb +28 -0
- data/lib/grafana/version.rb +17 -0
- data/lib/logging.rb +35 -0
- data/lib/monkey_patches.rb +92 -0
- metadata +294 -0
@@ -0,0 +1,47 @@
|
|
1
|
+
|
2
|
+
module Grafana
|
3
|
+
|
4
|
+
# http://docs.grafana.org/http_api/snapshot/
|
5
|
+
#
|
6
|
+
module Snapshot
|
7
|
+
|
8
|
+
# Get Snapshot by Id
|
9
|
+
# GET /api/snapshots/:key
|
10
|
+
def snapshot(key)
|
11
|
+
|
12
|
+
raise ArgumentError.new('key must be an String') unless( key.is_a?(String) )
|
13
|
+
|
14
|
+
endpoint = format('/api/snapshot/%s', key)
|
15
|
+
@logger.debug("Get Snapshot by Id #{key} (GET #{endpoint})") if @debug
|
16
|
+
|
17
|
+
get(endpoint)
|
18
|
+
end
|
19
|
+
|
20
|
+
# Create new snapshot
|
21
|
+
# POST /api/snapshots
|
22
|
+
def create_snapshot( dashboard = {} )
|
23
|
+
|
24
|
+
raise ArgumentError.new('dashboard must be an Hash') unless( dashboard.is_a?(String) )
|
25
|
+
|
26
|
+
endpoint = '/api/snapshot'
|
27
|
+
@logger.debug("Creating dashboard snapshot (POST #{endpoint})") if @debug
|
28
|
+
|
29
|
+
post(endpoint, dashboard)
|
30
|
+
end
|
31
|
+
|
32
|
+
|
33
|
+
# Delete Snapshot by Id
|
34
|
+
# GET /api/snapshots-delete/:key
|
35
|
+
def delete_snapshot(key)
|
36
|
+
|
37
|
+
raise ArgumentError.new('key must be an String') unless( key.is_a?(String) )
|
38
|
+
|
39
|
+
endpoint = format( '/api/snapshots-delete/%s', key)
|
40
|
+
@logger.debug("Deleting snapshot id #{key} (GET #{endpoint})") if @debug
|
41
|
+
|
42
|
+
delete(endpoint)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
data/lib/grafana/tags.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
module Grafana
|
2
|
+
|
3
|
+
module Tags
|
4
|
+
|
5
|
+
# expand the Template Tags
|
6
|
+
#
|
7
|
+
#
|
8
|
+
#
|
9
|
+
def expand_tags( params )
|
10
|
+
|
11
|
+
raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
|
12
|
+
|
13
|
+
dashboard = params.dig(:dashboard)
|
14
|
+
additional_tags = params.dig(:additional_tags) || []
|
15
|
+
|
16
|
+
raise ArgumentError.new(format('wrong type. \'dashboard\' must be an Hash, given \'%s\'', dashboard.class.to_s)) unless( dashboard.is_a?(Hash) )
|
17
|
+
raise ArgumentError.new(format('wrong type. \'additional_tags\' must be an Array, given \'%s\'', additional_tags.class.to_s)) unless( additional_tags.is_a?(Array) )
|
18
|
+
|
19
|
+
# add tags
|
20
|
+
# dashboard = JSON.parse( dashboard ) if( dashboard.is_a?( String ) )
|
21
|
+
|
22
|
+
additional_tags = additional_tags.values if( additional_tags.is_a?( Hash ) )
|
23
|
+
|
24
|
+
current_tags = dashboard.dig( 'dashboard', 'tags' )
|
25
|
+
|
26
|
+
if( !current_tags.nil? && additional_tags.count > 0 )
|
27
|
+
|
28
|
+
current_tags << additional_tags
|
29
|
+
|
30
|
+
current_tags.flatten!
|
31
|
+
current_tags.sort!
|
32
|
+
|
33
|
+
dashboard['dashboard']['tags'] = current_tags
|
34
|
+
end
|
35
|
+
|
36
|
+
JSON.generate( dashboard ) if( dashboard.is_a?( Hash ) )
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
|
2
|
+
module Grafana
|
3
|
+
|
4
|
+
module Tools
|
5
|
+
|
6
|
+
def slug( text )
|
7
|
+
|
8
|
+
raise ArgumentError.new(format('wrong type. \'text\' must be an String, given \'%s\'', text.class.to_s)) unless( text.is_a?(String) )
|
9
|
+
|
10
|
+
begin
|
11
|
+
if( text =~ /\s/ && text =~ /-/ )
|
12
|
+
# if( text =~ /-/ )
|
13
|
+
text = text.gsub( /\s+/, '' )
|
14
|
+
else
|
15
|
+
text = text.gsub( /\s+/, '-' )
|
16
|
+
# end
|
17
|
+
end
|
18
|
+
|
19
|
+
rescue => e
|
20
|
+
puts e
|
21
|
+
end
|
22
|
+
|
23
|
+
text.downcase
|
24
|
+
end
|
25
|
+
|
26
|
+
|
27
|
+
def regenerate_template_ids( params )
|
28
|
+
|
29
|
+
raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
|
30
|
+
|
31
|
+
rows = params.dig('dashboard','rows')
|
32
|
+
|
33
|
+
unless( rows.nil? )
|
34
|
+
|
35
|
+
# counter = 1
|
36
|
+
id_counter = 10
|
37
|
+
rows.each_with_index do |r, _counter|
|
38
|
+
|
39
|
+
panel = r.dig('panels')
|
40
|
+
|
41
|
+
next if( panel.nil? )
|
42
|
+
|
43
|
+
panel.each do |p|
|
44
|
+
p['id'] = id_counter
|
45
|
+
id_counter = id_counter +=1 # id_counter+1 # id_counter +=1 ??
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
JSON.generate( params )
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
def valid_json?( json )
|
55
|
+
begin
|
56
|
+
JSON.parse( json )
|
57
|
+
return true
|
58
|
+
rescue JSON::ParserError => e
|
59
|
+
@logger.error("json parse error: #{e}") if @debug
|
60
|
+
return false
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
data/lib/grafana/user.rb
ADDED
@@ -0,0 +1,116 @@
|
|
1
|
+
|
2
|
+
module Grafana
|
3
|
+
|
4
|
+
# http://docs.grafana.org/http_api/user/
|
5
|
+
#
|
6
|
+
module User
|
7
|
+
|
8
|
+
# Actual User
|
9
|
+
# GET /api/user
|
10
|
+
def current_user
|
11
|
+
endpoint = '/api/user'
|
12
|
+
@logger.debug("Getting user current user (GET #{endpoint})") if @debug
|
13
|
+
get(endpoint)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Change Password
|
17
|
+
# PUT /api/user/password
|
18
|
+
def update_current_user_password( params )
|
19
|
+
|
20
|
+
raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
|
21
|
+
|
22
|
+
old_password = params.dig(:old_password)
|
23
|
+
new_password = params.dig(:new_password)
|
24
|
+
|
25
|
+
raise ArgumentError.new('missing old_password for update') if( old_password.nil? )
|
26
|
+
raise ArgumentError.new('missing new_password for update') if( new_password.nil? )
|
27
|
+
|
28
|
+
endpoint = '/api/user/password'
|
29
|
+
@logger.debug("Updating current user password (PUT #{endpoint})") if @debug
|
30
|
+
put( endpoint, { oldPassword: old_password, newPassword: new_password, confirmNew: new_password }.to_json )
|
31
|
+
end
|
32
|
+
|
33
|
+
# Switch user context for signed in user
|
34
|
+
# POST /api/user/using/:organizationId
|
35
|
+
def switch_current_user_organization( organization )
|
36
|
+
|
37
|
+
raise ArgumentError.new('organization must be an String') unless( params.is_a?(String) )
|
38
|
+
|
39
|
+
org = organization_by_name( organization )
|
40
|
+
|
41
|
+
if org.nil? || org.dig('status').to_i != 200
|
42
|
+
return {
|
43
|
+
'status' => 404,
|
44
|
+
'message' => format('Organization \'%s\' not found', organization)
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
org_id = org.dig('id')
|
49
|
+
|
50
|
+
endpoint = format( '/api/user/using/%d', org_id )
|
51
|
+
@logger.debug("Switching current user to Organization #{organization} (GET #{endpoint})") if @debug
|
52
|
+
|
53
|
+
post( endpoint, {} )
|
54
|
+
end
|
55
|
+
|
56
|
+
# Organisations of the actual User
|
57
|
+
# GET /api/user/orgs
|
58
|
+
def current_user_oganizations
|
59
|
+
|
60
|
+
endpoint = '/api/user/orgs'
|
61
|
+
@logger.debug("Getting current user organizations (GET #{endpoint})") if @debug
|
62
|
+
get(endpoint)
|
63
|
+
end
|
64
|
+
|
65
|
+
# Star a dashboard
|
66
|
+
# POST /api/user/stars/dashboard/:dashboardId
|
67
|
+
def add_dashboard_star( dashboard )
|
68
|
+
|
69
|
+
if( !dashboard.is_a?(String) && !dashboard.is_a?(Integer) )
|
70
|
+
raise ArgumentError.new('dashboard must be an String (for an Dashboard name) or an Integer (for an Dashboard ID)')
|
71
|
+
end
|
72
|
+
|
73
|
+
dashboard_id = dashboard if(dashboard.is_a?(Integer))
|
74
|
+
|
75
|
+
if(dashboard.is_a?(String))
|
76
|
+
search = { query: dashboard }
|
77
|
+
r = search_dashboards( search )
|
78
|
+
message = r.dig('message')
|
79
|
+
dashboard_id = message.first.dig('id')
|
80
|
+
end
|
81
|
+
|
82
|
+
raise format('Dashboard id can not be 0') if dashboard_id.zero?
|
83
|
+
|
84
|
+
endpoint = format( '/api/user/stars/dashboard/%d', dashboard_id )
|
85
|
+
@logger.debug("Adding star to dashboard id #{dashboard_id} (GET #{endpoint})") if @debug
|
86
|
+
post(endpoint, {}.to_json)
|
87
|
+
end
|
88
|
+
|
89
|
+
# Unstar a dashboard
|
90
|
+
# DELETE /api/user/stars/dashboard/:dashboardId
|
91
|
+
def remove_dashboard_star( dashboard )
|
92
|
+
|
93
|
+
if( !dashboard.is_a?(String) && !dashboard.is_a?(Integer) )
|
94
|
+
raise ArgumentError.new('dashboard must be an String (for an Dashboard name) or an Integer (for an Dashboard ID)')
|
95
|
+
end
|
96
|
+
|
97
|
+
dashboard_id = dashboard if(dashboard.is_a?(Integer))
|
98
|
+
|
99
|
+
if(dashboard.is_a?(String))
|
100
|
+
|
101
|
+
search = { query: dashboard }
|
102
|
+
r = search_dashboards( search )
|
103
|
+
message = r.dig('message')
|
104
|
+
dashboard_id = message.first.dig('id')
|
105
|
+
end
|
106
|
+
|
107
|
+
raise format('Dashboard Id can not be 0') if dashboard_id.zero?
|
108
|
+
|
109
|
+
endpoint = format( '/api/user/stars/dashboard/%d', dashboard_id )
|
110
|
+
@logger.debug("Deleting star on dashboard id #{dashboard_id} (GET #{endpoint})") if @debug
|
111
|
+
delete( endpoint )
|
112
|
+
end
|
113
|
+
|
114
|
+
end
|
115
|
+
|
116
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
|
2
|
+
module Grafana
|
3
|
+
|
4
|
+
# http://docs.grafana.org/http_api/user/
|
5
|
+
#
|
6
|
+
module Users
|
7
|
+
|
8
|
+
# Search Users
|
9
|
+
# GET /api/users
|
10
|
+
def all_users
|
11
|
+
endpoint = '/api/users'
|
12
|
+
@logger.debug("Getting all users (GET #{endpoint})") if @debug
|
13
|
+
get(endpoint)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Get single user by Id
|
17
|
+
# GET /api/users/:id
|
18
|
+
def user_by_id(id)
|
19
|
+
|
20
|
+
raise ArgumentError.new('id must be an Integer') unless( id.is_a?(Integer) )
|
21
|
+
|
22
|
+
endpoint = format( '/api/users/%d', id )
|
23
|
+
@logger.debug("Getting user by Id #{id} (GET #{endpoint})") if @debug
|
24
|
+
get(endpoint)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Get single user by Username(login) or Email
|
28
|
+
# GET /api/users/lookup?loginOrEmail=user@mygraf.com
|
29
|
+
def user_by_name( name )
|
30
|
+
|
31
|
+
endpoint = format( '/api/users/lookup?loginOrEmail=%s', URI.escape( name ) )
|
32
|
+
@logger.debug("Get User by Name (GET #{endpoint})") if @debug
|
33
|
+
get( endpoint )
|
34
|
+
end
|
35
|
+
|
36
|
+
#
|
37
|
+
#
|
38
|
+
def search_for_users_by( params )
|
39
|
+
|
40
|
+
raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
|
41
|
+
|
42
|
+
all_users = self.all_users()
|
43
|
+
key, value = params.first
|
44
|
+
|
45
|
+
logger.debug("Searching for users matching '#{key}' = '#{value}'") if @debug
|
46
|
+
users = []
|
47
|
+
|
48
|
+
all_users.dig('message').each do |u|
|
49
|
+
users.push(u) if u.select { |_k,v| v == value }.count >= 1
|
50
|
+
end
|
51
|
+
|
52
|
+
(users.length >= 1 ? users : false)
|
53
|
+
end
|
54
|
+
|
55
|
+
# User Update
|
56
|
+
# PUT /api/users/:id
|
57
|
+
def update_user( params = {} )
|
58
|
+
|
59
|
+
raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
|
60
|
+
|
61
|
+
user_name = params.dig(:user_name)
|
62
|
+
|
63
|
+
raise ArgumentError.new('missing \'user_name\'') if( user_name.nil? )
|
64
|
+
|
65
|
+
if( !user_name.is_a?(String) && !user_name.is_a?(Integer) )
|
66
|
+
raise ArgumentError.new('user_name must be an String (for an Username) or an Integer (for an User Id)')
|
67
|
+
end
|
68
|
+
|
69
|
+
usr = user_by_id(user_name) if(user_name.is_a?(Integer))
|
70
|
+
usr = user_by_name(user_name) if(user_name.is_a?(String))
|
71
|
+
|
72
|
+
if usr.nil? || usr.dig('status').to_i != 200
|
73
|
+
return {
|
74
|
+
'status' => 404,
|
75
|
+
'message' => format('User \'%s\' not found', user_name)
|
76
|
+
}
|
77
|
+
end
|
78
|
+
|
79
|
+
user_id = usr.dig('id')
|
80
|
+
|
81
|
+
endpoint = format( '/api/users/%d', user_id )
|
82
|
+
|
83
|
+
@logger.debug("Updating user with Id #{user_id}") if @debug
|
84
|
+
|
85
|
+
usr = usr.deep_string_keys
|
86
|
+
params = params.deep_string_keys
|
87
|
+
|
88
|
+
params = usr.merge(params)
|
89
|
+
|
90
|
+
put( endpoint, params.to_json )
|
91
|
+
end
|
92
|
+
|
93
|
+
# Get Organisations for user
|
94
|
+
# GET /api/users/:id/orgs
|
95
|
+
def user_organizations(user)
|
96
|
+
|
97
|
+
if( !user.is_a?(String) && !user.is_a?(Integer) )
|
98
|
+
raise ArgumentError.new('user must be an String (for an Dashboard name) or an Integer (for an Dashboard ID)')
|
99
|
+
end
|
100
|
+
|
101
|
+
usr = user_by_id(user) if(user.is_a?(Integer))
|
102
|
+
usr = user_by_name(user) if(user.is_a?(String))
|
103
|
+
|
104
|
+
if usr.nil? || usr.dig('status').to_i != 200
|
105
|
+
return {
|
106
|
+
'status' => 404,
|
107
|
+
'message' => format('User \'%s\' not found', user)
|
108
|
+
}
|
109
|
+
end
|
110
|
+
|
111
|
+
user_id = usr.dig('id')
|
112
|
+
|
113
|
+
endpoint = format('/api/users/%d/orgs', user_id )
|
114
|
+
@logger.debug("Getting organizations for User #{user} (GET #{endpoint})") if @debug
|
115
|
+
get(endpoint)
|
116
|
+
end
|
117
|
+
|
118
|
+
# Switch user context for a specified user
|
119
|
+
# POST /api/users/:userId/using/:organizationId
|
120
|
+
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
|
2
|
+
module Grafana
|
3
|
+
|
4
|
+
# namespace for validate options
|
5
|
+
module Validator
|
6
|
+
|
7
|
+
# validate( params, { required: true, var: name, type: String } )
|
8
|
+
def validate( params, options )
|
9
|
+
required = options.dig(:required) || false
|
10
|
+
var = options.dig(:var)
|
11
|
+
type = options.dig(:type)
|
12
|
+
|
13
|
+
params = params.deep_symbolize_keys
|
14
|
+
variable = params.dig(var.to_sym)
|
15
|
+
|
16
|
+
raise ArgumentError.new(format('\'%s\' is requiered and missing!', var)) if(variable.nil?) if(required == true )
|
17
|
+
|
18
|
+
unless( type.nil? )
|
19
|
+
clazz = Object.const_get(type.to_s)
|
20
|
+
raise ArgumentError.new(format('wrong type. \'%s\' must be an %s, given \'%s\'', var, type, variable.class.to_s)) unless( variable.nil? || variable.is_a?(clazz) )
|
21
|
+
end
|
22
|
+
|
23
|
+
variable
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Grafana
|
2
|
+
|
3
|
+
# namespace for version information
|
4
|
+
module Version
|
5
|
+
|
6
|
+
# major part of version
|
7
|
+
MAJOR = 0
|
8
|
+
# minor part of version
|
9
|
+
MINOR = 8
|
10
|
+
# tiny part of version
|
11
|
+
TINY = 2
|
12
|
+
end
|
13
|
+
|
14
|
+
# Current version of gem.
|
15
|
+
VERSION = [Version::MAJOR, Version::MINOR, Version::TINY].compact * '.'
|
16
|
+
|
17
|
+
end
|
data/lib/logging.rb
ADDED
@@ -0,0 +1,35 @@
|
|
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
|
+
# -------------------------------------------------------------------------------------------------
|