logstash-output-elasticsearch 7.4.3-java → 8.0.0-java

Sign up to get free protection for your applications and to get access to all the features.
Files changed (28) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG.md +5 -18
  3. data/docs/index.asciidoc +13 -50
  4. data/lib/logstash/outputs/elasticsearch/common.rb +39 -43
  5. data/lib/logstash/outputs/elasticsearch/common_configs.rb +2 -11
  6. data/lib/logstash/outputs/elasticsearch/http_client.rb +22 -27
  7. data/lib/logstash/outputs/elasticsearch/http_client/manticore_adapter.rb +2 -2
  8. data/lib/logstash/outputs/elasticsearch/http_client/pool.rb +12 -31
  9. data/lib/logstash/outputs/elasticsearch/template_manager.rb +6 -4
  10. data/logstash-output-elasticsearch.gemspec +1 -1
  11. data/spec/es_spec_helper.rb +0 -6
  12. data/spec/integration/outputs/compressed_indexing_spec.rb +44 -46
  13. data/spec/integration/outputs/delete_spec.rb +49 -51
  14. data/spec/integration/outputs/groovy_update_spec.rb +129 -131
  15. data/spec/integration/outputs/index_version_spec.rb +81 -82
  16. data/spec/integration/outputs/ingest_pipeline_spec.rb +49 -51
  17. data/spec/integration/outputs/painless_update_spec.rb +130 -170
  18. data/spec/integration/outputs/parent_spec.rb +55 -149
  19. data/spec/integration/outputs/sniffer_spec.rb +2 -5
  20. data/spec/integration/outputs/templates_5x_spec.rb +82 -81
  21. data/spec/integration/outputs/templates_spec.rb +81 -81
  22. data/spec/integration/outputs/update_spec.rb +99 -101
  23. data/spec/unit/outputs/elasticsearch/http_client/manticore_adapter_spec.rb +5 -30
  24. data/spec/unit/outputs/elasticsearch/http_client/pool_spec.rb +0 -3
  25. data/spec/unit/outputs/elasticsearch/http_client_spec.rb +12 -11
  26. data/spec/unit/outputs/elasticsearch/template_manager_spec.rb +25 -13
  27. data/spec/unit/outputs/elasticsearch_spec.rb +1 -10
  28. metadata +4 -6
@@ -1,116 +1,114 @@
1
1
  require_relative "../../../spec/es_spec_helper"
2
2
 
3
- if ESHelper.es_version_satisfies?(">= 2")
4
- describe "Update actions without scripts", :integration => true do
5
- require "logstash/outputs/elasticsearch"
6
-
7
- def get_es_output( options={} )
8
- settings = {
9
- "manage_template" => true,
10
- "index" => "logstash-update",
11
- "template_overwrite" => true,
12
- "hosts" => get_host_port(),
13
- "action" => "update"
14
- }
15
- LogStash::Outputs::ElasticSearch.new(settings.merge!(options))
3
+ describe "Update actions without scripts", :integration => true, :version_greater_than_equal_to_2x => true do
4
+ require "logstash/outputs/elasticsearch"
5
+
6
+ def get_es_output( options={} )
7
+ settings = {
8
+ "manage_template" => true,
9
+ "index" => "logstash-update",
10
+ "template_overwrite" => true,
11
+ "hosts" => get_host_port(),
12
+ "action" => "update"
13
+ }
14
+ LogStash::Outputs::ElasticSearch.new(settings.merge!(options))
15
+ end
16
+
17
+ before :each do
18
+ @es = get_client
19
+ # Delete all templates first.
20
+ # Clean ES of data before we start.
21
+ @es.indices.delete_template(:name => "*")
22
+ # This can fail if there are no indexes, ignore failure.
23
+ @es.indices.delete(:index => "*") rescue nil
24
+ @es.index(
25
+ :index => 'logstash-update',
26
+ :type => 'logs',
27
+ :id => "123",
28
+ :body => { :message => 'Test', :counter => 1 }
29
+ )
30
+ @es.indices.refresh
31
+ end
32
+
33
+ it "should fail without a document_id" do
34
+ subject = get_es_output
35
+ expect { subject.register }.to raise_error(LogStash::ConfigurationError)
36
+ end
37
+
38
+ context "when update only" do
39
+ it "should not create new document" do
40
+ subject = get_es_output({ 'document_id' => "456" } )
41
+ subject.register
42
+ subject.multi_receive([LogStash::Event.new("message" => "sample message here")])
43
+ expect {@es.get(:index => 'logstash-update', :type => 'logs', :id => "456", :refresh => true)}.to raise_error(Elasticsearch::Transport::Transport::Errors::NotFound)
44
+ end
45
+
46
+ it "should update existing document" do
47
+ subject = get_es_output({ 'document_id' => "123" })
48
+ subject.register
49
+ subject.multi_receive([LogStash::Event.new("message" => "updated message here")])
50
+ r = @es.get(:index => 'logstash-update', :type => 'logs', :id => "123", :refresh => true)
51
+ insist { r["_source"]["message"] } == 'updated message here'
52
+ end
53
+
54
+ # The es ruby client treats the data field differently. Make sure this doesn't
55
+ # raise an exception
56
+ it "should update an existing document that has a 'data' field" do
57
+ subject = get_es_output({ 'document_id' => "123" })
58
+ subject.register
59
+ subject.multi_receive([LogStash::Event.new("data" => "updated message here", "message" => "foo")])
60
+ r = @es.get(:index => 'logstash-update', :type => 'logs', :id => "123", :refresh => true)
61
+ insist { r["_source"]["data"] } == 'updated message here'
62
+ insist { r["_source"]["message"] } == 'foo'
63
+ end
64
+
65
+ it "should allow default (internal) version" do
66
+ subject = get_es_output({ 'document_id' => "123", "version" => "99" })
67
+ subject.register
16
68
  end
