wavefront-sdk 1.6.2 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +6 -0
  3. data/HISTORY.md +39 -13
  4. data/README.md +75 -28
  5. data/Rakefile +1 -1
  6. data/lib/wavefront-sdk/alert.rb +113 -17
  7. data/lib/wavefront-sdk/cloudintegration.rb +8 -8
  8. data/lib/wavefront-sdk/core/api.rb +99 -0
  9. data/lib/wavefront-sdk/core/api_caller.rb +211 -0
  10. data/lib/wavefront-sdk/{exception.rb → core/exception.rb} +11 -6
  11. data/lib/wavefront-sdk/{logger.rb → core/logger.rb} +2 -3
  12. data/lib/wavefront-sdk/{response.rb → core/response.rb} +69 -52
  13. data/lib/wavefront-sdk/credentials.rb +6 -3
  14. data/lib/wavefront-sdk/dashboard.rb +14 -14
  15. data/lib/wavefront-sdk/{constants.rb → defs/constants.rb} +1 -0
  16. data/lib/wavefront-sdk/defs/version.rb +1 -0
  17. data/lib/wavefront-sdk/derivedmetric.rb +14 -14
  18. data/lib/wavefront-sdk/distribution.rb +75 -0
  19. data/lib/wavefront-sdk/event.rb +13 -13
  20. data/lib/wavefront-sdk/externallink.rb +8 -8
  21. data/lib/wavefront-sdk/integration.rb +9 -9
  22. data/lib/wavefront-sdk/maintenancewindow.rb +54 -8
  23. data/lib/wavefront-sdk/message.rb +4 -4
  24. data/lib/wavefront-sdk/metric.rb +3 -3
  25. data/lib/wavefront-sdk/notificant.rb +9 -9
  26. data/lib/wavefront-sdk/paginator/base.rb +148 -0
  27. data/lib/wavefront-sdk/paginator/delete.rb +11 -0
  28. data/lib/wavefront-sdk/paginator/get.rb +11 -0
  29. data/lib/wavefront-sdk/paginator/post.rb +64 -0
  30. data/lib/wavefront-sdk/paginator/put.rb +11 -0
  31. data/lib/wavefront-sdk/proxy.rb +7 -7
  32. data/lib/wavefront-sdk/query.rb +4 -4
  33. data/lib/wavefront-sdk/report.rb +9 -25
  34. data/lib/wavefront-sdk/savedsearch.rb +8 -8
  35. data/lib/wavefront-sdk/search.rb +16 -13
  36. data/lib/wavefront-sdk/source.rb +14 -14
  37. data/lib/wavefront-sdk/{mixins.rb → support/mixins.rb} +8 -2
  38. data/lib/wavefront-sdk/{parse_time.rb → support/parse_time.rb} +2 -0
  39. data/lib/wavefront-sdk/types/status.rb +52 -0
  40. data/lib/wavefront-sdk/user.rb +8 -8
  41. data/lib/wavefront-sdk/validators.rb +52 -3
  42. data/lib/wavefront-sdk/webhook.rb +8 -8
  43. data/lib/wavefront-sdk/write.rb +153 -52
  44. data/lib/wavefront-sdk/writers/api.rb +38 -0
  45. data/lib/wavefront-sdk/writers/core.rb +146 -0
  46. data/lib/wavefront-sdk/writers/http.rb +42 -0
  47. data/lib/wavefront-sdk/writers/socket.rb +66 -0
  48. data/lib/wavefront-sdk/writers/summary.rb +39 -0
  49. data/lib/wavefront_sdk.rb +9 -0
  50. data/spec/spec_helper.rb +3 -0
  51. data/spec/wavefront-sdk/alert_spec.rb +6 -0
  52. data/spec/wavefront-sdk/{base_spec.rb → core/api_caller_spec.rb} +28 -41
  53. data/spec/wavefront-sdk/core/api_spec.rb +31 -0
  54. data/spec/wavefront-sdk/{logger_spec.rb → core/logger_spec.rb} +3 -3
  55. data/spec/wavefront-sdk/core/response_spec.rb +77 -0
  56. data/spec/wavefront-sdk/credentials_spec.rb +15 -10
  57. data/spec/wavefront-sdk/distribution_spec.rb +78 -0
  58. data/spec/wavefront-sdk/paginator/base_spec.rb +67 -0
  59. data/spec/wavefront-sdk/paginator/post_spec.rb +53 -0
  60. data/spec/wavefront-sdk/report_spec.rb +3 -1
  61. data/spec/wavefront-sdk/search_spec.rb +25 -0
  62. data/spec/wavefront-sdk/stdlib/array_spec.rb +2 -1
  63. data/spec/wavefront-sdk/stdlib/hash_spec.rb +6 -1
  64. data/spec/wavefront-sdk/stdlib/string_spec.rb +2 -0
  65. data/spec/wavefront-sdk/{mixins_spec.rb → support/mixins_spec.rb} +2 -2
  66. data/spec/wavefront-sdk/{parse_time_spec.rb → support/parse_time_spec.rb} +2 -2
  67. data/spec/wavefront-sdk/validators_spec.rb +64 -1
  68. data/spec/wavefront-sdk/write_spec.rb +55 -77
  69. data/spec/wavefront-sdk/writers/api_spec.rb +45 -0
  70. data/spec/wavefront-sdk/writers/core_spec.rb +49 -0
  71. data/spec/wavefront-sdk/writers/http_spec.rb +69 -0
  72. data/spec/wavefront-sdk/writers/socket_spec.rb +104 -0
  73. data/spec/wavefront-sdk/writers/summary_spec.rb +38 -0
  74. data/wavefront-sdk.gemspec +1 -1
  75. metadata +52 -24
  76. data/lib/wavefront-sdk/base.rb +0 -264
  77. data/lib/wavefront-sdk/base_write.rb +0 -185
  78. data/lib/wavefront-sdk/stdlib.rb +0 -5
  79. data/lib/wavefront-sdk/version.rb +0 -1
  80. data/spec/wavefront-sdk/base_write_spec.rb +0 -82
  81. data/spec/wavefront-sdk/response_spec.rb +0 -39
