wavefront-client 3.5.4 → 3.6.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|