grafana 0.8.2 → 1.0.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 (44) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +8 -3
  3. data/lib/grafana/admin.rb +39 -65
  4. data/lib/grafana/alerts.rb +334 -14
  5. data/lib/grafana/annotations.rb +284 -9
  6. data/lib/grafana/client.rb +38 -1
  7. data/lib/grafana/dashboard.rb +182 -39
  8. data/lib/grafana/dashboard_permissions.rb +132 -0
  9. data/lib/grafana/dashboard_versions.rb +101 -5
  10. data/lib/grafana/datasource.rb +93 -49
  11. data/lib/grafana/folder.rb +198 -0
  12. data/lib/grafana/folder_and_dashboard_search.rb +57 -0
  13. data/lib/grafana/folder_permissions.rb +155 -0
  14. data/lib/grafana/login.rb +41 -35
  15. data/lib/grafana/network.rb +128 -91
  16. data/lib/grafana/organization.rb +65 -34
  17. data/lib/grafana/organizations.rb +119 -175
  18. data/lib/grafana/playlist.rb +599 -0
  19. data/lib/grafana/preferences.rb +122 -0
  20. data/lib/grafana/tags.rb +19 -8
  21. data/lib/grafana/teams.rb +364 -0
  22. data/lib/grafana/tools.rb +44 -12
  23. data/lib/grafana/user.rb +78 -39
  24. data/lib/grafana/users.rb +104 -53
  25. data/lib/grafana/validator.rb +47 -2
  26. data/lib/grafana/version.rb +3 -3
  27. metadata +13 -38
  28. data/doc/Array.html +0 -200
  29. data/doc/Boolean.html +0 -122
  30. data/doc/FalseClass.html +0 -132
  31. data/doc/Grafana.html +0 -172
  32. data/doc/Hash.html +0 -212
  33. data/doc/Logging.html +0 -326
  34. data/doc/Object.html +0 -286
  35. data/doc/Time.html +0 -200
  36. data/doc/TrueClass.html +0 -132
  37. data/doc/_index.html +0 -380
  38. data/doc/class_list.html +0 -51
  39. data/doc/file.README.html +0 -117
  40. data/doc/file_list.html +0 -56
  41. data/doc/frames.html +0 -17
  42. data/doc/index.html +0 -117
  43. data/doc/method_list.html +0 -771
  44. data/doc/top-level-namespace.html +0 -112
@@ -3,77 +3,151 @@ module Grafana
3
3
 
4
4
  module Network
5
5
 
6
+ # GET request
7
+ #
8
+ # @param endpoint [String]
9
+ #
6
10
  def get( endpoint )
7
-
8
11
  request( 'GET', endpoint )
9
12
  end
10
13
 
14
+ # POST request
15
+ #
16
+ # @param endpoint [String]
17
+ # @param data [Hash]
18
+ #
11
19
  def post( endpoint, data )
12
-
13
20
  request( 'POST', endpoint, data )
14
21
  end
15
22
 
23
+ # PUT request
24
+ #
25
+ # @param endpoint [String]
26
+ # @param data [Hash]
27
+ #
16
28
  def put( endpoint, data )
17
-
18
29
  request( 'PUT', endpoint, data )
19
30
  end
20
31
 
32
+ # PATCH request
33
+ #
34
+ # @param endpoint [String]
35
+ # @param data [Hash]
36
+ #
21
37
  def patch( endpoint, data )
22
-
23
38
  request( 'PATCH', endpoint, data )
24
39
  end
25
40
 
41
+ # DELETE request
42
+ #
43
+ # @param endpoint [String]
44
+ #
26
45
  def delete( endpoint )
27
-
28
46
  request( 'DELETE', endpoint )
29
47
  end
30
48
 
49
+
50
+ private
51
+ # helper function for all request methods
52
+ #
53
+ # @param method_type [String]
54
+ # @param endpoint [String]
55
+ # @param data [Hash]
56
+ #
57
+ # @example
58
+ #
59
+ #
60
+ # @return [Hash]
61
+ #
31
62
  def request( method_type = 'GET', endpoint = '/', data = {} )
32
63
 
33
- raise 'try first login()' if @api_instance.nil?
64
+ raise 'try first login()' if @api_instance.nil?
65
+
66
+ login( username: @username, password: @password )
34
67
 
35
68
  response = nil
36
69
  response_code = 404
37
70
  response_body = ''
38
71
 
39
72
  begin
40
-
41
73
  case method_type.upcase
42
74
  when 'GET'
43
- response = @api_instance[endpoint].get( @headers )
75
+ response = @api_instance[endpoint].get( headers )
44
76
  when 'POST'
45
- response = @api_instance[endpoint].post( data, @headers )
77
+ response = @api_instance[endpoint].post( data, headers )
46
78
  when 'PATCH'
47
- response = @api_instance[endpoint].patch( data, @headers )
79
+ response = @api_instance[endpoint].patch( data, headers )
48
80
  when 'PUT'
49
- # response = @api_instance[endpoint].put( data, @headers )
50
- @api_instance[endpoint].put( data, @headers ) do |response, request, result|
51
81
 