@@ -1,11 +1,11 @@
1
- require_relative 'base'
1
+ require_relative 'core/api'
2
2
 
3
3
  module Wavefront
4
4
  #
5
5
  # View and manage Cloud Integrations. These are identified by
6
6
  # a UUID.
7
7
  #
8
- class CloudIntegration < Base
8
+ class CloudIntegration < CoreApi
9
9
  # GET /api/v2/cloudintegration
10
10
  # Get all cloud integrations for a customer
11
11
  #
@@ -14,7 +14,7 @@ module Wavefront
14
14
  # @return [Wavefront::Response]
15
15
  #
16
16
  def list(offset = 0, limit = 100)
17
- api_get('', offset: offset, limit: limit)
17
+ api.get('', offset: offset, limit: limit)
18
18
  end
19
19
 
20
20
  # POST /api/v2/cloudintegration
@@ -26,7 +26,7 @@ module Wavefront
26
26
  #
27
27
  def create(body)
28
28
  raise ArgumentError unless body.is_a?(Hash)
29
- api_post('', body, 'application/json')
29
+ api.post('', body, 'application/json')
30
30
  end
31
31
 
32
32
  # DELETE /api/v2/cloudintegration/id
@@ -41,7 +41,7 @@ module Wavefront
41
41
  #
42
42
  def delete(id)
43
43
  wf_cloudintegration_id?(id)
44
- api_delete(id)
44
+ api.delete(id)
45
45
  end
46
46
 
47
47
  # GET /api/v2/cloudintegration/id
@@ -52,7 +52,7 @@ module Wavefront
52
52
  #
53
53
  def describe(id)
54
54
  wf_cloudintegration_id?(id)
55
- api_get(id)
55
+ api.get(id)
56
56
  end
57
57
 
58
58
  # PUT /api/v2/cloudintegration/id
@@ -64,7 +64,7 @@ module Wavefront
64
64
  def update(id, body)
65
65
  wf_cloudintegration_id?(id)
66
66
  raise ArgumentError unless body.is_a?(Hash)
67
- api_put(id, body)
67
+ api.put(id, body)
68
68
  end
