logstash-input-http_poller 5.0.1 → 5.2.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +13 -1
- data/Gemfile +2 -0
- data/LICENSE +3 -3
- data/README.md +1 -1
- data/docs/index.asciidoc +176 -20
- data/lib/logstash/inputs/http_poller.rb +87 -42
- data/logstash-input-http_poller.gemspec +6 -4
- data/spec/inputs/http_poller_spec.rb +277 -224
- metadata +46 -13
@@ -1,9 +1,11 @@
|
|
1
1
|
require "logstash/devutils/rspec/spec_helper"
|
2
|
+
require "logstash/devutils/rspec/shared_examples"
|
2
3
|
require 'logstash/inputs/http_poller'
|
3
4
|
require 'flores/random'
|
4
5
|
require "timecop"
|
5
6
|
# Workaround for the bug reported in https://github.com/jruby/jruby/issues/4637
|
6
7
|
require 'rspec/matchers/built_in/raise_error.rb'
|
8
|
+
require 'logstash/plugin_mixins/ecs_compatibility_support/spec_helper'
|
7
9
|
|
8
10
|
describe LogStash::Inputs::HTTP_Poller do
|
9
11
|
let(:metadata_target) { "_http_poller_metadata" }
|
@@ -23,17 +25,19 @@ describe LogStash::Inputs::HTTP_Poller do
|
|
23
25
|
"schedule" => default_schedule,
|
24
26
|
"urls" => default_urls,
|
25
27
|
"codec" => "json",
|
26
|
-
"metadata_target" => metadata_target
|
28
|
+
"metadata_target" => metadata_target,
|
29
|
+
"pool_max" => 3, "pool_max_per_route" => 1, 'keepalive' => false
|
27
30
|
}
|
28
31
|
}
|
29
|
-
let(:
|
32
|
+
let(:opts) { default_opts }
|
33
|
+
|
34
|
+
subject(:plugin) { described_class.new(opts) }
|
30
35
|
|
31
36
|
describe "instances" do
|
32
|
-
subject {
|
37
|
+
subject { described_class.new(default_opts) }
|
33
38
|
|
34
|
-
before
|
35
|
-
|
36
|
-
end
|
39
|
+
before { subject.register }
|
40
|
+
after { subject.stop }
|
37
41
|
|
38
42
|
describe "#run" do
|
39
43
|
it "should setup a scheduler" do
|
@@ -132,10 +136,10 @@ describe LogStash::Inputs::HTTP_Poller do
|
|
132
136
|
|
133
137
|
it "should properly set the auth parameter" do
|
134
138
|
expect(normalized[2][:auth]).to eq({
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
+
:user => auth["user"],
|
140
|
+
:pass => auth["password"],
|
141
|
+
:eager => true
|
142
|
+
})
|
139
143
|
end
|
140
144
|
end
|
141
145
|
end
|
@@ -143,14 +147,14 @@ describe LogStash::Inputs::HTTP_Poller do
|
|
143
147
|
# Legacy way of doing things, kept for backwards compat.
|
144
148
|
describe "auth with nested auth hash" do
|
145
149
|
let(:url) { {"url" => "http://localhost", "method" => "get", "auth" => auth} }
|
146
|
-
|
150
|
+
|
147
151
|
include_examples("auth")
|
148
152
|
end
|
149
153
|
|
150
154
|
# The new 'right' way to do things
|
151
155
|
describe "auth with direct auth options" do
|
152
156
|
let(:url) { {"url" => "http://localhost", "method" => "get", "user" => auth["user"], "password" => auth["password"]} }
|
153
|
-
|
157
|
+
|
154
158
|
include_examples("auth")
|
155
159
|
end
|
156
160
|
end
|
@@ -186,22 +190,21 @@ describe LogStash::Inputs::HTTP_Poller do
|
|
186
190
|
"metadata_target" => metadata_target
|
187
191
|
}
|
188
192
|
}
|
189
|
-
|
190
|
-
|
191
|
-
instance.register
|
193
|
+
|
194
|
+
before do
|
192
195
|
Timecop.travel(Time.new(2000,1,1,0,0,0,'+00:00'))
|
193
196
|
Timecop.scale(60)
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
end
|
198
|
-
sleep 3
|
199
|
-
instance.stop
|
200
|
-
runner.kill
|
201
|
-
runner.join
|
202
|
-
expect(queue.size).to eq(2)
|
197
|
+
end
|
198
|
+
|
199
|
+
after do
|
203
200
|
Timecop.return
|
204
201
|
end
|
202
|
+
|
203
|
+
it "should run at the schedule" do
|
204
|
+
run_plugin_and_yield_queue(plugin, sleep: 3) do |queue|
|
205
|
+
try(5) { expect(queue.size).to be >= 2 }
|
206
|
+
end
|
207
|
+
end
|
205
208
|
end
|
206
209
|
|
207
210
|
context "given 'at' expression" do
|
@@ -213,22 +216,21 @@ describe LogStash::Inputs::HTTP_Poller do
|
|
213
216
|
"metadata_target" => metadata_target
|
214
217
|
}
|
215
218
|
}
|
216
|
-
|
217
|
-
|
218
|
-
instance.register
|
219
|
+
|
220
|
+
before do
|
219
221
|
Timecop.travel(Time.new(2000,1,1,0,0,0,'+00:00'))
|
220
|
-
Timecop.scale(60 * 5)
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
end
|
225
|
-
sleep 2
|
226
|
-
instance.stop
|
227
|
-
runner.kill
|
228
|
-
runner.join
|
229
|
-
expect(queue.size).to eq(1)
|
222
|
+
Timecop.scale (60 * 5) / 2
|
223
|
+
end
|
224
|
+
|
225
|
+
after do
|
230
226
|
Timecop.return
|
231
227
|
end
|
228
|
+
|
229
|
+
it "should run at the schedule" do
|
230
|
+
run_plugin_and_yield_queue(plugin, sleep: 2) do |queue|
|
231
|
+
try(5) { expect(queue.size).to eq(1) }
|
232
|
+
end
|
233
|
+
end
|
232
234
|
end
|
233
235
|
|
234
236
|
context "given 'every' expression" do
|
@@ -241,20 +243,12 @@ describe LogStash::Inputs::HTTP_Poller do
|
|
241
243
|
}
|
242
244
|
}
|
243
245
|
it "should run at the schedule" do
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
246
|
+
run_plugin_and_yield_queue(plugin, sleep: 5) do |queue|
|
247
|
+
#T 0123456
|
248
|
+
#events x x x x
|
249
|
+
#expects 3 events at T=5
|
250
|
+
try(5) { expect(queue.size).to be_between(2, 3) }
|
249
251
|
end
|
250
|
-
#T 0123456
|
251
|
-
#events x x x x
|
252
|
-
#expects 3 events at T=5
|
253
|
-
sleep 5
|
254
|
-
instance.stop
|
255
|
-
runner.kill
|
256
|
-
runner.join
|
257
|
-
expect(queue.size).to eq(3)
|
258
252
|
end
|
259
253
|
end
|
260
254
|
|
@@ -268,231 +262,288 @@ describe LogStash::Inputs::HTTP_Poller do
|
|
268
262
|
}
|
269
263
|
}
|
270
264
|
it "should run at the schedule" do
|
271
|
-
|
272
|
-
|
273
|
-
queue = Queue.new
|
274
|
-
runner = Thread.new do
|
275
|
-
instance.run(queue)
|
265
|
+
run_plugin_and_yield_queue(plugin, sleep: 2.5) do |queue|
|
266
|
+
try(5) { expect(queue.size).to eq(1) }
|
276
267
|
end
|
277
|
-
sleep 3
|
278
|
-
instance.stop
|
279
|
-
runner.kill
|
280
|
-
runner.join
|
281
|
-
expect(queue.size).to eq(1)
|
282
268
|
end
|
283
269
|
end
|
284
270
|
end
|
285
271
|
|
286
|
-
|
287
|
-
|
288
|
-
|
272
|
+
def run_plugin_and_yield_queue(plugin, sleep: nil)
|
273
|
+
plugin.register
|
274
|
+
queue = Queue.new
|
275
|
+
begin
|
276
|
+
runner = Thread.new do
|
277
|
+
plugin.run(queue)
|
278
|
+
end
|
279
|
+
sleep(sleep) if sleep
|
280
|
+
yield(queue)
|
281
|
+
ensure
|
282
|
+
plugin.stop
|
283
|
+
runner.join if runner
|
284
|
+
end
|
285
|
+
end
|
289
286
|
|
290
|
-
|
291
|
-
|
287
|
+
describe "events", :ecs_compatibility_support, :aggregate_failures do
|
288
|
+
ecs_compatibility_matrix(:disabled, :v1, :v8 => :v1) do |ecs_select|
|
289
|
+
before do
|
290
|
+
allow_any_instance_of(described_class).to receive(:ecs_compatibility).and_return(ecs_compatibility)
|
292
291
|
end
|
293
292
|
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
293
|
+
shared_examples("matching metadata") {
|
294
|
+
let(:metadata) { event.get(metadata_target) }
|
295
|
+
|
296
|
+
it "should have the correct name" do
|
297
|
+
field = ecs_select[disabled: "[#{metadata_target}][name]", v1: "[#{metadata_target}][input][http_poller][request][name]"]
|
298
|
+
expect(event.get(field)).to eql(name)
|
299
299
|
end
|
300
|
-
end
|
301
300
|
|
302
|
-
|
303
|
-
|
304
|
-
|
305
|
-
|
301
|
+
it "should have the correct request url" do
|
302
|
+
if url.is_a?(Hash) # If the url was specified as a complex test the whole thing
|
303
|
+
http_client_field = ecs_select[disabled: "[#{metadata_target}][request]",
|
304
|
+
v1: "[#{metadata_target}][input][http_poller][request][original]"]
|
305
|
+
expect(event.get(http_client_field)).to eql(url)
|
306
|
+
else # Otherwise we have to make some assumptions
|
307
|
+
url_field = ecs_select[disabled: "[#{metadata_target}][request][url]",
|
308
|
+
v1: "[#{metadata_target}][input][http_poller][request][original][url]"]
|
309
|
+
expect(event.get(url_field)).to eql(url)
|
310
|
+
end
|
311
|
+
end
|
306
312
|
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
}
|
313
|
+
it "should have the correct code" do
|
314
|
+
expect(event.get(ecs_select[disabled: "[#{metadata_target}][code]",
|
315
|
+
v1: "[#{metadata_target}][input][http_poller][response][status_code]"]))
|
316
|
+
.to eql(code)
|
317
|
+
end
|
313
318
|
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
319
|
+
it "should have the correct host" do
|
320
|
+
expect(event.get(ecs_select[disabled: "[#{metadata_target}][host]",
|
321
|
+
v1: "[#{metadata_target}][input][http_poller][request][host][hostname]"]))
|
322
|
+
.not_to be_nil
|
323
|
+
end
|
324
|
+
}
|
320
325
|
|
321
|
-
|
322
|
-
|
323
|
-
|
326
|
+
shared_examples "unprocessable_requests" do
|
327
|
+
let(:poller) { LogStash::Inputs::HTTP_Poller.new(settings) }
|
328
|
+
subject(:event) {
|
329
|
+
poller.send(:run_once, queue)
|
330
|
+
queue.pop(true)
|
331
|
+
}
|
324
332
|
|
325
|
-
|
326
|
-
|
327
|
-
|
333
|
+
before do
|
334
|
+
poller.register
|
335
|
+
allow(poller).to receive(:handle_failure).and_call_original
|
336
|
+
allow(poller).to receive(:handle_success)
|
337
|
+
event # materialize the subject
|
338
|
+
end
|
328
339
|
|
329
|
-
|
330
|
-
expect(event.get("tags")).to include('_http_request_failure')
|
331
|
-
end
|
340
|
+
after { poller.stop }
|
332
341
|
|
333
|
-
|
334
|
-
|
335
|
-
|
342
|
+
it "should enqueue a message" do
|
343
|
+
expect(event).to be_a(LogStash::Event)
|
344
|
+
end
|
336
345
|
|
337
|
-
|
338
|
-
|
339
|
-
|
346
|
+
it "should enqueue a message with 'http_request_failure' set" do
|
347
|
+
if ecs_compatibility == :disabled
|
348
|
+
expect(event.get("http_request_failure")).to be_a(Hash)
|
349
|
+
expect(event.get("[http_request_failure][runtime_seconds]")).to be_a(Float)
|
350
|
+
else
|
351
|
+
expect(event.get("http_request_failure")).to be_nil
|
352
|
+
expect(event.get("error")).to be_a(Hash)
|
353
|
+
expect(event.get("[event][duration]")).to be_a(Integer)
|
354
|
+
expect(event.get("[url][full]")).to eq(url)
|
355
|
+
expect(event.get("[http][request][method]")).to be_a(String)
|
356
|
+
expect(event.get("[host][hostname]")).to be_a(String)
|
357
|
+
end
|
358
|
+
end
|
340
359
|
|
341
|
-
|
342
|
-
|
360
|
+
it "should tag the event with '_http_request_failure'" do
|
361
|
+
expect(event.get("tags")).to include('_http_request_failure')
|
362
|
+
end
|
343
363
|
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
let(:url) { "http://thouetnhoeu89ueoueohtueohtneuohn" }
|
348
|
-
let(:code) { nil } # no response expected
|
364
|
+
it "should invoke handle failure exactly once" do
|
365
|
+
expect(poller).to have_received(:handle_failure).once
|
366
|
+
end
|
349
367
|
|
350
|
-
|
368
|
+
it "should not invoke handle success at all" do
|
369
|
+
expect(poller).not_to have_received(:handle_success)
|
370
|
+
end
|
351
371
|
|
352
|
-
include_examples("
|
372
|
+
include_examples("matching metadata")
|
353
373
|
end
|
354
374
|
|
355
|
-
context "
|
356
|
-
|
375
|
+
context "with a non responsive server" do
|
376
|
+
context "due to a non-existant host" do # Fail with handlers
|
377
|
+
let(:name) { default_name }
|
378
|
+
let(:url) { "http://thouetnhoeu89ueoueohtueohtneuohn" }
|
379
|
+
let(:code) { nil } # no response expected
|
357
380
|
|
358
|
-
|
359
|
-
let(:url) { "http://127.0.0.1:#{invalid_port}" }
|
360
|
-
let(:settings) { default_opts.merge("urls" => {name => url}) }
|
361
|
-
let(:code) { nil } # No response expected
|
381
|
+
let(:settings) { default_opts.merge("urls" => { name => url}) }
|
362
382
|
|
363
|
-
|
364
|
-
|
365
|
-
end
|
383
|
+
include_examples("unprocessable_requests")
|
384
|
+
end
|
366
385
|
|
367
|
-
|
368
|
-
|
369
|
-
let(:response_body) { LogStash::Json.dump(payload) }
|
370
|
-
let(:opts) { default_opts }
|
371
|
-
let(:instance) {
|
372
|
-
klass.new(opts)
|
373
|
-
}
|
374
|
-
let(:name) { default_name }
|
375
|
-
let(:url) { default_url }
|
376
|
-
let(:code) { 202 }
|
386
|
+
context "due to a bogus port number" do # fail with return?
|
387
|
+
let(:invalid_port) { Flores::Random.integer(65536..1000000) }
|
377
388
|
|
378
|
-
|
379
|
-
|
380
|
-
|
389
|
+
let(:name) { default_name }
|
390
|
+
let(:url) { "http://127.0.0.1:#{invalid_port}" }
|
391
|
+
let(:settings) { default_opts.merge("urls" => {name => url}) }
|
392
|
+
let(:code) { nil } # No response expected
|
381
393
|
|
382
|
-
|
383
|
-
|
384
|
-
u = url.is_a?(Hash) ? url["url"] : url # handle both complex specs and simple string URLs
|
385
|
-
instance.client.stub(u,
|
386
|
-
:body => response_body,
|
387
|
-
:code => code
|
388
|
-
)
|
389
|
-
allow(instance).to receive(:decorate)
|
390
|
-
instance.send(:run_once, queue)
|
394
|
+
include_examples("unprocessable_requests")
|
395
|
+
end
|
391
396
|
end
|
392
397
|
|
393
|
-
|
394
|
-
|
395
|
-
|
398
|
+
describe "a valid request and decoded response" do
|
399
|
+
let(:payload) { {"a" => 2, "hello" => ["a", "b", "c"]} }
|
400
|
+
let(:response_body) { LogStash::Json.dump(payload) }
|
401
|
+
let(:opts) { default_opts }
|
402
|
+
let(:name) { default_name }
|
403
|
+
let(:url) { default_url }
|
404
|
+
let(:code) { 202 }
|
396
405
|
|
397
|
-
|
398
|
-
|
399
|
-
|
406
|
+
subject(:event) {
|
407
|
+
queue.pop(true)
|
408
|
+
}
|
400
409
|
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
410
|
+
before do
|
411
|
+
plugin.register
|
412
|
+
u = url.is_a?(Hash) ? url["url"] : url # handle both complex specs and simple string URLs
|
413
|
+
plugin.client.stub(u,
|
414
|
+
:body => response_body,
|
415
|
+
:code => code
|
416
|
+
)
|
417
|
+
allow(plugin).to receive(:decorate)
|
418
|
+
plugin.send(:run_once, queue)
|
408
419
|
end
|
409
|
-
end
|
410
420
|
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
opts.delete("metadata_target")
|
415
|
-
opts
|
416
|
-
}
|
421
|
+
it "should have a matching message" do
|
422
|
+
expect(event.to_hash).to include(payload)
|
423
|
+
end
|
417
424
|
|
418
|
-
it "should
|
419
|
-
|
420
|
-
expect(event.get(metadata_target)).to be_nil
|
425
|
+
it "should decorate the event" do
|
426
|
+
expect(plugin).to have_received(:decorate).once
|
421
427
|
end
|
422
|
-
end
|
423
428
|
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
429
|
+
include_examples("matching metadata")
|
430
|
+
|
431
|
+
context "with an empty body" do
|
432
|
+
let(:response_body) { "" }
|
433
|
+
it "should return an empty event" do
|
434
|
+
plugin.send(:run_once, queue)
|
435
|
+
headers_field = ecs_select[disabled: "[#{metadata_target}][response_headers]",
|
436
|
+
v1: "[#{metadata_target}][input][http_poller][response][headers]"]
|
437
|
+
expect(event.get("#{headers_field}[content-length]")).to eql("0")
|
438
|
+
end
|
439
|
+
end
|
440
|
+
|
441
|
+
context "with metadata omitted" do
|
442
|
+
let(:opts) {
|
443
|
+
opts = default_opts.clone
|
444
|
+
opts.delete("metadata_target")
|
445
|
+
opts
|
446
|
+
}
|
447
|
+
|
448
|
+
it "should not have any metadata on the event" do
|
449
|
+
plugin.send(:run_once, queue)
|
450
|
+
expect(event.get(metadata_target)).to be_nil
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
454
|
+
context "with a complex URL spec" do
|
455
|
+
let(:url) {
|
456
|
+
{
|
457
|
+
"method" => "get",
|
458
|
+
"url" => default_url,
|
459
|
+
"headers" => {
|
460
|
+
"X-Fry" => "I'm having one of those things, like a headache, with pictures..."
|
461
|
+
}
|
431
462
|
}
|
432
463
|
}
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
464
|
+
let(:opts) {
|
465
|
+
{
|
466
|
+
"schedule" => {
|
467
|
+
"cron" => "* * * * * UTC"
|
468
|
+
},
|
469
|
+
"urls" => {
|
470
|
+
default_name => url
|
438
471
|
},
|
439
|
-
|
440
|
-
|
441
|
-
}
|
442
|
-
"codec" => "json",
|
443
|
-
"metadata_target" => metadata_target
|
472
|
+
"codec" => "json",
|
473
|
+
"metadata_target" => metadata_target
|
474
|
+
}
|
444
475
|
}
|
445
|
-
}
|
446
476
|
|
447
|
-
|
477
|
+
include_examples("matching metadata")
|
448
478
|
|
449
|
-
|
450
|
-
|
479
|
+
it "should have a matching message" do
|
480
|
+
expect(event.to_hash).to include(payload)
|
481
|
+
end
|
451
482
|
end
|
452
|
-
end
|
453
483
|
|
454
|
-
|
455
|
-
|
456
|
-
|
484
|
+
context "with a specified target" do
|
485
|
+
let(:target) { "mytarget" }
|
486
|
+
let(:opts) { default_opts.merge("target" => target) }
|
457
487
|
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
488
|
+
it "should store the event info in the target" do
|
489
|
+
# When events go through the pipeline they are java-ified
|
490
|
+
# this normalizes the payload to java types
|
491
|
+
payload_normalized = LogStash::Json.load(LogStash::Json.dump(payload))
|
492
|
+
expect(event.get(target)).to include(payload_normalized)
|
493
|
+
end
|
463
494
|
end
|
464
|
-
end
|
465
495
|
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
496
|
+
context "with default metadata target" do
|
497
|
+
let(:metadata_target) { "@metadata" }
|
498
|
+
|
499
|
+
it "should store the metadata info in @metadata" do
|
500
|
+
if ecs_compatibility == :disabled
|
501
|
+
expect(event.get("[@metadata][response_headers]")).to be_a(Hash)
|
502
|
+
expect(event.get("[@metadata][runtime_seconds]")).to be_a(Float)
|
503
|
+
expect(event.get("[@metadata][times_retried]")).to eq(0)
|
504
|
+
expect(event.get("[@metadata][name]")).to eq(default_name)
|
505
|
+
expect(event.get("[@metadata][request]")).to be_a(Hash)
|
506
|
+
else
|
507
|
+
expect(event.get("[@metadata][input][http_poller][response][headers]")).to be_a(Hash)
|
508
|
+
expect(event.get("[@metadata][input][http_poller][response][elapsed_time_ns]")).to be_a(Integer)
|
509
|
+
expect(event.get("[@metadata][input][http_poller][request][retry_count]")).to eq(0)
|
510
|
+
expect(event.get("[@metadata][input][http_poller][request][name]")).to eq(default_name)
|
511
|
+
expect(event.get("[@metadata][input][http_poller][request][original]")).to be_a(Hash)
|
512
|
+
end
|
473
513
|
end
|
474
514
|
end
|
475
515
|
|
476
|
-
context '
|
477
|
-
let(:
|
478
|
-
|
479
|
-
expect(events.size).to equal(4)
|
480
|
-
messages = events.map{|e| e.get('message')}
|
481
|
-
expect(messages).to include('one')
|
482
|
-
expect(messages).to include('two')
|
483
|
-
expect(messages).to include('three')
|
484
|
-
expect(messages).to include('four')
|
516
|
+
context 'using a line codec' do
|
517
|
+
let(:opts) do
|
518
|
+
default_opts.merge({"codec" => "line"})
|
485
519
|
end
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
520
|
+
subject(:events) do
|
521
|
+
[].tap do |events|
|
522
|
+
events << queue.pop until queue.empty?
|
523
|
+
end
|
524
|
+
end
|
525
|
+
|
526
|
+
context 'when response has a trailing newline' do
|
527
|
+
let(:response_body) { "one\ntwo\nthree\nfour\n" }
|
528
|
+
it 'emits all events' do
|
529
|
+
expect(events.size).to equal(4)
|
530
|
+
messages = events.map{|e| e.get('message')}
|
531
|
+
expect(messages).to include('one')
|
532
|
+
expect(messages).to include('two')
|
533
|
+
expect(messages).to include('three')
|
534
|
+
expect(messages).to include('four')
|
535
|
+
end
|
536
|
+
end
|
537
|
+
context 'when response has no trailing newline' do
|
538
|
+
let(:response_body) { "one\ntwo\nthree\nfour" }
|
539
|
+
it 'emits all events' do
|
540
|
+
expect(events.size).to equal(4)
|
541
|
+
messages = events.map{|e| e.get('message')}
|
542
|
+
expect(messages).to include('one')
|
543
|
+
expect(messages).to include('two')
|
544
|
+
expect(messages).to include('three')
|
545
|
+
expect(messages).to include('four')
|
546
|
+
end
|
496
547
|
end
|
497
548
|
end
|
498
549
|
end
|
@@ -501,6 +552,8 @@ describe LogStash::Inputs::HTTP_Poller do
|
|
501
552
|
|
502
553
|
describe "stopping" do
|
503
554
|
let(:config) { default_opts }
|
504
|
-
it_behaves_like "an interruptible input plugin"
|
555
|
+
it_behaves_like "an interruptible input plugin" do
|
556
|
+
let(:allowed_lag) { 10 } # CI: wait till scheduler shuts down
|
557
|
+
end
|
505
558
|
end
|
506
559
|
end
|