52
- case response.code
82
+ # response = @api_instance[endpoint].put( data, headers )
83
+ @api_instance[endpoint].put( data, headers ) do |resp, _request, _result|
84
+
85
+ response_code = resp.code.to_i
86
+ response_body = resp.body
87
+ response_body = JSON.parse(response_body) if response_body.is_a?(String)
88
+
89
+ #logger.debug( "code : #{response_code}" )
90
+ #logger.debug( "message: #{response_body}" )
91
+
92
+ case response_code.to_i
53
93
  when 200
54
- response_body = response.body
55
- response_code = response.code.to_i
56
- response_body = JSON.parse(response_body) if response_body.is_a?(String)
57
-
58
- return {
59
- 'status' => response_code,
60
- 'message' => response_body.dig('message').nil? ? 'Successful' : response_body.dig('message')
61
- }
94
+ return { 'status' => response_code, 'message' => response_body.dig('message').nil? ? 'Successful' : response_body.dig('message') }
62
95
  when 400
63
- response_body = response.body
64
- response_code = response.code.to_i
65
96
  raise RestClient::BadRequest
97
+ when 412
98
+ status = response_body.dig('status')
99
+ message = response_body.dig('message')
100
+ message += " (#{status})" unless(status.nil?)
101
+ return { 'status' => response_code, 'message' => message }
102
+ when 422
103
+ logger.error('422')
104
+
105
+ response_body = response_body.first if(response_body.is_a?(Array))
106
+ message_field_name = response_body.dig('fieldNames')
107
+
108
+ #status = response_code # response_body.dig('status')
109
+ message = response_body # .dig('message')
110
+ #message += " (#{status})" unless(status.nil?)
111
+
112
+ # [{fieldNames"=>["Id"], "classification"=>"RequiredError", "message"=>"Required"}]
113
+
114
+ logger.error(message)
115
+ return { 'status' => response_code, 'message' => message }
116
+ # #raise RestClient::UnprocessableEntity
66
117
  else
67
- logger.error( response.code )
68
- logger.error( response.body )
69
- response.return! # (request, result)
118
+ # logger.error( response_code )
119
+ # logger.error( response_body )
120
+ return { 'status' => response_code, 'message' => response_body.dig('message') }
121
+ # response.return! # (request, result)
70
122
  end
71
123
  end
72
124
 
73
125
  when 'DELETE'
74
- response = @api_instance[endpoint].delete( @headers )
126
+
127
+ @api_instance[endpoint].delete( headers ) do |resp, _request, _result|
128
+
129
+ response_code = resp.code.to_i
130
+ response_body = resp.body
131
+ response_body = JSON.parse(response_body) if response_body.is_a?(String)
132
+
133
+ #logger.debug( "code : #{response_code}" )
134
+ #logger.debug( "message: #{response_body}" )
135
+
136
+ case response_code.to_i
137
+ when 200
138
+ return { 'status' => response_code, 'message' => response_body.dig('message').nil? ? 'Successful' : response_body.dig('message') }
139
+ when 404
140
+ return { 'status' => response_code, 'message' => response_body.dig('message').nil? ? 'Successful' : response_body.dig('message') }
141
+ else
142
+ # logger.error( response_code )
143
+ # logger.error( response_body )
144
+ return { 'status' => response_code, 'message' => response_body.dig('message') }
145
+ end
146
+
147
+ end
148
+
75
149
  else
76
- @logger.error( "Error: #{__method__} is not a valid request method." )
150
+ logger.error( "Error: #{__method__} is not a valid request method." )
77
151
  return false
78
152
  end
79
153
 
@@ -81,89 +155,52 @@ module Grafana
81
155
  response_body = response.body
82
156
  response_headers = response.headers
83
157
 
84
- if( @debug )
85
- logger.debug("response_code : #{response_code}" )
86
- logger.debug("response_body : #{response_body}" )
87
- logger.debug("response_headers : #{response_headers}" )
88
- end
89
-
90
158
  if( ( response_code >= 200 && response_code <= 299 ) || ( response_code >= 400 && response_code <= 499 ) )
91
159
 
92
- result = JSON.parse( response_body )
93
-
94
- if( result.is_a?(Array) )
95
- r_result= {
96
- 'status' => response_code,
97
- 'message' => result
98
- }
99
- return r_result
160
+ if( response_body =~ /^\[.*\]$/ || response_body =~ /^\{.*\}$/ )
161
+ result = JSON.parse( response_body )
162
+ return { 'status' => response_code, 'message' => result } if( result.is_a?(Array) )
163
+ else
164
+ return { 'status' => response_code, 'message' => response_body }
100
165
  end
101
166
 
102
- result_status = result.dig('status') if( result.is_a?( Hash ) )
103
-
167
+ result_status = result.dig('status') if( result.is_a?( Hash ) )
104
168
  result['message'] = result_status unless( result_status.nil? )
105
169
  result['status'] = response_code
106
170
 
107
171
  return result
108
172
  else
