grafana 0.10.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d62ca27f8f2d01a27309e9b947fa2f633caf75d2bcc94443a9208c36416ff5e3
4
- data.tar.gz: 30f9a883ac3b492ea294a090960f733c7a163d59c39975c3efb12391410387af
3
+ metadata.gz: 8e73fd657e1a344d3cb67b5bf01cd33f8e227447e92e6e93b575a51a0091a253
4
+ data.tar.gz: c9f41ad884326c341d9c25746bfb80967206c5d0f94ef2bf94a4de6dd7e74435
5
5
  SHA512:
6
- metadata.gz: 81a9b8b26d5de44f741045268ce8fc4eb0581414cecba178abea7e8c614be0c2586256ace00669719b87eee37c47c90e1fb9a0c5d23171a236ff49938caf3934
7
- data.tar.gz: f680c1a86f1aa778eb00e440fc00d290683bafc0eb245c67215c071079ad8ca43b6499e54ee9aeee2bd6dd15f7c89eff9a86b6ebfd70604a831f1717169b528c
6
+ metadata.gz: 4aa2e43dbde3b105b5f85c74ac84a4269cd67d2de6b327cc597854ef1e6e4d66ce52628e9564785a0f1729527e90514e2577c83a651d8fe6c82c765c73a8ecbc
7
+ data.tar.gz: 50df29f0e9ad79c5dd7586dd1190585badb8ae3e09b82847433721cded33a6aa562ccba34be65c12356ca00cde64a45a18bf9dde1592af614a52263d71bca2f4
data/README.md CHANGED
@@ -26,9 +26,14 @@ TODO: Write usage instructions here
26
26
 
27
27
  ## Development
28
28
 
29
- After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake rake` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
30
-
31
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
29
+ After checking out the repo, run `bin/setup` to install dependencies.
30
+ Then, run `rake rake` to run the tests.
31
+ You can also run `bin/console` for an interactive prompt that will allow you to experiment.
32
+
33
+ To install this gem onto your local machine, run `bundle exec rake install`.
34
+ To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`,
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).
32
37
 
33
38
  ## Contributing
34
39
 
@@ -27,6 +27,7 @@ require_relative 'alerts'
27
27
  require_relative 'folder'
28
28
  require_relative 'folder_permissions'
29
29
  require_relative 'folder_and_dashboard_search'
30
+ require_relative 'playlist'
30
31
 
31
32
  # -------------------------------------------------------------------------------------------------------------------
32
33
  #
@@ -68,6 +69,7 @@ module Grafana
68
69
  include Grafana::Folder
69
70
  include Grafana::FolderPermissions
70
71
  include Grafana::FolderSearch
72
+ include Grafana::Playlist
71
73
 
72
74
  attr_accessor :debug
73
75
 
@@ -78,7 +78,7 @@ module Grafana
78
78
  raise ArgumentError.new('missing \'uid\'') if( uid.size.zero? )
79
79
 
80
80
  v, mv = version.values
81
- return { 'status' => 404, 'message' => format( 'only Grafana 5 has uid support. you use version %s', v) } if(mv != 5)
81
+ return { 'status' => 404, 'message' => format( 'uid has been supported in Grafana since version 5. you use version %s', v) } if(mv < 5)
82
82
 
83
83
  return { 'status' => 404, 'message' => format( 'The uid can have a maximum length of 40 characters, but it is %s characters long', uid.length) } if( uid.length > 40 )
84
84
 
@@ -148,7 +148,7 @@ module Grafana
148
148
  title = db.dig('dashboard','title')
149
149
  uid = db.dig('dashboard','uid')
150
150
 
151
- return { 'status' => 404, 'message' => format( 'the template \'%s\' can\'t be create. The uid can have a maximum length of 40 characters, but it is %s characters long', title, uid.length) } if( ! uid.nil? && uid.length > 40 )
151
+ return { 'status' => 404, 'message' => format( 'The template \'%s\' can\'t be create. The uid can have a maximum length of 40 characters, but it is %s characters long', title, uid.length) } if( ! uid.nil? && uid.length > 40 )
152
152
 
153
153
  endpoint = '/api/dashboards/db'
154
154
 
@@ -51,7 +51,7 @@ module Grafana
51
51
  raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
52
52
 
53
53
  v, mv = version.values
54
- return { 'status' => 404, 'message' => format( 'only Grafana 5 has folder support. you use version %s', v) } if(mv != 5)
54
+ return { 'status' => 404, 'message' => format( 'folder has been supported in Grafana since version 5. you use version %s', v) } if(mv < 5)
55
55
 
56
56
  dashboard_id = validate( params, required: true, var: 'dashboard_id', type: Integer )