69
69
 
70
70
  # POST /api/v2/cloudintegration/id/undelete
@@ -75,7 +75,7 @@ module Wavefront
75
75
  #
76
76
  def undelete(id)
77
77
  wf_cloudintegration_id?(id)
78
- api_post([id, 'undelete'].uri_concat)
78
+ api.post([id, 'undelete'].uri_concat)
79
79
  end
80
80
  end
81
81
  end
@@ -0,0 +1,99 @@
1
+ require_relative 'logger'
2
+ require_relative 'api_caller'
3
+ require_relative 'exception'
4
+ require_relative '../validators'
5
+ require_relative '../support/mixins'
6
+
7
+ module Wavefront
8
+ #
9
+ # Abstract class from which all API classes inherit. When you make
10
+ # any call to the Wavefront API from this SDK, you are returned an
11
+ # OpenStruct object.
12
+ #
13
+ # @return a Wavefront::Response object
14
+ #
15
+ class CoreApi
16
+ include Wavefront::Validators
17
+ include Wavefront::Mixins
18
+ attr_reader :api, :update_keys, :logger, :creds, :opts
19
+
20
+ # Create a new API object. This will always be called from a
21
+ # class which inherits this one. If the inheriting class defines
22
+ # #post_initialize, that method will be called afterwards, with
23
+ # the same arguments.
24
+ #
25
+ # @param creds [Hash] must contain the keys `endpoint` (the
26
+ # Wavefront API server) and `token`, the user token with which
27
+ # you wish to access the endpoint. Can optionally contain
28
+ # `agent`, which will become the `user-agent` string sent with
29
+ # all requests. Passed through to the ApiCaller class.
30
+ # @param opts [Hash] options governing class behaviour. Expected
31
+ # keys are `debug`, `noop` and `verbose`, all boolean; and
32
+ # `logger`, which must be a standard Ruby logger object. You
33
+ # can also pass :response_only. If this is true, you will only
34
+ # be returned a hash of the 'response' object returned by
35
+ # Wavefront. Passed through to the ApiCaller class.
36
+ # @return [Nil]
37
+ #
38
+ def initialize(creds = {}, opts = {})
39
+ @creds = creds
40
+ @opts = opts
41
+ @api = setup_api(creds, opts)
42
+ @s_api = setup_api(creds, opts)
43
+ @logger = Wavefront::Logger.new(opts)
44
+ post_initialize(creds, opts) if respond_to?(:post_initialize)
45
+ end
46
+
47
+ def setup_api(creds, opts)
48
+ Wavefront::ApiCaller.new(self, creds, opts)
49
+ end
50
+
51
+ # Derive the first part of the API path from the class name. You
52
+ # can override this in your class if you wish. This method is
53
+ # called by the ApiCaller class.
54
+ #
55
+ # @return [String] portion of API URI
56
+ #
57
+ def api_base
58
+ self.class.name.split('::').last.downcase
59
+ end
60
+
61
+ # The API path is normally /api/v2/something, but not always.
62
+ # Override this method if not
63
+ #
64
+ def api_path
65
+ ['', 'api', 'v2', api_base].uri_concat
66
+ end
67
+
68
+ # Convert an epoch timestamp into epoch milliseconds. If the
69
+ # timestamp looks like it's already epoch milliseconds, return
70
+ # it as-is.
71
+ #
72
+ # @param t [Integer] epoch timestamp
73
+ # @return [Ingeter] epoch millisecond timestamp
74
+ #
75
+ def time_to_ms(time)
76
+ return false unless time.is_a?(Integer)
77
+ return time if time.to_s.size == 13
78
+ (time.to_f * 1000).round
79
+ end
80
+
81
+ # doing a PUT to update an object requires only a certain subset of
82
+ # the keys returned by #describe(). This method takes the
83
+ # existing description of an object and turns it into a new has
84
+ # which can be PUT.
85
+ #
86
+ # @param old [Hash] a hash of the existing object
87
+ # @param new [Hash] the keys you wish to update
88
+ # @return [Hash] a hash containing only the keys which need to be
89
+ # sent to the API. Keys will be symbolized.
90
+ #
91
+ def hash_for_update(old, new)
92
+ raise ArgumentError unless old.is_a?(Hash) && new.is_a?(Hash)
93
+
94
+ Hash[old.merge(new).map { |k, v| [k.to_sym, v] }].select do |k, _v|
95
+ update_keys.include?(k)
96
+ end
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,211 @@
1
+ require 'json'
2
+ require 'faraday'
3
+ require 'addressable'
4
+ require_relative 'response'
5
+ require_relative '../defs/version'
6
+ require_relative '../support/mixins'
7
+
8
+ module Wavefront
9
+ #
10
+ # Constructs and makes API calls to Wavefront.
11
+ #
12
+ class ApiCaller
13
+ include Wavefront::Mixins
14
+
15
+ attr_reader :opts, :noop, :debug, :verbose, :net, :logger,
16
+ :calling_class
17
+
18
+ # @param calling_class [
19
+ # @param creds [Hash] Wavefront credentials
20
+ # @param opts [Hash]
21
+ # @return [Nil]
22
+ #
23
+ def initialize(calling_class, creds = {}, opts = {})
24
+ @calling_class = calling_class
25
+ @opts = opts
26
+ setup_class_vars(opts)
27
+ setup_endpoint(creds)
28
+ end
29
+
30
+ def setup_class_vars(opts)
31
+ @logger = Wavefront::Logger.new(opts)
32
+ @noop = opts[:noop] || false
33
+ @verbose = opts[:verbose] || false
34
+ @debug = opts[:debug] || false
35
+ end
36
+
37
+ # Create a Faraday connection object. The server comes from the
38
+ # endpoint passed to the initializer in the 'creds' hash; the
39
+ # root of the URI is dynamically derived by the #setup_endpoint
40
+ # method.
41
+ #
42
+ # @param headers [Hash] additional headers
43
+ # @return [URI::HTTPS]
44
+ #
45
+ def mk_conn(path, headers = {})
46
+ url = format('%s://%s%s', net[:scheme], net[:endpoint],
47
+ [net[:api_base], path].uri_concat)
48
+ Faraday.new(url: Addressable::URI.encode(url),
49
+ headers: net[:headers].merge(headers))
50
+ end
51
+
52
+ # Make a GET call to the Wavefront API and return the result as
53
+ # a Ruby hash.
54
+ #
55
+ # @param path [String] path to be appended to the
56
+ # #net[:api_base] path.
57
+ # @param query [Hash] optional key-value pairs with will be made
58
+ # into aquery string
59
+ # @return [Hash] API response
60
+ #
61
+ def get(path, query = {})
62
+ make_call(mk_conn(path), :get, nil, query)
63
+ end
64
+
65
+ # Make a POST call to the Wavefront API and return the result as
66
+ # a Ruby hash.
67
+ #
68
+ # @param path [String] path to be appended to the
69
+ # #net[:api_base] path.
70
+ # @param body [String,Object] optional body text to post.
71
+ # Objects will be converted to JSON
72
+ # @param ctype [String] the content type to use when posting
73
+ # @return [Hash] API response
74
+ #
75
+ def post(path, body = nil, ctype = 'text/plain')
76
+ body = body.to_json unless body.is_a?(String)
77
+ make_call(mk_conn(path, 'Content-Type': ctype,
78
+ 'Accept': 'application/json'),
79
+ :post, nil, body)
80
+ end
81
+
82
+ # Make a PUT call to the Wavefront API and return the result as
83
+ # a Ruby hash.
84
+ #
85
+ # @param path [String] path to be appended to the
86
+ # #net[:api_base] path.
87
+ # @param body [String] optional body text to post
88
+ # @param ctype [String] the content type to use when putting
89
+ # @return [Hash] API response
90
+ #
91
+ def put(path, body = nil, ctype = 'application/json')
92
+ make_call(mk_conn(path, 'Content-Type': ctype,
93
+ 'Accept': 'application/json'),
94
+ :put, nil, body.to_json)
95
+ end
96
+
97
+ # Make a DELETE call to the Wavefront API and return the result
98
+ # as a Ruby hash.
99
+ #
100
+ # @param path [String] path to be appended to the
101
+ # #net[:api_base] path.
102
+ # @return [Hash] API response
103
+ #
104
+ def delete(path)
105
+ make_call(mk_conn(path), :delete)
106
+ end
107
+
108
+ # If we need to massage a raw response to fit what the
109
+ # Wavefront::Response class expects (I'm looking at you,
110
+ # 'User'), a class can provide a {#response_shim} method.
111
+ #
112
+ def respond(resp)
113
+ body = if calling_class.respond_to?(:response_shim)
114
+ calling_class.response_shim(resp.body, resp.status)
115
+ else
116
+ resp.body
117
+ end
118
+
119
+ Wavefront::Response.new(body, resp.status, @opts)
120
+ end
121
+
122
+ # Try to describe the actual HTTP calls we make. There's a bit
123
+ # of clumsy guesswork here
124
+ #
125
+ def verbosity(conn, method, *args)
126
+ return unless noop || verbose
127
+ log format('uri: %s %s', method.upcase, conn.url_prefix)
128
+
129
+ return unless args.last && !args.last.empty?
130
+
131
+ log method == :get ? "params: #{args.last}" : "body: #{args.last}"
132
+ end
133
+
134
+ private
135
+
136
+ def paginator_class(method)
137
+ require_relative File.join('..', 'paginator', method.to_s)
138
+ Object.const_get(format('Wavefront::Paginator::%s',
139
+ method.to_s.capitalize))
140
+ end
141
+
142
+ # A dispatcher for making API calls. We now have three methods
143
+ # that do the real call, two of which live inside the requisite
144
+ # Wavefront::Paginator class
145
+ # @raise [Faraday::ConnectionFailed] if cannot connect to
146
+ # endpoint
147
+ #
148
+ def make_call(conn, method, *args)
149
+ verbosity(conn, method, *args)
150
+ return if noop
151
+
152
+ paginator = paginator_class(method).new(self, conn, method, *args)
153
+
154
+ case paginator.initial_limit
155
+ when :all, 'all'
156
+ paginator.make_recursive_call
157
+ when :lazy, 'lazy'
158
+ paginator.make_lazy_call
159
+ else
160
+ make_single_call(conn, method, *args)
161
+ end
162
+ end
163
+
164
+ def make_single_call(conn, method, *args)
165
+ resp = conn.public_send(method, *args)
166
+
167
+ if debug
168
+ require 'pp'
169
+ pp resp
170
+ end
171
+
172
+ respond(resp)
173
+ end
174
+
175
+ def setup_endpoint(creds)
176
+ validate_credentials(creds)
177
+
178
+ unless creds.key?(:agent) && creds[:agent]
179
+ creds[:agent] = "wavefront-sdk #{WF_SDK_VERSION}"
180
+ end
181
+
182
+ @net = { headers: headers(creds),
183
+ scheme: opts[:scheme] || 'https',
184
+ endpoint: creds[:endpoint],
185
+ api_base: calling_class.api_path }
186
+ end
187
+
188
+ def headers(creds)
189
+ ret = { 'user-agent': creds[:agent] }
190
+ ret[:Authorization] = "Bearer #{creds[:token]}" if creds[:token]
191
+ ret
192
+ end
193
+
194
+ def validate_credentials(creds)
195
+ if calling_class.respond_to?(:validate_credentials)
196
+ calling_class.validate_credentials(creds)
197
+ else
198
+ _validate_credentials(creds)
199
+ end
200
+ end
201
+
202
+ def _validate_credentials(creds)
203
+ %w[endpoint token].each do |k|
204
+ unless creds.key?(k.to_sym)
205
+ raise(Wavefront::Exception::CredentialError,
206
+ format('credentials must contain %s', k))
207
+ end
208
+ end
209
+ end
210
+ end
211
+ end
@@ -5,41 +5,46 @@ module Wavefront
5
5
  class Exception