109
-
110
- @logger.error( "#{__method__} #{method_type.upcase} on #{endpoint} failed: HTTP #{response.code} - #{response_body}" )
111
- @logger.error( @headers )
112
- @logger.error( JSON.pretty_generate( response_headers ) )
173
+ logger.error( "#{__method__} #{method_type.upcase} on #{endpoint} failed: HTTP #{response.code} - #{response_body}" )
174
+ logger.error( headers )
175
+ logger.error( JSON.pretty_generate( response_headers ) )
113
176
 
114
177
  return JSON.parse( response_body )
115
178
  end
116
179
 
117
180
  rescue RestClient::BadRequest
118
-
119
181
  response_body = JSON.parse(response_body) if response_body.is_a?(String)
120
-
121
- return {
122
- 'status' => 400,
123
- 'message' => response_body.dig('message').nil? ? 'Bad Request' : response_body.dig('message')
124
- }
125
-
182
+ return { 'status' => 400, 'message' => response_body.dig('message').nil? ? 'Bad Request' : response_body.dig('message') }
126
183
  rescue RestClient::Unauthorized
127
-
128
- return {
129
- 'status' => 401,
130
- 'message' => format('Not authorized to connect \'%s/%s\' - wrong username or password?', @url, endpoint)
131
- }
132
-
184
+ return { 'status' => 401, 'message' => format('Not authorized to connect \'%s/%s\' - wrong username or password?', @url, endpoint) }
185
+ rescue RestClient::Forbidden
186
+ return { 'status' => 403, 'message' => format('The operation is forbidden \'%s/%s\'', @url, endpoint) }
133
187
  rescue RestClient::NotFound
134
-
135
- return {
136
- 'status' => 404,
137
- 'message' => 'Not Found'
138
- }
139
-
188
+ return { 'status' => 404, 'message' => 'Not Found' }
140
189
  rescue RestClient::Conflict
141
-
142
- return {
143
- 'status' => 409,
144
- 'message' => 'Conflict with the current state of the target resource'
145
- }
146
-
190
+ return { 'status' => 409, 'message' => 'Conflict with the current state of the target resource' }
147
191
  rescue RestClient::PreconditionFailed
148
-
149
- return {
150
- 'status' => 412,
151
- 'message' => 'Precondition failed. The Object probably already exists.'
152
- }
153
-
154
- rescue RestClient::ExceptionWithResponse => e
155
-
156
- logger.error( "Error: #{__method__} #{method_type.upcase} on #{endpoint} error: '#{e}'" )
157
- logger.error( data )
158
- logger.error( @headers )
159
- logger.error( JSON.pretty_generate( response_headers ) )
160
-
161
- return false
162
-
192
+ return { 'status' => 412, 'message' => 'Precondition failed. The Object probably already exists.' }
193
+ rescue RestClient::PreconditionFailed
194
+ return { 'status' => 412, 'message' => 'Precondition failed. The Object probably already exists.' }
195
+ rescue RestClient::ExceptionWithResponse => error
196
+ #logger.error( "Error: (RestClient::ExceptionWithResponse) #{__method__} #{method_type.upcase} on #{endpoint} error: '#{error}'" )
197
+ #logger.error( "query: #{data}" )
198
+ return { 'status' => 500, 'message' => "Internal Server Error: #{error}" }
199
+ rescue => error
200
+ #logger.error( "Error: #{__method__} #{method_type.upcase} on #{endpoint} error: '#{error}'" )
201
+ #logger.error( "query: #{data}" )
202
+ return { 'status' => 500, 'message' => "Internal Server Error: #{error}" }
163
203
  end
164
-
165
204
  end
166
-
167
205
  end
168
-
169
206
  end
@@ -6,9 +6,11 @@ module Grafana
6
6
  module Organization
7
7
 
8
8
  # Get current Organisation
9
- # GET /api/org
10
9
  #
11
- # -> {"id"=>1, "name"=>"Docker", "address"=>{"address1"=>"", "address2"=>"", "city"=>"", "zipCode"=>"", "state"=>"", "country"=>""}, "status"=>200}
10
+ # @example
11
+ # current_organization
12
+ #
13
+ # @return [Hash]
12
14
  #
13
15
  def current_organization
14
16
  endpoint = '/api/org'
@@ -17,25 +19,40 @@ module Grafana
17
19
  end
18
20
 
19
21
  # Update current Organisation
20
- # PUT /api/org
21
22
  #
23
+ # @param [Hash] params
24
+ # @option params [String] name new Organisation Name
25
+ #
26
+ # @example
27
+ # params = {
28
+ # name: 'foo'
29
+ # }
30
+ # update_current_organization( params )
22
31
  #
32
+ # @return [Hash]
23
33
  #
24
- def update_current_organization( params = {} )
34
+ def update_current_organization( params )
25
35
 
26
36
  raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
27
- name = params.dig(:name)
28
- raise ArgumentError.new('missing name') if( name.nil? )
37
+ raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
38
+
39
+ name = validate( params, required: true, var: 'name', type: String )
29
40
 