17
69
 
18
- before :each do
19
- @es = get_client
20
- # Delete all templates first.
21
- # Clean ES of data before we start.
22
- @es.indices.delete_template(:name => "*")
23
- # This can fail if there are no indexes, ignore failure.
24
- @es.indices.delete(:index => "*") rescue nil
25
- @es.index(
26
- :index => 'logstash-update',
27
- :type => 'logs',
28
- :id => "123",
29
- :body => { :message => 'Test', :counter => 1 }
30
- )
31
- @es.indices.refresh
70
+ it "should allow internal version" do
71
+ subject = get_es_output({ 'document_id' => "123", "version" => "99", "version_type" => "internal" })
72
+ subject.register
32
73
  end
33
74
 
34
- it "should fail without a document_id" do
35
- subject = get_es_output
75
+ it "should not allow external version" do
76
+ subject = get_es_output({ 'document_id' => "123", "version" => "99", "version_type" => "external" })
36
77
  expect { subject.register }.to raise_error(LogStash::ConfigurationError)
37
78
  end
38
79
 
39
- context "when update only" do
40
- it "should not create new document" do
41
- subject = get_es_output({ 'document_id' => "456" } )
42
- subject.register
43
- subject.multi_receive([LogStash::Event.new("message" => "sample message here")])
44
- expect {@es.get(:index => 'logstash-update', :type => 'logs', :id => "456", :refresh => true)}.to raise_error(Elasticsearch::Transport::Transport::Errors::NotFound)
45
- end
46
-
47
- it "should update existing document" do
48
- subject = get_es_output({ 'document_id' => "123" })
49
- subject.register
50
- subject.multi_receive([LogStash::Event.new("message" => "updated message here")])
51
- r = @es.get(:index => 'logstash-update', :type => 'logs', :id => "123", :refresh => true)
52
- insist { r["_source"]["message"] } == 'updated message here'
53
- end
54
-
55
- # The es ruby client treats the data field differently. Make sure this doesn't
56
- # raise an exception
57
- it "should update an existing document that has a 'data' field" do
58
- subject = get_es_output({ 'document_id' => "123" })
59
- subject.register
60
- subject.multi_receive([LogStash::Event.new("data" => "updated message here", "message" => "foo")])
61
- r = @es.get(:index => 'logstash-update', :type => 'logs', :id => "123", :refresh => true)
62
- insist { r["_source"]["data"] } == 'updated message here'
63
- insist { r["_source"]["message"] } == 'foo'
64
- end
65
-
66
- it "should allow default (internal) version" do
67
- subject = get_es_output({ 'document_id' => "123", "version" => "99" })
68
- subject.register
69
- end
70
-
71
- it "should allow internal version" do
72
- subject = get_es_output({ 'document_id' => "123", "version" => "99", "version_type" => "internal" })
73
- subject.register
74
- end
75
-
76
- it "should not allow external version" do
77
- subject = get_es_output({ 'document_id' => "123", "version" => "99", "version_type" => "external" })
78
- expect { subject.register }.to raise_error(LogStash::ConfigurationError)
79
- end
80
-
81
- it "should not allow external_gt version" do
82
- subject = get_es_output({ 'document_id' => "123", "version" => "99", "version_type" => "external_gt" })
83
- expect { subject.register }.to raise_error(LogStash::ConfigurationError)
84
- end
85
-
86
- it "should not allow external_gte version" do
87
- subject = get_es_output({ 'document_id' => "123", "version" => "99", "version_type" => "external_gte" })
88
- expect { subject.register }.to raise_error(LogStash::ConfigurationError)
89
- end
80
+ it "should not allow external_gt version" do
81
+ subject = get_es_output({ 'document_id' => "123", "version" => "99", "version_type" => "external_gt" })
82
+ expect { subject.register }.to raise_error(LogStash::ConfigurationError)
83
+ end
90
84
 