6
6
  class CredentialError < RuntimeError; end
7
7
  class EmptyMetricName < RuntimeError; end
8
+ class EnumerableError < RuntimeError; end
8
9
  class InvalidAlertId < RuntimeError; end
9
10
  class InvalidAlertSeverity < RuntimeError; end
10
11
  class InvalidCloudIntegrationId < RuntimeError; end
11
12
  class InvalidDashboardId < RuntimeError; end
12
13
  class InvalidDerivedMetricId < RuntimeError; end
14
+ class InvalidDistribution < RuntimeError; end
15
+ class InvalidDistributionInterval < RuntimeError; end
16
+ class InvalidDistributionCount < RuntimeError; end
13
17
  class InvalidEndpoint < RuntimeError; end
14
18
  class InvalidEventId < RuntimeError; end
15
19
  class InvalidExternalLinkId < RuntimeError; end
16
20
  class InvalidGranularity < RuntimeError; end
17
21
  class InvalidHostname < RuntimeError; end
18
22
  class InvalidIntegrationId < RuntimeError; end
19
- class InvalidRelativeTime < RuntimeError; end
20
- class InvalidTimeUnit < RuntimeError; end
23
+ class InvalidLinkTemplate < RuntimeError; end
21
24
  class InvalidMaintenanceWindowId < RuntimeError; end