30
41
  endpoint = '/api/org'
42
+ payload = {
43
+ name: name
44
+ }
45
+
31
46
  @logger.debug("Updating current organization (PUT #{endpoint})") if @debug
32
- put(endpoint, params.to_json)
47
+ put(endpoint, payload.to_json)
33
48
  end
34
49
 
35
50
  # Get all users within the actual organisation
36
- # GET /api/org/users
37
51
  #
52
+ # @example
53
+ # current_organization_users
38
54
  #
55
+ # @return [Hash]
39
56
  #
40
57
  def current_organization_users
41
58
  endpoint = '/api/org/users'
@@ -44,46 +61,60 @@ module Grafana
44
61
  end
45
62
 
46
63
  # Add a new user to the actual organisation
47
- # POST /api/org/users
48
64
  #
65
+ # @param [Hash] params
66
+ # @option params [String] login_or_email Login or email
67
+ # @option params [String] role Name of the Role - only 'Viewer', 'Editor', 'Read Only Editor' or 'Admin' allowed
68
+ #
69
+ # @example
70
+ # params = {
71
+ # login_or_email: 'foo',
72
+ # role: 'Editor'
73
+ # }
74
+ # add_user_to_current_organization( params )
49
75
  #
76
+ # @return [Hash]
50
77
  #
51
- def add_user_to_current_organization( params = {} )
78
+ def add_user_to_current_organization( params )
52
79
 
53
80
  raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
54
- login_or_email = params.dig(:loginOrEmail)
55
- role = params.dig(:role)
56
- raise ArgumentError.new('missing loginOrEmail') if( login_or_email.nil? )
57
- raise ArgumentError.new('missing role') if( role.nil? )
58
- # Defaults to Viewer, other valid options are Admin and Editor and Read Only Editor
59
- # valid_perms = ['Viewer','Editor','Read Only Editor','Admin']
60
- raise ArgumentError.new( format( 'wrong role. only \'Admin\', \'Viewer\' or \'Editor\' allowed (\'%s\' giving)',role)) if( %w[Admin Viewer Editor].include?(role) == false )
61
-
62
- org = current_organization_users
63
- usr = user_by_name( login_or_email )
64
-
65
- if( org )
66
-
67
- org = org.dig('message')
81
+ raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
68
82
 
69
- if( org.select { |x| x.dig('email') == login_or_email }.count >= 1 )
70
- return {
71
- 'status' => 404,
72
- 'message' => format('User \'%s\' are already in the organisation', login_or_email)
73
- }
74
- end
75
- end
83
+ login_or_email = validate( params, required: true, var: 'login_or_email', type: String )
84
+ role = validate( params, required: true, var: 'role', type: String )
85
+ valid_roles = ['Viewer', 'Editor', 'Read Only Editor', 'Admin']
76
86
 
77
- if( usr.nil? || usr.dig('status').to_i != 200 )
87
+ # https://stackoverflow.com/questions/9333952/case-insensitive-arrayinclude?answertab=votes#tab-top
88
+ # Do this once, or each time the array changes
89
+ downcased = Set.new valid_roles.map(&:downcase)
90
+ unless( downcased.include?( role.downcase ) )
78
91
  return {
79
92
  'status' => 404,
80
- 'message' => format('User \'%s\' not found', login_or_email)
93
+ 'login_or_email' => login_or_email,
94
+ 'role' => role,
95
+ 'message' => format( 'wrong role. Role must be one of %s, given \'%s\'', valid_roles.join(', '), role )
81
96
  }
82
97
  end
83
98
 
99
+ org = current_organization_users
100
+ usr = user( login_or_email )
101
+
102
+ return { 'status' => 404, 'message' => format('User \'%s\' not found', login_or_email) } if( usr.nil? || usr.dig('status').to_i != 200 )
103
+
104
+ if( org.is_a?(Hash) && org.dig('status').to_i == 200 )
105
+ org = org.dig('message')
106
+ return { 'status' => 404, 'message' => format('User \'%s\' are already in the organisation', login_or_email) } \
107
+ if( org.select { |x| x.dig('email') == login_or_email || x.dig('login') == login_or_email }.count >= 1 )
108
+ end
109
+
84
110
  endpoint = '/api/org/users'
111
+ payload = {
112
+ loginOrEmail: login_or_email,
113
+ role: role
114
+ }
115
+
85
116
  @logger.debug("Adding user to current organization (POST #{endpoint})") if @debug
86
- post(endpoint, params.to_json)
117
+ post(endpoint, payload.to_json)
87
118
  end
88
119
 
89
120
  # Updates the given user
@@ -13,7 +13,6 @@ module Grafana
13
13
  get( endpoint )
14
14
  end
15
15
 
16
-
17
16
  # Get a single data sources by Id or Name
18
17
  #
19
18
  # @example
@@ -24,39 +23,20 @@ module Grafana
24
23
  #
25
24
  def organization( organisation_id )
26
25
 
