logstash-input-http_poller 5.0.1 → 5.2.1
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/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
|