57
57
  permissions = validate( params, required: true, var: 'permissions' , type: Hash )
@@ -20,7 +20,7 @@ module Grafana
20
20
  raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
21
21
 
22
22
  # v, mv = version.values
23
- # return { 'status' => 404, 'message' => format( 'only Grafana 5 has dashboard version support. you use version %s', v) } if(mv != 5)
23
+ # return { 'status' => 404, 'message' => format( 'dashboard has been supported in Grafana since version 5. you use version %s', v) } if(mv < 5)
24
24
 
25
25
  dashboard_id = validate( params, required: true , var: 'dashboard_id', type: Integer )
26
26
  start = validate( params, required: false, var: 'start' , type: Integer )
@@ -44,7 +44,7 @@ module Grafana
44
44
  raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
45
45
 
46
46
  v, mv = version.values
47
- return { 'status' => 404, 'message' => format( 'only Grafana 5 has folder support. you use version %s', v) } if(mv != 5)
47
+ return { 'status' => 404, 'message' => format( 'folder has been supported in Grafana since version 5. you use version %s', v) } if(mv < 5)
48
48
 
49
49
  dashboard_id = validate( params, required: true, var: 'dashboard_id', type: Integer )
50
50
  version = validate( params, required: true, var: 'version' , type: Integer )
@@ -67,7 +67,7 @@ module Grafana
67
67
  raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
68
68
 
69
69
  # v, mv = version.values
70
- # return { 'status' => 404, 'message' => format( 'only Grafana 5 has folder support. you use version %s', v) } if(mv != 5)
70
+ # return { 'status' => 404, 'message' => format( 'folder has been supported in Grafana since version 5. you use version %s', v) } if(mv < 5)
71
71
 
72
72
  dashboard_id = validate( params, required: true, var: 'dashboard_id', type: Integer )
73
73
  version = validate( params, required: true, var: 'version' , type: Integer )
@@ -16,7 +16,7 @@ module Grafana
16
16
  def folders
17
17
 
18
18
  v, mv = version.values
19
- return { 'status' => 404, 'message' => format( 'only Grafana 5 has folder support. you use version %s', v) } if(mv != 5)
19
+ return { 'status' => 404, 'message' => format( 'folder has been supported in Grafana since version 5. you use version %s', v) } if(mv < 5)
20
20
 
21
21
  endpoint = '/api/folders'
22
22
  @logger.debug("Getting all folders (GET #{endpoint})") if @debug
@@ -39,7 +39,7 @@ module Grafana
39
39
  raise ArgumentError.new('missing \'folder_uid\'') if( folder_uid.size.zero? )
40
40
 
41
41
  v, mv = version.values
42
- return { 'status' => 404, 'message' => format( 'only Grafana 5 has folder support. you use version %s', v) } if(mv != 5)
42
+ return { 'status' => 404, 'message' => format( 'folder has been supported in Grafana since version 5. you use version %s', v) } if(mv < 5)
43
43
 
44
44
  if(folder_uid.is_a?(Integer))
45
45
 
@@ -58,7 +58,7 @@ module Grafana
58
58
  return { 'status' => 404, 'message' => format( 'No Folder \'%s\' found', folder_uid) } if( folder_uid.is_a?(Integer) )
59
59
  end
60
60
 
61
- return { 'status' => 404, 'message' => format( 'The uid can have a maximum length of 40 characters. \'%s\' given', folder_uid.length) } \
61
+ return { 'status' => 404, 'message' => format( 'The uid can have a maximum length of 40 characters, but it is %s characters long', folder_uid.length) } \
62
62
  if( folder_uid.is_a?(String) && folder_uid.length > 40 )
63
63
  return { 'status' => 404, 'message' => format( 'No Folder \'%s\' found', folder_uid) } if( folder_uid.nil? )
64
64
 
@@ -82,7 +82,7 @@ module Grafana
82
82
  raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
83
83
 
84
84
  v, mv = version.values
85
- return { 'status' => 404, 'message' => format( 'only Grafana 5 has folder support. you use version %s', v) } if(mv != 5)
85
+ return { 'status' => 404, 'message' => format( 'folder has been supported in Grafana since version 5. you use version %s', v) } if(mv < 5)
86
86
 
87
87
  title = validate( params, required: false, var: 'title', type: String )
88
88
  uid = validate( params, required: true , var: 'uid' , type: String )
@@ -124,7 +124,7 @@ module Grafana
124
124
  raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
125
125
 
126
126
  v, mv = version.values
127
- return { 'status' => 404, 'message' => format( 'only Grafana 5 has folder support. you use version %s', v) } if(mv != 5)
127
+ return { 'status' => 404, 'message' => format( 'folder has been supported in Grafana since version 5. you use version %s', v) } if(mv < 5)
128
128
 