27
- raise ArgumentError.new(format('wrong type. user \'organisation_id\' must be an String (for an Datasource name) or an Integer (for an Datasource Id), given \'%s\'', organisation_id.class.to_s)) if( organisation_id.is_a?(String) && organisation_id.is_a?(Integer) )
26
+ if( organisation_id.is_a?(String) && organisation_id.is_a?(Integer))
27
+ raise ArgumentError.new(format('wrong type. \'organisation_id\' must be an String (for an Datasource name) ' \
28
+ 'or an Integer (for an Datasource Id), given \'%s\'', organisation_id.class.to_s))
29
+ end
28
30
  raise ArgumentError.new('missing \'organisation_id\'') if( organisation_id.size.zero? )
29
31
 
30
32
  endpoint = format( '/api/orgs/%d', organisation_id ) if(organisation_id.is_a?(Integer))
31
- endpoint = format( '/api/orgs/name/%s', URI.escape( organisation_id ) ) if(organisation_id.is_a?(String))
33
+ endpoint = format( '/api/orgs/name/%s', ERB::Util.url_encode( organisation_id ) ) if(organisation_id.is_a?(String))
32
34
 
33
35
  @logger.debug("Attempting to get existing data source Id #{organisation_id} (GET #{endpoint})") if @debug
34
36
 
35
37
  get(endpoint)
36
38
  end
37
39
 
38
- # # Get Organisation by Id
39
- # # GET /api/orgs/:orgId
40
- # def organization_by_id( id )
41
- #
42
- # raise ArgumentError.new('id must be an Integer') unless( id.is_a?(Integer) )
43
- #
44
- # endpoint = format( '/api/orgs/%d', id )
45
- # @logger.debug("Get Organisation by Id (GET #{endpoint}})") if @debug
46
- # get( endpoint )
47
- # end
48
- #
49
- # # Get Organisation by Name
50
- # # GET /api/orgs/name/:orgName
51
- # def organization_by_name( name )
52
- #
53
- # raise ArgumentError.new('name must be an String') unless( name.is_a?(String) )
54
- #
55
- # endpoint = format( '/api/orgs/name/%s', URI.escape( name ) )
56
- # @logger.debug("Get Organisation by Name (GET #{endpoint})") if @debug
57
- # get( endpoint )
58
- # end
59
-
60
40
  # Update Organisation
61
41
  #
62
42
  # fields Adress 1, Adress 2, City are not implemented yet.
@@ -78,30 +58,25 @@ module Grafana
78
58
  raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
79
59
  raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
80
60
 
81
- organization = validate( params, required: true, var: 'organization', type: String )
82
- name = validate( params, required: true, var: 'name', type: String )
61
+ organization = validate( params, required: true, var: 'organization', type: String )
62
+ name = validate( params, required: true, var: 'name', type: String )
63
+ org = organization( organization )
83
64
 
84
- org = organization( organization )
65
+ return { 'status' => 404, 'message' => format('Organization \'%s\' not found', organization) } if( org.nil? || org.dig('status').to_i != 200 )
85
66
 
86
- if( org.nil? || org.dig('status').to_i != 200 )
87
- return {
88
- 'status' => 404,
89
- 'message' => format('Organization \'%s\' not found', organization)
90
- }
91
- end
92
- org_id = org.dig('id')
67
+ organization_id = org.dig('id')
93
68
 
69
+ endpoint = format( '/api/orgs/%s', organization_id )
94
70
  payload = { name: name }
95
71
 
96
- endpoint = format( '/api/orgs/%s', org_id )
97
- @logger.debug("Update Organisation id #{org_id} (PUT #{endpoint})") if @debug
72
+ @logger.debug("Update Organisation id #{organization_id} (PUT #{endpoint})") if @debug
98
73
 
99
74
  put( endpoint, payload.to_json )
100
75
  end
101
76
 
102
77
  # Get Users in Organisation
103
78
  #
104
- # @param [Mixed] user_id Username (String) or Userid (Integer) for delete User
79
+ # @param [Mixed] organization_id Organistaion Name (String) or Organistaion Id (Integer)
105
80
  #
106
81
  # @example
107
82
  # organization_users( 1 )
@@ -109,36 +84,35 @@ module Grafana
109
84
  #
110
85
  # @return [Hash]
111
86
  #
112
- def organization_users( org_id )
87
+ def organization_users( organization_id )
113
88
 
114
- raise ArgumentError.new(format('wrong type. user \'org_id\' must be an String (for an Organisation name) or an Integer (for an Organisation Id), given \'%s\'', org_id.class.to_s)) if( org_id.is_a?(String) && org_id.is_a?(Integer) )
115
- raise ArgumentError.new('missing \'org_id\'') if( org_id.size.zero? )
89
+ if( organization_id.is_a?(String) && organization_id.is_a?(Integer))
90
+ raise ArgumentError.new(format('wrong type. \'organization_id\' must be an String (for an Organisation name) '\
91
+ 'or an Integer (for an Organisation Id), given \'%s\'', organization_id.class.to_s))
92
+ end
93
+ raise ArgumentError.new('missing \'organization_id\'') if( organization_id.size.zero? )
116
94
 