85
+ it "should not allow external_gte version" do
86
+ subject = get_es_output({ 'document_id' => "123", "version" => "99", "version_type" => "external_gte" })
87
+ expect { subject.register }.to raise_error(LogStash::ConfigurationError)
91
88
  end
92
89
 
93
- context "when update with upsert" do
94
- it "should create new documents with provided upsert" do
95
- subject = get_es_output({ 'document_id' => "456", 'upsert' => '{"message": "upsert message"}' })
96
- subject.register
97
- subject.multi_receive([LogStash::Event.new("message" => "sample message here")])
98
- r = @es.get(:index => 'logstash-update', :type => 'logs', :id => "456", :refresh => true)
99
- insist { r["_source"]["message"] } == 'upsert message'
100
- end
101
-
102
- it "should create new documents with event/doc as upsert" do
103
- subject = get_es_output({ 'document_id' => "456", 'doc_as_upsert' => true })
104
- subject.register
105
- subject.multi_receive([LogStash::Event.new("message" => "sample message here")])
106
- r = @es.get(:index => 'logstash-update', :type => 'logs', :id => "456", :refresh => true)
107
- insist { r["_source"]["message"] } == 'sample message here'
108
- end
109
-
110
- it "should fail on documents with event/doc as upsert at external version" do
111
- subject = get_es_output({ 'document_id' => "456", 'doc_as_upsert' => true, 'version' => 999, "version_type" => "external" })
112
- expect { subject.register }.to raise_error(LogStash::ConfigurationError)
113
- end
90
+ end
91
+
92
+ context "when update with upsert" do
93
+ it "should create new documents with provided upsert" do
94
+ subject = get_es_output({ 'document_id' => "456", 'upsert' => '{"message": "upsert message"}' })
95
+ subject.register
96
+ subject.multi_receive([LogStash::Event.new("message" => "sample message here")])
97
+ r = @es.get(:index => 'logstash-update', :type => 'logs', :id => "456", :refresh => true)
98
+ insist { r["_source"]["message"] } == 'upsert message'
99
+ end
100
+
101
+ it "should create new documents with event/doc as upsert" do
102
+ subject = get_es_output({ 'document_id' => "456", 'doc_as_upsert' => true })
103
+ subject.register
104
+ subject.multi_receive([LogStash::Event.new("message" => "sample message here")])
105
+ r = @es.get(:index => 'logstash-update', :type => 'logs', :id => "456", :refresh => true)
106
+ insist { r["_source"]["message"] } == 'sample message here'
107
+ end
108
+
109
+ it "should fail on documents with event/doc as upsert at external version" do
110
+ subject = get_es_output({ 'document_id' => "456", 'doc_as_upsert' => true, 'version' => 999, "version_type" => "external" })
111
+ expect { subject.register }.to raise_error(LogStash::ConfigurationError)
114
112
  end