129
129
  uid = validate( params, required: true , var: 'uid' , type: String )
130
130
  title = validate( params, required: true , var: 'title' , type: String )
@@ -168,7 +168,7 @@ module Grafana
168
168
  raise ArgumentError.new('missing \'folder_uid\'') if( folder_uid.size.zero? )
169
169
 
170
170
  v, mv = version.values
171
- return { 'status' => 404, 'message' => format( 'only Grafana 5 has folder support. you use version %s', v) } if(mv != 5)
171
+ return { 'status' => 404, 'message' => format( 'folder has been supported in Grafana since version 5. you use version %s', v) } if(mv < 5)
172
172
 
173
173
  if(folder_uid.is_a?(Integer))
174
174
 
@@ -21,7 +21,7 @@ module Grafana
21
21
  raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
22
22
 
23
23
  v, mv = version.values
24
- return { 'status' => 404, 'message' => format( 'only Grafana 5 has team support. you use version %s', v) } if(mv != 5)
24
+ return { 'status' => 404, 'message' => format( 'team has been supported in Grafana since version 5. you use version %s', v) } if(mv < 5)
25
25
 
26
26
  query = validate( params, required: false, var: 'query' , type: String )
27
27
  tag = validate( params, required: false, var: 'tag ' , type: String )
@@ -23,7 +23,7 @@ module Grafana
23
23
  def folder_permissions( folder_id )
24
24
 
25
25
  v, mv = version.values
26
- return { 'status' => 404, 'message' => format( 'only Grafana 5 has folder support. you use version %s', v) } if(mv != 5)
26
+ return { 'status' => 404, 'message' => format( 'folder has been supported in Grafana since version 5. you use version %s', v) } if(mv < 5)
27
27
 
28
28
  f = folder( folder_id )
29
29
 
@@ -53,7 +53,7 @@ module Grafana
53
53
  raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
54
54
 
55
55
  v, mv = version.values
56
- return { 'status' => 404, 'message' => format( 'only Grafana 5 has folder support. you use version %s', v) } if(mv != 5)
56
+ return { 'status' => 404, 'message' => format( 'folder has been supported in Grafana since version 5. you use version %s', v) } if(mv < 5)
57
57
 
58
58
  folder = validate( params, required: true, var: 'folder' , type: String )
59
59
  permissions = validate( params, required: true, var: 'permissions', type: Hash )
data/lib/grafana/login.rb CHANGED
@@ -131,8 +131,8 @@ module Grafana
131
131
  # @return [Hash]
132
132
  #
133
133
  def ping_session
134
- endpoint = '/api/login/ping'
135
134
  logger.debug( "Pinging current session (GET #{endpoint})" ) if @debug
135
+ endpoint = '/api/login/ping'
136
136
  get( endpoint )
137
137
  end
138
138
 
@@ -60,7 +60,7 @@ module Grafana
60
60
  # @return [Hash]
61
61
  #
62
62
  def request( method_type = 'GET', endpoint = '/', data = {} )
63
- # logger.debug( "request( #{method_type}, #{endpoint}, data )" )
63
+
64
64
  raise 'try first login()' if @api_instance.nil?
65
65
 
66
66
  login( username: @username, password: @password )
@@ -78,13 +78,18 @@ module Grafana
78
78
  when 'PATCH'
79
79
  response = @api_instance[endpoint].patch( data, headers )
80
80
  when 'PUT'
81
+
81
82
  # response = @api_instance[endpoint].put( data, headers )
82
83
  @api_instance[endpoint].put( data, headers ) do |resp, _request, _result|
83
- response_body = resp.body
84
+
84
85
  response_code = resp.code.to_i
86
+ response_body = resp.body
85
87
  response_body = JSON.parse(response_body) if response_body.is_a?(String)
86
88
 
87
- case response_code
89
+ #logger.debug( "code : #{response_code}" )
90
+ #logger.debug( "message: #{response_body}" )
91
+
92
+ case response_code.to_i
88
93
  when 200
89
94
  return { 'status' => response_code, 'message' => response_body.dig('message').nil? ? 'Successful' : response_body.dig('message') }
90
95
  when 400
@@ -95,19 +100,54 @@ module Grafana
95
100
  message += " (#{status})" unless(status.nil?)
96
101
  return { 'status' => response_code, 'message' => message }
97
102
  when 422
98
- raise RestClient::UnprocessableEntity
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
99
117
  else
100
- # logger.error( response_code )
101
- # logger.error( response_body )
118
+ # logger.error( response_code )
119
+ # logger.error( response_body )
102
120
  return { 'status' => response_code, 'message' => response_body.dig('message') }