117
- if(org_id.is_a?(String))
118
- org = organization(org_id)
119
- if( org.nil? || org.dig('status').to_i != 200 )
120
- return {
121
- 'status' => 404,
122
- 'message' => format('Organization \'%s\' not found', organization)
123
- }
124
- end
125
- org_id = org.dig('id')
95
+ if(organization_id.is_a?(String))
96
+ org = organization(organization_id)
97
+ return { 'status' => 404, 'message' => format('Organization \'%s\' not found', organization) } if( org.nil? || org.dig('status').to_i != 200 )
98
+
99
+ organization_id = org.dig('id')
126
100
  end
127
101
 
128
- endpoint = format( '/api/orgs/%s/users', org_id )
102
+ endpoint = format( '/api/orgs/%s/users', organization_id )
129
103
 
130
- @logger.debug("Getting users in Organisation id #{org_id} (GET #{endpoint})") if @debug
104
+ @logger.debug("Getting users in Organisation id #{organization_id} (GET #{endpoint})") if @debug
131
105
  get(endpoint)
132
106
  end
133
107
 
134
108
  # Add User in Organisation
135
109
  #
136
- # @param
110
+ # @param [Hash] params
137
111
  # @option params [String] organization Organisation name
138
112
  # @option params [String] login_or_email Login or email
139
113
  # @option params [String] role Name of the Role - only 'Viewer', 'Editor', 'Read Only Editor' or 'Admin' allowed
140
114
  #
141
- # @examle
115
+ # @example
142
116
  # params = {
143
117
  # organization: 'Foo',
144
118
  # login_or_email: 'foo@foo-bar.tld',
@@ -150,54 +124,25 @@ module Grafana
150
124
  #
151
125
  def add_user_to_organization( params )
152
126
 
153
- raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
154
- raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
155
-
156
- organization = validate( params, required: true, var: 'organization', type: String )
157
- login_or_email = validate( params, required: true, var: 'login_or_email', type: String )
158
- role = validate( params, required: true, var: 'role', type: String )
159
- valid_roles = ['Viewer', 'Editor', 'Read Only Editor', 'Admin']
160
-
161
- # https://stackoverflow.com/questions/9333952/case-insensitive-arrayinclude?answertab=votes#tab-top
162
- # Do this once, or each time the array changes
163
- downcased = Set.new valid_roles.map(&:downcase)
164
- unless( downcased.include?( role.downcase ) )
165
-
166
- message = format( 'wrong role. Role must be one of %s, given \'%s\'', valid_roles.join(', '), role )
167
-
168
- return {
169
- 'status' => 404,
170
- 'login_or_email' => login_or_email,
171
- 'role' => role,
172
- 'message' => message
173
- }
174
- end
175
-
176
- org = organization( organization )
177
- usr = user_by_name( login_or_email )
127
+ data = validate_organisation_user( params )
128
+ status = data.dig('status')
178
129
 
179
- if( org.nil? || org.dig('status').to_i != 200 )
180
- return {
181
- 'status' => 404,
182
- 'message' => format('Organization \'%s\' not found', organization)
183
- }
184
- end
130
+ return data if( status.nil? || status.to_i == 404 )
185
131
 
186
- if( usr.nil? || usr.dig('status').to_i != 200 )
187
- return {
188
- 'status' => 404,
189
- 'message' => format('User \'%s\' not found', login_or_email)
190
- }
191
- end
132
+ org = data.dig('organisation')
133
+ usr = data.dig('user')
192
134
 
193
- org_id = org.dig('id')
135
+ organization_id = org.dig('id')
136
+ organization = org.dig('name')
137
+ login_or_email = usr.dig('email')
138
+ role = data.dig('role')
194
139
 
140
+ endpoint = format( '/api/orgs/%d/users', organization_id )
195
141
  payload = {
196
142
  loginOrEmail: login_or_email,
197
143
  role: role
198
144
  }
199
145
 
200
- endpoint = format( '/api/orgs/%d/users', org_id )
201
146
  @logger.debug("Adding user '#{login_or_email}' to organisation '#{organization}' (POST #{endpoint})") if @debug
202
147
 
203
148
  post( endpoint, payload.to_json )
@@ -205,12 +150,12 @@ module Grafana
205
150
 
206
151
  # Update Users in Organisation
207
152
  #
208
- # @param
153
+ # @param [Hash] params
209
154
  # @option params [String] organization Organisation name
210
155
  # @option params [String] login_or_email Login or email
211
156
  # @option params [String] role Name of the Role - only 'Viewer', 'Editor', 'Read Only Editor' or 'Admin' allowed
212
157
  #
213
- # @examle
158
+ # @example
214
159
  # params = {
215
160
  # organization: 'Foo',
216
161
  # login_or_email: 'foo@foo-bar.tld',
@@ -222,67 +167,36 @@ module Grafana
222
167
  #
223
168
  def update_organization_user( params )
224
169
 