115
113
  end
116
114
  end
@@ -44,44 +44,19 @@ describe LogStash::Outputs::ElasticSearch::HttpClient::ManticoreAdapter do
44
44
  end
45
45
  end
46
46
 
47
- describe "bad response codes" do
48
- let(:uri) { ::LogStash::Util::SafeURI.new("http://localhost:9200") }
49
-
50
- it "should raise a bad response code error" do
51
- resp = double("response")
52
- allow(resp).to receive(:call)
53
- allow(resp).to receive(:code).and_return(500)
54
- allow(resp).to receive(:body).and_return("a body")
55
-
56
- expect(subject.manticore).to receive(:get).
57
- with(uri.to_s + "/", anything).
58
- and_return(resp)
59
-
60
- uri_with_path = uri.clone
61
- uri_with_path.path = "/"
62
-
63
- expect(::LogStash::Outputs::ElasticSearch::HttpClient::Pool::BadResponseCodeError).to receive(:new).
64
- with(resp.code, uri_with_path, nil, resp.body).and_call_original
65
-
66
- expect do
67
- subject.perform_request(uri, :get, "/")
68
- end.to raise_error(::LogStash::Outputs::ElasticSearch::HttpClient::Pool::BadResponseCodeError)
69
- end
70
- end
71
-
72
47
  describe "format_url" do
73
48
  let(:url) { ::LogStash::Util::SafeURI.new("http://localhost:9200/path/") }
74
49
  let(:path) { "_bulk" }
75
50
  subject { described_class.new(double("logger"), {}) }
76
51
 
77
52
  it "should add the path argument to the uri's path" do
78
- expect(subject.format_url(url, path).path).to eq("/path/_bulk")
53
+ expect(java.net.URI.new(subject.format_url(url, path)).path).to eq("/path/_bulk")
79
54
  end
80
55
 
81
56
  context "when uri contains query parameters" do
82
57
  let(:query_params) { "query=value&key=value2" }
83
58
  let(:url) { ::LogStash::Util::SafeURI.new("http://localhost:9200/path/?#{query_params}") }
84
- let(:formatted) { subject.format_url(url, path)}
59
+ let(:formatted) { java.net.URI.new(subject.format_url(url, path))}
85
60
 
86
61
  it "should retain query_params after format" do
87
62
  expect(formatted.query).to eq(query_params)
@@ -98,7 +73,7 @@ describe LogStash::Outputs::ElasticSearch::HttpClient::ManticoreAdapter do
98
73
 
99
74
  context "when the path contains query parameters" do
100
75
  let(:path) { "/special_bulk?pathParam=1"}
101
- let(:formatted) { subject.format_url(url, path) }
76
+ let(:formatted) { java.net.URI.new(subject.format_url(url, path)) }
102
77
 
103
78
  it "should add the path correctly" do
104
79
  expect(formatted.path).to eq("#{url.path}special_bulk")
@@ -111,10 +86,10 @@ describe LogStash::Outputs::ElasticSearch::HttpClient::ManticoreAdapter do
111
86
 
112
87
  context "when uri contains credentials" do
113
88
  let(:url) { ::LogStash::Util::SafeURI.new("http://myuser:mypass@localhost:9200") }
114
- let(:formatted) { subject.format_url(url, path) }
89
+ let(:formatted) { java.net.URI.new(subject.format_url(url, path)) }
115
90
 
116
91
  it "should remove credentials after format" do
117
- expect(formatted.userinfo).to be_nil
92
+ expect(formatted.user_info).to be_nil
118
93
  end
119
94
  end
120
95
  end
@@ -21,9 +21,6 @@ describe LogStash::Outputs::ElasticSearch::HttpClient::Pool do
21
21
 
22
22
  allow(::Manticore::Client).to receive(:new).and_return(manticore_double)
23
23
 
24
- allow(subject).to receive(:connected_es_versions).with(any_args).and_return(["0.0.0"])
25
- allow(subject).to receive(:get_es_version).with(any_args).and_return("0.0.0")
26
-
27
24
  subject.start
28
25
  end
29
26
 
