logstash-input-elasticsearch 4.9.1 → 4.11.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/CHANGELOG.md +15 -0
- data/docs/index.asciidoc +37 -10
- data/lib/logstash/inputs/{patch.rb → elasticsearch/patches/_elasticsearch_transport_connections_selector.rb} +9 -6
- data/lib/logstash/inputs/elasticsearch/patches/_elasticsearch_transport_http_manticore.rb +43 -0
- data/lib/logstash/inputs/elasticsearch.rb +60 -35
- data/logstash-input-elasticsearch.gemspec +10 -8
- data/spec/es_helper.rb +17 -16
- data/spec/fixtures/test_certs/ca.crt +20 -0
- data/spec/fixtures/test_certs/ca.key +27 -0
- data/spec/fixtures/test_certs/es.crt +20 -0
- data/spec/fixtures/test_certs/es.key +27 -0
- data/spec/inputs/elasticsearch_spec.rb +306 -132
- data/spec/inputs/integration/elasticsearch_spec.rb +24 -12
- metadata +78 -50
- data/spec/fixtures/test_certs/ca/ca.crt +0 -32
- data/spec/fixtures/test_certs/ca/ca.key +0 -51
- data/spec/fixtures/test_certs/test.crt +0 -36
- data/spec/fixtures/test_certs/test.key +0 -51
@@ -7,14 +7,15 @@ require "timecop"
|
|
7
7
|
require "stud/temporary"
|
8
8
|
require "time"
|
9
9
|
require "date"
|
10
|
+
require "cabin"
|
11
|
+
require "webrick"
|
12
|
+
require "uri"
|
10
13
|
|
11
|
-
|
12
|
-
attr_reader :client
|
13
|
-
end
|
14
|
+
require 'logstash/plugin_mixins/ecs_compatibility_support/spec_helper'
|
14
15
|
|
15
|
-
describe LogStash::Inputs::
|
16
|
+
describe LogStash::Inputs::Elasticsearch, :ecs_compatibility_support do
|
16
17
|
|
17
|
-
let(:plugin) {
|
18
|
+
let(:plugin) { described_class.new(config) }
|
18
19
|
let(:queue) { Queue.new }
|
19
20
|
|
20
21
|
it_behaves_like "an interruptible input plugin" do
|
@@ -40,7 +41,13 @@ describe LogStash::Inputs::TestableElasticsearch do
|
|
40
41
|
end
|
41
42
|
end
|
42
43
|
|
43
|
-
|
44
|
+
|
45
|
+
ecs_compatibility_matrix(:disabled, :v1, :v8) do |ecs_select|
|
46
|
+
|
47
|
+
before(:each) do
|
48
|
+
allow_any_instance_of(described_class).to receive(:ecs_compatibility).and_return(ecs_compatibility)
|
49
|
+
end
|
50
|
+
|
44
51
|
let(:config) do
|
45
52
|
%q[
|
46
53
|
input {
|
@@ -97,7 +104,6 @@ describe LogStash::Inputs::TestableElasticsearch do
|
|
97
104
|
end
|
98
105
|
|
99
106
|
expect(event).to be_a(LogStash::Event)
|
100
|
-
puts event.to_hash_with_metadata
|
101
107
|
expect(event.get("message")).to eql [ "ohayo" ]
|
102
108
|
end
|
103
109
|
|
@@ -120,10 +126,10 @@ describe LogStash::Inputs::TestableElasticsearch do
|
|
120
126
|
end
|
121
127
|
|
122
128
|
expect(event).to be_a(LogStash::Event)
|
123
|
-
puts event.to_hash_with_metadata
|
124
129
|
expect(event.get("[@metadata][_source][message]")).to eql [ "ohayo" ]
|
125
130
|
end
|
126
131
|
end
|
132
|
+
|
127
133
|
end
|
128
134
|
|
129
135
|
# This spec is an adapter-spec, ensuring that we send the right sequence of messages to our Elasticsearch Client
|
@@ -135,6 +141,7 @@ describe LogStash::Inputs::TestableElasticsearch do
|
|
135
141
|
'query' => "#{LogStash::Json.dump(query)}",
|
136
142
|
'slices' => slices,
|
137
143
|
'docinfo' => true, # include ids
|
144
|
+
'docinfo_target' => '[@metadata]'
|
138
145
|
}
|
139
146
|
end
|
140
147
|
let(:query) do
|
@@ -166,7 +173,7 @@ describe LogStash::Inputs::TestableElasticsearch do
|
|
166
173
|
end
|
167
174
|
|
168
175
|
context 'without slices directive' do
|
169
|
-
let(:config) { super.tap { |h| h.delete('slices') } }
|
176
|
+
let(:config) { super().tap { |h| h.delete('slices') } }
|
170
177
|
it 'runs just one slice' do
|
171
178
|
expect(plugin).to receive(:do_run_slice).with(duck_type(:<<))
|
172
179
|
expect(Thread).to_not receive(:new)
|
@@ -405,127 +412,140 @@ describe LogStash::Inputs::TestableElasticsearch do
|
|
405
412
|
allow(client).to receive(:clear_scroll).and_return(nil)
|
406
413
|
end
|
407
414
|
|
408
|
-
|
409
|
-
let(:config_metadata) do
|
410
|
-
%q[
|
411
|
-
input {
|
412
|
-
elasticsearch {
|
413
|
-
hosts => ["localhost"]
|
414
|
-
query => '{ "query": { "match": { "city_name": "Okinawa" } }, "fields": ["message"] }'
|
415
|
-
docinfo => true
|
416
|
-
}
|
417
|
-
}
|
418
|
-
]
|
419
|
-
end
|
415
|
+
ecs_compatibility_matrix(:disabled, :v1, :v8) do |ecs_select|
|
420
416
|
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
417
|
+
before(:each) do
|
418
|
+
allow_any_instance_of(described_class).to receive(:ecs_compatibility).and_return(ecs_compatibility)
|
419
|
+
end
|
420
|
+
|
421
|
+
context 'with docinfo enabled' do
|
422
|
+
let(:config_metadata) do
|
423
|
+
%q[
|
424
|
+
input {
|
425
|
+
elasticsearch {
|
426
|
+
hosts => ["localhost"]
|
427
|
+
query => '{ "query": { "match": { "city_name": "Okinawa" } }, "fields": ["message"] }'
|
428
|
+
docinfo => true
|
429
|
+
}
|
429
430
|
}
|
430
|
-
|
431
|
-
]
|
432
|
-
|
433
|
-
event = input(config_metadata_with_hash) do |pipeline, queue|
|
434
|
-
queue.pop
|
431
|
+
]
|
435
432
|
end
|
436
433
|
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
"
|
446
|
-
|
447
|
-
"
|
448
|
-
"
|
449
|
-
|
450
|
-
|
451
|
-
expect(client).not_to receive(:clear_scroll)
|
452
|
-
plugin.register
|
453
|
-
expect { plugin.run([]) }.to raise_error(Exception, /incompatible event/)
|
434
|
+
it "provides document info under metadata" do
|
435
|
+
event = input(config_metadata) do |pipeline, queue|
|
436
|
+
queue.pop
|
437
|
+
end
|
438
|
+
|
439
|
+
if ecs_select.active_mode == :disabled
|
440
|
+
expect(event.get("[@metadata][_index]")).to eq('logstash-2014.10.12')
|
441
|
+
expect(event.get("[@metadata][_type]")).to eq('logs')
|
442
|
+
expect(event.get("[@metadata][_id]")).to eq('C5b2xLQwTZa76jBmHIbwHQ')
|
443
|
+
else
|
444
|
+
expect(event.get("[@metadata][input][elasticsearch][_index]")).to eq('logstash-2014.10.12')
|
445
|
+
expect(event.get("[@metadata][input][elasticsearch][_type]")).to eq('logs')
|
446
|
+
expect(event.get("[@metadata][input][elasticsearch][_id]")).to eq('C5b2xLQwTZa76jBmHIbwHQ')
|
447
|
+
end
|
454
448
|
end
|
455
|
-
end
|
456
449
|
|
457
|
-
|
458
|
-
|
459
|
-
|
450
|
+
it 'merges values if the `docinfo_target` already exist in the `_source` document' do
|
451
|
+
config_metadata_with_hash = %Q[
|
452
|
+
input {
|
453
|
+
elasticsearch {
|
454
|
+
hosts => ["localhost"]
|
455
|
+
query => '{ "query": { "match": { "city_name": "Okinawa" } }, "fields": ["message"] }'
|
456
|
+
docinfo => true
|
457
|
+
docinfo_target => 'metadata_with_hash'
|
458
|
+
}
|
459
|
+
}
|
460
|
+
]
|
461
|
+
|
462
|
+
event = input(config_metadata_with_hash) do |pipeline, queue|
|
463
|
+
queue.pop
|
464
|
+
end
|
465
|
+
|
466
|
+
expect(event.get("[metadata_with_hash][_index]")).to eq('logstash-2014.10.12')
|
467
|
+
expect(event.get("[metadata_with_hash][_type]")).to eq('logs')
|
468
|
+
expect(event.get("[metadata_with_hash][_id]")).to eq('C5b2xLQwTZa76jBmHIbwHQ')
|
469
|
+
expect(event.get("[metadata_with_hash][awesome]")).to eq("logstash")
|
460
470
|
end
|
461
471
|
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
472
|
+
context 'if the `docinfo_target` exist but is not of type hash' do
|
473
|
+
let (:config) { {
|
474
|
+
"hosts" => ["localhost"],
|
475
|
+
"query" => '{ "query": { "match": { "city_name": "Okinawa" } }, "fields": ["message"] }',
|
476
|
+
"docinfo" => true,
|
477
|
+
"docinfo_target" => 'metadata_with_string'
|
478
|
+
} }
|
479
|
+
it 'thows an exception if the `docinfo_target` exist but is not of type hash' do
|
480
|
+
expect(client).not_to receive(:clear_scroll)
|
481
|
+
plugin.register
|
482
|
+
expect { plugin.run([]) }.to raise_error(Exception, /incompatible event/)
|
483
|
+
end
|
484
|
+
end
|
466
485
|
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
486
|
+
it 'should move the document information to the specified field' do
|
487
|
+
config = %q[
|
488
|
+
input {
|
489
|
+
elasticsearch {
|
490
|
+
hosts => ["localhost"]
|
491
|
+
query => '{ "query": { "match": { "city_name": "Okinawa" } }, "fields": ["message"] }'
|
492
|
+
docinfo => true
|
493
|
+
docinfo_target => 'meta'
|
494
|
+
}
|
475
495
|
}
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
496
|
+
]
|
497
|
+
event = input(config) do |pipeline, queue|
|
498
|
+
queue.pop
|
499
|
+
end
|
500
|
+
|
501
|
+
expect(event.get("[meta][_index]")).to eq('logstash-2014.10.12')
|
502
|
+
expect(event.get("[meta][_type]")).to eq('logs')
|
503
|
+
expect(event.get("[meta][_id]")).to eq('C5b2xLQwTZa76jBmHIbwHQ')
|
480
504
|
end
|
481
505
|
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
506
|
+
it "allows to specify which fields from the document info to save to metadata" do
|
507
|
+
fields = ["_index"]
|
508
|
+
config = %Q[
|
509
|
+
input {
|
510
|
+
elasticsearch {
|
511
|
+
hosts => ["localhost"]
|
512
|
+
query => '{ "query": { "match": { "city_name": "Okinawa" } }, "fields": ["message"] }'
|
513
|
+
docinfo => true
|
514
|
+
docinfo_fields => #{fields}
|
515
|
+
}
|
516
|
+
}]
|
517
|
+
|
518
|
+
event = input(config) do |pipeline, queue|
|
519
|
+
queue.pop
|
520
|
+
end
|
521
|
+
|
522
|
+
meta_base = event.get(ecs_select.active_mode == :disabled ? "@metadata" : "[@metadata][input][elasticsearch]")
|
523
|
+
expect(meta_base.keys).to eq(fields)
|
524
|
+
end
|
486
525
|
|
487
|
-
|
488
|
-
|
489
|
-
config = %Q[
|
526
|
+
it 'should be able to reference metadata fields in `add_field` decorations' do
|
527
|
+
config = %q[
|
490
528
|
input {
|
491
529
|
elasticsearch {
|
492
530
|
hosts => ["localhost"]
|
493
531
|
query => '{ "query": { "match": { "city_name": "Okinawa" } }, "fields": ["message"] }'
|
494
532
|
docinfo => true
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
event = input(config) do |pipeline, queue|
|
500
|
-
queue.pop
|
501
|
-
end
|
502
|
-
|
503
|
-
expect(event.get("@metadata").keys).to eq(fields)
|
504
|
-
expect(event.get("[@metadata][_type]")).to eq(nil)
|
505
|
-
expect(event.get("[@metadata][_index]")).to eq('logstash-2014.10.12')
|
506
|
-
expect(event.get("[@metadata][_id]")).to eq(nil)
|
507
|
-
end
|
508
|
-
|
509
|
-
it 'should be able to reference metadata fields in `add_field` decorations' do
|
510
|
-
config = %q[
|
511
|
-
input {
|
512
|
-
elasticsearch {
|
513
|
-
hosts => ["localhost"]
|
514
|
-
query => '{ "query": { "match": { "city_name": "Okinawa" } }, "fields": ["message"] }'
|
515
|
-
docinfo => true
|
516
|
-
add_field => {
|
517
|
-
'identifier' => "foo:%{[@metadata][_type]}:%{[@metadata][_id]}"
|
533
|
+
add_field => {
|
534
|
+
'identifier' => "foo:%{[@metadata][_type]}:%{[@metadata][_id]}"
|
535
|
+
}
|
518
536
|
}
|
519
537
|
}
|
520
|
-
|
521
|
-
]
|
538
|
+
]
|
522
539
|
|
523
|
-
|
524
|
-
|
525
|
-
|
540
|
+
event = input(config) do |pipeline, queue|
|
541
|
+
queue.pop
|
542
|
+
end
|
543
|
+
|
544
|
+
expect(event.get('identifier')).to eq('foo:logs:C5b2xLQwTZa76jBmHIbwHQ')
|
545
|
+
end if ecs_select.active_mode == :disabled
|
526
546
|
|
527
|
-
expect(event.get('identifier')).to eq('foo:logs:C5b2xLQwTZa76jBmHIbwHQ')
|
528
547
|
end
|
548
|
+
|
529
549
|
end
|
530
550
|
|
531
551
|
context "when not defining the docinfo" do
|
@@ -542,9 +562,7 @@ describe LogStash::Inputs::TestableElasticsearch do
|
|
542
562
|
queue.pop
|
543
563
|
end
|
544
564
|
|
545
|
-
expect(event.get("[@metadata]
|
546
|
-
expect(event.get("[@metadata][_type]")).to eq(nil)
|
547
|
-
expect(event.get("[@metadata][_id]")).to eq(nil)
|
565
|
+
expect(event.get("[@metadata]")).to be_empty
|
548
566
|
end
|
549
567
|
end
|
550
568
|
end
|
@@ -563,22 +581,22 @@ describe LogStash::Inputs::TestableElasticsearch do
|
|
563
581
|
'sample:dXMtY2VudHJhbDEuZ2NwLmNsb3VkLmVzLmlvJGFjMzFlYmI5MDI0MTc3MzE1NzA0M2MzNGZkMjZmZDQ2OjkyNDMkYTRjMDYyMzBlNDhjOGZjZTdiZTg4YTA3NGEzYmIzZTA6OTI0NA=='
|
564
582
|
end
|
565
583
|
|
566
|
-
let(:config) { super.merge({ 'cloud_id' => valid_cloud_id }) }
|
584
|
+
let(:config) { super().merge({ 'cloud_id' => valid_cloud_id }) }
|
567
585
|
|
568
586
|
it "should set host(s)" do
|
569
587
|
plugin.register
|
570
588
|
client = plugin.send(:client)
|
571
|
-
expect( client.
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
589
|
+
expect( extract_transport(client).hosts ).to eql [{
|
590
|
+
:scheme => "https",
|
591
|
+
:host => "ac31ebb90241773157043c34fd26fd46.us-central1.gcp.cloud.es.io",
|
592
|
+
:port => 9243,
|
593
|
+
:path => "",
|
594
|
+
:protocol => "https"
|
595
|
+
}]
|
578
596
|
end
|
579
597
|
|
580
598
|
context 'invalid' do
|
581
|
-
let(:config) { super.merge({ 'cloud_id' => 'invalid:dXMtY2VudHJhbDEuZ2NwLmNsb3VkLmVzLmlv' }) }
|
599
|
+
let(:config) { super().merge({ 'cloud_id' => 'invalid:dXMtY2VudHJhbDEuZ2NwLmNsb3VkLmVzLmlv' }) }
|
582
600
|
|
583
601
|
it "should fail" do
|
584
602
|
expect { plugin.register }.to raise_error LogStash::ConfigurationError, /cloud_id.*? is invalid/
|
@@ -586,7 +604,7 @@ describe LogStash::Inputs::TestableElasticsearch do
|
|
586
604
|
end
|
587
605
|
|
588
606
|
context 'hosts also set' do
|
589
|
-
let(:config) { super.merge({ 'cloud_id' => valid_cloud_id, 'hosts' => [ 'localhost:9200' ] }) }
|
607
|
+
let(:config) { super().merge({ 'cloud_id' => valid_cloud_id, 'hosts' => [ 'localhost:9200' ] }) }
|
590
608
|
|
591
609
|
it "should fail" do
|
592
610
|
expect { plugin.register }.to raise_error LogStash::ConfigurationError, /cloud_id and hosts/
|
@@ -595,18 +613,18 @@ describe LogStash::Inputs::TestableElasticsearch do
|
|
595
613
|
end if LOGSTASH_VERSION > '6.0'
|
596
614
|
|
597
615
|
describe "cloud.auth" do
|
598
|
-
let(:config) { super.merge({ 'cloud_auth' => LogStash::Util::Password.new('elastic:my-passwd-00') }) }
|
616
|
+
let(:config) { super().merge({ 'cloud_auth' => LogStash::Util::Password.new('elastic:my-passwd-00') }) }
|
599
617
|
|
600
618
|
it "should set authorization" do
|
601
619
|
plugin.register
|
602
620
|
client = plugin.send(:client)
|
603
|
-
auth_header = client.
|
621
|
+
auth_header = extract_transport(client).options[:transport_options][:headers]['Authorization']
|
604
622
|
|
605
623
|
expect( auth_header ).to eql "Basic #{Base64.encode64('elastic:my-passwd-00').rstrip}"
|
606
624
|
end
|
607
625
|
|
608
626
|
context 'invalid' do
|
609
|
-
let(:config) { super.merge({ 'cloud_auth' => 'invalid-format' }) }
|
627
|
+
let(:config) { super().merge({ 'cloud_auth' => 'invalid-format' }) }
|
610
628
|
|
611
629
|
it "should fail" do
|
612
630
|
expect { plugin.register }.to raise_error LogStash::ConfigurationError, /cloud_auth.*? format/
|
@@ -614,7 +632,7 @@ describe LogStash::Inputs::TestableElasticsearch do
|
|
614
632
|
end
|
615
633
|
|
616
634
|
context 'user also set' do
|
617
|
-
let(:config) { super.merge({ 'cloud_auth' => 'elastic:my-passwd-00', 'user' => 'another' }) }
|
635
|
+
let(:config) { super().merge({ 'cloud_auth' => 'elastic:my-passwd-00', 'user' => 'another' }) }
|
618
636
|
|
619
637
|
it "should fail" do
|
620
638
|
expect { plugin.register }.to raise_error LogStash::ConfigurationError, /Multiple authentication options are specified/
|
@@ -624,7 +642,7 @@ describe LogStash::Inputs::TestableElasticsearch do
|
|
624
642
|
|
625
643
|
describe "api_key" do
|
626
644
|
context "without ssl" do
|
627
|
-
let(:config) { super.merge({ 'api_key' => LogStash::Util::Password.new('foo:bar') }) }
|
645
|
+
let(:config) { super().merge({ 'api_key' => LogStash::Util::Password.new('foo:bar') }) }
|
628
646
|
|
629
647
|
it "should fail" do
|
630
648
|
expect { plugin.register }.to raise_error LogStash::ConfigurationError, /api_key authentication requires SSL\/TLS/
|
@@ -632,18 +650,18 @@ describe LogStash::Inputs::TestableElasticsearch do
|
|
632
650
|
end
|
633
651
|
|
634
652
|
context "with ssl" do
|
635
|
-
let(:config) { super.merge({ 'api_key' => LogStash::Util::Password.new('foo:bar'), "ssl" => true }) }
|
653
|
+
let(:config) { super().merge({ 'api_key' => LogStash::Util::Password.new('foo:bar'), "ssl" => true }) }
|
636
654
|
|
637
655
|
it "should set authorization" do
|
638
656
|
plugin.register
|
639
657
|
client = plugin.send(:client)
|
640
|
-
auth_header = client.
|
658
|
+
auth_header = extract_transport(client).options[:transport_options][:headers]['Authorization']
|
641
659
|
|
642
660
|
expect( auth_header ).to eql "ApiKey #{Base64.strict_encode64('foo:bar')}"
|
643
661
|
end
|
644
662
|
|
645
663
|
context 'user also set' do
|
646
|
-
let(:config) { super.merge({ 'api_key' => 'foo:bar', 'user' => 'another' }) }
|
664
|
+
let(:config) { super().merge({ 'api_key' => 'foo:bar', 'user' => 'another' }) }
|
647
665
|
|
648
666
|
it "should fail" do
|
649
667
|
expect { plugin.register }.to raise_error LogStash::ConfigurationError, /Multiple authentication options are specified/
|
@@ -653,24 +671,174 @@ describe LogStash::Inputs::TestableElasticsearch do
|
|
653
671
|
end if LOGSTASH_VERSION > '6.0'
|
654
672
|
|
655
673
|
describe "proxy" do
|
656
|
-
let(:config) { super.merge({ 'proxy' => 'http://localhost:1234' }) }
|
674
|
+
let(:config) { super().merge({ 'proxy' => 'http://localhost:1234' }) }
|
657
675
|
|
658
676
|
it "should set proxy" do
|
659
677
|
plugin.register
|
660
678
|
client = plugin.send(:client)
|
661
|
-
proxy = client.
|
679
|
+
proxy = extract_transport(client).options[:transport_options][:proxy]
|
662
680
|
|
663
681
|
expect( proxy ).to eql "http://localhost:1234"
|
664
682
|
end
|
665
683
|
|
666
684
|
context 'invalid' do
|
667
|
-
let(:config) { super.merge({ 'proxy' => '${A_MISSING_ENV_VAR:}' }) }
|
685
|
+
let(:config) { super().merge({ 'proxy' => '${A_MISSING_ENV_VAR:}' }) }
|
668
686
|
|
669
687
|
it "should not set proxy" do
|
670
688
|
plugin.register
|
671
689
|
client = plugin.send(:client)
|
672
690
|
|
673
|
-
expect( client.
|
691
|
+
expect( extract_transport(client).options[:transport_options] ).to_not include(:proxy)
|
692
|
+
end
|
693
|
+
end
|
694
|
+
end
|
695
|
+
|
696
|
+
class StoppableServer
|
697
|
+
|
698
|
+
attr_reader :port
|
699
|
+
|
700
|
+
def initialize()
|
701
|
+
queue = Queue.new
|
702
|
+
@first_req_waiter = java.util.concurrent.CountDownLatch.new(1)
|
703
|
+
@first_request = nil
|
704
|
+
|
705
|
+
@t = java.lang.Thread.new(
|
706
|
+
proc do
|
707
|
+
begin
|
708
|
+
@server = WEBrick::HTTPServer.new :Port => 0, :DocumentRoot => ".",
|
709
|
+
:Logger => Cabin::Channel.get, # silence WEBrick logging
|
710
|
+
:StartCallback => Proc.new {
|
711
|
+
queue.push("started")
|
712
|
+
}
|
713
|
+
@port = @server.config[:Port]
|
714
|
+
@server.mount_proc '/' do |req, res|
|
715
|
+
res.body = '''
|
716
|
+
{
|
717
|
+
"name": "ce7ccfb438e8",
|
718
|
+
"cluster_name": "docker-cluster",
|
719
|
+
"cluster_uuid": "DyR1hN03QvuCWXRy3jtb0g",
|
720
|
+
"version": {
|
721
|
+
"number": "7.13.1",
|
722
|
+
"build_flavor": "default",
|
723
|
+
"build_type": "docker",
|
724
|
+
"build_hash": "9a7758028e4ea59bcab41c12004603c5a7dd84a9",
|
725
|
+
"build_date": "2021-05-28T17:40:59.346932922Z",
|
726
|
+
"build_snapshot": false,
|
727
|
+
"lucene_version": "8.8.2",
|
728
|
+
"minimum_wire_compatibility_version": "6.8.0",
|
729
|
+
"minimum_index_compatibility_version": "6.0.0-beta1"
|
730
|
+
},
|
731
|
+
"tagline": "You Know, for Search"
|
732
|
+
}
|
733
|
+
'''
|
734
|
+
res.status = 200
|
735
|
+
res['Content-Type'] = 'application/json'
|
736
|
+
@first_request = req
|
737
|
+
@first_req_waiter.countDown()
|
738
|
+
end
|
739
|
+
|
740
|
+
@server.mount_proc '/logstash_unit_test/_search' do |req, res|
|
741
|
+
res.body = '''
|
742
|
+
{
|
743
|
+
"took" : 1,
|
744
|
+
"timed_out" : false,
|
745
|
+
"_shards" : {
|
746
|
+
"total" : 1,
|
747
|
+
"successful" : 1,
|
748
|
+
"skipped" : 0,
|
749
|
+
"failed" : 0
|
750
|
+
},
|
751
|
+
"hits" : {
|
752
|
+
"total" : {
|
753
|
+
"value" : 10000,
|
754
|
+
"relation" : "gte"
|
755
|
+
},
|
756
|
+
"max_score" : 1.0,
|
757
|
+
"hits" : [
|
758
|
+
{
|
759
|
+
"_index" : "test_bulk_index_2",
|
760
|
+
"_type" : "_doc",
|
761
|
+
"_id" : "sHe6A3wBesqF7ydicQvG",
|
762
|
+
"_score" : 1.0,
|
763
|
+
"_source" : {
|
764
|
+
"@timestamp" : "2021-09-20T15:02:02.557Z",
|
765
|
+
"message" : "{\"name\": \"Andrea\"}",
|
766
|
+
"@version" : "1",
|
767
|
+
"host" : "kalispera",
|
768
|
+
"sequence" : 5
|
769
|
+
}
|
770
|
+
}
|
771
|
+
]
|
772
|
+
}
|
773
|
+
}
|
774
|
+
'''
|
775
|
+
res.status = 200
|
776
|
+
res['Content-Type'] = 'application/json'
|
777
|
+
@first_request = req
|
778
|
+
@first_req_waiter.countDown()
|
779
|
+
end
|
780
|
+
|
781
|
+
|
782
|
+
|
783
|
+
@server.start
|
784
|
+
rescue => e
|
785
|
+
puts "Error in webserver thread #{e}"
|
786
|
+
# ignore
|
787
|
+
end
|
788
|
+
end
|
789
|
+
)
|
790
|
+
@t.daemon = true
|
791
|
+
@t.start
|
792
|
+
queue.pop # blocks until the server is up
|
793
|
+
end
|
794
|
+
|
795
|
+
def stop
|
796
|
+
@server.shutdown
|
797
|
+
end
|
798
|
+
|
799
|
+
def wait_receive_request
|
800
|
+
@first_req_waiter.await(2, java.util.concurrent.TimeUnit::SECONDS)
|
801
|
+
@first_request
|
802
|
+
end
|
803
|
+
end
|
804
|
+
|
805
|
+
describe "'user-agent' header" do
|
806
|
+
let!(:webserver) { StoppableServer.new } # webserver must be started before the call, so no lazy "let"
|
807
|
+
|
808
|
+
after :each do
|
809
|
+
webserver.stop
|
810
|
+
end
|
811
|
+
|
812
|
+
it "server should be started" do
|
813
|
+
require 'net/http'
|
814
|
+
response = nil
|
815
|
+
Net::HTTP.start('localhost', webserver.port) {|http|
|
816
|
+
response = http.request_get('/')
|
817
|
+
}
|
818
|
+
expect(response.code.to_i).to eq(200)
|
819
|
+
end
|
820
|
+
|
821
|
+
context "used by plugin" do
|
822
|
+
let(:config) do
|
823
|
+
{
|
824
|
+
"hosts" => ["localhost:#{webserver.port}"],
|
825
|
+
"query" => '{ "query": { "match": { "statuscode": 200 } }, "sort": [ "_doc" ] }',
|
826
|
+
"index" => "logstash_unit_test"
|
827
|
+
}
|
828
|
+
end
|
829
|
+
let(:plugin) { described_class.new(config) }
|
830
|
+
let(:event) { LogStash::Event.new({}) }
|
831
|
+
|
832
|
+
it "client should sent the expect user-agent" do
|
833
|
+
plugin.register
|
834
|
+
|
835
|
+
queue = []
|
836
|
+
plugin.run(queue)
|
837
|
+
|
838
|
+
request = webserver.wait_receive_request
|
839
|
+
|
840
|
+
expect(request.header['user-agent'].size).to eq(1)
|
841
|
+
expect(request.header['user-agent'][0]).to match(/logstash\/\d*\.\d*\.\d* \(OS=.*; JVM=.*\) logstash-input-elasticsearch\/\d*\.\d*\.\d*/)
|
674
842
|
end
|
675
843
|
end
|
676
844
|
end
|
@@ -756,4 +924,10 @@ describe LogStash::Inputs::TestableElasticsearch do
|
|
756
924
|
end
|
757
925
|
|
758
926
|
end
|
927
|
+
|
928
|
+
# @note can be removed once we depends on elasticsearch gem >= 6.x
|
929
|
+
def extract_transport(client) # on 7.x client.transport is a ES::Transport::Client
|
930
|
+
client.transport.respond_to?(:transport) ? client.transport.transport : client.transport
|
931
|
+
end
|
932
|
+
|
759
933
|
end
|
@@ -11,7 +11,7 @@ describe LogStash::Inputs::Elasticsearch do
|
|
11
11
|
'query' => '{ "query": { "match": { "message": "Not found"} }}' } }
|
12
12
|
let(:plugin) { described_class.new(config) }
|
13
13
|
let(:event) { LogStash::Event.new({}) }
|
14
|
-
let(:client_options) {
|
14
|
+
let(:client_options) { Hash.new }
|
15
15
|
|
16
16
|
before(:each) do
|
17
17
|
@es = ESHelper.get_client(client_options)
|
@@ -47,17 +47,29 @@ describe LogStash::Inputs::Elasticsearch do
|
|
47
47
|
end
|
48
48
|
|
49
49
|
describe 'against a secured elasticsearch', :secure_integration => true do
|
50
|
-
let(:user) { 'simpleuser' }
|
51
|
-
let(:password) { 'abc123' }
|
52
|
-
let(:ca_file) { "spec/fixtures/test_certs/
|
53
|
-
|
54
|
-
let(:
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
'ca_file' => ca_file })
|
59
|
-
}
|
50
|
+
let(:user) { ENV['ELASTIC_USER'] || 'simpleuser' }
|
51
|
+
let(:password) { ENV['ELASTIC_PASSWORD'] || 'abc123' }
|
52
|
+
let(:ca_file) { "spec/fixtures/test_certs/ca.crt" }
|
53
|
+
|
54
|
+
let(:client_options) { { :ca_file => ca_file, :user => user, :password => password } }
|
55
|
+
|
56
|
+
let(:config) { super().merge('user' => user, 'password' => password, 'ssl' => true, 'ca_file' => ca_file) }
|
57
|
+
|
60
58
|
it_behaves_like 'an elasticsearch index plugin'
|
59
|
+
|
60
|
+
context "incorrect auth credentials" do
|
61
|
+
|
62
|
+
let(:config) do
|
63
|
+
super().merge('user' => 'archer', 'password' => 'b0gus!')
|
64
|
+
end
|
65
|
+
|
66
|
+
let(:queue) { [] }
|
67
|
+
|
68
|
+
it "fails to run the plugin" do
|
69
|
+
plugin.register
|
70
|
+
expect { plugin.run queue }.to raise_error Elasticsearch::Transport::Transport::Errors::Unauthorized
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
61
74
|
end
|
62
75
|
end
|
63
|
-
|