225
- raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
226
- raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
227
-
228
- organization = validate( params, required: true, var: 'organization', type: String )
229
- login_or_email = validate( params, required: true, var: 'login_or_email', type: String )
230
- role = validate( params, required: true, var: 'role', type: String )
231
- valid_roles = ['Viewer', 'Editor', 'Read Only Editor', 'Admin']
232
-
233
- # https://stackoverflow.com/questions/9333952/case-insensitive-arrayinclude?answertab=votes#tab-top
234
- # Do this once, or each time the array changes
235
- downcased = Set.new valid_roles.map(&:downcase)
236
- unless( downcased.include?( role.downcase ) )
237
-
238
- message = format( 'wrong role. Role must be one of %s, given \'%s\'', valid_roles.join(', '), role )
239
-
240
- return {
241
- 'status' => 404,
242
- 'login_or_email' => login_or_email,
243
- 'role' => role,
244
- 'message' => message
245
- }
246
- end
247
-
248
- org = organization( organization )
249
- usr = user_by_name( login_or_email )
170
+ data = validate_organisation_user( params )
171
+ status = data.dig('status')
250
172
 
251
- if( org.nil? || org.dig('status').to_i != 200 )
252
- return {
253
- 'status' => 404,
254
- 'message' => format('Organization \'%s\' not found', organization)
255
- }
256
- end
173
+ return data if( status.nil? || status.to_i == 404 )
257
174
 
258
- if( usr.nil? || usr.dig('status').to_i != 200 )
259
- return {
260
- 'status' => 404,
261
- 'message' => format('User \'%s\' not found', login_or_email)
262
- }
263
- end
175
+ org = data.dig('organisation')
176
+ usr = data.dig('user')
264
177
 
265
- org_id = org.dig('id')
178
+ organization_id = org.dig('id')
179
+ organization = org.dig('name')
266
180
  usr_id = usr.dig('id')
181
+ login_or_email = usr.dig('name')
182
+ role = data.dig(:role)
267
183
 
184
+ endpoint = format( '/api/orgs/%d/users/%d', organization_id, usr_id )
268
185
  payload = {
269
186
  role: role
270
187
  }
271
188
 
272
- endpoint = format( '/api/orgs/%d/users/%d', org_id, usr_id )
273
-
274
189
  @logger.debug("Updating user '#{login_or_email}' in organization '#{organization}' (PATCH #{endpoint})") if @debug
275
190
  patch( endpoint, payload.to_json )
276
191
  end
277
192
 
278
193
  # Delete User in Organisation
279
194
  #
280
- # @param
195
+ # @param [Hash] params
281
196
  # @option params [String] organization Organisation name
282
197
  # @option params [String] login_or_email Login or email
283
- # @option params [String] role Name of the Role - only 'Viewer', 'Editor', 'Read Only Editor' or 'Admin' allowed
284
198
  #
285
- # @examle
199
+ # @example
286
200
  # params = {
287
201
  # organization: 'Foo',
288
202
  # login_or_email: 'foo@foo-bar.tld'
@@ -291,7 +205,6 @@ module Grafana
291
205
  #
292
206
  # @return [Hash]
293
207
  #
294
- # DELETE /api/orgs/:orgId/users/:userId
295
208
  def delete_user_from_organization( params )
296
209
 
297
210
  raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
@@ -301,26 +214,15 @@ module Grafana
301
214
  login_or_email = validate( params, required: true, var: 'login_or_email', type: String )
302
215
 
303
216
  org = organization( organization )
304
- usr = user_by_name( login_or_email )
305
-
306
- if( org.nil? || org.dig('status').to_i != 200 )
307
- return {
308
- 'status' => 404,
309
- 'message' => format('Organization \'%s\' not found', organization)
310
- }
311
- end
217
+ usr = user( login_or_email )
312
218
 
313
- if( usr.nil? || usr.dig('status').to_i != 200 )
314
- return {
315
- 'status' => 404,
316
- 'message' => format('User \'%s\' not found', login_or_email)
317
- }
318
- end
219
+ return { 'status' => 404, 'message' => format('Organization \'%s\' not found', organization) } if( org.nil? || org.dig('status').to_i != 200 )
220
+ return { 'status' => 404, 'message' => format('User \'%s\' not found', login_or_email) } if( usr.nil? || usr.dig('status').to_i != 200 )
319
221
 
320
- org_id = org.dig('id')
222
+ organization_id = org.dig('id')
321
223
  usr_id = usr.dig('id')
322
224
 
323
- endpoint = format( '/api/orgs/%d/users/%d', org_id, usr_id )
225
+ endpoint = format( '/api/orgs/%d/users/%d', organization_id, usr_id )
324
226
 
325
227
  @logger.debug("Deleting user '#{login_or_email}' in organization '#{organization}' (DELETE #{endpoint})") if @debug
326
228
  delete(endpoint)
@@ -328,10 +230,10 @@ module Grafana
328
230
 
329
231
  # Create Organisation
330
232
  #
331
- # @param
233
+ # @param [Hash] params
332
234
  # @option params [String] organization Organisation name
333
235
  #
334
- # @examle
236
+ # @example
335
237
  # params = {