22
25
  class InvalidMessageId < RuntimeError; end
23
26
  class InvalidMetricName < RuntimeError; end
24
27
  class InvalidMetricValue < RuntimeError; end
25
- class InvalidNotificantId < RuntimeError; end
26
28
  class InvalidName < RuntimeError; end
29
+ class InvalidNotificantId < RuntimeError; end
27
30
  class InvalidPoint < RuntimeError; end
28
31
  class InvalidPrefixLength < RuntimeError; end
29
32
  class InvalidProxyId < RuntimeError; end
30
- class InvalidSavedSearchId < RuntimeError; end
33
+ class InvalidRelativeTime < RuntimeError; end
31
34
  class InvalidSavedSearchEntity < RuntimeError; end
35
+ class InvalidSavedSearchId < RuntimeError; end
32
36
  class InvalidSourceId < RuntimeError; end
33
37
  class InvalidString < RuntimeError; end
34
38
  class InvalidTag < RuntimeError; end
35
- class InvalidLinkTemplate < RuntimeError; end
36
39
  class InvalidTimeFormat < RuntimeError; end
40
+ class InvalidTimeUnit < RuntimeError; end
37
41
  class InvalidTimestamp < RuntimeError; end
38
42
  class InvalidUserId < RuntimeError; end
39
- class InvalidWebhookId < RuntimeError; end
40
43
  class InvalidVersion < RuntimeError; end