@@ -29,7 +29,7 @@ describe LogStash::Outputs::ElasticSearch::HttpClient do
29
29
  let(:http_hostname_port) { ::LogStash::Util::SafeURI.new("http://#{hostname_port}") }
30
30
  let(:https_hostname_port) { ::LogStash::Util::SafeURI.new("https://#{hostname_port}") }
31
31
  let(:http_hostname_port_path) { ::LogStash::Util::SafeURI.new("http://#{hostname_port}/path") }
32
-
32
+
33
33
  shared_examples("proper host handling") do
34
34
  it "should properly transform a host:port string to a URL" do
35
35
  expect(subject.host_to_url(hostname_port_uri).to_s).to eq(http_hostname_port.to_s + "/")
@@ -58,7 +58,7 @@ describe LogStash::Outputs::ElasticSearch::HttpClient do
58
58
  context "when SSL is false" do
59
59
  let(:ssl) { false }
60
60
  let(:base_options) { super.merge(:hosts => [https_hostname_port]) }
61
-
61
+
62
62
  it "should refuse to handle an https url" do
63
63
  expect {
64
64
  subject.host_to_url(https_hostname_port)
@@ -72,32 +72,32 @@ describe LogStash::Outputs::ElasticSearch::HttpClient do
72
72
  subject
73
73
  expect(subject.host_to_url(https_hostname_port).to_s).to eq(https_hostname_port.to_s + "/")
74
74
  end
75
- end
75
+ end
76
76
  end
77
77
 
78
78
  describe "path" do
79
79
  let(:url) { http_hostname_port_path }
80
80
  let(:base_options) { super.merge(:hosts => [url]) }
81
-
81
+
82
82
  it "should allow paths in a url" do
83
83
  expect(subject.host_to_url(url)).to eq(url)
84
84
  end
85
85
 
86
86
  context "with the path option set" do
87
87
  let(:base_options) { super.merge(:client_settings => {:path => "/otherpath"}) }
88
-
88
+
89
89
  it "should not allow paths in two places" do
90
90
  expect {
91
91
  subject.host_to_url(url)
92
92
  }.to raise_error(LogStash::ConfigurationError)
93
93
  end
94
94
  end
95
-
95
+
96
96
  context "with a path missing a leading /" do
97
97
  let(:url) { http_hostname_port }
98
98
  let(:base_options) { super.merge(:client_settings => {:path => "otherpath"}) }
99
-
100
-
99
+
100
+
101
101
  it "should automatically insert a / in front of path overlays" do
102
102
  expected = url.clone
103
103
  expected.path = url.path + "/otherpath"
@@ -132,7 +132,7 @@ describe LogStash::Outputs::ElasticSearch::HttpClient do
132
132
  }
133
133
 
134
134
  it "returns the hash response" do
135
- expect(subject.pool).to receive(:get).with(path, nil).and_return(get_response)
135
+ expect(subject.pool).to receive(:get).with(path, nil).and_return([nil, get_response])
136
136
  expect(subject.get(path)["body"]).to eq(body)
137
137
  end
138
138
  end
@@ -182,6 +182,8 @@ describe LogStash::Outputs::ElasticSearch::HttpClient do
182
182
 
183
183
  describe "#bulk" do
184
184
  subject { described_class.new(base_options) }
185
+
186
+ require "json"
185
187
  let(:message) { "hey" }
186
188
  let(:actions) { [
187
189
  ["index", {:_id=>nil, :_index=>"logstash"}, {"message"=> message}],
@@ -191,7 +193,7 @@ describe LogStash::Outputs::ElasticSearch::HttpClient do
191
193
  let(:target_bulk_bytes) { LogStash::Outputs::ElasticSearch::TARGET_BULK_BYTES }
192
194
  let(:message) { "a" * (target_bulk_bytes + 1) }
193
195
 
194
- it "sends the message as its own bulk payload" do
196
+ it "should be handled properly" do
195
197
  allow(subject).to receive(:join_bulk_responses)
196
198
  expect(subject).to receive(:bulk_send).once do |data|
197
199
  expect(data.size).to be > target_bulk_bytes
@@ -207,7 +209,6 @@ describe LogStash::Outputs::ElasticSearch::HttpClient do
207
209
  ["index", {:_id=>nil, :_index=>"logstash"}, {"message"=> message1}],
208
210
  ["index", {:_id=>nil, :_index=>"logstash"}, {"message"=> message2}],
209
211
  ]}