336
238
  # name: 'Foo'
337
239
  # }
@@ -345,15 +247,9 @@ module Grafana
345
247
  raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
346
248
 
347
249
  name = validate( params, required: true, var: 'name', type: String )
250
+ org = organization( name )
348
251
 
349
- org = organization( name )
350
-
351
- if( org.nil? || org.dig('status').to_i == 200 )
352
- return {
353
- 'status' => 409,
354
- 'message' => format('Organisation \'%s\' already exists', name )
355
- }
356
- end
252
+ return { 'status' => 409, 'message' => format('Organisation \'%s\' already exists', name ) } if( org.nil? || org.dig('status').to_i == 200 )
357
253
 
358
254
  endpoint = '/api/orgs'
359
255
  payload = {
@@ -376,31 +272,79 @@ module Grafana
376
272
  #
377
273
  def delete_organisation( organisation_id )
378
274
 
379
- raise ArgumentError.new(format('wrong type. user \'organisation_id\' must be an String (for an Datasource name) or an Integer (for an Datasource Id), given \'%s\'', organisation_id.class.to_s)) if( organisation_id.is_a?(String) && organisation_id.is_a?(Integer) )
275
+ if( organisation_id.is_a?(String) && organisation_id.is_a?(Integer) )
276
+ raise ArgumentError.new(format('wrong type. \'organisation_id\' must be an String (for an Organisation name) ' \
277
+ 'or an Integer (for an Organisation Id), given \'%s\'', organisation_id.class.to_s))
278
+ end
380
279
  raise ArgumentError.new('missing \'organisation_id\'') if( organisation_id.size.zero? )
381
280
 
382
281
  if(organisation_id.is_a?(String))
383
282
  data = organizations.dig('message')
384
283
  organisation_map = {}
385
- data.each do |ds|
386
- organisation_map[ds['id']] = ds
284
+ data.each do |d|
285
+ organisation_map[d.dig('id')] = d.dig('name')
387
286
  end
388
- organisation_map.select { |_k,v| v['name'] == organisation_id }
389
- organisation_id = organisation_map.keys.first if( data )
287
+ organisation_id = organisation_map.select { |_,y| y == organisation_id }.keys.first if( organisation_map )
390
288
  end
391
289
 
392
- if( organisation_id.nil? )
290
+ return { 'status' => 404, 'message' => format( 'No Organisation \'%s\' found', organisation_id) } if( organisation_id.nil? )
291
+
292
+ endpoint = format( '/api/orgs/%d', organisation_id )
293
+ @logger.debug("Deleting organization #{organisation_id} (DELETE #{endpoint})") if @debug
294
+
295
+ delete(endpoint)
296
+ end
297
+
298
+
299
+ private
300
+ # validate an user for an organisation
301
+ #
302
+ # @example
303
+ # params = {
304
+ # organization: 'Foo',
305
+ # login_or_email: 'foo@foo-bar.tld',
306
+ # role: 'Viewer'
307
+ # }
308
+ # validate_organisation_user( params )
309
+ #
310
+ # @return [Hash]
311
+ #
312
+ def validate_organisation_user( params )
313
+
314
+ raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
315
+ raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
316
+
317
+ organization = validate( params, required: true, var: 'organization', type: String )
318
+ login_or_email = validate( params, required: true, var: 'login_or_email', type: String )
319
+ role = validate( params, required: true, var: 'role', type: String )
320
+ valid_roles = ['Viewer', 'Editor', 'Read Only Editor', 'Admin']
321
+
322
+ # https://stackoverflow.com/questions/9333952/case-insensitive-arrayinclude?answertab=votes#tab-top
323
+ # Do this once, or each time the array changes
324
+ downcased = Set.new valid_roles.map(&:downcase)
325
+ unless( downcased.include?( role.downcase ) )
393
326
  return {
394
327
  'status' => 404,
395
- 'message' => format( 'No Organisation \'%s\' found', organisation_id)
328
+ 'login_or_email' => login_or_email,
329
+ 'role' => role,
330
+ 'message' => format( 'wrong role. Role must be one of %s, given \'%s\'', valid_roles.join(', '), role )
396
331
  }
397
332
  end
398
333
 
399
- endpoint = format( '/api/orgs/%d', organisation_id )
400
- @logger.debug("Deleting organization #{organisation_id} (DELETE #{endpoint})") if @debug
334
+ org = organization( organization )
335
+ usr = user( login_or_email )
401
336
 
402
- delete(endpoint)
337
+ return { 'status' => 404, 'message' => format('Organization \'%s\' not found', organization) } if( org.nil? || org.dig('status').to_i != 200 )
338
+ return { 'status' => 404, 'message' => format('User \'%s\' not found', login_or_email) } if( usr.nil? || usr.dig('status').to_i != 200 )
339
+
340
+ {
341
+ 'status' => 200,
342
+ 'organisation' => org,
343
+ 'user' => usr,
344
+ 'role' => role
345
+ }
403
346
  end
404
347
 
348
+
405
349
  end
406
350
  end