103
121
  # response.return! # (request, result)
104
122
  end
105
123
  end
106
124
 
107
125
  when 'DELETE'
108
- 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
+
109
149
  else
110
- @logger.error( "Error: #{__method__} is not a valid request method." )
150
+ logger.error( "Error: #{__method__} is not a valid request method." )
111
151
  return false
112
152
  end
113
153
 
@@ -115,16 +155,14 @@ module Grafana
115
155
  response_body = response.body
116
156
  response_headers = response.headers
117
157
 
118
- # if( @debug )
119
- # logger.debug("response_code : #{response_code}" )
120
- # logger.debug("response_body : #{response_body}" )
121
- # logger.debug("response_headers : #{response_headers}" )
122
- # end
123
-
124
158
  if( ( response_code >= 200 && response_code <= 299 ) || ( response_code >= 400 && response_code <= 499 ) )
125
159
 
126
- result = JSON.parse( response_body )
127
- return { 'status' => response_code, 'message' => result } if( result.is_a?(Array) )
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 }
165
+ end
128
166
 
129
167
  result_status = result.dig('status') if( result.is_a?( Hash ) )
130
168
  result['message'] = result_status unless( result_status.nil? )
@@ -132,9 +170,9 @@ module Grafana
132
170
 
133
171
  return result
134
172
  else
135
- @logger.error( "#{__method__} #{method_type.upcase} on #{endpoint} failed: HTTP #{response.code} - #{response_body}" )
136
- @logger.error( headers )
137
- @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 ) )
138
176
 
139
177
  return JSON.parse( response_body )
140
178
  end
@@ -155,12 +193,12 @@ module Grafana
155
193
  rescue RestClient::PreconditionFailed
156
194
  return { 'status' => 412, 'message' => 'Precondition failed. The Object probably already exists.' }
157
195
  rescue RestClient::ExceptionWithResponse => error
158
- # logger.error( "Error: #{__method__} #{method_type.upcase} on #{endpoint} error: '#{error}'" )
159
- # logger.error( "query: #{data}" )
196
+ #logger.error( "Error: (RestClient::ExceptionWithResponse) #{__method__} #{method_type.upcase} on #{endpoint} error: '#{error}'" )
197
+ #logger.error( "query: #{data}" )
160
198
  return { 'status' => 500, 'message' => "Internal Server Error: #{error}" }
161
199
  rescue => error
162
- # logger.error( "Error: #{__method__} #{method_type.upcase} on #{endpoint} error: '#{error}'" )
163
- # logger.error( "query: #{data}" )
200
+ #logger.error( "Error: #{__method__} #{method_type.upcase} on #{endpoint} error: '#{error}'" )
201
+ #logger.error( "query: #{data}" )
164
202
  return { 'status' => 500, 'message' => "Internal Server Error: #{error}" }
165
203
  end
166
204
  end
@@ -30,7 +30,7 @@ module Grafana
30
30
  raise ArgumentError.new('missing \'organisation_id\'') if( organisation_id.size.zero? )
31
31
 
32
32
  endpoint = format( '/api/orgs/%d', organisation_id ) if(organisation_id.is_a?(Integer))
33
- 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))
34
34
 
35
35
  @logger.debug("Attempting to get existing data source Id #{organisation_id} (GET #{endpoint})") if @debug
36
36
 