44
+ class InvalidWebhookId < RuntimeError; end
41
45
  class NotImplemented < RuntimeError; end
42
46
  class UnparseableResponse < RuntimeError; end
47
+ class UnsupportedWriter < RuntimeError; end
43
48
  class ValueOutOfRange < RuntimeError; end
44
49
  end
45
50
  end
@@ -46,12 +46,11 @@ module Wavefront
46
46
  end
47
47
 
48
48
  def print_debug_message(msg)
49
- return unless debug
50
- puts msg
49
+ puts msg if debug
51
50
  end
52
51
 
53
52
  def print_info_message(msg)
54
- puts msg
53
+ puts msg if debug || verbose
55
54
  end
56
55
 
57
56
  def print_warn_message(msg)
@@ -1,7 +1,9 @@
1
1
  require 'json'
2
2
  require 'map'
3
+ require_relative 'logger'
3
4
  require_relative 'exception'
4
- require_relative 'mixins'
5
+ require_relative '../types/status'
6
+ require_relative '../support/mixins'
5
7
 
6
8
  module Wavefront
7
9
  #
@@ -32,13 +34,10 @@ module Wavefront
32
34
  # has changed underneath us.
33
35
  #
34
36
  def initialize(json, status, opts = {})
37
+ setup_vars(opts)
35
38
  raw = raw_response(json, status)
36
39
  @status = build_status(raw, status)
37
40
  @response = build_response(raw)
38
- @opts = opts
39
-
40
- setup_opts
41
-
42
41
  logger.log(self, :debug)
43
42
  rescue StandardError => e
44
43
  logger.log(format("could not parse:\n%s", json), :debug)
