wavefront-sdk 1.6.2 → 2.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 (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