logstash-output-elasticsearch-test 11.16.0-x86_64-linux
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 +7 -0
- data/CHANGELOG.md +649 -0
- data/CONTRIBUTORS +34 -0
- data/Gemfile +16 -0
- data/LICENSE +202 -0
- data/NOTICE.TXT +5 -0
- data/README.md +106 -0
- data/docs/index.asciidoc +1369 -0
- data/lib/logstash/outputs/elasticsearch/data_stream_support.rb +282 -0
- data/lib/logstash/outputs/elasticsearch/default-ilm-policy.json +14 -0
- data/lib/logstash/outputs/elasticsearch/http_client/manticore_adapter.rb +155 -0
- data/lib/logstash/outputs/elasticsearch/http_client/pool.rb +534 -0
- data/lib/logstash/outputs/elasticsearch/http_client.rb +497 -0
- data/lib/logstash/outputs/elasticsearch/http_client_builder.rb +201 -0
- data/lib/logstash/outputs/elasticsearch/ilm.rb +92 -0
- data/lib/logstash/outputs/elasticsearch/license_checker.rb +52 -0
- data/lib/logstash/outputs/elasticsearch/template_manager.rb +131 -0
- data/lib/logstash/outputs/elasticsearch/templates/ecs-disabled/elasticsearch-6x.json +45 -0
- data/lib/logstash/outputs/elasticsearch/templates/ecs-disabled/elasticsearch-7x.json +44 -0
- data/lib/logstash/outputs/elasticsearch/templates/ecs-disabled/elasticsearch-8x.json +50 -0
- data/lib/logstash/outputs/elasticsearch.rb +699 -0
- data/lib/logstash/plugin_mixins/elasticsearch/api_configs.rb +237 -0
- data/lib/logstash/plugin_mixins/elasticsearch/common.rb +409 -0
- data/lib/logstash/plugin_mixins/elasticsearch/noop_license_checker.rb +9 -0
- data/logstash-output-elasticsearch.gemspec +40 -0
- data/spec/es_spec_helper.rb +225 -0
- data/spec/fixtures/_nodes/6x.json +81 -0
- data/spec/fixtures/_nodes/7x.json +92 -0
- data/spec/fixtures/htpasswd +2 -0
- data/spec/fixtures/license_check/active.json +16 -0
- data/spec/fixtures/license_check/inactive.json +5 -0
- data/spec/fixtures/nginx_reverse_proxy.conf +22 -0
- data/spec/fixtures/scripts/painless/scripted_update.painless +2 -0
- data/spec/fixtures/scripts/painless/scripted_update_nested.painless +1 -0
- data/spec/fixtures/scripts/painless/scripted_upsert.painless +1 -0
- data/spec/fixtures/template-with-policy-es6x.json +48 -0
- data/spec/fixtures/template-with-policy-es7x.json +45 -0
- data/spec/fixtures/template-with-policy-es8x.json +50 -0
- data/spec/fixtures/test_certs/ca.crt +29 -0
- data/spec/fixtures/test_certs/ca.der.sha256 +1 -0
- data/spec/fixtures/test_certs/ca.key +51 -0
- data/spec/fixtures/test_certs/renew.sh +13 -0
- data/spec/fixtures/test_certs/test.crt +30 -0
- data/spec/fixtures/test_certs/test.der.sha256 +1 -0
- data/spec/fixtures/test_certs/test.key +51 -0
- data/spec/fixtures/test_certs/test.p12 +0 -0
- data/spec/fixtures/test_certs/test_invalid.crt +36 -0
- data/spec/fixtures/test_certs/test_invalid.key +51 -0
- data/spec/fixtures/test_certs/test_invalid.p12 +0 -0
- data/spec/fixtures/test_certs/test_self_signed.crt +32 -0
- data/spec/fixtures/test_certs/test_self_signed.key +54 -0
- data/spec/fixtures/test_certs/test_self_signed.p12 +0 -0
- data/spec/integration/outputs/compressed_indexing_spec.rb +70 -0
- data/spec/integration/outputs/create_spec.rb +67 -0
- data/spec/integration/outputs/data_stream_spec.rb +68 -0
- data/spec/integration/outputs/delete_spec.rb +63 -0
- data/spec/integration/outputs/ilm_spec.rb +534 -0
- data/spec/integration/outputs/index_spec.rb +421 -0
- data/spec/integration/outputs/index_version_spec.rb +98 -0
- data/spec/integration/outputs/ingest_pipeline_spec.rb +75 -0
- data/spec/integration/outputs/metrics_spec.rb +66 -0
- data/spec/integration/outputs/no_es_on_startup_spec.rb +78 -0
- data/spec/integration/outputs/painless_update_spec.rb +99 -0
- data/spec/integration/outputs/parent_spec.rb +94 -0
- data/spec/integration/outputs/retry_spec.rb +182 -0
- data/spec/integration/outputs/routing_spec.rb +61 -0
- data/spec/integration/outputs/sniffer_spec.rb +94 -0
- data/spec/integration/outputs/templates_spec.rb +133 -0
- data/spec/integration/outputs/unsupported_actions_spec.rb +75 -0
- data/spec/integration/outputs/update_spec.rb +114 -0
- data/spec/spec_helper.rb +10 -0
- data/spec/support/elasticsearch/api/actions/delete_ilm_policy.rb +19 -0
- data/spec/support/elasticsearch/api/actions/get_alias.rb +18 -0
- data/spec/support/elasticsearch/api/actions/get_ilm_policy.rb +18 -0
- data/spec/support/elasticsearch/api/actions/put_alias.rb +24 -0
- data/spec/support/elasticsearch/api/actions/put_ilm_policy.rb +25 -0
- data/spec/unit/http_client_builder_spec.rb +185 -0
- data/spec/unit/outputs/elasticsearch/data_stream_support_spec.rb +612 -0
- data/spec/unit/outputs/elasticsearch/http_client/manticore_adapter_spec.rb +151 -0
- data/spec/unit/outputs/elasticsearch/http_client/pool_spec.rb +501 -0
- data/spec/unit/outputs/elasticsearch/http_client_spec.rb +339 -0
- data/spec/unit/outputs/elasticsearch/template_manager_spec.rb +189 -0
- data/spec/unit/outputs/elasticsearch_proxy_spec.rb +103 -0
- data/spec/unit/outputs/elasticsearch_spec.rb +1573 -0
- data/spec/unit/outputs/elasticsearch_ssl_spec.rb +197 -0
- data/spec/unit/outputs/error_whitelist_spec.rb +56 -0
- data/spec/unit/outputs/license_check_spec.rb +57 -0
- metadata +423 -0
@@ -0,0 +1,339 @@
|
|
1
|
+
require_relative "../../../../spec/spec_helper"
|
2
|
+
require "logstash/outputs/elasticsearch/http_client"
|
3
|
+
require "cabin"
|
4
|
+
require "webrick"
|
5
|
+
require "java"
|
6
|
+
|
7
|
+
describe LogStash::Outputs::ElasticSearch::HttpClient do
|
8
|
+
let(:ssl) { nil }
|
9
|
+
let(:base_options) do
|
10
|
+
opts = {
|
11
|
+
:hosts => [::LogStash::Util::SafeURI.new("127.0.0.1")],
|
12
|
+
:logger => Cabin::Channel.get,
|
13
|
+
:metric => ::LogStash::Instrument::NullMetric.new(:dummy).namespace(:alsodummy)
|
14
|
+
}
|
15
|
+
|
16
|
+
if !ssl.nil? # Shortcut to set this
|
17
|
+
opts[:client_settings] = {:ssl => {:enabled => ssl}}
|
18
|
+
end
|
19
|
+
|
20
|
+
opts
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "Host/URL Parsing" do
|
24
|
+
subject { described_class.new(base_options) }
|
25
|
+
|
26
|
+
let(:true_hostname) { "my-dash.hostname" }
|
27
|
+
let(:ipv6_hostname) { "[::1]" }
|
28
|
+
let(:ipv4_hostname) { "127.0.0.1" }
|
29
|
+
let(:port) { 9202 }
|
30
|
+
let(:hostname_port) { "#{hostname}:#{port}" }
|
31
|
+
let(:hostname_port_uri) { ::LogStash::Util::SafeURI.new("//#{hostname_port}") }
|
32
|
+
let(:http_hostname_port) { ::LogStash::Util::SafeURI.new("http://#{hostname_port}") }
|
33
|
+
let(:https_hostname_port) { ::LogStash::Util::SafeURI.new("https://#{hostname_port}") }
|
34
|
+
let(:http_hostname_port_path) { ::LogStash::Util::SafeURI.new("http://#{hostname_port}/path") }
|
35
|
+
|
36
|
+
shared_examples("proper host handling") do
|
37
|
+
it "should properly transform a host:port string to a URL" do
|
38
|
+
expect(subject.host_to_url(hostname_port_uri).to_s).to eq(http_hostname_port.to_s + "/")
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should not raise an error with a / for a path" do
|
42
|
+
expect(subject.host_to_url(::LogStash::Util::SafeURI.new("#{http_hostname_port}/"))).to eq(LogStash::Util::SafeURI.new("#{http_hostname_port}/"))
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should parse full URLs correctly" do
|
46
|
+
expect(subject.host_to_url(http_hostname_port).to_s).to eq(http_hostname_port.to_s + "/")
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "ssl" do
|
50
|
+
context "when SSL is true" do
|
51
|
+
let(:ssl) { true }
|
52
|
+
let(:base_options) { super().merge(:hosts => [http_hostname_port]) }
|
53
|
+
|
54
|
+
it "should refuse to handle an http url" do
|
55
|
+
expect {
|
56
|
+
subject.host_to_url(http_hostname_port)
|
57
|
+
}.to raise_error(LogStash::ConfigurationError)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "when SSL is false" do
|
62
|
+
let(:ssl) { false }
|
63
|
+
let(:base_options) { super().merge(:hosts => [https_hostname_port]) }
|
64
|
+
|
65
|
+
it "should refuse to handle an https url" do
|
66
|
+
expect {
|
67
|
+
subject.host_to_url(https_hostname_port)
|
68
|
+
}.to raise_error(LogStash::ConfigurationError)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
describe "ssl is nil" do
|
73
|
+
let(:base_options) { super().merge(:hosts => [https_hostname_port]) }
|
74
|
+
it "should handle an ssl url correctly when SSL is nil" do
|
75
|
+
subject
|
76
|
+
expect(subject.host_to_url(https_hostname_port).to_s).to eq(https_hostname_port.to_s + "/")
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe "path" do
|
82
|
+
let(:url) { http_hostname_port_path }
|
83
|
+
let(:base_options) { super().merge(:hosts => [url]) }
|
84
|
+
|
85
|
+
it "should allow paths in a url" do
|
86
|
+
expect(subject.host_to_url(url)).to eq(url)
|
87
|
+
end
|
88
|
+
|
89
|
+
context "with the path option set" do
|
90
|
+
let(:base_options) { super().merge(:client_settings => {:path => "/otherpath"}) }
|
91
|
+
|
92
|
+
it "should not allow paths in two places" do
|
93
|
+
expect {
|
94
|
+
subject.host_to_url(url)
|
95
|
+
}.to raise_error(LogStash::ConfigurationError)
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
context "with a path missing a leading /" do
|
100
|
+
let(:url) { http_hostname_port }
|
101
|
+
let(:base_options) { super().merge(:client_settings => {:path => "otherpath"}) }
|
102
|
+
|
103
|
+
|
104
|
+
it "should automatically insert a / in front of path overlays" do
|
105
|
+
expected = url.clone
|
106
|
+
expected.path = url.path + "/otherpath"
|
107
|
+
expect(subject.host_to_url(url)).to eq(expected)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
describe "an regular hostname" do
|
114
|
+
let(:hostname) { true_hostname }
|
115
|
+
include_examples("proper host handling")
|
116
|
+
end
|
117
|
+
|
118
|
+
describe "an ipv4 host" do
|
119
|
+
let(:hostname) { ipv4_hostname }
|
120
|
+
include_examples("proper host handling")
|
121
|
+
end
|
122
|
+
|
123
|
+
describe "an ipv6 host" do
|
124
|
+
let(:hostname) { ipv6_hostname }
|
125
|
+
include_examples("proper host handling")
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
describe "get" do
|
130
|
+
subject { described_class.new(base_options) }
|
131
|
+
let(:body) { "foobar" }
|
132
|
+
let(:path) { "/hello-id" }
|
133
|
+
let(:get_response) {
|
134
|
+
double("response", :body => LogStash::Json::dump( { "body" => body }))
|
135
|
+
}
|
136
|
+
|
137
|
+
it "returns the hash response" do
|
138
|
+
expect(subject.pool).to receive(:get).with(path, nil).and_return(get_response)
|
139
|
+
expect(subject.get(path)["body"]).to eq(body)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
describe "join_bulk_responses" do
|
144
|
+
subject { described_class.new(base_options) }
|
145
|
+
|
146
|
+
context "when items key is available" do
|
147
|
+
require "json"
|
148
|
+
let(:bulk_response) {
|
149
|
+
LogStash::Json.load ('[{
|
150
|
+
"items": [{
|
151
|
+
"delete": {
|
152
|
+
"_index": "website",
|
153
|
+
"_type": "blog",
|
154
|
+
"_id": "123",
|
155
|
+
"_version": 2,
|
156
|
+
"status": 200,
|
157
|
+
"found": true
|
158
|
+
}
|
159
|
+
}],
|
160
|
+
"errors": false
|
161
|
+
}]')
|
162
|
+
}
|
163
|
+
it "should be handled properly" do
|
164
|
+
s = subject.send(:join_bulk_responses, bulk_response)
|
165
|
+
expect(s["errors"]).to be false
|
166
|
+
expect(s["items"].size).to be 1
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
context "when items key is not available" do
|
171
|
+
require "json"
|
172
|
+
let(:bulk_response) {
|
173
|
+
JSON.parse ('[{
|
174
|
+
"took": 4,
|
175
|
+
"errors": false
|
176
|
+
}]')
|
177
|
+
}
|
178
|
+
it "should be handled properly" do
|
179
|
+
s = subject.send(:join_bulk_responses, bulk_response)
|
180
|
+
expect(s["errors"]).to be false
|
181
|
+
expect(s["items"].size).to be 0
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
describe "#bulk" do
|
187
|
+
subject(:http_client) { described_class.new(base_options) }
|
188
|
+
|
189
|
+
require "json"
|
190
|
+
let(:message) { "hey" }
|
191
|
+
let(:actions) { [
|
192
|
+
["index", {:_id=>nil, :_index=>"logstash"}, {"message"=> message}],
|
193
|
+
]}
|
194
|
+
|
195
|
+
[true,false].each do |http_compression_enabled|
|
196
|
+
context "with `http_compression => #{http_compression_enabled}`" do
|
197
|
+
|
198
|
+
let(:base_options) { super().merge(:client_settings => {:http_compression => http_compression_enabled}) }
|
199
|
+
|
200
|
+
before(:each) do
|
201
|
+
if http_compression_enabled
|
202
|
+
expect(http_client).to receive(:gzip_writer).at_least(:once).and_call_original
|
203
|
+
else
|
204
|
+
expect(http_client).to_not receive(:gzip_writer)
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
context "if a message is over TARGET_BULK_BYTES" do
|
209
|
+
let(:target_bulk_bytes) { LogStash::Outputs::ElasticSearch::TARGET_BULK_BYTES }
|
210
|
+
let(:message) { "a" * (target_bulk_bytes + 1) }
|
211
|
+
|
212
|
+
it "should be handled properly" do
|
213
|
+
allow(subject).to receive(:join_bulk_responses)
|
214
|
+
expect(subject).to receive(:bulk_send).once do |data|
|
215
|
+
if !http_compression_enabled
|
216
|
+
expect(data.size).to be > target_bulk_bytes
|
217
|
+
else
|
218
|
+
expect(Zlib::gunzip(data.string).size).to be > target_bulk_bytes
|
219
|
+
end
|
220
|
+
end
|
221
|
+
s = subject.send(:bulk, actions)
|
222
|
+
end
|
223
|
+
end
|
224
|
+
|
225
|
+
context "with two messages" do
|
226
|
+
let(:message1) { "hey" }
|
227
|
+
let(:message2) { "you" }
|
228
|
+
let(:actions) { [
|
229
|
+
["index", {:_id=>nil, :_index=>"logstash"}, {"message"=> message1}],
|
230
|
+
["index", {:_id=>nil, :_index=>"logstash"}, {"message"=> message2}],
|
231
|
+
]}
|
232
|
+
it "executes one bulk_send operation" do
|
233
|
+
allow(subject).to receive(:join_bulk_responses)
|
234
|
+
expect(subject).to receive(:bulk_send).once
|
235
|
+
s = subject.send(:bulk, actions)
|
236
|
+
end
|
237
|
+
|
238
|
+
context "if one exceeds TARGET_BULK_BYTES" do
|
239
|
+
let(:target_bulk_bytes) { LogStash::Outputs::ElasticSearch::TARGET_BULK_BYTES }
|
240
|
+
let(:message1) { "a" * (target_bulk_bytes + 1) }
|
241
|
+
it "executes two bulk_send operations" do
|
242
|
+
allow(subject).to receive(:join_bulk_responses)
|
243
|
+
expect(subject).to receive(:bulk_send).twice
|
244
|
+
s = subject.send(:bulk, actions)
|
245
|
+
end
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
describe "sniffing" do
|
254
|
+
let(:client) { LogStash::Outputs::ElasticSearch::HttpClient.new(base_options.merge(client_opts)) }
|
255
|
+
|
256
|
+
context "with sniffing enabled" do
|
257
|
+
let(:client_opts) { {:sniffing => true, :sniffing_delay => 1 } }
|
258
|
+
|
259
|
+
it "should start the sniffer" do
|
260
|
+
expect(client.pool.sniffing).to be_truthy
|
261
|
+
end
|
262
|
+
end
|
263
|
+
|
264
|
+
context "with sniffing disabled" do
|
265
|
+
let(:client_opts) { {:sniffing => false} }
|
266
|
+
|
267
|
+
it "should not start the sniffer" do
|
268
|
+
expect(client.pool.sniffing).to be_falsey
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
class StoppableServer
|
274
|
+
|
275
|
+
attr_reader :port
|
276
|
+
|
277
|
+
def initialize()
|
278
|
+
queue = Queue.new
|
279
|
+
@first_req_waiter = java.util.concurrent.CountDownLatch.new(1)
|
280
|
+
@first_request = nil
|
281
|
+
|
282
|
+
@t = java.lang.Thread.new(
|
283
|
+
proc do
|
284
|
+
begin
|
285
|
+
@server = WEBrick::HTTPServer.new :Port => 0, :DocumentRoot => ".",
|
286
|
+
:Logger => Cabin::Channel.get, # silence WEBrick logging
|
287
|
+
:StartCallback => Proc.new {
|
288
|
+
queue.push("started")
|
289
|
+
}
|
290
|
+
@port = @server.config[:Port]
|
291
|
+
@server.mount_proc '/headers_check' do |req, res|
|
292
|
+
res.body = 'Hello, world from WEBrick mocking server!'
|
293
|
+
@first_request = req
|
294
|
+
@first_req_waiter.countDown()
|
295
|
+
end
|
296
|
+
|
297
|
+
@server.start
|
298
|
+
rescue => e
|
299
|
+
puts "Error in webserver thread #{e}"
|
300
|
+
# ignore
|
301
|
+
end
|
302
|
+
end
|
303
|
+
)
|
304
|
+
@t.daemon = true
|
305
|
+
@t.start
|
306
|
+
queue.pop # blocks until the server is up
|
307
|
+
end
|
308
|
+
|
309
|
+
def stop
|
310
|
+
@server.shutdown
|
311
|
+
end
|
312
|
+
|
313
|
+
def wait_receive_request
|
314
|
+
@first_req_waiter.await(2, java.util.concurrent.TimeUnit::SECONDS)
|
315
|
+
@first_request
|
316
|
+
end
|
317
|
+
end
|
318
|
+
|
319
|
+
describe "#build_adapter" do
|
320
|
+
let(:client) { LogStash::Outputs::ElasticSearch::HttpClient.new(base_options) }
|
321
|
+
let!(:webserver) { StoppableServer.new } # webserver must be started before the call, so no lazy "let"
|
322
|
+
|
323
|
+
after :each do
|
324
|
+
webserver.stop
|
325
|
+
end
|
326
|
+
|
327
|
+
context "the 'user-agent' header" do
|
328
|
+
it "contains the Logstash environment details" do
|
329
|
+
adapter = client.build_adapter(client.options)
|
330
|
+
adapter.perform_request(::LogStash::Util::SafeURI.new("http://localhost:#{webserver.port}"), :get, "/headers_check")
|
331
|
+
|
332
|
+
request = webserver.wait_receive_request
|
333
|
+
|
334
|
+
transmitted_user_agent = request.header['user-agent'][0]
|
335
|
+
expect(transmitted_user_agent).to match(/Logstash\/\d*\.\d*\.\d* \(OS=.*; JVM=.*\) logstash-output-elasticsearch\/\d*\.\d*\.\d*/)
|
336
|
+
end
|
337
|
+
end
|
338
|
+
end
|
339
|
+
end
|
@@ -0,0 +1,189 @@
|
|
1
|
+
require_relative "../../../../spec/spec_helper"
|
2
|
+
require "logstash/outputs/elasticsearch/template_manager"
|
3
|
+
|
4
|
+
describe LogStash::Outputs::ElasticSearch::TemplateManager do
|
5
|
+
|
6
|
+
describe ".default_template_path" do
|
7
|
+
context "elasticsearch 6.x" do
|
8
|
+
it "chooses the 6x template" do
|
9
|
+
expect(described_class.default_template_path(6)).to end_with("/templates/ecs-disabled/elasticsearch-6x.json")
|
10
|
+
end
|
11
|
+
end
|
12
|
+
context "elasticsearch 7.x" do
|
13
|
+
it "chooses the 7x template" do
|
14
|
+
expect(described_class.default_template_path(7)).to end_with("/templates/ecs-disabled/elasticsearch-7x.json")
|
15
|
+
end
|
16
|
+
end
|
17
|
+
context "elasticsearch 8.x" do
|
18
|
+
it "chooses the 8x template" do
|
19
|
+
expect(described_class.default_template_path(8)).to end_with("/templates/ecs-disabled/elasticsearch-8x.json")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'when ECS v1 is requested' do
|
25
|
+
it 'resolves' do
|
26
|
+
expect(described_class.default_template_path(7, :v1)).to end_with("/templates/ecs-v1/elasticsearch-7x.json")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'when ECS v8 is requested' do
|
31
|
+
it 'resolves' do
|
32
|
+
expect(described_class.default_template_path(7, :v8)).to end_with("/templates/ecs-v8/elasticsearch-7x.json")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context "index template with ilm settings" do
|
37
|
+
let(:plugin_settings) { {"manage_template" => true, "template_overwrite" => true} }
|
38
|
+
let(:plugin) { LogStash::Outputs::ElasticSearch.new(plugin_settings) }
|
39
|
+
|
40
|
+
describe "with custom template" do
|
41
|
+
|
42
|
+
describe "in version 8+" do
|
43
|
+
let(:file_path) { described_class.default_template_path(8) }
|
44
|
+
let(:template) { described_class.read_template_file(file_path)}
|
45
|
+
|
46
|
+
it "should update settings" do
|
47
|
+
expect(plugin).to receive(:maximum_seen_major_version).at_least(:once).and_return(8)
|
48
|
+
described_class.add_ilm_settings_to_template(plugin, template)
|
49
|
+
expect(template['template']['settings']['index.lifecycle.name']).not_to eq(nil)
|
50
|
+
expect(template['template']['settings']['index.lifecycle.rollover_alias']).not_to eq(nil)
|
51
|
+
expect(template.include?('settings')).to be_falsey
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
describe "in version < 8" do
|
56
|
+
let(:file_path) { described_class.default_template_path(7) }
|
57
|
+
let(:template) { described_class.read_template_file(file_path)}
|
58
|
+
|
59
|
+
it "should update settings" do
|
60
|
+
expect(plugin).to receive(:maximum_seen_major_version).at_least(:once).and_return(7)
|
61
|
+
described_class.add_ilm_settings_to_template(plugin, template)
|
62
|
+
expect(template['settings']['index.lifecycle.name']).not_to eq(nil)
|
63
|
+
expect(template['settings']['index.lifecycle.rollover_alias']).not_to eq(nil)
|
64
|
+
expect(template.include?('template')).to be_falsey
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context "resolve template setting" do
|
70
|
+
let(:plugin_settings) { super().merge({"template_api" => template_api}) }
|
71
|
+
|
72
|
+
describe "with composable template API" do
|
73
|
+
let(:template_api) { "composable" }
|
74
|
+
|
75
|
+
it 'resolves composable index template API compatible setting' do
|
76
|
+
expect(plugin).to receive(:serverless?).and_return(false)
|
77
|
+
expect(plugin).to receive(:maximum_seen_major_version).at_least(:once).and_return(8) # required to log
|
78
|
+
template = {}
|
79
|
+
described_class.resolve_template_settings(plugin, template)
|
80
|
+
expect(template["template"]["settings"]).not_to eq(nil)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "with legacy template API" do
|
85
|
+
let(:template_api) { "legacy" }
|
86
|
+
|
87
|
+
it 'resolves legacy index template API compatible setting' do
|
88
|
+
expect(plugin).to receive(:serverless?).and_return(false)
|
89
|
+
expect(plugin).to receive(:maximum_seen_major_version).at_least(:once).and_return(7) # required to log
|
90
|
+
template = {}
|
91
|
+
described_class.resolve_template_settings(plugin, template)
|
92
|
+
expect(template["settings"]).not_to eq(nil)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
describe "with `template_api => 'auto'`" do
|
97
|
+
let(:template_api) { "auto" }
|
98
|
+
|
99
|
+
describe "with ES < 8 versions" do
|
100
|
+
|
101
|
+
it 'resolves legacy index template API compatible setting' do
|
102
|
+
expect(plugin).to receive(:serverless?).and_return(false)
|
103
|
+
expect(plugin).to receive(:maximum_seen_major_version).at_least(:once).and_return(7)
|
104
|
+
template = {}
|
105
|
+
described_class.resolve_template_settings(plugin, template)
|
106
|
+
expect(template["settings"]).not_to eq(nil)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
110
|
+
describe "with ES >= 8 versions" do
|
111
|
+
it 'resolves composable index template API compatible setting' do
|
112
|
+
expect(plugin).to receive(:serverless?).and_return(false)
|
113
|
+
expect(plugin).to receive(:maximum_seen_major_version).at_least(:once).and_return(8)
|
114
|
+
template = {}
|
115
|
+
described_class.resolve_template_settings(plugin, template)
|
116
|
+
expect(template["template"]["settings"]).not_to eq(nil)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
describe "template endpoint" do
|
124
|
+
describe "template_api => 'auto'" do
|
125
|
+
let(:plugin_settings) { {"manage_template" => true, "template_api" => 'auto'} }
|
126
|
+
let(:plugin) { LogStash::Outputs::ElasticSearch.new(plugin_settings) }
|
127
|
+
|
128
|
+
describe "in version 8+" do
|
129
|
+
it "should use index template API" do
|
130
|
+
expect(plugin).to receive(:serverless?).and_return(false)
|
131
|
+
expect(plugin).to receive(:maximum_seen_major_version).at_least(:once).and_return(8)
|
132
|
+
endpoint = described_class.template_endpoint(plugin)
|
133
|
+
expect(endpoint).to be_equal(LogStash::Outputs::ElasticSearch::TemplateManager::INDEX_TEMPLATE_ENDPOINT)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe "in version < 8" do
|
138
|
+
it "should use legacy template API" do
|
139
|
+
expect(plugin).to receive(:serverless?).and_return(false)
|
140
|
+
expect(plugin).to receive(:maximum_seen_major_version).at_least(:once).and_return(7)
|
141
|
+
endpoint = described_class.template_endpoint(plugin)
|
142
|
+
expect(endpoint).to be_equal(LogStash::Outputs::ElasticSearch::TemplateManager::LEGACY_TEMPLATE_ENDPOINT)
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
describe "template_api => 'legacy'" do
|
148
|
+
let(:plugin_settings) { {"manage_template" => true, "template_api" => 'legacy'} }
|
149
|
+
let(:plugin) { LogStash::Outputs::ElasticSearch.new(plugin_settings) }
|
150
|
+
|
151
|
+
describe "in version 8+" do
|
152
|
+
it "should use legacy template API" do
|
153
|
+
expect(plugin).to receive(:serverless?).and_return(false)
|
154
|
+
expect(plugin).to receive(:maximum_seen_major_version).never
|
155
|
+
endpoint = described_class.template_endpoint(plugin)
|
156
|
+
expect(endpoint).to be_equal(LogStash::Outputs::ElasticSearch::TemplateManager::LEGACY_TEMPLATE_ENDPOINT)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
describe "template_api => 'composable'" do
|
162
|
+
let(:plugin_settings) { {"manage_template" => true, "template_api" => 'composable'} }
|
163
|
+
let(:plugin) { LogStash::Outputs::ElasticSearch.new(plugin_settings) }
|
164
|
+
|
165
|
+
describe "in version 8+" do
|
166
|
+
it "should use legacy template API" do
|
167
|
+
expect(plugin).to receive(:serverless?).and_return(false)
|
168
|
+
expect(plugin).to receive(:maximum_seen_major_version).never
|
169
|
+
endpoint = described_class.template_endpoint(plugin)
|
170
|
+
expect(endpoint).to be_equal(LogStash::Outputs::ElasticSearch::TemplateManager::INDEX_TEMPLATE_ENDPOINT)
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
174
|
+
|
175
|
+
describe "in serverless" do
|
176
|
+
[:auto, :composable, :legacy].each do |api|
|
177
|
+
let(:plugin_settings) { {"manage_template" => true, "template_api" => api.to_s} }
|
178
|
+
let(:plugin) { LogStash::Outputs::ElasticSearch.new(plugin_settings) }
|
179
|
+
|
180
|
+
it "use index template API when template_api set to #{api}" do
|
181
|
+
expect(plugin).to receive(:serverless?).and_return(true)
|
182
|
+
endpoint = described_class.template_endpoint(plugin)
|
183
|
+
expect(endpoint).to be_equal(LogStash::Outputs::ElasticSearch::TemplateManager::INDEX_TEMPLATE_ENDPOINT)
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require_relative "../../../spec/spec_helper"
|
2
|
+
require 'stud/temporary'
|
3
|
+
require 'manticore/client'
|
4
|
+
|
5
|
+
describe "Proxy option" do
|
6
|
+
let(:settings) { { "hosts" => "node01" } }
|
7
|
+
subject {
|
8
|
+
LogStash::Outputs::ElasticSearch.new(settings)
|
9
|
+
}
|
10
|
+
|
11
|
+
before do
|
12
|
+
allow(::Manticore::Client).to receive(:new).with(any_args).and_call_original
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "valid configs" do
|
16
|
+
before do
|
17
|
+
subject.register
|
18
|
+
end
|
19
|
+
|
20
|
+
after do
|
21
|
+
subject.close
|
22
|
+
end
|
23
|
+
|
24
|
+
context "when specified as a URI" do
|
25
|
+
shared_examples("hash conversion") do |hash|
|
26
|
+
let(:settings) { super().merge("proxy" => proxy)}
|
27
|
+
|
28
|
+
it "should set the proxy to the correct hash value" do
|
29
|
+
expect(::Manticore::Client).to have_received(:new) do |options|
|
30
|
+
expect(options[:proxy]).to eq(hash)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "simple proxy" do
|
36
|
+
let(:proxy) { LogStash::Util::SafeURI.new("http://127.0.0.1:1234") }
|
37
|
+
|
38
|
+
include_examples("hash conversion",
|
39
|
+
{
|
40
|
+
:host => "127.0.0.1",
|
41
|
+
:scheme => "http",
|
42
|
+
:port => 1234
|
43
|
+
}
|
44
|
+
)
|
45
|
+
end
|
46
|
+
|
47
|
+
|
48
|
+
describe "a secure authed proxy" do
|
49
|
+
let(:proxy) { LogStash::Util::SafeURI.new("https://myuser:mypass@127.0.0.1:1234") }
|
50
|
+
|
51
|
+
include_examples("hash conversion",
|
52
|
+
{
|
53
|
+
:host => "127.0.0.1",
|
54
|
+
:scheme => "https",
|
55
|
+
:user => "myuser",
|
56
|
+
:password => "mypass",
|
57
|
+
:port => 1234
|
58
|
+
}
|
59
|
+
)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
context "when not specified" do
|
64
|
+
it "should not send the proxy option to manticore" do
|
65
|
+
expect(::Manticore::Client).to have_received(:new) do |options|
|
66
|
+
expect(options).not_to include(:proxy)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context "when specified as ''" do
|
73
|
+
let(:settings) { super().merge("proxy" => "${A_MISSING_ENV_VARIABLE:}")}
|
74
|
+
|
75
|
+
it "should not send the proxy option to manticore" do
|
76
|
+
expect { subject.register }.not_to raise_error
|
77
|
+
|
78
|
+
expect(::Manticore::Client).to have_received(:new) do |options|
|
79
|
+
expect(options).not_to include(:proxy)
|
80
|
+
end
|
81
|
+
|
82
|
+
subject.close
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
context "when specified as invalid uri" do
|
87
|
+
let(:settings) { super().merge("proxy" => ":")}
|
88
|
+
|
89
|
+
it "should fail" do
|
90
|
+
# SafeURI isn't doing the proper exception wrapping for us, we can not simply :
|
91
|
+
# expect { subject.register }.to raise_error(ArgumentError, /URI is not valid/i)
|
92
|
+
begin
|
93
|
+
subject.register
|
94
|
+
rescue ArgumentError => e
|
95
|
+
expect(e.message).to match /URI is not valid/i
|
96
|
+
rescue java.net.URISyntaxException => e
|
97
|
+
expect(e.message).to match /scheme name/i
|
98
|
+
else
|
99
|
+
fail 'exception not raised'
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|