wavefront-client 3.5.4 → 3.6.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 +4 -4
- data/README-cli.md +162 -9
- data/bin/wavefront +41 -1
- data/lib/wavefront/alerting.rb +111 -24
- data/lib/wavefront/cli/alerts.rb +61 -7
- data/lib/wavefront/cli/dashboards.rb +138 -0
- data/lib/wavefront/client/version.rb +1 -1
- data/lib/wavefront/constants.rb +5 -2
- data/lib/wavefront/dashboards.rb +106 -0
- data/lib/wavefront/metadata.rb +0 -34
- data/lib/wavefront/mixins.rb +57 -8
- data/spec/cli_spec.rb +335 -9
- data/spec/spec_helper.rb +7 -0
- data/spec/wavefront/alerting_spec.rb +62 -15
- data/spec/wavefront/cli/alerts_spec.rb +2 -2
- data/spec/wavefront/cli/resources/alert.human.erb +2 -2
- data/spec/wavefront/cli/resources/alert.human2 +2 -2
- data/spec/wavefront/{resources → cli/resources}/conf.yaml +0 -0
- data/spec/wavefront/cli/resources/input_alert.json +34 -0
- data/spec/wavefront/cli/resources/input_alert.yaml +22 -0
- data/spec/wavefront/cli/resources/sample_alert.json +63 -0
- data/spec/wavefront/cli/resources/sample_alert.txt +2 -0
- data/spec/wavefront/cli/resources/sample_alert.yaml +47 -0
- data/spec/wavefront/cli/resources/sample_dash.json +1 -0
- data/spec/wavefront/cli/resources/sample_dash.txt +2 -0
- data/spec/wavefront/cli/resources/sample_dash.yaml +1114 -0
- data/spec/wavefront/opt_handler_spec.rb +3 -5
- metadata +22 -4
data/spec/cli_spec.rb
CHANGED
@@ -23,11 +23,6 @@ require 'uri'
|
|
23
23
|
require_relative './spec_helper'
|
24
24
|
require 'wavefront/client/version'
|
25
25
|
|
26
|
-
ROOT = Pathname.new(__FILE__).dirname.parent
|
27
|
-
WF = ROOT + 'bin' + 'wavefront'
|
28
|
-
LIB = ROOT + 'lib'
|
29
|
-
CF = ROOT + 'spec' + 'wavefront' + 'resources' + 'conf.yaml'
|
30
|
-
|
31
26
|
# Things from the sample config file, for shorthand
|
32
27
|
#
|
33
28
|
DEF_TOKEN = '12345678-abcd-1234-abcd-123456789012'
|
@@ -48,6 +43,263 @@ TIME = {
|
|
48
43
|
}
|
49
44
|
}
|
50
45
|
|
46
|
+
describe 'dashboard mode' do
|
47
|
+
cmds = %W(list import export create clone delete undelete
|
48
|
+
history).each do |cmd|
|
49
|
+
it "#{cmd} fails with no token if there is no token" do
|
50
|
+
args = 'arg1'
|
51
|
+
args = '' if cmd == 'list'
|
52
|
+
args = 'arg1 arg2 arg3' if cmd == 'clone'
|
53
|
+
args = 'arg1 arg2' if cmd == 'create'
|
54
|
+
o = wf("dashboard #{cmd} -c/nf #{args}")
|
55
|
+
expect(o.status).to eq(1)
|
56
|
+
expect(o.stderr).to eq(
|
57
|
+
'dashboard query failed. Please supply an API token.')
|
58
|
+
expect(o.stdout).to eq(
|
59
|
+
"config file '/nf' not found. Taking options from command-line.")
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe 'list subcommand' do
|
64
|
+
it 'performs a verbose noop with default options' do
|
65
|
+
o = wf('dashboard -c /nf -n -t token list')
|
66
|
+
expect(o.stderr).to be_empty
|
67
|
+
expect(o.status).to eq(0)
|
68
|
+
expect(o.stdout_a[-1]).to eq('HEADERS {:"X-AUTH-TOKEN"=>"token"}')
|
69
|
+
expect(o.stdout_a[-2]).to match(
|
70
|
+
'GET https://metrics.wavefront.com/api/dashboard')
|
71
|
+
expect(o.stdout).to match(/Taking options from command-line/)
|
72
|
+
end
|
73
|
+
|
74
|
+
it 'performs a verbose noop with default config file options' do
|
75
|
+
o = wf("dashboard -c #{CF} -n -T tag1 list")
|
76
|
+
expect(o.stderr).to be_empty
|
77
|
+
expect(o.status).to eq(0)
|
78
|
+
expect(o.stdout_a[-1]).to eq(
|
79
|
+
"HEADERS {:\"X-AUTH-TOKEN\"=>\"#{DEF_TOKEN}\"}")
|
80
|
+
expect(o.stdout_a[-2]).to start_with(
|
81
|
+
'GET https://default.wavefront.com/api/dashboard/')
|
82
|
+
expect(o.stdout_a[-2]).to have_element([:customerTag, 'tag1'])
|
83
|
+
expect(o.stdout).to_not match(/Taking options from command-line/)
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'performs a verbose noop with config file and CLI options' do
|
87
|
+
o = wf("dashboard -c #{CF} -P other -n list -a")
|
88
|
+
expect(o.stderr).to be_empty
|
89
|
+
expect(o.status).to eq(0)
|
90
|
+
expect(o.stdout_a[-1]).to eq(
|
91
|
+
'HEADERS {:"X-AUTH-TOKEN"=>"abcdefab-0123-abcd-0123-abcdefabcdef"}')
|
92
|
+
expect(o.stdout_a[-2]).to start_with(
|
93
|
+
'GET https://other.wavefront.com/api/dashboard/')
|
94
|
+
expect(o.stdout).to_not match(/Taking options from command-line/)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe 'import subcommand' do
|
99
|
+
it 'errors safely on a non-existent file' do
|
100
|
+
o = wf("dashboard -c #{CF} -t token import /no/such/file")
|
101
|
+
expect(o.stdout).to be_empty
|
102
|
+
expect(o.status).to eq(1)
|
103
|
+
expect(o.stderr).to eq(
|
104
|
+
'dashboard query failed. Import file does not exist.')
|
105
|
+
end
|
106
|
+
|
107
|
+
it 'errors safely on an unsupported file type' do
|
108
|
+
o = wf("dashboard -c #{CF} -t token import #{RES_DIR +
|
109
|
+
'sample_dash.txt'}")
|
110
|
+
expect(o.stdout).to be_empty
|
111
|
+
expect(o.status).to eq(1)
|
112
|
+
expect(o.stderr).to eq(
|
113
|
+
'dashboard query failed. Unsupported file format.')
|
114
|
+
end
|
115
|
+
|
116
|
+
it 'performs a verbose no-op with a JSON import file' do
|
117
|
+
o = wf("dashboard -c #{CF} -n -t token import #{RES_DIR +
|
118
|
+
'sample_dash.json'}")
|
119
|
+
expect(o.stderr).to be_empty
|
120
|
+
expect(o.status).to eq(0)
|
121
|
+
expect(o.stdout_a[-3]).to eq('POST ' \
|
122
|
+
'https://default.wavefront.com/api/dashboard/?rejectIfExists=true')
|
123
|
+
expect(o.stdout_a[-2]).to start_with(
|
124
|
+
'QUERY {"customer":"sysdef","url":"internal_metrics"')
|
125
|
+
expect(o.stdout_a[-1]).to eq('HEADERS {:"X-AUTH-TOKEN"=>"token"}')
|
126
|
+
end
|
127
|
+
|
128
|
+
it 'performs a verbose no-op with a YAML import file' do
|
129
|
+
o = wf("dashboard -c #{CF} -P other -n -F import #{RES_DIR +
|
130
|
+
'sample_dash.yaml'}")
|
131
|
+
expect(o.stderr).to be_empty
|
132
|
+
expect(o.status).to eq(0)
|
133
|
+
expect(o.stdout_a[-3]).to eq('POST ' \
|
134
|
+
'https://other.wavefront.com/api/dashboard/')
|
135
|
+
expect(o.stdout_a[-2]).to start_with(
|
136
|
+
'QUERY {"customer":"sysdef","url":"internal_metrics"')
|
137
|
+
expect(o.stdout_a[-1]).to eq(
|
138
|
+
'HEADERS {:"X-AUTH-TOKEN"=>"abcdefab-0123-abcd-0123-abcdefabcdef"}')
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
describe 'export subcommand' do
|
143
|
+
it 'performs a verbose no-op with options' do
|
144
|
+
o = wf("dashboard -E endpoint.wavefront.com -n -t token export mydash")
|
145
|
+
expect(o.stderr).to be_empty
|
146
|
+
expect(o.status).to eq(0)
|
147
|
+
expect(o.stdout_a[-2]).to eq('GET ' \
|
148
|
+
'https://endpoint.wavefront.com/api/dashboard/mydash')
|
149
|
+
expect(o.stdout_a[-1]).to eq('HEADERS {:"X-AUTH-TOKEN"=>"token"}')
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'performs a verbose no-op with a config file' do
|
153
|
+
o = wf("dashboard -c #{CF} -n export mydash")
|
154
|
+
expect(o.stderr).to be_empty
|
155
|
+
expect(o.status).to eq(0)
|
156
|
+
expect(o.stdout_a[-2]).to eq('GET ' \
|
157
|
+
'https://default.wavefront.com/api/dashboard/mydash')
|
158
|
+
expect(o.stdout_a[-1]).to eq(
|
159
|
+
'HEADERS {:"X-AUTH-TOKEN"=>"12345678-abcd-1234-abcd-123456789012"}')
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
describe 'create subcommand' do
|
164
|
+
it 'performs a verbose no-op with defaults' do
|
165
|
+
o = wf("dashboard -t token -n create test_id \"test name\"")
|
166
|
+
expect(o.stderr).to be_empty
|
167
|
+
expect(o.status).to eq(0)
|
168
|
+
expect(o.stdout_a[-3]).to eq('POST ' \
|
169
|
+
'https://metrics.wavefront.com/api/dashboard/test_id/create')
|
170
|
+
expect(o.stdout_a[-2]).to eq('QUERY name=test%20name')
|
171
|
+
expect(o.stdout_a[-1]).to eq('HEADERS {:"X-AUTH-TOKEN"=>"token"}')
|
172
|
+
end
|
173
|
+
|
174
|
+
it 'performs a verbose no-op with a config file' do
|
175
|
+
o = wf("dashboard -c #{CF} -P other -n create test_id \"test name\"")
|
176
|
+
expect(o.stderr).to be_empty
|
177
|
+
expect(o.status).to eq(0)
|
178
|
+
expect(o.stdout_a[-3]).to eq('POST ' \
|
179
|
+
'https://other.wavefront.com/api/dashboard/test_id/create')
|
180
|
+
expect(o.stdout_a[-2]).to eq('QUERY name=test%20name')
|
181
|
+
expect(o.stdout_a[-1]).to eq(
|
182
|
+
'HEADERS {:"X-AUTH-TOKEN"=>"abcdefab-0123-abcd-0123-abcdefabcdef"}')
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
describe 'clone subcommand' do
|
187
|
+
it 'performs a verbose no-op with defaults' do
|
188
|
+
o = wf('dashboard clone -t token -n src_id new_id "new name"')
|
189
|
+
expect(o.stderr).to be_empty
|
190
|
+
expect(o.status).to eq(0)
|
191
|
+
expect(o.stdout_a[-3]).to eq('POST ' \
|
192
|
+
'https://metrics.wavefront.com/api/dashboard/src_id/clone')
|
193
|
+
expect(o.stdout_a[-2]).to eq('QUERY name=new%20name&url=new_id')
|
194
|
+
expect(o.stdout_a[-1]).to eq('HEADERS {:"X-AUTH-TOKEN"=>"token"}')
|
195
|
+
end
|
196
|
+
|
197
|
+
it 'performs a verbose no-op with config file' do
|
198
|
+
o = wf("dashboard clone -c #{CF} -n src_id new_id 'new name'")
|
199
|
+
expect(o.stderr).to be_empty
|
200
|
+
expect(o.status).to eq(0)
|
201
|
+
expect(o.stdout_a[-3]).to eq('POST ' \
|
202
|
+
'https://default.wavefront.com/api/dashboard/src_id/clone')
|
203
|
+
expect(o.stdout_a[-2]).to eq('QUERY name=new%20name&url=new_id')
|
204
|
+
expect(o.stdout_a[-1]).to eq(
|
205
|
+
'HEADERS {:"X-AUTH-TOKEN"=>"12345678-abcd-1234-abcd-123456789012"}')
|
206
|
+
end
|
207
|
+
|
208
|
+
it 'performs a verbose no-op with options and config file' do
|
209
|
+
o = wf("dashboard clone -E endpoint.wavefront.com -c #{CF} " \
|
210
|
+
'-v 14 -P other -n src_id new_id "new name"')
|
211
|
+
expect(o.stderr).to be_empty
|
212
|
+
expect(o.status).to eq(0)
|
213
|
+
expect(o.stdout_a[-3]).to eq('POST ' \
|
214
|
+
'https://endpoint.wavefront.com/api/dashboard/src_id/clone')
|
215
|
+
expect(o.stdout_a[-2]).to eq('QUERY name=new%20name&url=new_id&v=14')
|
216
|
+
expect(o.stdout_a[-1]).to eq(
|
217
|
+
'HEADERS {:"X-AUTH-TOKEN"=>"abcdefab-0123-abcd-0123-abcdefabcdef"}')
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
describe 'delete subcommand' do
|
222
|
+
it 'performs a verbose no-op with options ' do
|
223
|
+
o = wf(
|
224
|
+
'dashboard -E endpoint.wavefront.com -t token -n delete mydash')
|
225
|
+
expect(o.stderr).to be_empty
|
226
|
+
expect(o.status).to eq(0)
|
227
|
+
expect(o.stdout_a[-2]).to eq('POST ' \
|
228
|
+
'https://endpoint.wavefront.com/api/dashboard/mydash/delete')
|
229
|
+
expect(o.stdout_a[-1]).to eq('HEADERS {:"X-AUTH-TOKEN"=>"token"}')
|
230
|
+
end
|
231
|
+
|
232
|
+
it 'performs a verbose no-op with a config file' do
|
233
|
+
o = wf("dashboard -c #{CF} -n delete mydash")
|
234
|
+
expect(o.stderr).to be_empty
|
235
|
+
expect(o.status).to eq(0)
|
236
|
+
expect(o.stdout_a[-2]).to eq('POST ' \
|
237
|
+
'https://default.wavefront.com/api/dashboard/mydash/delete')
|
238
|
+
expect(o.stdout_a[-1]).to eq(
|
239
|
+
'HEADERS {:"X-AUTH-TOKEN"=>"12345678-abcd-1234-abcd-123456789012"}')
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
describe 'undelete subcommand' do
|
244
|
+
it 'performs a verbose no-op with options ' do
|
245
|
+
o = wf(
|
246
|
+
'dashboard -E endpoint.wavefront.com -t token -n undelete mydash')
|
247
|
+
expect(o.stderr).to be_empty
|
248
|
+
expect(o.status).to eq(0)
|
249
|
+
expect(o.stdout_a[-2]).to eq('POST ' \
|
250
|
+
'https://endpoint.wavefront.com/api/dashboard/mydash/undelete')
|
251
|
+
expect(o.stdout_a[-1]).to eq('HEADERS {:"X-AUTH-TOKEN"=>"token"}')
|
252
|
+
end
|
253
|
+
|
254
|
+
it 'performs a verbose no-op with a config file' do
|
255
|
+
o = wf("dashboard -c #{CF} -n undelete mydash")
|
256
|
+
expect(o.stderr).to be_empty
|
257
|
+
expect(o.status).to eq(0)
|
258
|
+
expect(o.stdout_a[-2]).to eq('POST ' \
|
259
|
+
'https://default.wavefront.com/api/dashboard/mydash/undelete')
|
260
|
+
expect(o.stdout_a[-1]).to eq(
|
261
|
+
'HEADERS {:"X-AUTH-TOKEN"=>"12345678-abcd-1234-abcd-123456789012"}')
|
262
|
+
end
|
263
|
+
end
|
264
|
+
|
265
|
+
|
266
|
+
describe 'history subcommand' do
|
267
|
+
it 'performs a verbose no-op with no options' do
|
268
|
+
o = wf('dashboard -t token -n history mydash')
|
269
|
+
expect(o.stderr).to be_empty
|
270
|
+
expect(o.status).to eq(0)
|
271
|
+
expect(o.stdout_a[-2]).to eq('GET https://metrics.wavefront.com/' \
|
272
|
+
'api/dashboard/mydash/history?start=100')
|
273
|
+
expect(o.stdout_a[-1]).to eq('HEADERS {:"X-AUTH-TOKEN"=>"token"}')
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
describe 'history subcommand' do
|
278
|
+
it 'performs a verbose no-op with config file' do
|
279
|
+
o = wf("dashboard -c #{CF} -S 10 -n history mydash")
|
280
|
+
expect(o.stderr).to be_empty
|
281
|
+
expect(o.status).to eq(0)
|
282
|
+
expect(o.stdout_a[-2]).to eq('GET https://default.wavefront.com/' \
|
283
|
+
'api/dashboard/mydash/history?start=10')
|
284
|
+
expect(o.stdout_a[-1]).to eq(
|
285
|
+
'HEADERS {:"X-AUTH-TOKEN"=>"12345678-abcd-1234-abcd-123456789012"}')
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
describe 'history subcommand' do
|
290
|
+
it 'performs a verbose no-op with config file and options' do
|
291
|
+
o = wf("dashboard -c #{CF} -P other -S 10 -L 5 -n history mydash")
|
292
|
+
expect(o.stderr).to be_empty
|
293
|
+
expect(o.status).to eq(0)
|
294
|
+
expect(o.stdout_a[-2]).to eq('GET https://other.wavefront.com/' \
|
295
|
+
'api/dashboard/mydash/history?start=10&limit=5')
|
296
|
+
expect(o.stdout_a[-1]).to eq(
|
297
|
+
'HEADERS {:"X-AUTH-TOKEN"=>"abcdefab-0123-abcd-0123-abcdefabcdef"}')
|
298
|
+
end
|
299
|
+
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
51
303
|
describe 'usage' do
|
52
304
|
commands = %w(alerts event source ts write)
|
53
305
|
|
@@ -85,6 +337,75 @@ describe 'usage' do
|
|
85
337
|
end
|
86
338
|
end
|
87
339
|
|
340
|
+
describe 'alerts mode' do
|
341
|
+
|
342
|
+
describe 'export subcommand' do
|
343
|
+
it 'performs a verbose noop with a CLI token' do
|
344
|
+
o = wf('alerts -n -t token export 1489152324000')
|
345
|
+
expect(o.status).to eq(0)
|
346
|
+
expect(o.stderr).to be_empty
|
347
|
+
expect(o.stdout_a[-2]).to eq(
|
348
|
+
'GET https://metrics.wavefront.com/api/alert/1489152324000')
|
349
|
+
expect(o.stdout_a[-1]).to eq('HEADERS {:"X-AUTH-TOKEN"=>"token"}')
|
350
|
+
end
|
351
|
+
|
352
|
+
it 'performs a verbose noop with a config file and CLI token' do
|
353
|
+
o = wf("alerts -c #{CF} -n -t token -f yaml export 1489152324000")
|
354
|
+
expect(o.status).to eq(0)
|
355
|
+
expect(o.stderr).to be_empty
|
356
|
+
expect(o.stdout_a[-2]).to eq(
|
357
|
+
'GET https://default.wavefront.com/api/alert/1489152324000')
|
358
|
+
expect(o.stdout_a[-1]).to eq('HEADERS {:"X-AUTH-TOKEN"=>"token"}')
|
359
|
+
end
|
360
|
+
end
|
361
|
+
|
362
|
+
describe 'import subcommand' do
|
363
|
+
it 'errors safely on a non-existent file' do
|
364
|
+
o = wf("alerts -c #{CF} -t token import /no/such/file")
|
365
|
+
expect(o.stdout).to be_empty
|
366
|
+
expect(o.status).to eq(1)
|
367
|
+
expect(o.stderr).to eq(
|
368
|
+
'alerts query failed. Import file does not exist.')
|
369
|
+
end
|
370
|
+
|
371
|
+
it 'errors safely on an unsupported file type' do
|
372
|
+
o = wf("alerts -c #{CF} -t token import #{RES_DIR +
|
373
|
+
'sample_alert.txt'}")
|
374
|
+
expect(o.stdout).to be_empty
|
375
|
+
expect(o.status).to eq(1)
|
376
|
+
expect(o.stderr).to eq(
|
377
|
+
'alerts query failed. Unsupported file format.')
|
378
|
+
end
|
379
|
+
|
380
|
+
it 'performs a verbose no-op with a JSON import file' do
|
381
|
+
o = wf("alerts -c #{CF} -n -t token import #{RES_DIR +
|
382
|
+
'sample_alert.json'}")
|
383
|
+
expect(o.stderr).to be_empty
|
384
|
+
expect(o.status).to eq(0)
|
385
|
+
expect(o.stdout_a[-2]).to have_element([:severity, 'WARN'])
|
386
|
+
expect(o.stdout_a[-2]).to have_element([:resolveMinutes, 5])
|
387
|
+
expect(o.stdout_a[-2]).to_not have_element([:resolveAfterMinutes, 5])
|
388
|
+
expect(o.stdout_a[-3]).to eq('POST ' \
|
389
|
+
'https://default.wavefront.com/api/alert/create')
|
390
|
+
expect(o.stdout_a[-1]).to eq('HEADERS {:"X-AUTH-TOKEN"=>"token"}')
|
391
|
+
end
|
392
|
+
|
393
|
+
it 'performs a verbose no-op with a YAML import file' do
|
394
|
+
o = wf("alerts -c #{CF} -n -E test.wavefront.com import #{RES_DIR +
|
395
|
+
'sample_alert.yaml'}")
|
396
|
+
expect(o.stderr).to be_empty
|
397
|
+
expect(o.status).to eq(0)
|
398
|
+
expect(o.stdout_a[-2]).to have_element([:severity, 'WARN'])
|
399
|
+
expect(o.stdout_a[-2]).to have_element([:resolveMinutes, 5])
|
400
|
+
expect(o.stdout_a[-2]).to_not have_element([:resolveAfterMinutes, 5])
|
401
|
+
expect(o.stdout_a[-3]).to eq('POST ' \
|
402
|
+
'https://test.wavefront.com/api/alert/create')
|
403
|
+
expect(o.stdout_a[-1]).to eq(
|
404
|
+
'HEADERS {:"X-AUTH-TOKEN"=>"12345678-abcd-1234-abcd-123456789012"}')
|
405
|
+
end
|
406
|
+
end
|
407
|
+
end
|
408
|
+
|
88
409
|
describe 'alerts mode' do
|
89
410
|
it 'fails with no token if there is no token' do
|
90
411
|
o = wf('alerts -c/nf -E metrics.wavefront.com active')
|
@@ -107,24 +428,29 @@ describe 'alerts mode' do
|
|
107
428
|
o = wf('alerts -n -c/nf -t token -E test.wavefront.com active')
|
108
429
|
expect(o.status).to eq(0)
|
109
430
|
expect(o.stderr).to be_empty
|
110
|
-
expect(o.stdout_a[-
|
111
|
-
'GET https://test.wavefront.com/api/alert/active
|
431
|
+
expect(o.stdout_a[-2]).to eq(
|
432
|
+
'GET https://test.wavefront.com/api/alert/active')
|
112
433
|
end
|
113
434
|
|
114
435
|
it 'performs a verbose noop with default config file options' do
|
115
436
|
o = wf("alerts -n -c #{CF} active")
|
116
437
|
expect(o.status).to eq(0)
|
117
438
|
expect(o.stderr).to be_empty
|
439
|
+
expect(o.stdout_a[-2]).to eq(
|
440
|
+
'GET https://default.wavefront.com/api/alert/active')
|
118
441
|
expect(o.stdout_a.last).to eq(
|
119
|
-
"
|
442
|
+
"HEADERS {:\"X-AUTH-TOKEN\"=>\"#{DEF_TOKEN}\"}")
|
443
|
+
|
120
444
|
end
|
121
445
|
|
122
446
|
it 'performs a verbose noop with config file and CLI options' do
|
123
447
|
o = wf("alerts -n -c #{CF} -E cli.wavefront.com active")
|
124
448
|
expect(o.status).to eq(0)
|
125
449
|
expect(o.stderr).to be_empty
|
450
|
+
expect(o.stdout_a[-2]).to eq(
|
451
|
+
'GET https://cli.wavefront.com/api/alert/active')
|
126
452
|
expect(o.stdout_a.last).to eq(
|
127
|
-
"
|
453
|
+
"HEADERS {:\"X-AUTH-TOKEN\"=>\"#{DEF_TOKEN}\"}")
|
128
454
|
end
|
129
455
|
end
|
130
456
|
|
data/spec/spec_helper.rb
CHANGED
@@ -23,15 +23,22 @@ require 'wavefront/events'
|
|
23
23
|
require 'wavefront/batch_writer'
|
24
24
|
require 'wavefront/validators'
|
25
25
|
require 'wavefront/opt_handler'
|
26
|
+
require 'wavefront/dashboards'
|
26
27
|
require 'wavefront/cli'
|
27
28
|
require 'wavefront/cli/alerts'
|
28
29
|
require 'wavefront/cli/events'
|
29
30
|
require 'wavefront/cli/batch_write'
|
30
31
|
require 'wavefront/cli/write'
|
31
32
|
require 'wavefront/cli/sources'
|
33
|
+
require 'wavefront/cli/dashboards'
|
32
34
|
|
33
35
|
TEST_TOKEN = "test"
|
34
36
|
TEST_HOST = "metrics.wavefront.com"
|
37
|
+
ROOT = Pathname.new(__FILE__).dirname.parent
|
38
|
+
RES_DIR = ROOT + 'spec' + 'wavefront' + 'cli' + 'resources'
|
39
|
+
CF = RES_DIR + 'conf.yaml'
|
40
|
+
WF = ROOT + 'bin' + 'wavefront'
|
41
|
+
LIB = ROOT + 'lib'
|
35
42
|
|
36
43
|
# The following RSpec matcher is used to test things which `puts`
|
37
44
|
# (or related), which RSpec can't do by default. It works with RSpec
|
@@ -44,67 +44,114 @@ describe Wavefront::Alerting do
|
|
44
44
|
|
45
45
|
describe '#get_alerts' do
|
46
46
|
it 'makes API request with default options' do
|
47
|
-
expect(RestClient).to receive(:get).with("https://#{File.join(Wavefront::Alerting::DEFAULT_HOST, Wavefront::Alerting::DEFAULT_PATH,
|
47
|
+
expect(RestClient).to receive(:get).with("https://#{File.join(Wavefront::Alerting::DEFAULT_HOST, Wavefront::Alerting::DEFAULT_PATH, 'all')}", {:"X-AUTH-TOKEN"=>"test"})
|
48
48
|
@wave.all
|
49
49
|
end
|
50
50
|
|
51
51
|
it 'makes API request with specified host' do
|
52
52
|
host = 'madeup.wavefront.com'
|
53
|
-
expect(RestClient).to receive(:get).with("https://#{File.join(host, Wavefront::Alerting::DEFAULT_PATH,
|
53
|
+
expect(RestClient).to receive(:get).with("https://#{File.join(host, Wavefront::Alerting::DEFAULT_PATH, 'all')}", {:"X-AUTH-TOKEN"=>"test"})
|
54
54
|
@wave.all({ :host => host })
|
55
55
|
end
|
56
56
|
|
57
|
-
it 'makes API request with specified path' do
|
58
|
-
path = '/api/new_alerts'
|
59
|
-
expect(RestClient).to receive(:get).with("https://#{File.join(Wavefront::Alerting::DEFAULT_HOST, path, "all?t=#{TEST_TOKEN}")}")
|
60
|
-
@wave.all({ :path => path })
|
61
|
-
end
|
62
|
-
|
63
57
|
it 'makes API request with appended shared tags' do
|
64
58
|
tags = [ 'first', 'second' ]
|
65
|
-
expect(RestClient).to receive(:get).with("https://#{File.join(Wavefront::Alerting::DEFAULT_HOST, Wavefront::Alerting::DEFAULT_PATH, "all?
|
59
|
+
expect(RestClient).to receive(:get).with("https://#{File.join(Wavefront::Alerting::DEFAULT_HOST, Wavefront::Alerting::DEFAULT_PATH, "all?customerTag=first&customerTag=second")}", {:"X-AUTH-TOKEN"=>"test"})
|
66
60
|
@wave.all({ :shared_tags => tags })
|
67
61
|
end
|
68
62
|
|
69
63
|
it 'makes API request with appended private tags' do
|
70
64
|
tags = [ 'first', 'second' ]
|
71
|
-
expect(RestClient).to receive(:get).with("https://#{File.join(Wavefront::Alerting::DEFAULT_HOST, Wavefront::Alerting::DEFAULT_PATH, "all?
|
65
|
+
expect(RestClient).to receive(:get).with("https://#{File.join(Wavefront::Alerting::DEFAULT_HOST, Wavefront::Alerting::DEFAULT_PATH, "all?userTag=first&userTag=second")}", {:"X-AUTH-TOKEN"=>"test"})
|
72
66
|
@wave.all({ :private_tags => tags })
|
73
67
|
end
|
74
68
|
|
75
69
|
it 'makes API request with both appended private tags and shared tags' do
|
76
70
|
private_tag = 'first'
|
77
71
|
shared_tag = 'second'
|
78
|
-
expect(RestClient).to receive(:get).with("https://#{File.join(Wavefront::Alerting::DEFAULT_HOST, Wavefront::Alerting::DEFAULT_PATH, "all?
|
72
|
+
expect(RestClient).to receive(:get).with("https://#{File.join(Wavefront::Alerting::DEFAULT_HOST, Wavefront::Alerting::DEFAULT_PATH, "all?customerTag=second&userTag=first")}", {:"X-AUTH-TOKEN"=>"test"})
|
79
73
|
@wave.all({ :private_tags => private_tag, :shared_tags => shared_tag })
|
80
74
|
end
|
81
75
|
end
|
82
76
|
|
83
77
|
describe '#active' do
|
84
78
|
it 'requests all active alerts' do
|
85
|
-
expect(@wave).to receive(:
|
79
|
+
expect(@wave).to receive(:create_uri).with(path: "active", qs: "")
|
80
|
+
expect(@wave).to receive(:call_get)
|
86
81
|
@wave.active
|
87
82
|
end
|
88
83
|
end
|
89
84
|
|
90
85
|
describe '#snoozed' do
|
91
86
|
it 'requests all snoozed alerts' do
|
92
|
-
expect(@wave).to receive(:
|
87
|
+
expect(@wave).to receive(:create_uri).with(path: "snoozed", qs: "")
|
88
|
+
expect(@wave).to receive(:call_get)
|
93
89
|
@wave.snoozed
|
94
90
|
end
|
95
91
|
end
|
96
92
|
|
97
93
|
describe '#invalid' do
|
98
94
|
it 'requests all invalid alerts' do
|
99
|
-
expect(@wave).to receive(:
|
95
|
+
expect(@wave).to receive(:create_uri).with(path: "invalid", qs: "")
|
96
|
+
expect(@wave).to receive(:call_get)
|
100
97
|
@wave.invalid
|
101
98
|
end
|
102
99
|
end
|
103
100
|
|
104
101
|
describe '#affected_by_maintenance' do
|
105
102
|
it 'requests all affected_by_maintenance alerts' do
|
106
|
-
expect(@wave).to receive(:
|
103
|
+
expect(@wave).to receive(:create_uri).with(path: "affected_by_maintenance", qs: "")
|
104
|
+
expect(@wave).to receive(:call_get)
|
107
105
|
@wave.affected_by_maintenance
|
108
106
|
end
|
109
107
|
end
|
108
|
+
|
109
|
+
describe '#import_to_create' do
|
110
|
+
it 'produces expected output from known input' do
|
111
|
+
raw = JSON.load(IO.read(RES_DIR + 'input_alert.json'))
|
112
|
+
out = @wave.import_to_create(raw)
|
113
|
+
p out
|
114
|
+
expect(out).to be_instance_of(Hash)
|
115
|
+
expect(out.keys).to match_array(
|
116
|
+
[:name, :condition, :minutes, :resolveMinutes, :notifications,
|
117
|
+
:severity, :sharedTags, :additionalInformation])
|
118
|
+
expect(out[:sharedTags]).to be_instance_of(Array)
|
119
|
+
expect(out[:minutes]).to be_instance_of(Fixnum)
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'ignores extraneous fields' do
|
123
|
+
raw = JSON.load(IO.read(RES_DIR + 'input_alert.json'))
|
124
|
+
raw[:junk] = 'nonsense'
|
125
|
+
raw.delete('name')
|
126
|
+
out = @wave.import_to_create(raw)
|
127
|
+
expect(out).to be_instance_of(Hash)
|
128
|
+
expect(out.keys).not_to include(:junk)
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
describe '#create_alert' do
|
133
|
+
input = {:name=>"test1", :condition=>"ts(\"cpu\") > 0",
|
134
|
+
:minutes=>3, :notifications=>["slackboy@gmail.com",
|
135
|
+
"rob@sysdef.xyz"], :severity=>"INFO",
|
136
|
+
:resolveMinutes=>2, :sharedTags=>[],
|
137
|
+
:additionalInformation=>"some information"}
|
138
|
+
|
139
|
+
it 'makes a correct API call on good data' do
|
140
|
+
expect(@wave).to receive(:create_uri).with(path: 'create')
|
141
|
+
expect(@wave).to receive(:call_post)
|
142
|
+
out = @wave.create_alert(input)
|
143
|
+
end
|
144
|
+
|
145
|
+
it 'throws an error on bad severity data' do
|
146
|
+
input[:severity] = 'NOT_THAT_SERIOUS'
|
147
|
+
expect{@wave.create_alert(input)}.to raise_exception(
|
148
|
+
'invalid severity')
|
149
|
+
end
|
150
|
+
|
151
|
+
it 'throws an error on missing severity data' do
|
152
|
+
input.delete(:severity)
|
153
|
+
expect{@wave.create_alert(input)}.to raise_exception(
|
154
|
+
'missing field: severity')
|
155
|
+
end
|
156
|
+
end
|
110
157
|
end
|