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