@@ -46,69 +45,87 @@ module Wavefront
46
45
  raise Wavefront::Exception::UnparseableResponse
47
46
  end
48
47
 
49
- def setup_opts
50
- @logger = Wavefront::Logger.new(opts)
48
+ # Were there items in the response?
49
+ #
50
+ def empty?
51
+ response.items.size.zero?
52
+ rescue StandardError
53
+ false
51
54
  end
52
55
 
53
- def raw_response(json, status)
54
- json.empty? ? {} : JSON.parse(json, symbolize_names: true)
56
+ # Was the API's response positive?
57
+ # @return [Bool]
58
+ #
59
+ def ok?
60
+ respond_to?(:status) && status.result == 'OK'
61
+ end
62
+
63
+ # Are there more items in paginated output?
64
+ # @return [Bool]
65
+ #
66
+ def more_items?
67
+ return false unless response.key?(:moreItems)
68
+ !!response.moreItems
69
+ end
70
+
71
+ # On paginated output, the offset of the next item, or nil.
72
+ # @return [Integer, Nil]
73
+ #
74
+ def next_item
75
+ return nil unless more_items?
76
+ reponse.offset + response.limit
55
77
  rescue StandardError
56
- { message: json, code: status }
78
+ nil
57
79
  end
58
80
 
59
- def build_status(raw, status)
60
- Wavefront::Type::Status.new(raw, status)
81
+ # A printable version of a Wavefront::Response object
82
+ # @return [String]
83
+ #
84
+ def to_s
85
+ inspect.to_s
61
86
  end
62
87
 
88
+ # We often want the IDs of all the objects we retrieved. This
89
+ # does it.
90
+
91
+ def ids
92
+ response.items.map(&:id)
93
+ end
94
+
95
+ # We often want the names of all the objects we retrieved.
96
+ #
97
+ def names
98
+ response.items.map(&:name)
99
+ end
100
+
101
+ private
102
+
103
+ def setup_vars(opts)
104
+ @opts = opts
105
+ @logger = Wavefront::Logger.new(opts)
106
+ end
107
+
108
+ # @params raw [Hash] created by #raw_response
109
+ #
63
110
  def build_response(raw)
64
111
  return Map.new unless raw.is_a?(Hash)
65
112
  return Map.new(raw) unless raw.key?(:response)
66
113
  return raw[:response] unless raw[:response].is_a?(Hash)
67
114
  Map(raw[:response])
68
115
  end
69
- end
70
116
 
71
- # Status types are used by the Wavefront::Response class
72
- #
73
- class Type
74
- #
75
- # An object which provides information about whether the request
76
- # was successful or not. Ordinarily this is easy to construct
77
- # from the API's JSON response, but some classes, for instance
78
- # Wavefront::Write fake it by constructing their own.
79
- #
80
- # @!attribute [r] result
81
- # @return [OK, ERROR] a string telling us how the request went
82
- # @!attribute [r] message
83
- # @return [String] Any informational message from the API
84
- # @!attribute [r] code
85
- # @return [Integer] the HTTP response code from the API
86
- # request
117
+ # Turn the API's JSON response and HTTP status code into a Ruby
118
+ # object.
119
+ # @return [Hash]
87
120
  #
88
- class Status
89
- attr_reader :obj, :status
90
-
91
- # @param response [Hash] the API response, turned into a hash
92
- # @param status [Integer] HTTP status code
93
- #
94
- def initialize(response, status)
95
- @obj = response.fetch(:status, response)
96
- @status = status
97
- end
98
-
99
- def message
100
- obj[:message] || nil
101
- end
102
-
103
- def code
104
- obj[:code] || status
105
- end
121
+ def raw_response(json, status)
122
+ json.empty? ? {} : JSON.parse(json, symbolize_names: true)
123
+ rescue StandardError
124
+ { message: json, code: status }
125
+ end
106
126
 
107
- def result
108
- return obj[:result] if obj[:result]
109
- return 'OK' if status.between?(200, 299)
110
- 'ERROR'
111
- end
127
+ def build_status(raw, status)
128
+ Wavefront::Type::Status.new(raw, status)
112
129
  end
113
130
  end
114
131
  end