210
-
211
212
  it "executes one bulk_send operation" do
212
213
  allow(subject).to receive(:join_bulk_responses)
213
214
  expect(subject).to receive(:bulk_send).once
@@ -6,21 +6,32 @@ require "json"
6
6
  describe LogStash::Outputs::ElasticSearch::TemplateManager do
7
7
 
8
8
  describe ".get_es_major_version" do
9
+ let(:es_1x_version) { '{ "number" : "1.7.0", "build_hash" : "929b9739cae115e73c346cb5f9a6f24ba735a743", "build_timestamp" : "2015-07-16T14:31:07Z", "build_snapshot" : false, "lucene_version" : "4.10.4" }' }
10
+ let(:es_2x_version) { '{ "number" : "2.3.4", "build_hash" : "e455fd0c13dceca8dbbdbb1665d068ae55dabe3f", "build_timestamp" : "2016-06-30T11:24:31Z", "build_snapshot" : false, "lucene_version" : "5.5.0" }' }
11
+ let(:es_5x_version) { '{ "number" : "5.0.0-alpha4", "build_hash" : "b0da471", "build_date" : "2016-06-22T12:33:48.164Z", "build_snapshot" : false, "lucene_version" : "6.1.0" }' }
9
12
  let(:client) { double("client") }
10
-
11
- before(:each) do
12
- allow(client).to receive(:connected_es_versions).and_return(["5.3.0"])
13
+ context "elasticsearch 1.x" do
14
+ before(:each) do
15
+ allow(client).to receive(:get_version).and_return(JSON.parse(es_1x_version))
16
+ end
17
+ it "detects major version is 1" do
18
+ expect(described_class.get_es_major_version(client)).to eq("1")
19
+ end
13
20
  end
14
-
15
- it "picks the largest major version" do
16
- expect(described_class.get_es_major_version(client)).to eq(5)
21
+ context "elasticsearch 2.x" do
22
+ before(:each) do
23
+ allow(client).to receive(:get_version).and_return(JSON.parse(es_2x_version))
24
+ end
25
+ it "detects major version is 2" do
26
+ expect(described_class.get_es_major_version(client)).to eq("2")
27
+ end
17
28
  end
18
- context "if there are nodes with multiple major versions" do
29
+ context "elasticsearch 5.x" do
19
30
  before(:each) do
20
- allow(client).to receive(:connected_es_versions).and_return(["5.3.0", "6.0.0"])
31
+ allow(client).to receive(:get_version).and_return(JSON.parse(es_5x_version))
21
32
  end
22
- it "picks the largest major version" do
23
- expect(described_class.get_es_major_version(client)).to eq(6)
33
+ it "detects major version is 5" do
34
+ expect(described_class.get_es_major_version(client)).to eq("5")
24
35
  end
25
36
  end
26
37
  end
@@ -28,18 +39,19 @@ describe LogStash::Outputs::ElasticSearch::TemplateManager do
28
39
  describe ".default_template_path" do
29
40
  context "elasticsearch 1.x" do
30
41
  it "chooses the 2x template" do
31
- expect(described_class.default_template_path(1)).to match(/elasticsearch-template-es2x.json/)
42
+ expect(described_class.default_template_path("1")).to match(/elasticsearch-template-es2x.json/)
32
43
  end
33
44
  end
34
45
  context "elasticsearch 2.x" do
35
46
  it "chooses the 2x template" do
36
- expect(described_class.default_template_path(2)).to match(/elasticsearch-template-es2x.json/)
47
+ expect(described_class.default_template_path("2")).to match(/elasticsearch-template-es2x.json/)
37
48
  end
38
49
  end
39
50
  context "elasticsearch 5.x" do
40
51
  it "chooses the 5x template" do
41
- expect(described_class.default_template_path(5)).to match(/elasticsearch-template-es5x.json/)
52
+ expect(described_class.default_template_path("5")).to match(/elasticsearch-template-es5x.json/)
42
53
  end
43
54
  end
44
55
  end
56
+
45
57
  end