@@ -0,0 +1,599 @@
1
+
2
+ module Grafana
3
+
4
+ # +++
5
+ # title = "Playlist HTTP API "
6
+ # description = "Playlist Admin HTTP API"
7
+ # keywords = ["grafana", "http", "documentation", "api", "playlist"]
8
+ # aliases = ["/http_api/playlist/"]
9
+ # type = "docs"
10
+ # [menu.docs]
11
+ # name = "Playlist"
12
+ # parent = "http_api"
13
+ # +++
14
+
15
+ # https://github.com/grafana/grafana/blob/1165d098b0d0ae705955f9d2ea104beea98ca6eb/pkg/api/dtos/playlist.go
16
+
17
+ module Playlist
18
+
19
+ ## Playlist API
20
+ #
21
+ ### Search Playlist
22
+ #
23
+ #`GET /api/playlists`
24
+ #
25
+ #Get all existing playlist for the current organization using pagination
26
+ #
27
+ #**Example Request**:
28
+ #
29
+ #```bash
30
+ #GET /api/playlists HTTP/1.1
31
+ #Accept: application/json
32
+ #Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
33
+ #```
34
+ #
35
+ # Querystring Parameters:
36
+ #
37
+ # These parameters are used as querystring parameters.
38
+ #
39
+ # - **query** - Limit response to playlist having a name like this value.
40
+ # - **limit** - Limit response to *X* number of playlist.
41
+ #
42
+ #**Example Response**:
43
+ #
44
+ #```json
45
+ #HTTP/1.1 200
46
+ #Content-Type: application/json
47
+ #[
48
+ # {
49
+ # "id": 1,
50
+ # "name": "my playlist",
51
+ # "interval": "5m"
52
+ # }
53
+ #]
54
+ #```
55
+ def playlists
56
+
57
+ endpoint = '/api/playlists'
58
+
59
+ @logger.debug("Attempting to get all existing playlists (GET #{endpoint})") if @debug
60
+
61
+ playlists = get( endpoint )
62
+
63
+ return { 'status' => 404, 'message' => 'No Playlists found' } if( playlists.nil? || playlists == false || playlists.dig('status').to_i != 200 )
64
+
65
+ playlists
66
+ end
67
+
68
+ ### Get one playlist
69
+ #
70
+ #`GET /api/playlists/:id`
71
+ #
72
+ #**Example Request**:
73
+ #
74
+ #```bash
75
+ #GET /api/playlists/1 HTTP/1.1
76
+ #Accept: application/json
77
+ #Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
78
+ #```
79
+ #
80
+ #**Example Response**:
81
+ #
82
+ #```json
83
+ #HTTP/1.1 200
84
+ #Content-Type: application/json
85
+ #{
86
+ # "id" : 1,
87
+ # "name": "my playlist",
88
+ # "interval": "5m",
89
+ # "orgId": "my org",
90
+ # "items": [
91
+ # {
92
+ # "id": 1,
93
+ # "playlistId": 1,
94
+ # "type": "dashboard_by_id",
95
+ # "value": "3",
96
+ # "order": 1,
97
+ # "title":"my third dasboard"
98
+ # },
99
+ # {
100
+ # "id": 2,
101
+ # "playlistId": 1,
102
+ # "type": "dashboard_by_tag",
103
+ # "value": "myTag",
104
+ # "order": 2,
105
+ # "title":"my other dasboard"
106
+ # }
107
+ # ]
108
+ #}
109
+ #```
110
+
111
+ def playlist( playlist_id )
112
+
113
+ if( playlist_id.is_a?(String) && playlist_id.is_a?(Integer) )
114
+ raise ArgumentError.new(format('wrong type. \'playlist_id\' must be an String (for an Playlist name) or an Integer (for an Playlist Id), given \'%s\'', playlist_id.class.to_s))
115
+ end
116
+ raise ArgumentError.new('missing \'playlist_id\'') if( playlist_id.size.zero? )
117
+
118
+ if(playlist_id.is_a?(String))
119
+
120
+ data = playlists
121
+ status = data.dig('status')
122
+ d = data.dig('message')
123
+ data = d.select { |k| k['name'] == playlist_id }
124
+
125
+ return { 'status' => 404, 'message' => format( 'No Playlist \'%s\' found', playlist_id) } if( data.size == 0 )
126
+
127
+ if( data.size != 0 )
128
+
129
+ _d = []
130
+ data.each do |k,v|
131
+ _d << playlist( k['id'] )
132
+ end
133
+ return { 'status' => status, 'playlists' => _d }
134
+ end
135
+ # return { 'status' => 200, 'message' => data } if( data.size != 0 )
136
+ end
137
+
138
+ raise format('playlist id can not be 0') if( playlist_id.zero? )
139
+
140
+ endpoint = format('/api/playlists/%d', playlist_id )
141
+
142
+ @logger.debug("Attempting to get existing playlist id #{playlist_id} (GET #{endpoint})") if @debug
143
+
144
+ result = get(endpoint)
145
+
146
+ return { 'status' => 404, 'message' => 'playlist is empty', 'items' => [] } if( result.dig('status') == 404 )
147
+
148
+ return result
149
+ end
150
+
151
+ ### Get Playlist items
152
+
153
+ #`GET /api/playlists/:id/items`
154
+ #
155
+ #**Example Request**:
156
+ #
157
+ #```bash
158
+ #GET /api/playlists/1/items HTTP/1.1
159
+ #Accept: application/json
160
+ #Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
161
+ #```
162
+ #
163
+ #**Example Response**:
164
+ #
165
+ #```json
166
+ #HTTP/1.1 200
167
+ #Content-Type: application/json
168
+ #[
169
+ # {
170
+ # "id": 1,
171
+ # "playlistId": 1,
172
+ # "type": "dashboard_by_id",
173
+ # "value": "3",
174
+ # "order": 1,
175
+ # "title":"my third dasboard"
176
+ # },
177
+ # {
178
+ # "id": 2,
179
+ # "playlistId": 1,
180
+ # "type": "dashboard_by_tag",
181
+ # "value": "myTag",
182
+ # "order": 2,
183
+ # "title":"my other dasboard"
184
+ # }
185
+ #]
186
+ #```
187
+
188
+ def playlist_items( playlist_id, multi_result = false )
189
+
190
+ if( playlist_id.is_a?(String) && playlist_id.is_a?(Integer) )
191
+ raise ArgumentError.new(format('wrong type. \'playlist_id\' must be an String (for an playlist name) or an Integer (for an playlist Id), given \'%s\'', playlist_id.class.to_s))
192
+ end
193
+ raise ArgumentError.new('missing \'playlist_id\'') if( playlist_id.size.zero? )
194
+
195
+ _playlists = playlists
196
+
197
+ begin
198
+ status = _playlists.dig('status')
199
+ message = _playlists.dig('message')
200
+
201
+ if( status == 200 )
202
+
203
+ data = message.select { |k| k['id'] == playlist_id } if( playlist_id.is_a?(Integer) )
204
+ data = message.select { |k| k['name'] == playlist_id } if( playlist_id.is_a?(String) )
205
+
206
+ return { 'status' => 404, 'message' => 'No Playlist found' } if( !data.is_a?(Array) || data.count == 0 || status.to_i != 200 )
207
+ return { 'status' => 404, 'message' => format('found %d playlists with name %s', data.count, playlist_id ) } if( data.count > 1 && multi_result == false )
208
+
209
+ id = data.first.dig('id')
210
+ else
211
+ return _playlists
212
+ end
213
+ rescue
214
+ return { 'status' => 404, 'message' => 'No Playlists found' } if( playlists.nil? || playlists == false || playlists.dig('status').to_i != 200 )
215
+ end
216
+
217
+ endpoint = "/api/playlists/#{id}/items"
218
+
219
+ result = get( endpoint )
220
+
221
+ return { 'status' => 404, 'message' => 'playlist is empty' } if( result.dig('status') == 404 )
222
+
223
+ return result
224
+ end
225
+
226
+ ### Get Playlist dashboards
227
+ #
228
+ #`GET /api/playlists/:id/dashboards`
229
+ #
230
+ #**Example Request**:
231
+ #
232
+ #```bash
233
+ #GET /api/playlists/1/dashboards HTTP/1.1
234
+ #Accept: application/json
235
+ #Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
236
+ #```
237
+ #
238
+ #**Example Response**:
239
+ #
240
+ #```json
241
+ #HTTP/1.1 200
242
+ #Content-Type: application/json
243
+ #[
244
+ # {
245
+ # "id": 3,
246
+ # "title": "my third dasboard",
247
+ # "order": 1,
248
+ # },
249
+ # {
250
+ # "id": 5,
251
+ # "title":"my other dasboard"
252
+ # "order": 2,
253
+ #
254
+ # }
255
+ #]
256
+ #```
257
+
258
+ def playlist_dashboards( playlist_id )
259
+
260
+ raise ArgumentError.new(format('wrong type. \'playlist_id\' must be an Integer, given \'%s\'', playlist_id.class)) unless( playlist_id.is_a?(Integer) )
261
+ raise ArgumentError.new('missing \'playlist_id\'') if( playlist_id.size.zero? )
262
+
263
+ endpoint = format('/api/playlists/%s/dashboards', playlist_id)
264
+
265
+ @logger.debug( "Attempting to get playlist (GET #{endpoint})" ) if @debug
266
+ get(endpoint)
267
+ end
268
+
269
+ # Create a playlist
270
+
271
+ # `POST /api/playlists/`
272
+ #
273
+ #**Example Request**:
274
+ #
275
+ #```bash
276
+ #PUT /api/playlists/1 HTTP/1.1
277
+ #Accept: application/json
278
+ #Content-Type: application/json
279
+ #Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
280
+ # {
281
+ # "name": "my playlist",
282
+ # "interval": "5m",
283
+ # "items": [
284
+ # {
285
+ # "type": "dashboard_by_id",
286
+ # "value": "3",
287
+ # "order": 1,
288
+ # "title":"my third dasboard"
289
+ # },
290
+ # {
291
+ # "type": "dashboard_by_tag",
292
+ # "value": "myTag",
293
+ # "order": 2,
294
+ # "title":"my other dasboard"
295
+ # }
296
+ # ]
297
+ # }
298
+ #```
299
+ #
300
+ #**Example Response**:
301
+ #
302
+ #```json
303
+ #HTTP/1.1 200
304
+ #Content-Type: application/json
305
+ # {
306
+ # "id": 1,
307
+ # "name": "my playlist",
308
+ # "interval": "5m"
309
+ # }
310
+ #```
311
+
312
+ def create_playlist( 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
+ # v, mv = version.values
318
+ # return { 'status' => 404, 'message' => format( 'folder has been supported in Grafana since version 5. you use version %s', v) } if(mv < 5)
319
+
320
+ name = validate( params, required: true , var: 'name' , type: String )
321
+ interval = validate( params, required: true , var: 'interval' , type: String )
322
+ items = validate( params, required: true , var: 'items' , type: Array )
323
+
324
+ return { 'status' => 404, 'message' => 'There are no elements for a playlist' } if(items.count == 0)
325
+
326
+ payload_items = create_playlist_items(items)
327
+
328
+ payload = {
329
+ name: name,
330
+ interval: interval,
331
+ items: payload_items
332
+ }
333
+ payload.reject!{ |_k, v| v.nil? }
334
+
335
+ endpoint = '/api/playlists'
336
+
337
+ post(endpoint, payload.to_json)
338
+ end
339
+
340
+ ### Update a playlist
341
+ #
342
+ #`PUT /api/playlists/:id`
343
+ #
344
+ #**Example Request**:
345
+ #
346
+ #```bash
347
+ #PUT /api/playlists/1 HTTP/1.1
348
+ #Accept: application/json
349
+ #Content-Type: application/json
350
+ #Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
351
+ # {
352
+ # "name": "my playlist",
353
+ # "interval": "5m",
354
+ # "items": [
355
+ # {
356
+ # "playlistId": 1,
357
+ # "type": "dashboard_by_id",
358
+ # "value": "3",
359
+ # "order": 1,
360
+ # "title":"my third dasboard"
361
+ # },
362
+ # {
363
+ # "playlistId": 1,
364
+ # "type": "dashboard_by_tag",
365
+ # "value": "myTag",
366
+ # "order": 2,
367
+ # "title":"my other dasboard"
368
+ # }
369
+ # ]
370
+ # }
371
+ #```
372
+ #
373
+ #**Example Response**:
374
+ #
375
+ #```json
376
+ #HTTP/1.1 200
377
+ #Content-Type: application/json
378
+ #{
379
+ # "id" : 1,
380
+ # "name": "my playlist",
381
+ # "interval": "5m",
382
+ # "orgId": "my org",
383
+ # "items": [
384
+ # {
385
+ # "id": 1,
386
+ # "playlistId": 1,
387
+ # "type": "dashboard_by_id",
388
+ # "value": "3",
389
+ # "order": 1,
390
+ # "title":"my third dasboard"
391
+ # },
392
+ # {
393
+ # "id": 2,
394
+ # "playlistId": 1,
395
+ # "type": "dashboard_by_tag",
396
+ # "value": "myTag",
397
+ # "order": 2,
398
+ # "title":"my other dasboard"
399
+ # }
400
+ # ]
401
+ #}
402
+ #```
403
+
404
+ def update_playlist( params )
405
+
406
+ raise ArgumentError.new(format('wrong type. \'params\' must be an Hash, given \'%s\'', params.class.to_s)) unless( params.is_a?(Hash) )
407
+ raise ArgumentError.new('missing \'params\'') if( params.size.zero? )
408
+
409
+ playlist_id = validate( params, required: true , var: 'playlist' )
410
+ name = validate( params, required: false, var: 'name' )
411
+ interval = validate( params, required: false, var: 'interval', type: String )
412
+ # organisation = validate( params, required: false, var: 'organisation' )
413
+ items = validate( params, required: false, var: 'items', type: Array )
414
+
415
+ _playlists = playlists
416
+
417
+ data = []
418
+
419
+ begin
420
+ status = _playlists.dig('status')
421
+ message = _playlists.dig('message')
422
+
423
+ if( status == 200 )
424
+ data = message.select { |k| k['id'] == playlist_id } if( playlist_id.is_a?(Integer) )
425
+ data = message.select { |k| k['name'] == playlist_id } if( playlist_id.is_a?(String) )
426
+
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
+ rescue
433
+ return { 'status' => 404, 'message' => 'no playlists found' } if( playlists.nil? || playlists == false || playlists.dig('status').to_i != 200 )
434
+ end
435
+
436
+ playlist_id = data.first.dig('id')
437
+ playlist_name = data.first.dig('name')
438
+ payload_items = create_playlist_items(items, playlist_id)
439
+
440
+ payload = {
441
+ id: playlist_id,
442
+ name: name,
443
+ interval: interval,
444
+ items: payload_items
445
+ }
446
+ payload.reject!{ |_k, v| v.nil? }
447
+
448
+ endpoint = format( '/api/playlists/%d', playlist_id )
449
+
450
+ put( endpoint, payload.to_json )
451
+
452
+ end
453
+
454
+
455
+ ### Delete a playlist
456
+ #
457
+ #`DELETE /api/playlists/:id`
458
+ #
459
+ #**Example Request**:
460
+ #
461
+ #```bash
462
+ #DELETE /api/playlists/1 HTTP/1.1
463
+ #Accept: application/json
464
+ #Authorization: Bearer eyJrIjoiT0tTcG1pUlY2RnVKZTFVaDFsNFZXdE9ZWmNrMkZYbk
465
+ #```
466
+ #
467
+ #**Example Response**:
468
+ #
469
+ #```json
470
+ #HTTP/1.1 200
471
+ #Content-Type: application/json
472
+ #{}
473
+ #```
474
+
475
+ def delete_playlist(playlist_id, multi_result = false )
476
+
477
+ if( playlist_id.is_a?(String) && playlist_id.is_a?(Integer) )
478
+ raise ArgumentError.new(format('wrong type. \'playlist_id\' must be an String (for an Playlist name) or an Integer (for an Playlist Id), given \'%s\'', playlist_id.class.to_s))
479
+ end
480
+ raise ArgumentError.new('missing \'playlist_id\'') if( playlist_id.size.zero? )
481
+
482
+ _playlists = playlists
483
+
484
+ data = []
485
+
486
+ begin
487
+ status = _playlists.dig('status')
488
+ message = _playlists.dig('message')
489
+
490
+ if( status == 200 )
491
+
492
+ data = message.select { |k| k['id'] == playlist_id } if( playlist_id.is_a?(Integer) )
493
+ data = message.select { |k| k['name'] == playlist_id } if( playlist_id.is_a?(String) )
494
+
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
+ rescue
501
+ return { 'status' => 404, 'message' => 'no playlists found' } if( playlists.nil? || playlists == false || playlists.dig('status').to_i != 200 )
502
+ end
503
+
504
+ if( multi_result == true )
505
+
506
+ result = { 'status' => 0, 'message' => 'under development' }
507
+ data.each do |x|
508
+
509
+ endpoint = format( '/api/playlists/%d', x.dig('id') )
510
+
511
+ begin
512
+ result = delete( endpoint )
513
+ rescue => error
514
+ logger.error( "error: #{error}" )
515
+ end
516
+ end
517
+
518
+ return result
519
+ else
520
+
521
+ playlist_id = data.first.dig('id')
522
+
523
+ endpoint = format( '/api/playlists/%d', playlist_id )
524
+
525
+ result = delete( endpoint )
526
+
527
+ if(result.dig('status').to_i == 500)
528
+ # check if the playlist exists
529
+ r = playlist( playlist_id )
530
+ return { 'status' => 200, 'message' => 'playlist deleted' } if(r.dig('status').to_i == 404)
531
+ end
532
+
533
+ return result
534
+ end
535
+
536
+ end
537
+
538
+
539
+ private
540
+ def create_playlist_items( items, playlistId = nil)
541
+
542
+ _items = []
543
+
544
+ items.each do |r|
545
+ _element = {}
546
+
547
+ if( r['name'] )
548
+
549
+ _name = search_dashboards( query: r['name'] )
550
+ _name_status = _name.dig('status')
551
+
552
+ next unless( _name_status == 200 )
553
+
554
+ _name = _name.dig('message')
555
+ _name_id = _name.first.dig('id')
556
+ _name_title = _name.first.dig('title')
557
+
558
+ _element[:type] = 'dashboard_by_id'
559
+ _element[:value] = _name_id.to_s
560
+ _element[:title] = _name_title
561
+ _element[:playlistId] = playlistId unless(playlistId.nil?)
562
+
563
+ elsif( r['id'] )
564
+
565
+ _uid = dashboard_by_uid(r['id'])
566
+ _uid_status = _uid.dig('status')
567
+
568
+ next unless( _uid_status == 200 )
569
+
570
+ _element[:type] = 'dashboard_by_id'
571
+ _element[:value] = r['id']
572
+ _element[:playlistId] = playlistId unless(playlistId.nil?)
573
+
574
+ elsif( r['tag'] )
575
+
576
+ _tags = search_dashboards( tags: r['tag'] )
577
+ _tags_status = _tags.dig('status')
578
+
579
+ next unless( _tags_status == 200 )
580
+
581
+ _element[:type] = 'dashboard_by_tag'
582
+ _element[:value] = r['tag']
583
+ _element[:title] = r['tag']
584
+ _element[:playlistId] = playlistId unless(playlistId.nil?)
585
+
586
+ else
587
+ next
588
+ end
589
+
590
+ _element[:order] = r['order'] if(r['order'])
591
+
592
+ _items << _element if(_element.count >= 4)
593
+ end
594
+
595
+ _items
596
+ end
597
+
598
+ end
599
+ end