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

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.
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