wavefront-sdk 3.3.2 → 3.3.3
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 +4 -4
- data/HISTORY.md +42 -35
- data/README.md +5 -5
- data/lib/wavefront-sdk/alert.rb +2 -0
- data/lib/wavefront-sdk/core/api_caller.rb +6 -3
- data/lib/wavefront-sdk/defs/version.rb +2 -2
- data/lib/wavefront-sdk/derivedmetric.rb +7 -0
- data/lib/wavefront-sdk/externallink.rb +2 -2
- data/lib/wavefront-sdk/maintenancewindow.rb +6 -2
- data/lib/wavefront-sdk/notificant.rb +7 -0
- data/lib/wavefront-sdk/paginator/base.rb +8 -0
- data/lib/wavefront-sdk/search.rb +11 -2
- data/lib/wavefront-sdk/user.rb +39 -8
- data/lib/wavefront-sdk/webhook.rb +1 -1
- data/spec/constants.rb +30 -0
- data/spec/spec_helper.rb +12 -237
- data/spec/support/bad_mocket.rb +15 -0
- data/spec/support/hash.rb +9 -0
- data/spec/support/minitest_assertions.rb +110 -0
- data/spec/support/mocket.rb +19 -0
- data/spec/test_mixins/acl.rb +78 -0
- data/spec/test_mixins/general.rb +120 -0
- data/spec/test_mixins/tag.rb +55 -0
- data/spec/test_mixins/update_keys.rb +11 -0
- data/spec/wavefront-sdk/alert_spec.rb +88 -136
- data/spec/wavefront-sdk/apitoken_spec.rb +26 -13
- data/spec/wavefront-sdk/cloudintegration_spec.rb +42 -44
- data/spec/wavefront-sdk/dashboard_spec.rb +53 -72
- data/spec/wavefront-sdk/derivedmetric_spec.rb +23 -49
- data/spec/wavefront-sdk/distribution_spec.rb +14 -14
- data/spec/wavefront-sdk/event_spec.rb +39 -48
- data/spec/wavefront-sdk/externallink_spec.rb +19 -50
- data/spec/wavefront-sdk/integration_spec.rb +33 -38
- data/spec/wavefront-sdk/maintenancewindow_spec.rb +18 -33
- data/spec/wavefront-sdk/message_spec.rb +19 -4
- data/spec/wavefront-sdk/metric_spec.rb +13 -9
- data/spec/wavefront-sdk/notificant_spec.rb +16 -15
- data/spec/wavefront-sdk/proxy_spec.rb +20 -25
- data/spec/wavefront-sdk/query_spec.rb +50 -24
- data/spec/wavefront-sdk/report_spec.rb +3 -6
- data/spec/wavefront-sdk/resources/user_responses/add_user_groups.json +1 -0
- data/spec/wavefront-sdk/resources/user_responses/create.json +28 -0
- data/spec/wavefront-sdk/resources/user_responses/delete_multiple.json +1 -0
- data/spec/wavefront-sdk/resources/user_responses/describe.json +1 -0
- data/spec/wavefront-sdk/resources/user_responses/grant.json +1 -0
- data/spec/wavefront-sdk/resources/user_responses/list.json +1 -0
- data/spec/wavefront-sdk/savedsearch_spec.rb +41 -35
- data/spec/wavefront-sdk/search_spec.rb +35 -29
- data/spec/wavefront-sdk/settings_spec.rb +18 -12
- data/spec/wavefront-sdk/source_spec.rb +29 -32
- data/spec/wavefront-sdk/user_spec.rb +101 -74
- data/spec/wavefront-sdk/usergroup_spec.rb +56 -67
- data/spec/wavefront-sdk/webhook_spec.rb +22 -34
- data/spec/wavefront-sdk/write_spec.rb +2 -0
- data/spec/wavefront-sdk/writers/core_spec.rb +2 -0
- data/spec/wavefront-sdk/writers/summary_spec.rb +2 -0
- data/wavefront-sdk.gemspec +5 -5
- metadata +44 -13
data/spec/constants.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# rubocop:disable Style/MutableConstant
|
2
|
+
CREDS = { endpoint: 'test.example.com',
|
3
|
+
token: '0123456789-ABCDEF' }
|
4
|
+
# rubocop:enable Style/MutableConstant
|
5
|
+
|
6
|
+
W_CREDS = { proxy: 'wavefront', port: 2878 }.freeze
|
7
|
+
|
8
|
+
POST_HEADERS = {
|
9
|
+
'Content-Type': 'text/plain', Accept: 'application/json'
|
10
|
+
}.freeze
|
11
|
+
|
12
|
+
JSON_POST_HEADERS = {
|
13
|
+
'Content-Type': 'application/json', Accept: 'application/json'
|
14
|
+
}.freeze
|
15
|
+
|
16
|
+
DUMMY_RESPONSE = '{"status":{"result":"OK","message":"","code":200},' \
|
17
|
+
'"response":{"items":[{"name":"test data"}],"offset":0,' \
|
18
|
+
'"limit":100,"totalItems":3,"moreItems":false}}'.freeze
|
19
|
+
|
20
|
+
RESOURCE_DIR = (Pathname.new(__FILE__).dirname +
|
21
|
+
'wavefront-sdk' + 'resources').freeze
|
22
|
+
|
23
|
+
U_ACL_1 = 'someone@example.com'.freeze
|
24
|
+
U_ACL_2 = 'other@elsewhere.com'.freeze
|
25
|
+
GRP_ACL = 'f8dc0c14-91a0-4ca9-8a2a-7d47f4db4672'.freeze
|
26
|
+
|
27
|
+
DEFAULT_HEADERS = { 'Accept': /.*/,
|
28
|
+
'Accept-Encoding': /.*/,
|
29
|
+
'Authorization': 'Bearer 0123456789-ABCDEF',
|
30
|
+
'User-Agent': /wavefront-sdk \d+\.\d+\.\d+/ }.freeze
|
data/spec/spec_helper.rb
CHANGED
@@ -1,258 +1,33 @@
|
|
1
|
-
#
|
2
|
-
# Stuff needed by multiple tests
|
3
|
-
#
|
4
|
-
|
5
1
|
require 'simplecov'
|
6
|
-
SimpleCov.start
|
7
|
-
add_filter '/spec/'
|
8
|
-
end
|
2
|
+
SimpleCov.start { add_filter '/spec/' }
|
9
3
|
require 'minitest/autorun'
|
10
4
|
require 'spy/integration'
|
11
5
|
require 'webmock/minitest'
|
6
|
+
require_relative 'support/minitest_assertions'
|
7
|
+
require_relative 'constants'
|
12
8
|
|
13
|
-
#
|
14
|
-
|
15
|
-
token: '0123456789-ABCDEF' }
|
16
|
-
# rubocop:enable Style/MutableConstant
|
17
|
-
|
18
|
-
W_CREDS = { proxy: 'wavefront', port: 2878 }.freeze
|
19
|
-
|
20
|
-
POST_HEADERS = {
|
21
|
-
'Content-Type': 'text/plain', Accept: 'application/json'
|
22
|
-
}.freeze
|
23
|
-
|
24
|
-
JSON_POST_HEADERS = {
|
25
|
-
'Content-Type': 'application/json', Accept: 'application/json'
|
26
|
-
}.freeze
|
27
|
-
|
28
|
-
DUMMY_RESPONSE = '{"status":{"result":"OK","message":"","code":200},' \
|
29
|
-
'"response":{"items":[{"name":"test data"}],"offset":0,' \
|
30
|
-
'"limit":100,"totalItems":3,"moreItems":false}}'.freeze
|
31
|
-
|
32
|
-
RESOURCE_DIR = (Pathname.new(__FILE__).dirname +
|
33
|
-
'wavefront-sdk' + 'resources').freeze
|
34
|
-
|
35
|
-
U_ACL_1 = 'someone@example.com'.freeze
|
36
|
-
U_ACL_2 = 'other@elsewhere.com'.freeze
|
37
|
-
GRP_ACL = 'f8dc0c14-91a0-4ca9-8a2a-7d47f4db4672'.freeze
|
38
|
-
|
39
|
-
# Common testing code
|
9
|
+
# Abstract class which sets up everything needed by the API tests
|
10
|
+
#
|
40
11
|
class WavefrontTestBase < MiniTest::Test
|
41
|
-
attr_reader :wf, :wf_noop, :headers
|
12
|
+
attr_reader :wf, :wf_noop, :headers, :invalid_id, :valid_id
|
42
13
|
|
43
14
|
def initialize(args)
|
44
15
|
require_relative "../lib/wavefront-sdk/#{class_basename.downcase}"
|
16
|
+
setup_fixtures if respond_to?(:setup_fixtures)
|
45
17
|
super(args)
|
46
18
|
end
|
47
19
|
|
48
|
-
|
49
|
-
self.class.name.match(/Wavefront(\w+)Test/)[1]
|
50
|
-
end
|
51
|
-
|
52
|
-
def api_base
|
53
|
-
class_basename.downcase
|
54
|
-
end
|
20
|
+
private
|
55
21
|
|
56
22
|
def setup
|
57
|
-
|
58
|
-
@wf = klass.new(CREDS)
|
59
|
-
@uri_base = uri_base
|
60
|
-
@headers = { 'Authorization' => "Bearer #{CREDS[:token]}" }
|
23
|
+
@wf = Object.const_get("Wavefront::#{class_basename}").new(CREDS)
|
61
24
|
end
|
62
25
|
|
63
|
-
def
|
64
|
-
|
65
|
-
end
|
66
|
-
|
67
|
-
def target_uri(path)
|
68
|
-
return "https://#{CREDS[:endpoint]}#{path}" if path.start_with?('/')
|
69
|
-
|
70
|
-
[uri_base, path].join(path.start_with?('?') ? '' : '/')
|
71
|
-
end
|
72
|
-
|
73
|
-
# A shorthand method for very common tests.
|
74
|
-
#
|
75
|
-
# @param method [String] the method you wish to test
|
76
|
-
# @args [String, Integer, Array] arguments with which to call method
|
77
|
-
# @path [String] extra API path components (beyond /api/v2/class)
|
78
|
-
# @call [Symbol] the type of API call (:get, :put etc.)
|
79
|
-
# @more_headers [Hash] any additional headers which should be
|
80
|
-
# sent. You will normally need to add these for :put and :post
|
81
|
-
# requests.
|
82
|
-
# @body [String] a JSON object you expect to be sent as part of
|
83
|
-
# the request
|
84
|
-
#
|
85
|
-
# rubocop:disable Metrics/PerceivedComplexity
|
86
|
-
# rubocop:disable Metrics/ParameterLists
|
87
|
-
def should_work(method, args, path, call = :get, more_headers = {},
|
88
|
-
body = nil, id = nil)
|
89
|
-
path = Array(path)
|
90
|
-
uri = target_uri(path.first).sub(%r{/$}, '')
|
91
|
-
|
92
|
-
headers = { 'Accept': /.*/,
|
93
|
-
'Accept-Encoding': /.*/,
|
94
|
-
'Authorization': 'Bearer 0123456789-ABCDEF',
|
95
|
-
'User-Agent': "wavefront-sdk #{WF_SDK_VERSION}" }
|
96
|
-
.merge(more_headers)
|
97
|
-
|
98
|
-
if body
|
99
|
-
stub_request(call, uri).with(body: body, headers: headers)
|
100
|
-
.to_return(body: DUMMY_RESPONSE, status: 200)
|
101
|
-
else
|
102
|
-
stub_request(call, uri).to_return(body: DUMMY_RESPONSE, status: 200)
|
103
|
-
end
|
104
|
-
|
105
|
-
if args.is_a?(Hash)
|
106
|
-
if id
|
107
|
-
wf.send(method, id, args)
|
108
|
-
else
|
109
|
-
wf.send(method, args)
|
110
|
-
end
|
111
|
-
elsif id
|
112
|
-
wf.send(method, id, *args)
|
113
|
-
else
|
114
|
-
wf.send(method, *args)
|
115
|
-
end
|
116
|
-
|
117
|
-
assert_requested(call, uri, headers: headers)
|
118
|
-
WebMock.reset!
|
26
|
+
def class_basename
|
27
|
+
self.class.name.match(/Wavefront(\w+)Test/)[1]
|
119
28
|
end
|
120
|
-
# rubocop:enable Metrics/PerceivedComplexity
|
121
|
-
# rubocop:enable Metrics/ParameterLists
|
122
29
|
|
123
30
|
def standard_exception
|
124
|
-
Object.const_get(
|
125
|
-
.const_get("Invalid#{class_basename}Id")
|
126
|
-
end
|
127
|
-
|
128
|
-
def should_be_invalid(method, args = '!!invalid_val!!')
|
129
|
-
assert_raises(standard_exception) { wf.send(method, *args) }
|
130
|
-
end
|
131
|
-
|
132
|
-
# Generic tag method testing.
|
133
|
-
#
|
134
|
-
def tag_tester(id)
|
135
|
-
# Can we get tags? : tests #tags
|
136
|
-
#
|
137
|
-
should_work('tags', id, "#{id}/tag")
|
138
|
-
should_be_invalid('tags')
|
139
|
-
|
140
|
-
# Can we set tags? tests #tag_set
|
141
|
-
#
|
142
|
-
should_work('tag_set', [id, 'tag'],
|
143
|
-
["#{id}/tag", ['tag'].to_json], :post, JSON_POST_HEADERS)
|
144
|
-
should_work('tag_set', [id, %w[tag1 tag2]],
|
145
|
-
["#{id}/tag", %w[tag1 tag2].to_json], :post,
|
146
|
-
JSON_POST_HEADERS)
|
147
|
-
should_fail_tags('tag_set', id)
|
148
|
-
|
149
|
-
# Can we add tags? : tests #tag_add
|
150
|
-
#
|
151
|
-
should_work('tag_add', [id, 'tagval'],
|
152
|
-
["#{id}/tag/tagval", nil], :put, JSON_POST_HEADERS)
|
153
|
-
should_fail_tags('tag_add', id)
|
154
|
-
|
155
|
-
# Can we delete tags? : tests #tag_delete
|
156
|
-
#
|
157
|
-
should_work('tag_delete', [id, 'tagval'], "#{id}/tag/tagval", :delete)
|
158
|
-
should_fail_tags('tag_delete', id)
|
159
|
-
end
|
160
|
-
|
161
|
-
def should_fail_tags(method, id)
|
162
|
-
assert_raises(standard_exception) do
|
163
|
-
wf.send(method, '!!invalid!!', 'tag1')
|
164
|
-
end
|
165
|
-
|
166
|
-
assert_raises(Wavefront::Exception::InvalidString) do
|
167
|
-
wf.send(method, id, '<!!!>')
|
168
|
-
end
|
169
|
-
end
|
170
|
-
|
171
|
-
def acl_tester(id)
|
172
|
-
id2 = id.reverse
|
173
|
-
should_work(:acls, [[id, id2]], "acl?id=#{id}&id=#{id2}")
|
174
|
-
|
175
|
-
should_work(:acl_add, [id, [U_ACL_1, U_ACL_2], [GRP_ACL]],
|
176
|
-
'acl/add', :post, {}, acl_body(id,
|
177
|
-
[U_ACL_1, U_ACL_2],
|
178
|
-
[GRP_ACL]))
|
179
|
-
|
180
|
-
should_work(:acl_add, [id, [U_ACL_1, U_ACL_2]],
|
181
|
-
'acl/add', :post, {}, acl_body(id,
|
182
|
-
[U_ACL_1, U_ACL_2]))
|
183
|
-
assert_raises(ArgumentError) { wf.acl_add(id, U_ACL_1) }
|
184
|
-
assert_raises(ArgumentError) { wf.acl_add(id, [U_ACL_1], GRP_ACL) }
|
185
|
-
|
186
|
-
should_work(:acl_delete, [id, [U_ACL_1, U_ACL_2], [GRP_ACL]],
|
187
|
-
'acl/remove', :post, {}, acl_body(id,
|
188
|
-
[U_ACL_1, U_ACL_2],
|
189
|
-
[GRP_ACL]))
|
190
|
-
|
191
|
-
should_work(:acl_delete, [id, [U_ACL_1, U_ACL_2]],
|
192
|
-
'acl/remove', :post, {}, acl_body(id,
|
193
|
-
[U_ACL_1, U_ACL_2]))
|
194
|
-
assert_raises(ArgumentError) { wf.acl_delete(id, U_ACL_1) }
|
195
|
-
|
196
|
-
should_work(:acl_set, [id, [U_ACL_1, U_ACL_2], [GRP_ACL]],
|
197
|
-
'acl/set', :put, {}, acl_body(id,
|
198
|
-
[U_ACL_1, U_ACL_2],
|
199
|
-
[GRP_ACL]))
|
200
|
-
|
201
|
-
should_work(:acl_set, [id, [U_ACL_1, U_ACL_2]],
|
202
|
-
'acl/set', :put, {}, acl_body(id,
|
203
|
-
[U_ACL_1, U_ACL_2]))
|
204
|
-
assert_raises(ArgumentError) { wf.acl_set(id, U_ACL_1) }
|
205
|
-
end
|
206
|
-
|
207
|
-
# used by acl_tester
|
208
|
-
#
|
209
|
-
def acl_body(id, view = [], modify = [])
|
210
|
-
[{ entityId: id, viewAcl: view, modifyAcl: modify }].to_json
|
211
|
-
end
|
212
|
-
end
|
213
|
-
|
214
|
-
# Extensions to stdlib
|
215
|
-
#
|
216
|
-
class Hash
|
217
|
-
# A quick way to deep-copy a hash.
|
218
|
-
#
|
219
|
-
def dup
|
220
|
-
Marshal.load(Marshal.dump(self))
|
221
|
-
end
|
222
|
-
end
|
223
|
-
|
224
|
-
# A mock socket
|
225
|
-
#
|
226
|
-
class Mocket
|
227
|
-
def puts(socket); end
|
228
|
-
|
229
|
-
def close; end
|
230
|
-
|
231
|
-
def ok?
|
232
|
-
true
|
233
|
-
end
|
234
|
-
|
235
|
-
def response
|
236
|
-
{ sent: 1, rejected: 0, unsent: 0 }
|
237
|
-
end
|
238
|
-
|
239
|
-
def status
|
240
|
-
{ result: 'OK', message: nil, code: nil }
|
241
|
-
end
|
242
|
-
end
|
243
|
-
|
244
|
-
# A mock socket which says things went wrong.
|
245
|
-
#
|
246
|
-
class BadMocket < Mocket
|
247
|
-
def ok?
|
248
|
-
false
|
249
|
-
end
|
250
|
-
|
251
|
-
def status
|
252
|
-
{ result: 'ERROR', message: nil, code: nil }
|
253
|
-
end
|
254
|
-
|
255
|
-
def response
|
256
|
-
{ sent: 0, rejected: 1, unsent: 0 }
|
31
|
+
Object.const_get("Wavefront::Exception::Invalid#{class_basename}Id")
|
257
32
|
end
|
258
33
|
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
module Minitest
|
2
|
+
#
|
3
|
+
# Some custom Minitest assertions to simplify testing
|
4
|
+
#
|
5
|
+
module Assertions
|
6
|
+
# Ensure the given call raises the correct InvalidId exception
|
7
|
+
# @param block [Proc] call to Wavefront SDK method
|
8
|
+
#
|
9
|
+
def assert_invalid_id(&block)
|
10
|
+
assert_raises(standard_exception) { yield block }
|
11
|
+
end
|
12
|
+
|
13
|
+
# Ensure that the correct API path is called by the given call
|
14
|
+
# @param api_path [String] full API path to be called
|
15
|
+
# @param block [Proc] call to SDK method
|
16
|
+
#
|
17
|
+
def assert_gets(api_path, &block)
|
18
|
+
headers = DEFAULT_HEADERS
|
19
|
+
stub_request(:get, uri(api_path))
|
20
|
+
.with(headers: headers)
|
21
|
+
.to_return(body: DUMMY_RESPONSE, status: 200)
|
22
|
+
yield block
|
23
|
+
assert_requested(:get, uri(api_path), headers: headers)
|
24
|
+
WebMock.reset!
|
25
|
+
end
|
26
|
+
|
27
|
+
# Ensure that the correct API path is hit by the given call, and
|
28
|
+
# that the correct HTTP payload is sent
|
29
|
+
# @param api_path [String] full API path to be called
|
30
|
+
# @param payload [Object] Ruby representation of payload we expect
|
31
|
+
# to see
|
32
|
+
# @param type [Symbol] override the content type
|
33
|
+
# @param block [Proc] call to SDK method
|
34
|
+
#
|
35
|
+
def assert_posts(api_path, payload = nil, type = nil, &block)
|
36
|
+
headers = DEFAULT_HEADERS.merge(extra_headers(payload, type))
|
37
|
+
payload = 'null' if payload.nil?
|
38
|
+
stub_request(:post, uri(api_path))
|
39
|
+
.with(body: payload, headers: headers)
|
40
|
+
.to_return(body: DUMMY_RESPONSE, status: 200)
|
41
|
+
yield block
|
42
|
+
assert_requested(:post, uri(api_path), headers: headers)
|
43
|
+
WebMock.reset!
|
44
|
+
end
|
45
|
+
|
46
|
+
# Ensure that the correct API path is hit by the given call, and
|
47
|
+
# that the correct HTTP payload is sent
|
48
|
+
# @param api_path [String] full API path to be called
|
49
|
+
# @param payload [Object] Ruby representation of payload we expect
|
50
|
+
# to see
|
51
|
+
# @param type [Symbol] override the content type
|
52
|
+
# @param block [Proc] call to SDK method
|
53
|
+
#
|
54
|
+
def assert_puts(api_path, payload = nil, type = nil, &block)
|
55
|
+
headers = DEFAULT_HEADERS.merge(extra_headers(payload, type))
|
56
|
+
payload = 'null' if payload.nil?
|
57
|
+
stub_request(:put, uri(api_path))
|
58
|
+
.with(body: payload, headers: headers)
|
59
|
+
.to_return(body: DUMMY_RESPONSE, status: 200)
|
60
|
+
yield block
|
61
|
+
assert_requested(:put, uri(api_path), headers: headers)
|
62
|
+
WebMock.reset!
|
63
|
+
end
|
64
|
+
|
65
|
+
# Ensure that the correct API path is called by the given call
|
66
|
+
# @param api_path [String] full API path to be called
|
67
|
+
# @param block [Proc] call to SDK method
|
68
|
+
#
|
69
|
+
def assert_deletes(api_path, &block)
|
70
|
+
headers = DEFAULT_HEADERS
|
71
|
+
stub_request(:delete, uri(api_path))
|
72
|
+
.with(headers: headers)
|
73
|
+
.to_return(body: DUMMY_RESPONSE, status: 200)
|
74
|
+
yield block
|
75
|
+
assert_requested(:delete, uri(api_path), headers: headers)
|
76
|
+
WebMock.reset!
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
def uri(api_path)
|
82
|
+
"https://#{CREDS[:endpoint]}#{api_path}"
|
83
|
+
end
|
84
|
+
|
85
|
+
def extra_headers(payload, type)
|
86
|
+
if payload.nil?
|
87
|
+
header_lookup(:plain)
|
88
|
+
elsif type.nil?
|
89
|
+
header_lookup(:json)
|
90
|
+
else
|
91
|
+
header_lookup(type)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def header_lookup(type)
|
96
|
+
ctype = case type
|
97
|
+
when :plain
|
98
|
+
'text/plain'
|
99
|
+
when :json
|
100
|
+
'application/json'
|
101
|
+
when :octet
|
102
|
+
'application/octet-stream'
|
103
|
+
when :form
|
104
|
+
'application/x-www-form-urlencoded'
|
105
|
+
end
|
106
|
+
|
107
|
+
{ 'Content-Type': ctype, Accept: 'application/json' }
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|