fluent-plugin-elasticsearch-dext 5.0.2
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/.coveralls.yml +2 -0
- data/.editorconfig +9 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +37 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +24 -0
- data/.github/workflows/issue-auto-closer.yml +12 -0
- data/.github/workflows/linux.yml +26 -0
- data/.github/workflows/macos.yml +26 -0
- data/.github/workflows/windows.yml +26 -0
- data/.gitignore +18 -0
- data/.travis.yml +40 -0
- data/CONTRIBUTING.md +24 -0
- data/Gemfile +11 -0
- data/History.md +553 -0
- data/ISSUE_TEMPLATE.md +30 -0
- data/LICENSE.txt +201 -0
- data/PULL_REQUEST_TEMPLATE.md +10 -0
- data/README.ElasticsearchGenID.md +116 -0
- data/README.ElasticsearchInput.md +293 -0
- data/README.Troubleshooting.md +601 -0
- data/README.md +1467 -0
- data/Rakefile +11 -0
- data/appveyor.yml +20 -0
- data/fluent-plugin-elasticsearch.gemspec +35 -0
- data/gemfiles/Gemfile.elasticsearch.v6 +12 -0
- data/lib/fluent/log-ext.rb +38 -0
- data/lib/fluent/plugin/default-ilm-policy.json +14 -0
- data/lib/fluent/plugin/elasticsearch_constants.rb +13 -0
- data/lib/fluent/plugin/elasticsearch_error.rb +5 -0
- data/lib/fluent/plugin/elasticsearch_error_handler.rb +129 -0
- data/lib/fluent/plugin/elasticsearch_fallback_selector.rb +9 -0
- data/lib/fluent/plugin/elasticsearch_index_lifecycle_management.rb +67 -0
- data/lib/fluent/plugin/elasticsearch_index_template.rb +211 -0
- data/lib/fluent/plugin/elasticsearch_simple_sniffer.rb +10 -0
- data/lib/fluent/plugin/elasticsearch_tls.rb +70 -0
- data/lib/fluent/plugin/filter_elasticsearch_genid.rb +77 -0
- data/lib/fluent/plugin/in_elasticsearch.rb +325 -0
- data/lib/fluent/plugin/oj_serializer.rb +22 -0
- data/lib/fluent/plugin/out_elasticsearch.rb +1108 -0
- data/lib/fluent/plugin/out_elasticsearch_data_stream.rb +218 -0
- data/lib/fluent/plugin/out_elasticsearch_dynamic.rb +282 -0
- data/test/helper.rb +24 -0
- data/test/plugin/test_alias_template.json +9 -0
- data/test/plugin/test_elasticsearch_error_handler.rb +646 -0
- data/test/plugin/test_elasticsearch_fallback_selector.rb +74 -0
- data/test/plugin/test_elasticsearch_index_lifecycle_management.rb +66 -0
- data/test/plugin/test_elasticsearch_tls.rb +145 -0
- data/test/plugin/test_filter_elasticsearch_genid.rb +215 -0
- data/test/plugin/test_in_elasticsearch.rb +459 -0
- data/test/plugin/test_index_alias_template.json +11 -0
- data/test/plugin/test_index_template.json +25 -0
- data/test/plugin/test_oj_serializer.rb +19 -0
- data/test/plugin/test_out_elasticsearch.rb +5688 -0
- data/test/plugin/test_out_elasticsearch_data_stream.rb +337 -0
- data/test/plugin/test_out_elasticsearch_dynamic.rb +1134 -0
- data/test/plugin/test_template.json +23 -0
- data/test/test_log-ext.rb +35 -0
- metadata +236 -0
@@ -0,0 +1,337 @@
|
|
1
|
+
require_relative '../helper'
|
2
|
+
require 'date'
|
3
|
+
require 'fluent/test/helpers'
|
4
|
+
require 'fluent/test/driver/output'
|
5
|
+
require 'flexmock/test_unit'
|
6
|
+
require 'fluent/plugin/out_elasticsearch_data_stream'
|
7
|
+
|
8
|
+
class ElasticsearchOutputDataStreamTest < Test::Unit::TestCase
|
9
|
+
include FlexMock::TestCase
|
10
|
+
include Fluent::Test::Helpers
|
11
|
+
|
12
|
+
attr_accessor :bulk_records
|
13
|
+
|
14
|
+
REQUIRED_ELASTIC_MESSAGE = "Elasticsearch 7.9.0 or later is needed."
|
15
|
+
ELASTIC_DATA_STREAM_TYPE = "elasticsearch_data_stream"
|
16
|
+
|
17
|
+
def setup
|
18
|
+
Fluent::Test.setup
|
19
|
+
@driver = nil
|
20
|
+
log = Fluent::Engine.log
|
21
|
+
log.out.logs.slice!(0, log.out.logs.length)
|
22
|
+
@bulk_records = 0
|
23
|
+
end
|
24
|
+
|
25
|
+
def driver(conf='', es_version=5, client_version="\"5.0\"")
|
26
|
+
# For request stub to detect compatibility.
|
27
|
+
@es_version ||= es_version
|
28
|
+
@client_version ||= client_version
|
29
|
+
Fluent::Plugin::ElasticsearchOutputDataStream.module_eval(<<-CODE)
|
30
|
+
def detect_es_major_version
|
31
|
+
#{@es_version}
|
32
|
+
end
|
33
|
+
CODE
|
34
|
+
@driver ||= Fluent::Test::Driver::Output.new(Fluent::Plugin::ElasticsearchOutputDataStream) {
|
35
|
+
# v0.12's test driver assume format definition. This simulates ObjectBufferedOutput format
|
36
|
+
if !defined?(Fluent::Plugin::Output)
|
37
|
+
def format(tag, time, record)
|
38
|
+
[time, record].to_msgpack
|
39
|
+
end
|
40
|
+
end
|
41
|
+
}.configure(conf)
|
42
|
+
end
|
43
|
+
|
44
|
+
def sample_data_stream
|
45
|
+
{
|
46
|
+
'data_streams': [
|
47
|
+
{
|
48
|
+
'name' => 'my-data-stream',
|
49
|
+
'timestamp_field' => {
|
50
|
+
'name' => '@timestamp'
|
51
|
+
}
|
52
|
+
}
|
53
|
+
]
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
def sample_record
|
58
|
+
{'@timestamp' => Time.now.iso8601, 'message' => 'Sample record'}
|
59
|
+
end
|
60
|
+
|
61
|
+
RESPONSE_ACKNOWLEDGED = {"acknowledged": true}
|
62
|
+
DUPLICATED_DATA_STREAM_EXCEPTION = {"error": {}, "status": 400}
|
63
|
+
NONEXISTENT_DATA_STREAM_EXCEPTION = {"error": {}, "status": 404}
|
64
|
+
|
65
|
+
def stub_ilm_policy(name="foo")
|
66
|
+
stub_request(:put, "http://localhost:9200/_ilm/policy/#{name}_policy").to_return(:status => [200, RESPONSE_ACKNOWLEDGED])
|
67
|
+
end
|
68
|
+
|
69
|
+
def stub_index_template(name="foo")
|
70
|
+
stub_request(:put, "http://localhost:9200/_index_template/#{name}").to_return(:status => [200, RESPONSE_ACKNOWLEDGED])
|
71
|
+
end
|
72
|
+
|
73
|
+
def stub_data_stream(name="foo")
|
74
|
+
stub_request(:put, "http://localhost:9200/_data_stream/#{name}").to_return(:status => [200, RESPONSE_ACKNOWLEDGED])
|
75
|
+
end
|
76
|
+
|
77
|
+
def stub_existent_data_stream?(name="foo")
|
78
|
+
stub_request(:get, "http://localhost:9200/_data_stream/#{name}").to_return(:status => [200, RESPONSE_ACKNOWLEDGED])
|
79
|
+
end
|
80
|
+
|
81
|
+
def stub_nonexistent_data_stream?(name="foo")
|
82
|
+
stub_request(:get, "http://localhost:9200/_data_stream/#{name}").to_return(:status => [200, Elasticsearch::Transport::Transport::Errors::NotFound])
|
83
|
+
end
|
84
|
+
|
85
|
+
def stub_bulk_feed(name="foo")
|
86
|
+
stub_request(:post, "http://localhost:9200/#{name}/_bulk").with do |req|
|
87
|
+
# bulk data must be pair of OP and records
|
88
|
+
# {"create": {}}\n
|
89
|
+
# {"@timestamp": ...}
|
90
|
+
@bulk_records += req.body.split("\n").size / 2
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def stub_default(name="foo")
|
95
|
+
stub_ilm_policy(name)
|
96
|
+
stub_index_template(name)
|
97
|
+
stub_existent_data_stream?(name)
|
98
|
+
stub_data_stream(name)
|
99
|
+
end
|
100
|
+
|
101
|
+
def data_stream_supported?
|
102
|
+
Gem::Version.create(::Elasticsearch::Transport::VERSION) >= Gem::Version.create("7.9.0")
|
103
|
+
end
|
104
|
+
|
105
|
+
# ref. https://www.elastic.co/guide/en/elasticsearch/reference/master/indices-create-data-stream.html
|
106
|
+
class DataStreamNameTest < self
|
107
|
+
|
108
|
+
def test_missing_data_stream_name
|
109
|
+
conf = config_element(
|
110
|
+
'ROOT', '', {
|
111
|
+
'@type' => 'elasticsearch_datastream'
|
112
|
+
})
|
113
|
+
assert_raise Fluent::ConfigError.new("'data_stream_name' parameter is required") do
|
114
|
+
driver(conf).run
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def test_invalid_uppercase
|
119
|
+
conf = config_element(
|
120
|
+
'ROOT', '', {
|
121
|
+
'@type' => 'elasticsearch_datastream',
|
122
|
+
'data_stream_name' => 'TEST'
|
123
|
+
})
|
124
|
+
assert_raise Fluent::ConfigError.new("'data_stream_name' must be lowercase only: <TEST>") do
|
125
|
+
driver(conf)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
data("backslash" => "\\",
|
130
|
+
"slash" => "/",
|
131
|
+
"asterisk" => "*",
|
132
|
+
"question" => "?",
|
133
|
+
"doublequote" => "\"",
|
134
|
+
"lt" => "<",
|
135
|
+
"gt" => ">",
|
136
|
+
"bar" => "|",
|
137
|
+
"space" => " ",
|
138
|
+
"comma" => ",",
|
139
|
+
"sharp" => "#",
|
140
|
+
"colon" => ":")
|
141
|
+
def test_invalid_characters(data)
|
142
|
+
c, _ = data
|
143
|
+
conf = config_element(
|
144
|
+
'ROOT', '', {
|
145
|
+
'@type' => ELASTIC_DATA_STREAM_TYPE,
|
146
|
+
'data_stream_name' => "TEST#{c}"
|
147
|
+
})
|
148
|
+
label = Fluent::Plugin::ElasticsearchOutputDataStream::INVALID_CHARACTERS.join(',')
|
149
|
+
assert_raise Fluent::ConfigError.new("'data_stream_name' must not contain invalid characters #{label}: <TEST#{c}>") do
|
150
|
+
driver(conf)
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
data("hyphen" => "-",
|
155
|
+
"underscore" => "_",
|
156
|
+
"plus" => "+",
|
157
|
+
"period" => ".")
|
158
|
+
def test_invalid_start_characters(data)
|
159
|
+
c, _ = data
|
160
|
+
conf = config_element(
|
161
|
+
'ROOT', '', {
|
162
|
+
'@type' => ELASTIC_DATA_STREAM_TYPE,
|
163
|
+
'data_stream_name' => "#{c}TEST"
|
164
|
+
})
|
165
|
+
label = Fluent::Plugin::ElasticsearchOutputDataStream::INVALID_START_CHRACTERS.join(',')
|
166
|
+
assert_raise Fluent::ConfigError.new("'data_stream_name' must not start with #{label}: <#{c}TEST>") do
|
167
|
+
driver(conf)
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
data("current" => ".",
|
172
|
+
"parents" => "..")
|
173
|
+
def test_invalid_dots
|
174
|
+
c, _ = data
|
175
|
+
conf = config_element(
|
176
|
+
'ROOT', '', {
|
177
|
+
'@type' => ELASTIC_DATA_STREAM_TYPE,
|
178
|
+
'data_stream_name' => "#{c}"
|
179
|
+
})
|
180
|
+
assert_raise Fluent::ConfigError.new("'data_stream_name' must not be . or ..: <#{c}>") do
|
181
|
+
driver(conf)
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def test_invalid_length
|
186
|
+
c = "a" * 256
|
187
|
+
conf = config_element(
|
188
|
+
'ROOT', '', {
|
189
|
+
'@type' => ELASTIC_DATA_STREAM_TYPE,
|
190
|
+
'data_stream_name' => "#{c}"
|
191
|
+
})
|
192
|
+
assert_raise Fluent::ConfigError.new("'data_stream_name' must not be longer than 255 bytes: <#{c}>") do
|
193
|
+
driver(conf)
|
194
|
+
end
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def test_datastream_configure
|
199
|
+
omit REQUIRED_ELASTIC_MESSAGE unless data_stream_supported?
|
200
|
+
|
201
|
+
stub_default
|
202
|
+
conf = config_element(
|
203
|
+
'ROOT', '', {
|
204
|
+
'@type' => ELASTIC_DATA_STREAM_TYPE,
|
205
|
+
'data_stream_name' => 'foo'
|
206
|
+
})
|
207
|
+
assert_equal "foo", driver(conf).instance.data_stream_name
|
208
|
+
end
|
209
|
+
|
210
|
+
def test_nonexistent_data_stream
|
211
|
+
omit REQUIRED_ELASTIC_MESSAGE unless data_stream_supported?
|
212
|
+
|
213
|
+
stub_ilm_policy
|
214
|
+
stub_index_template
|
215
|
+
stub_nonexistent_data_stream?
|
216
|
+
stub_data_stream
|
217
|
+
conf = config_element(
|
218
|
+
'ROOT', '', {
|
219
|
+
'@type' => ELASTIC_DATA_STREAM_TYPE,
|
220
|
+
'data_stream_name' => 'foo'
|
221
|
+
})
|
222
|
+
assert_equal "foo", driver(conf).instance.data_stream_name
|
223
|
+
end
|
224
|
+
|
225
|
+
def test_placeholder
|
226
|
+
omit REQUIRED_ELASTIC_MESSAGE unless data_stream_supported?
|
227
|
+
|
228
|
+
name = "foo_test"
|
229
|
+
stub_default(name)
|
230
|
+
stub_bulk_feed(name)
|
231
|
+
conf = config_element(
|
232
|
+
'ROOT', '', {
|
233
|
+
'@type' => ELASTIC_DATA_STREAM_TYPE,
|
234
|
+
'data_stream_name' => 'foo_${tag}'
|
235
|
+
})
|
236
|
+
driver(conf).run(default_tag: 'test') do
|
237
|
+
driver.feed(sample_record)
|
238
|
+
end
|
239
|
+
assert_equal 1, @bulk_records
|
240
|
+
end
|
241
|
+
|
242
|
+
def test_time_placeholder
|
243
|
+
omit REQUIRED_ELASTIC_MESSAGE unless data_stream_supported?
|
244
|
+
|
245
|
+
time = Time.now
|
246
|
+
name = "foo_#{time.strftime("%Y%m%d")}"
|
247
|
+
stub_default(name)
|
248
|
+
stub_bulk_feed(name)
|
249
|
+
conf = config_element(
|
250
|
+
'ROOT', '', {
|
251
|
+
'@type' => ELASTIC_DATA_STREAM_TYPE,
|
252
|
+
'data_stream_name' => 'foo_%Y%m%d'
|
253
|
+
}, [config_element('buffer', 'time', {
|
254
|
+
'timekey' => '1d'
|
255
|
+
}, [])]
|
256
|
+
)
|
257
|
+
driver(conf).run(default_tag: 'test') do
|
258
|
+
driver.feed(sample_record)
|
259
|
+
end
|
260
|
+
assert_equal 1, @bulk_records
|
261
|
+
end
|
262
|
+
|
263
|
+
def test_custom_record_placeholder
|
264
|
+
omit REQUIRED_ELASTIC_MESSAGE unless data_stream_supported?
|
265
|
+
|
266
|
+
keys = ["bar", "baz"]
|
267
|
+
keys.each do |key|
|
268
|
+
name = "foo_#{key}"
|
269
|
+
stub_default(name)
|
270
|
+
stub_bulk_feed(name)
|
271
|
+
end
|
272
|
+
conf = config_element(
|
273
|
+
'ROOT', '', {
|
274
|
+
'@type' => ELASTIC_DATA_STREAM_TYPE,
|
275
|
+
'data_stream_name' => 'foo_${key1}'
|
276
|
+
}, [config_element('buffer', 'tag,key1', {
|
277
|
+
'timekey' => '1d'
|
278
|
+
}, [])]
|
279
|
+
)
|
280
|
+
driver(conf).run(default_tag: 'test') do
|
281
|
+
keys.each do |key|
|
282
|
+
record = sample_record.merge({"key1" => key})
|
283
|
+
driver.feed(record)
|
284
|
+
end
|
285
|
+
end
|
286
|
+
assert_equal keys.count, @bulk_records
|
287
|
+
end
|
288
|
+
|
289
|
+
def test_bulk_insert_feed
|
290
|
+
omit REQUIRED_ELASTIC_MESSAGE unless data_stream_supported?
|
291
|
+
|
292
|
+
stub_default
|
293
|
+
stub_bulk_feed
|
294
|
+
conf = config_element(
|
295
|
+
'ROOT', '', {
|
296
|
+
'@type' => ELASTIC_DATA_STREAM_TYPE,
|
297
|
+
'data_stream_name' => 'foo'
|
298
|
+
})
|
299
|
+
driver(conf).run(default_tag: 'test') do
|
300
|
+
driver.feed(sample_record)
|
301
|
+
end
|
302
|
+
assert_equal 1, @bulk_records
|
303
|
+
end
|
304
|
+
|
305
|
+
def test_template_retry_install_fails
|
306
|
+
omit REQUIRED_ELASTIC_MESSAGE unless data_stream_supported?
|
307
|
+
|
308
|
+
cwd = File.dirname(__FILE__)
|
309
|
+
template_file = File.join(cwd, 'test_index_template.json')
|
310
|
+
|
311
|
+
config = %{
|
312
|
+
host logs.google.com
|
313
|
+
port 778
|
314
|
+
scheme https
|
315
|
+
data_stream_name foo
|
316
|
+
user john
|
317
|
+
password doe
|
318
|
+
template_name logstash
|
319
|
+
template_file #{template_file}
|
320
|
+
max_retry_putting_template 3
|
321
|
+
}
|
322
|
+
|
323
|
+
connection_resets = 0
|
324
|
+
# check if template exists
|
325
|
+
stub_request(:get, "https://logs.google.com:778/_index_template/logstash")
|
326
|
+
.with(basic_auth: ['john', 'doe']) do |req|
|
327
|
+
connection_resets += 1
|
328
|
+
raise Faraday::ConnectionFailed, "Test message"
|
329
|
+
end
|
330
|
+
|
331
|
+
assert_raise(Fluent::Plugin::ElasticsearchError::RetryableOperationExhaustedFailure) do
|
332
|
+
driver(config)
|
333
|
+
end
|
334
|
+
|
335
|
+
assert_equal(4, connection_resets)
|
336
|
+
end
|
337
|
+
end
|
@@ -0,0 +1,1134 @@
|
|
1
|
+
require_relative '../helper'
|
2
|
+
require 'date'
|
3
|
+
require 'fluent/test/helpers'
|
4
|
+
require 'fluent/test/driver/output'
|
5
|
+
require 'flexmock/test_unit'
|
6
|
+
require 'fluent/plugin/out_elasticsearch_dynamic'
|
7
|
+
|
8
|
+
class ElasticsearchOutputDynamic < Test::Unit::TestCase
|
9
|
+
include FlexMock::TestCase
|
10
|
+
include Fluent::Test::Helpers
|
11
|
+
|
12
|
+
attr_accessor :index_cmds, :index_command_counts
|
13
|
+
|
14
|
+
def setup
|
15
|
+
Fluent::Test.setup
|
16
|
+
@driver = nil
|
17
|
+
end
|
18
|
+
|
19
|
+
def driver(conf='', es_version=5)
|
20
|
+
# For request stub to detect compatibility.
|
21
|
+
@es_version ||= es_version
|
22
|
+
Fluent::Plugin::ElasticsearchOutputDynamic.module_eval(<<-CODE)
|
23
|
+
def detect_es_major_version
|
24
|
+
#{@es_version}
|
25
|
+
end
|
26
|
+
CODE
|
27
|
+
@driver ||= Fluent::Test::Driver::Output.new(Fluent::Plugin::ElasticsearchOutputDynamic) {
|
28
|
+
# v0.12's test driver assume format definition. This simulates ObjectBufferedOutput format
|
29
|
+
if !defined?(Fluent::Plugin::Output)
|
30
|
+
def format(tag, time, record)
|
31
|
+
[time, record].to_msgpack
|
32
|
+
end
|
33
|
+
end
|
34
|
+
}.configure(conf)
|
35
|
+
end
|
36
|
+
|
37
|
+
def default_type_name
|
38
|
+
Fluent::Plugin::ElasticsearchOutput::DEFAULT_TYPE_NAME
|
39
|
+
end
|
40
|
+
|
41
|
+
def sample_record
|
42
|
+
{'age' => 26, 'request_id' => '42', 'parent_id' => 'parent', 'routing_id' => 'routing'}
|
43
|
+
end
|
44
|
+
|
45
|
+
def nested_sample_record
|
46
|
+
{'nested' =>
|
47
|
+
{'age' => 26, 'parent_id' => 'parent', 'routing_id' => 'routing', 'request_id' => '42'}
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
def stub_elastic(url="http://localhost:9200/_bulk")
|
52
|
+
stub_request(:post, url).with do |req|
|
53
|
+
@index_cmds = req.body.split("\n").map {|r| JSON.parse(r) }
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def stub_elastic_unavailable(url="http://localhost:9200/_bulk")
|
58
|
+
stub_request(:post, url).to_return(:status => [503, "Service Unavailable"])
|
59
|
+
end
|
60
|
+
|
61
|
+
def stub_elastic_timeout(url="http://localhost:9200/_bulk")
|
62
|
+
stub_request(:post, url).to_timeout
|
63
|
+
end
|
64
|
+
|
65
|
+
def stub_elastic_with_store_index_command_counts(url="http://localhost:9200/_bulk")
|
66
|
+
if @index_command_counts == nil
|
67
|
+
@index_command_counts = {}
|
68
|
+
@index_command_counts.default = 0
|
69
|
+
end
|
70
|
+
|
71
|
+
stub_request(:post, url).with do |req|
|
72
|
+
index_cmds = req.body.split("\n").map {|r| JSON.parse(r) }
|
73
|
+
@index_command_counts[url] += index_cmds.size
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
def assert_logs_include(logs, msg, exp_matches=1)
|
78
|
+
matches = logs.grep /#{msg}/
|
79
|
+
assert_equal(exp_matches, matches.length, "Logs do not contain '#{msg}' '#{logs}'")
|
80
|
+
end
|
81
|
+
|
82
|
+
def test_configure
|
83
|
+
config = %{
|
84
|
+
host logs.google.com
|
85
|
+
port 777
|
86
|
+
scheme https
|
87
|
+
path /es/
|
88
|
+
user john
|
89
|
+
password doe
|
90
|
+
}
|
91
|
+
instance = driver(config).instance
|
92
|
+
|
93
|
+
conf = instance.dynamic_config
|
94
|
+
assert_equal 'logs.google.com', conf['host']
|
95
|
+
assert_equal "777", conf['port']
|
96
|
+
assert_equal :https, instance.scheme
|
97
|
+
assert_equal 'john', instance.user
|
98
|
+
assert_equal 'doe', instance.password
|
99
|
+
assert_equal '/es/', instance.path
|
100
|
+
assert_equal Fluent::Plugin::ElasticsearchTLS::DEFAULT_VERSION, instance.ssl_version
|
101
|
+
assert_nil instance.ssl_max_version
|
102
|
+
assert_nil instance.ssl_min_version
|
103
|
+
if Fluent::Plugin::ElasticsearchTLS::USE_TLS_MINMAX_VERSION
|
104
|
+
if defined?(OpenSSL::SSL::TLS1_3_VERSION)
|
105
|
+
assert_equal({max_version: OpenSSL::SSL::TLS1_3_VERSION, min_version: OpenSSL::SSL::TLS1_2_VERSION},
|
106
|
+
instance.ssl_version_options)
|
107
|
+
else
|
108
|
+
assert_equal({max_version: nil, min_version: OpenSSL::SSL::TLS1_2_VERSION},
|
109
|
+
instance.ssl_version_options)
|
110
|
+
end
|
111
|
+
else
|
112
|
+
assert_equal({version: Fluent::Plugin::ElasticsearchTLS::DEFAULT_VERSION},
|
113
|
+
instance.ssl_version_options)
|
114
|
+
end
|
115
|
+
assert_nil instance.client_key
|
116
|
+
assert_nil instance.client_cert
|
117
|
+
assert_nil instance.client_key_pass
|
118
|
+
assert_false instance.with_transporter_log
|
119
|
+
assert_equal :"application/json", instance.content_type
|
120
|
+
assert_equal :excon, instance.http_backend
|
121
|
+
assert_false instance.compression
|
122
|
+
assert_equal :no_compression, instance.compression_level
|
123
|
+
end
|
124
|
+
|
125
|
+
test 'configure compression' do
|
126
|
+
omit "elastisearch-ruby v7.2.0 or later is needed." if Gem::Version.create(::Elasticsearch::Transport::VERSION) < Gem::Version.create("7.2.0")
|
127
|
+
|
128
|
+
config = %{
|
129
|
+
compression_level best_compression
|
130
|
+
}
|
131
|
+
instance = driver(config).instance
|
132
|
+
|
133
|
+
assert_equal true, instance.compression
|
134
|
+
end
|
135
|
+
|
136
|
+
test 'check compression strategy' do
|
137
|
+
omit "elastisearch-ruby v7.2.0 or later is needed." if Gem::Version.create(::Elasticsearch::Transport::VERSION) < Gem::Version.create("7.2.0")
|
138
|
+
|
139
|
+
config = %{
|
140
|
+
compression_level best_speed
|
141
|
+
}
|
142
|
+
instance = driver(config).instance
|
143
|
+
|
144
|
+
assert_equal Zlib::BEST_SPEED, instance.compression_strategy
|
145
|
+
end
|
146
|
+
|
147
|
+
test 'check content-encoding header with compression' do
|
148
|
+
omit "elastisearch-ruby v7.2.0 or later is needed." if Gem::Version.create(::Elasticsearch::Transport::VERSION) < Gem::Version.create("7.2.0")
|
149
|
+
|
150
|
+
config = %{
|
151
|
+
compression_level best_compression
|
152
|
+
}
|
153
|
+
instance = driver(config).instance
|
154
|
+
|
155
|
+
assert_equal nil, instance.client.transport.options[:transport_options][:headers]["Content-Encoding"]
|
156
|
+
|
157
|
+
stub_request(:post, "http://localhost:9200/_bulk").
|
158
|
+
to_return(status: 200, body: "", headers: {})
|
159
|
+
driver.run(default_tag: 'test') do
|
160
|
+
driver.feed(sample_record)
|
161
|
+
end
|
162
|
+
compressable = instance.compressable_connection
|
163
|
+
|
164
|
+
assert_equal "gzip", instance.client(nil, compressable).transport.options[:transport_options][:headers]["Content-Encoding"]
|
165
|
+
end
|
166
|
+
|
167
|
+
test 'check compression option is passed to transport' do
|
168
|
+
omit "elastisearch-ruby v7.2.0 or later is needed." if Gem::Version.create(::Elasticsearch::Transport::VERSION) < Gem::Version.create("7.2.0")
|
169
|
+
|
170
|
+
config = %{
|
171
|
+
compression_level best_compression
|
172
|
+
}
|
173
|
+
instance = driver(config).instance
|
174
|
+
|
175
|
+
assert_equal false, instance.client.transport.options[:compression]
|
176
|
+
|
177
|
+
stub_request(:post, "http://localhost:9200/_bulk").
|
178
|
+
to_return(status: 200, body: "", headers: {})
|
179
|
+
driver.run(default_tag: 'test') do
|
180
|
+
driver.feed(sample_record)
|
181
|
+
end
|
182
|
+
compressable = instance.compressable_connection
|
183
|
+
|
184
|
+
assert_equal true, instance.client(nil, compressable).transport.options[:compression]
|
185
|
+
end
|
186
|
+
|
187
|
+
test 'configure Content-Type' do
|
188
|
+
config = %{
|
189
|
+
content_type application/x-ndjson
|
190
|
+
}
|
191
|
+
instance = driver(config).instance
|
192
|
+
assert_equal :"application/x-ndjson", instance.content_type
|
193
|
+
end
|
194
|
+
|
195
|
+
test 'invalid Content-Type' do
|
196
|
+
config = %{
|
197
|
+
content_type nonexistent/invalid
|
198
|
+
}
|
199
|
+
assert_raise(Fluent::ConfigError) {
|
200
|
+
driver(config)
|
201
|
+
}
|
202
|
+
end
|
203
|
+
|
204
|
+
test 'Detected Elasticsearch 7' do
|
205
|
+
config = %{
|
206
|
+
type_name changed
|
207
|
+
}
|
208
|
+
instance = driver(config, 7).instance
|
209
|
+
assert_equal '_doc', instance.type_name
|
210
|
+
end
|
211
|
+
|
212
|
+
def test_defaults
|
213
|
+
config = %{
|
214
|
+
host logs.google.com
|
215
|
+
scheme https
|
216
|
+
path /es/
|
217
|
+
user john
|
218
|
+
password doe
|
219
|
+
}
|
220
|
+
instance = driver(config).instance
|
221
|
+
|
222
|
+
conf = instance.dynamic_config
|
223
|
+
assert_equal "9200", conf['port']
|
224
|
+
assert_equal "false", conf['logstash_format']
|
225
|
+
assert_equal "true", conf['utc_index']
|
226
|
+
assert_equal false, instance.time_key_exclude_timestamp
|
227
|
+
end
|
228
|
+
|
229
|
+
def test_legacy_hosts_list
|
230
|
+
config = %{
|
231
|
+
hosts host1:50,host2:100,host3
|
232
|
+
scheme https
|
233
|
+
path /es/
|
234
|
+
port 123
|
235
|
+
}
|
236
|
+
instance = driver(config).instance
|
237
|
+
|
238
|
+
assert_equal 3, instance.get_connection_options(nil)[:hosts].length
|
239
|
+
host1, host2, host3 = instance.get_connection_options(nil)[:hosts]
|
240
|
+
|
241
|
+
assert_equal 'host1', host1[:host]
|
242
|
+
assert_equal 50, host1[:port]
|
243
|
+
assert_equal 'https', host1[:scheme]
|
244
|
+
assert_equal '/es/', host2[:path]
|
245
|
+
assert_equal 'host3', host3[:host]
|
246
|
+
assert_equal 123, host3[:port]
|
247
|
+
assert_equal 'https', host3[:scheme]
|
248
|
+
assert_equal '/es/', host3[:path]
|
249
|
+
end
|
250
|
+
|
251
|
+
def test_hosts_list
|
252
|
+
config = %{
|
253
|
+
hosts https://john:password@host1:443/elastic/,http://host2
|
254
|
+
path /default_path
|
255
|
+
user default_user
|
256
|
+
password default_password
|
257
|
+
}
|
258
|
+
instance = driver(config).instance
|
259
|
+
|
260
|
+
assert_equal 2, instance.get_connection_options(nil)[:hosts].length
|
261
|
+
host1, host2 = instance.get_connection_options(nil)[:hosts]
|
262
|
+
|
263
|
+
assert_equal 'host1', host1[:host]
|
264
|
+
assert_equal 443, host1[:port]
|
265
|
+
assert_equal 'https', host1[:scheme]
|
266
|
+
assert_equal 'john', host1[:user]
|
267
|
+
assert_equal 'password', host1[:password]
|
268
|
+
assert_equal '/elastic/', host1[:path]
|
269
|
+
|
270
|
+
assert_equal 'host2', host2[:host]
|
271
|
+
assert_equal 'http', host2[:scheme]
|
272
|
+
assert_equal 'default_user', host2[:user]
|
273
|
+
assert_equal 'default_password', host2[:password]
|
274
|
+
assert_equal '/default_path', host2[:path]
|
275
|
+
end
|
276
|
+
|
277
|
+
def test_hosts_list_with_escape_placeholders
|
278
|
+
config = %{
|
279
|
+
hosts https://%{j+hn}:%{passw@rd}@host1:443/elastic/,http://host2
|
280
|
+
path /default_path
|
281
|
+
user default_user
|
282
|
+
password default_password
|
283
|
+
}
|
284
|
+
instance = driver(config).instance
|
285
|
+
|
286
|
+
assert_equal 2, instance.get_connection_options(nil)[:hosts].length
|
287
|
+
host1, host2 = instance.get_connection_options(nil)[:hosts]
|
288
|
+
|
289
|
+
assert_equal 'host1', host1[:host]
|
290
|
+
assert_equal 443, host1[:port]
|
291
|
+
assert_equal 'https', host1[:scheme]
|
292
|
+
assert_equal 'j%2Bhn', host1[:user]
|
293
|
+
assert_equal 'passw%40rd', host1[:password]
|
294
|
+
assert_equal '/elastic/', host1[:path]
|
295
|
+
|
296
|
+
assert_equal 'host2', host2[:host]
|
297
|
+
assert_equal 'http', host2[:scheme]
|
298
|
+
assert_equal 'default_user', host2[:user]
|
299
|
+
assert_equal 'default_password', host2[:password]
|
300
|
+
assert_equal '/default_path', host2[:path]
|
301
|
+
end
|
302
|
+
|
303
|
+
def test_single_host_params_and_defaults
|
304
|
+
config = %{
|
305
|
+
host logs.google.com
|
306
|
+
user john
|
307
|
+
password doe
|
308
|
+
}
|
309
|
+
instance = driver(config).instance
|
310
|
+
|
311
|
+
assert_equal 1, instance.get_connection_options(nil)[:hosts].length
|
312
|
+
host1 = instance.get_connection_options(nil)[:hosts][0]
|
313
|
+
|
314
|
+
assert_equal 'logs.google.com', host1[:host]
|
315
|
+
assert_equal 9200, host1[:port]
|
316
|
+
assert_equal 'http', host1[:scheme]
|
317
|
+
assert_equal 'john', host1[:user]
|
318
|
+
assert_equal 'doe', host1[:password]
|
319
|
+
assert_equal nil, host1[:path]
|
320
|
+
end
|
321
|
+
|
322
|
+
def test_single_host_params_and_defaults_with_escape_placeholders
|
323
|
+
config = %{
|
324
|
+
host logs.google.com
|
325
|
+
user %{j+hn}
|
326
|
+
password %{d@e}
|
327
|
+
}
|
328
|
+
instance = driver(config).instance
|
329
|
+
|
330
|
+
assert_equal 1, instance.get_connection_options(nil)[:hosts].length
|
331
|
+
host1 = instance.get_connection_options(nil)[:hosts][0]
|
332
|
+
|
333
|
+
assert_equal 'logs.google.com', host1[:host]
|
334
|
+
assert_equal 9200, host1[:port]
|
335
|
+
assert_equal 'http', host1[:scheme]
|
336
|
+
assert_equal 'j%2Bhn', host1[:user]
|
337
|
+
assert_equal 'd%40e', host1[:password]
|
338
|
+
assert_equal nil, host1[:path]
|
339
|
+
end
|
340
|
+
|
341
|
+
def test_content_type_header
|
342
|
+
stub_request(:head, "http://localhost:9200/").
|
343
|
+
to_return(:status => 200, :body => "", :headers => {})
|
344
|
+
if Elasticsearch::VERSION >= "6.0.2"
|
345
|
+
elastic_request = stub_request(:post, "http://localhost:9200/_bulk").
|
346
|
+
with(headers: { "Content-Type" => "application/x-ndjson" })
|
347
|
+
else
|
348
|
+
elastic_request = stub_request(:post, "http://localhost:9200/_bulk").
|
349
|
+
with(headers: { "Content-Type" => "application/json" })
|
350
|
+
end
|
351
|
+
driver.run(default_tag: 'test') do
|
352
|
+
driver.feed(sample_record)
|
353
|
+
end
|
354
|
+
assert_requested(elastic_request)
|
355
|
+
end
|
356
|
+
|
357
|
+
def test_writes_to_default_index
|
358
|
+
stub_elastic
|
359
|
+
driver.run(default_tag: 'test') do
|
360
|
+
driver.feed(sample_record)
|
361
|
+
end
|
362
|
+
assert_equal('fluentd', index_cmds.first['index']['_index'])
|
363
|
+
end
|
364
|
+
|
365
|
+
# gzip compress data
|
366
|
+
def gzip(string, strategy)
|
367
|
+
wio = StringIO.new("w")
|
368
|
+
w_gz = Zlib::GzipWriter.new(wio, strategy = strategy)
|
369
|
+
w_gz.write(string)
|
370
|
+
w_gz.close
|
371
|
+
wio.string
|
372
|
+
end
|
373
|
+
|
374
|
+
def test_writes_to_default_index_with_compression
|
375
|
+
omit "elastisearch-ruby v7.2.0 or later is needed." if Gem::Version.create(::Elasticsearch::Transport::VERSION) < Gem::Version.create("7.2.0")
|
376
|
+
|
377
|
+
config = %[
|
378
|
+
compression_level default_compression
|
379
|
+
]
|
380
|
+
|
381
|
+
bodystr = %({
|
382
|
+
"took" : 500,
|
383
|
+
"errors" : false,
|
384
|
+
"items" : [
|
385
|
+
{
|
386
|
+
"create": {
|
387
|
+
"_index" : "fluentd",
|
388
|
+
"_type" : "fluentd"
|
389
|
+
}
|
390
|
+
}
|
391
|
+
]
|
392
|
+
})
|
393
|
+
|
394
|
+
compressed_body = gzip(bodystr, Zlib::DEFAULT_COMPRESSION)
|
395
|
+
|
396
|
+
elastic_request = stub_request(:post, "http://localhost:9200/_bulk").
|
397
|
+
to_return(:status => 200, :headers => {'Content-Type' => 'Application/json'}, :body => compressed_body)
|
398
|
+
|
399
|
+
driver(config)
|
400
|
+
driver.run(default_tag: 'test') do
|
401
|
+
driver.feed(sample_record)
|
402
|
+
end
|
403
|
+
|
404
|
+
assert_requested(elastic_request)
|
405
|
+
end
|
406
|
+
|
407
|
+
def test_writes_to_default_type
|
408
|
+
stub_elastic
|
409
|
+
driver.run(default_tag: 'test') do
|
410
|
+
driver.feed(sample_record)
|
411
|
+
end
|
412
|
+
assert_equal(default_type_name, index_cmds.first['index']['_type'])
|
413
|
+
end
|
414
|
+
|
415
|
+
def test_writes_to_specified_index
|
416
|
+
driver.configure("index_name myindex\n")
|
417
|
+
stub_elastic
|
418
|
+
driver.run(default_tag: 'test') do
|
419
|
+
driver.feed(sample_record)
|
420
|
+
end
|
421
|
+
assert_equal('myindex', index_cmds.first['index']['_index'])
|
422
|
+
end
|
423
|
+
|
424
|
+
def test_writes_to_specified_index_uppercase
|
425
|
+
driver.configure("index_name MyIndex\n")
|
426
|
+
stub_elastic
|
427
|
+
driver.run(default_tag: 'test') do
|
428
|
+
driver.feed(sample_record)
|
429
|
+
end
|
430
|
+
assert_equal('myindex', index_cmds.first['index']['_index'])
|
431
|
+
end
|
432
|
+
|
433
|
+
def test_writes_to_specified_type
|
434
|
+
driver.configure("type_name mytype\n")
|
435
|
+
stub_elastic
|
436
|
+
driver.run(default_tag: 'test') do
|
437
|
+
driver.feed(sample_record)
|
438
|
+
end
|
439
|
+
assert_equal('mytype', index_cmds.first['index']['_type'])
|
440
|
+
end
|
441
|
+
|
442
|
+
def test_writes_to_specified_host
|
443
|
+
driver.configure("host 192.168.33.50\n")
|
444
|
+
elastic_request = stub_elastic("http://192.168.33.50:9200/_bulk")
|
445
|
+
driver.run(default_tag: 'test') do
|
446
|
+
driver.feed(sample_record)
|
447
|
+
end
|
448
|
+
assert_requested(elastic_request)
|
449
|
+
end
|
450
|
+
|
451
|
+
def test_writes_to_specified_port
|
452
|
+
driver.configure("port 9201\n")
|
453
|
+
elastic_request = stub_elastic("http://localhost:9201/_bulk")
|
454
|
+
driver.run(default_tag: 'test') do
|
455
|
+
driver.feed(sample_record)
|
456
|
+
end
|
457
|
+
assert_requested(elastic_request)
|
458
|
+
end
|
459
|
+
|
460
|
+
def test_writes_to_multi_hosts
|
461
|
+
hosts = [['192.168.33.50', 9201], ['192.168.33.51', 9201], ['192.168.33.52', 9201]]
|
462
|
+
hosts_string = hosts.map {|x| "#{x[0]}:#{x[1]}"}.compact.join(',')
|
463
|
+
|
464
|
+
driver.configure("hosts #{hosts_string}")
|
465
|
+
|
466
|
+
hosts.each do |host_info|
|
467
|
+
host, port = host_info
|
468
|
+
stub_elastic_with_store_index_command_counts("http://#{host}:#{port}/_bulk")
|
469
|
+
end
|
470
|
+
|
471
|
+
driver.run(default_tag: 'test') do
|
472
|
+
1000.times do
|
473
|
+
driver.feed(sample_record.merge('age'=>rand(100)))
|
474
|
+
end
|
475
|
+
end
|
476
|
+
# @note: we cannot make multi chunks with options (flush_interval, buffer_chunk_limit)
|
477
|
+
# it's Fluentd test driver's constraint
|
478
|
+
# so @index_command_counts.size is always 1
|
479
|
+
|
480
|
+
assert(@index_command_counts.size > 0, "not working with hosts options")
|
481
|
+
|
482
|
+
total = 0
|
483
|
+
@index_command_counts.each do |url, count|
|
484
|
+
total += count
|
485
|
+
end
|
486
|
+
assert_equal(2000, total)
|
487
|
+
end
|
488
|
+
|
489
|
+
def test_nested_record_with_flattening_on
|
490
|
+
driver.configure("flatten_hashes true
|
491
|
+
flatten_hashes_separator |")
|
492
|
+
|
493
|
+
original_hash = {"foo" => {"bar" => "baz"}, "people" => [
|
494
|
+
{"age" => "25", "height" => "1ft"},
|
495
|
+
{"age" => "30", "height" => "2ft"}
|
496
|
+
]}
|
497
|
+
|
498
|
+
expected_output = {"foo|bar"=>"baz", "people" => [
|
499
|
+
{"age" => "25", "height" => "1ft"},
|
500
|
+
{"age" => "30", "height" => "2ft"}
|
501
|
+
]}
|
502
|
+
|
503
|
+
stub_elastic
|
504
|
+
driver.run(default_tag: 'test') do
|
505
|
+
driver.feed(original_hash)
|
506
|
+
end
|
507
|
+
assert_equal expected_output, index_cmds[1]
|
508
|
+
end
|
509
|
+
|
510
|
+
def test_nested_record_with_flattening_off
|
511
|
+
# flattening off by default
|
512
|
+
|
513
|
+
original_hash = {"foo" => {"bar" => "baz"}}
|
514
|
+
expected_output = {"foo" => {"bar" => "baz"}}
|
515
|
+
|
516
|
+
stub_elastic
|
517
|
+
driver.run(default_tag: 'test') do
|
518
|
+
driver.feed(original_hash)
|
519
|
+
end
|
520
|
+
assert_equal expected_output, index_cmds[1]
|
521
|
+
end
|
522
|
+
|
523
|
+
def test_makes_bulk_request
|
524
|
+
stub_elastic
|
525
|
+
driver.run(default_tag: 'test') do
|
526
|
+
driver.feed(sample_record)
|
527
|
+
driver.feed(sample_record.merge('age' => 27))
|
528
|
+
end
|
529
|
+
assert_equal(4, index_cmds.count)
|
530
|
+
end
|
531
|
+
|
532
|
+
def test_all_records_are_preserved_in_bulk
|
533
|
+
stub_elastic
|
534
|
+
driver.run(default_tag: 'test') do
|
535
|
+
driver.feed(sample_record)
|
536
|
+
driver.feed(sample_record.merge('age' => 27))
|
537
|
+
end
|
538
|
+
assert_equal(26, index_cmds[1]['age'])
|
539
|
+
assert_equal(27, index_cmds[3]['age'])
|
540
|
+
end
|
541
|
+
|
542
|
+
def test_writes_to_logstash_index
|
543
|
+
driver.configure("logstash_format true\n")
|
544
|
+
time = Time.parse Date.today.iso8601
|
545
|
+
logstash_index = "logstash-#{time.getutc.strftime("%Y.%m.%d")}"
|
546
|
+
stub_elastic
|
547
|
+
driver.run(default_tag: 'test') do
|
548
|
+
driver.feed(time.to_i, sample_record)
|
549
|
+
end
|
550
|
+
assert_equal(logstash_index, index_cmds.first['index']['_index'])
|
551
|
+
end
|
552
|
+
|
553
|
+
def test_writes_to_logstash_utc_index
|
554
|
+
driver.configure("logstash_format true
|
555
|
+
utc_index false")
|
556
|
+
time = Time.parse Date.today.iso8601
|
557
|
+
utc_index = "logstash-#{time.strftime("%Y.%m.%d")}"
|
558
|
+
stub_elastic
|
559
|
+
driver.run(default_tag: 'test') do
|
560
|
+
driver.feed(time.to_i, sample_record)
|
561
|
+
end
|
562
|
+
assert_equal(utc_index, index_cmds.first['index']['_index'])
|
563
|
+
end
|
564
|
+
|
565
|
+
def test_writes_to_logstash_index_with_specified_prefix
|
566
|
+
driver.configure("logstash_format true
|
567
|
+
logstash_prefix myprefix")
|
568
|
+
time = Time.parse Date.today.iso8601
|
569
|
+
logstash_index = "myprefix-#{time.getutc.strftime("%Y.%m.%d")}"
|
570
|
+
stub_elastic
|
571
|
+
driver.run(default_tag: 'test') do
|
572
|
+
driver.feed(time.to_i, sample_record)
|
573
|
+
end
|
574
|
+
assert_equal(logstash_index, index_cmds.first['index']['_index'])
|
575
|
+
end
|
576
|
+
|
577
|
+
def test_writes_to_logstash_index_with_specified_prefix_and_separator
|
578
|
+
separator = '_'
|
579
|
+
driver.configure("logstash_format true
|
580
|
+
logstash_prefix_separator #{separator}
|
581
|
+
logstash_prefix myprefix")
|
582
|
+
time = Time.parse Date.today.iso8601
|
583
|
+
logstash_index = "myprefix#{separator}#{time.getutc.strftime("%Y.%m.%d")}"
|
584
|
+
stub_elastic
|
585
|
+
driver.run(default_tag: 'test') do
|
586
|
+
driver.feed(time.to_i, sample_record)
|
587
|
+
end
|
588
|
+
assert_equal(logstash_index, index_cmds.first['index']['_index'])
|
589
|
+
end
|
590
|
+
|
591
|
+
def test_writes_to_logstash_index_with_specified_prefix_uppercase
|
592
|
+
driver.configure("logstash_format true
|
593
|
+
logstash_prefix MyPrefix")
|
594
|
+
time = Time.parse Date.today.iso8601
|
595
|
+
logstash_index = "myprefix-#{time.getutc.strftime("%Y.%m.%d")}"
|
596
|
+
stub_elastic
|
597
|
+
driver.run(default_tag: 'test') do
|
598
|
+
driver.feed(time.to_i, sample_record)
|
599
|
+
end
|
600
|
+
assert_equal(logstash_index, index_cmds.first['index']['_index'])
|
601
|
+
end
|
602
|
+
|
603
|
+
def test_writes_to_logstash_index_with_specified_dateformat
|
604
|
+
driver.configure("logstash_format true
|
605
|
+
logstash_dateformat %Y.%m")
|
606
|
+
time = Time.parse Date.today.iso8601
|
607
|
+
logstash_index = "logstash-#{time.getutc.strftime("%Y.%m")}"
|
608
|
+
stub_elastic
|
609
|
+
driver.run(default_tag: 'test') do
|
610
|
+
driver.feed(time.to_i, sample_record)
|
611
|
+
end
|
612
|
+
assert_equal(logstash_index, index_cmds.first['index']['_index'])
|
613
|
+
end
|
614
|
+
|
615
|
+
def test_writes_to_logstash_index_with_specified_prefix_and_dateformat
|
616
|
+
driver.configure("logstash_format true
|
617
|
+
logstash_prefix myprefix
|
618
|
+
logstash_dateformat %Y.%m")
|
619
|
+
time = Time.parse Date.today.iso8601
|
620
|
+
logstash_index = "myprefix-#{time.getutc.strftime("%Y.%m")}"
|
621
|
+
stub_elastic
|
622
|
+
driver.run(default_tag: 'test') do
|
623
|
+
driver.feed(time.to_i, sample_record)
|
624
|
+
end
|
625
|
+
assert_equal(logstash_index, index_cmds.first['index']['_index'])
|
626
|
+
end
|
627
|
+
|
628
|
+
def test_doesnt_add_logstash_timestamp_by_default
|
629
|
+
stub_elastic
|
630
|
+
driver.run(default_tag: 'test') do
|
631
|
+
driver.feed(sample_record)
|
632
|
+
end
|
633
|
+
assert_nil(index_cmds[1]['@timestamp'])
|
634
|
+
end
|
635
|
+
|
636
|
+
def test_adds_logstash_timestamp_when_configured
|
637
|
+
driver.configure("logstash_format true\n")
|
638
|
+
stub_elastic
|
639
|
+
time = Fluent::EventTime.new(Time.now.to_i, 123456789)
|
640
|
+
driver.run(default_tag: 'test') do
|
641
|
+
driver.feed(time, sample_record)
|
642
|
+
end
|
643
|
+
assert(index_cmds[1].has_key? '@timestamp')
|
644
|
+
assert_equal(Time.at(time).iso8601(9), index_cmds[1]['@timestamp'])
|
645
|
+
end
|
646
|
+
|
647
|
+
def test_uses_subsecond_precision_when_configured
|
648
|
+
driver.configure("logstash_format true
|
649
|
+
time_precision 3\n")
|
650
|
+
stub_elastic
|
651
|
+
time = Fluent::EventTime.new(Time.now.to_i, 123456789)
|
652
|
+
driver.run(default_tag: 'test') do
|
653
|
+
driver.feed(time, sample_record)
|
654
|
+
end
|
655
|
+
assert(index_cmds[1].has_key? '@timestamp')
|
656
|
+
assert_equal(Time.at(time).iso8601(3), index_cmds[1]['@timestamp'])
|
657
|
+
end
|
658
|
+
|
659
|
+
def test_uses_custom_timestamp_when_included_in_record
|
660
|
+
driver.configure("include_timestamp true\n")
|
661
|
+
stub_elastic
|
662
|
+
ts = DateTime.new(2001,2,3).iso8601
|
663
|
+
driver.run(default_tag: 'test') do
|
664
|
+
driver.feed(sample_record.merge!('@timestamp' => ts))
|
665
|
+
end
|
666
|
+
assert(index_cmds[1].has_key? '@timestamp')
|
667
|
+
assert_equal(ts, index_cmds[1]['@timestamp'])
|
668
|
+
end
|
669
|
+
|
670
|
+
def test_uses_custom_timestamp_when_included_in_record_logstash
|
671
|
+
driver.configure("logstash_format true\n")
|
672
|
+
stub_elastic
|
673
|
+
ts = DateTime.new(2001,2,3).iso8601
|
674
|
+
driver.run(default_tag: 'test') do
|
675
|
+
driver.feed(sample_record.merge!('@timestamp' => ts))
|
676
|
+
end
|
677
|
+
assert(index_cmds[1].has_key? '@timestamp')
|
678
|
+
assert_equal(ts, index_cmds[1]['@timestamp'])
|
679
|
+
end
|
680
|
+
|
681
|
+
def test_uses_custom_time_key_logstash
|
682
|
+
driver.configure("logstash_format true
|
683
|
+
time_key vtm\n")
|
684
|
+
stub_elastic
|
685
|
+
ts = DateTime.new(2001,2,3).iso8601
|
686
|
+
driver.run(default_tag: 'test') do
|
687
|
+
driver.feed(sample_record.merge!('vtm' => ts))
|
688
|
+
end
|
689
|
+
assert(index_cmds[1].has_key? '@timestamp')
|
690
|
+
assert_equal(ts, index_cmds[1]['@timestamp'])
|
691
|
+
end
|
692
|
+
|
693
|
+
def test_uses_custom_time_key_timestamp
|
694
|
+
driver.configure("include_timestamp true
|
695
|
+
time_key vtm\n")
|
696
|
+
stub_elastic
|
697
|
+
ts = DateTime.new(2001,2,3).iso8601
|
698
|
+
driver.run(default_tag: 'test') do
|
699
|
+
driver.feed(sample_record.merge!('vtm' => ts))
|
700
|
+
end
|
701
|
+
assert(index_cmds[1].has_key? '@timestamp')
|
702
|
+
assert_equal(ts, index_cmds[1]['@timestamp'])
|
703
|
+
end
|
704
|
+
|
705
|
+
def test_uses_custom_time_key_timestamp_custom_index
|
706
|
+
driver.configure("include_timestamp true
|
707
|
+
index_name test
|
708
|
+
time_key vtm\n")
|
709
|
+
stub_elastic
|
710
|
+
ts = DateTime.new(2001,2,3).iso8601
|
711
|
+
driver.run(default_tag: 'test') do
|
712
|
+
driver.feed(sample_record.merge!('vtm' => ts))
|
713
|
+
end
|
714
|
+
assert(index_cmds[1].has_key? '@timestamp')
|
715
|
+
assert_equal(ts, index_cmds[1]['@timestamp'])
|
716
|
+
assert_equal('test', index_cmds.first['index']['_index'])
|
717
|
+
end
|
718
|
+
|
719
|
+
def test_uses_custom_time_key_exclude_timestamp
|
720
|
+
driver.configure("include_timestamp true
|
721
|
+
time_key vtm
|
722
|
+
time_key_exclude_timestamp true\n")
|
723
|
+
stub_elastic
|
724
|
+
ts = DateTime.new(2001,2,3).iso8601
|
725
|
+
driver.run(default_tag: 'test') do
|
726
|
+
driver.feed(sample_record.merge!('vtm' => ts))
|
727
|
+
end
|
728
|
+
assert(!index_cmds[1].key?('@timestamp'), '@timestamp should be missing')
|
729
|
+
end
|
730
|
+
|
731
|
+
def test_uses_custom_time_key_exclude_timestamp_logstash
|
732
|
+
driver.configure("logstash_format true
|
733
|
+
time_key vtm
|
734
|
+
time_key_exclude_timestamp true\n")
|
735
|
+
stub_elastic
|
736
|
+
ts = DateTime.new(2001,2,3).iso8601
|
737
|
+
driver.run(default_tag: 'test') do
|
738
|
+
driver.feed(sample_record.merge!('vtm' => ts))
|
739
|
+
end
|
740
|
+
assert(!index_cmds[1].key?('@timestamp'), '@timestamp should be missing')
|
741
|
+
end
|
742
|
+
|
743
|
+
def test_doesnt_add_tag_key_by_default
|
744
|
+
stub_elastic
|
745
|
+
driver.run(default_tag: 'test') do
|
746
|
+
driver.feed(sample_record)
|
747
|
+
end
|
748
|
+
assert_nil(index_cmds[1]['tag'])
|
749
|
+
end
|
750
|
+
|
751
|
+
def test_adds_tag_key_when_configured
|
752
|
+
driver.configure("include_tag_key true\n")
|
753
|
+
stub_elastic
|
754
|
+
driver.run(default_tag: 'mytag') do
|
755
|
+
driver.feed(sample_record)
|
756
|
+
end
|
757
|
+
assert(index_cmds[1].has_key?('tag'))
|
758
|
+
assert_equal('mytag', index_cmds[1]['tag'])
|
759
|
+
end
|
760
|
+
|
761
|
+
def test_adds_id_key_when_configured
|
762
|
+
driver.configure("id_key request_id\n")
|
763
|
+
stub_elastic
|
764
|
+
driver.run(default_tag: 'test') do
|
765
|
+
driver.feed(sample_record)
|
766
|
+
end
|
767
|
+
assert_equal('42', index_cmds[0]['index']['_id'])
|
768
|
+
end
|
769
|
+
|
770
|
+
class NestedIdKeyTest < self
|
771
|
+
def test_adds_nested_id_key_with_dot
|
772
|
+
driver.configure("id_key nested.request_id\n")
|
773
|
+
stub_elastic
|
774
|
+
driver.run(default_tag: 'test') do
|
775
|
+
driver.feed(nested_sample_record)
|
776
|
+
end
|
777
|
+
assert_equal('42', index_cmds[0]['index']['_id'])
|
778
|
+
end
|
779
|
+
|
780
|
+
def test_adds_nested_id_key_with_dollar_dot
|
781
|
+
driver.configure("id_key $.nested.request_id\n")
|
782
|
+
stub_elastic
|
783
|
+
driver.run(default_tag: 'test') do
|
784
|
+
driver.feed(nested_sample_record)
|
785
|
+
end
|
786
|
+
assert_equal('42', index_cmds[0]['index']['_id'])
|
787
|
+
end
|
788
|
+
|
789
|
+
def test_adds_nested_id_key_with_bracket
|
790
|
+
driver.configure("id_key $['nested']['request_id']\n")
|
791
|
+
stub_elastic
|
792
|
+
driver.run(default_tag: 'test') do
|
793
|
+
driver.feed(nested_sample_record)
|
794
|
+
end
|
795
|
+
assert_equal('42', index_cmds[0]['index']['_id'])
|
796
|
+
end
|
797
|
+
end
|
798
|
+
|
799
|
+
def test_doesnt_add_id_key_if_missing_when_configured
|
800
|
+
driver.configure("id_key another_request_id\n")
|
801
|
+
stub_elastic
|
802
|
+
driver.run(default_tag: 'test') do
|
803
|
+
driver.feed(sample_record)
|
804
|
+
end
|
805
|
+
assert(!index_cmds[0]['index'].has_key?('_id'))
|
806
|
+
end
|
807
|
+
|
808
|
+
def test_adds_id_key_when_not_configured
|
809
|
+
stub_elastic
|
810
|
+
driver.run(default_tag: 'test') do
|
811
|
+
driver.feed(sample_record)
|
812
|
+
end
|
813
|
+
assert(!index_cmds[0]['index'].has_key?('_id'))
|
814
|
+
end
|
815
|
+
|
816
|
+
def test_adds_parent_key_when_configured
|
817
|
+
driver.configure("parent_key parent_id\n")
|
818
|
+
stub_elastic
|
819
|
+
driver.run(default_tag: 'test') do
|
820
|
+
driver.feed(sample_record)
|
821
|
+
end
|
822
|
+
assert_equal('parent', index_cmds[0]['index']['_parent'])
|
823
|
+
end
|
824
|
+
|
825
|
+
class NestedParentKeyTest < self
|
826
|
+
def test_adds_nested_parent_key_with_dot
|
827
|
+
driver.configure("parent_key nested.parent_id\n")
|
828
|
+
stub_elastic
|
829
|
+
driver.run(default_tag: 'test') do
|
830
|
+
driver.feed(nested_sample_record)
|
831
|
+
end
|
832
|
+
assert_equal('parent', index_cmds[0]['index']['_parent'])
|
833
|
+
end
|
834
|
+
|
835
|
+
def test_adds_nested_parent_key_with_dollar_dot
|
836
|
+
driver.configure("parent_key $.nested.parent_id\n")
|
837
|
+
stub_elastic
|
838
|
+
driver.run(default_tag: 'test') do
|
839
|
+
driver.feed(nested_sample_record)
|
840
|
+
end
|
841
|
+
assert_equal('parent', index_cmds[0]['index']['_parent'])
|
842
|
+
end
|
843
|
+
|
844
|
+
def test_adds_nested_parent_key_with_bracket
|
845
|
+
driver.configure("parent_key $['nested']['parent_id']\n")
|
846
|
+
stub_elastic
|
847
|
+
driver.run(default_tag: 'test') do
|
848
|
+
driver.feed(nested_sample_record)
|
849
|
+
end
|
850
|
+
assert_equal('parent', index_cmds[0]['index']['_parent'])
|
851
|
+
end
|
852
|
+
end
|
853
|
+
|
854
|
+
def test_doesnt_add_parent_key_if_missing_when_configured
|
855
|
+
driver.configure("parent_key another_parent_id\n")
|
856
|
+
stub_elastic
|
857
|
+
driver.run(default_tag: 'test') do
|
858
|
+
driver.feed(sample_record)
|
859
|
+
end
|
860
|
+
assert(!index_cmds[0]['index'].has_key?('_parent'))
|
861
|
+
end
|
862
|
+
|
863
|
+
def test_adds_parent_key_when_not_configured
|
864
|
+
stub_elastic
|
865
|
+
driver.run(default_tag: 'test') do
|
866
|
+
driver.feed(sample_record)
|
867
|
+
end
|
868
|
+
assert(!index_cmds[0]['index'].has_key?('_parent'))
|
869
|
+
end
|
870
|
+
|
871
|
+
class AddsRoutingKeyWhenConfiguredTest < self
|
872
|
+
def test_es6
|
873
|
+
driver("routing_key routing_id\n", 6)
|
874
|
+
stub_elastic
|
875
|
+
driver.run(default_tag: 'test') do
|
876
|
+
driver.feed(sample_record)
|
877
|
+
end
|
878
|
+
assert_equal('routing', index_cmds[0]['index']['_routing'])
|
879
|
+
end
|
880
|
+
|
881
|
+
def test_es7
|
882
|
+
driver("routing_key routing_id\n", 7)
|
883
|
+
stub_elastic
|
884
|
+
driver.run(default_tag: 'test') do
|
885
|
+
driver.feed(sample_record)
|
886
|
+
end
|
887
|
+
assert_equal('routing', index_cmds[0]['index']['routing'])
|
888
|
+
end
|
889
|
+
end
|
890
|
+
|
891
|
+
class NestedRoutingKeyTest < self
|
892
|
+
def test_adds_nested_routing_key_with_dot
|
893
|
+
driver.configure("routing_key nested.routing_id\n")
|
894
|
+
stub_elastic
|
895
|
+
driver.run(default_tag: 'test') do
|
896
|
+
driver.feed(nested_sample_record)
|
897
|
+
end
|
898
|
+
assert_equal('routing', index_cmds[0]['index']['_routing'])
|
899
|
+
end
|
900
|
+
|
901
|
+
def test_adds_nested_routing_key_with_dollar_dot
|
902
|
+
driver.configure("routing_key $.nested.routing_id\n")
|
903
|
+
stub_elastic
|
904
|
+
driver.run(default_tag: 'test') do
|
905
|
+
driver.feed(nested_sample_record)
|
906
|
+
end
|
907
|
+
assert_equal('routing', index_cmds[0]['index']['_routing'])
|
908
|
+
end
|
909
|
+
|
910
|
+
def test_adds_nested_routing_key_with_bracket
|
911
|
+
driver.configure("routing_key $['nested']['routing_id']\n")
|
912
|
+
stub_elastic
|
913
|
+
driver.run(default_tag: 'test') do
|
914
|
+
driver.feed(nested_sample_record)
|
915
|
+
end
|
916
|
+
assert_equal('routing', index_cmds[0]['index']['_routing'])
|
917
|
+
end
|
918
|
+
end
|
919
|
+
|
920
|
+
def test_doesnt_add_routing_key_if_missing_when_configured
|
921
|
+
driver.configure("routing_key another_routing_id\n")
|
922
|
+
stub_elastic
|
923
|
+
driver.run(default_tag: 'test') do
|
924
|
+
driver.feed(sample_record)
|
925
|
+
end
|
926
|
+
assert(!index_cmds[0]['index'].has_key?('_routing'))
|
927
|
+
end
|
928
|
+
|
929
|
+
def test_adds_routing_key_when_not_configured
|
930
|
+
stub_elastic
|
931
|
+
driver.run(default_tag: 'test') do
|
932
|
+
driver.feed(sample_record)
|
933
|
+
end
|
934
|
+
assert(!index_cmds[0]['index'].has_key?('_routing'))
|
935
|
+
end
|
936
|
+
|
937
|
+
def test_remove_one_key
|
938
|
+
driver.configure("remove_keys key1\n")
|
939
|
+
stub_elastic
|
940
|
+
driver.run(default_tag: 'test') do
|
941
|
+
driver.feed(sample_record.merge('key1' => 'v1', 'key2' => 'v2'))
|
942
|
+
end
|
943
|
+
assert(!index_cmds[1].has_key?('key1'))
|
944
|
+
assert(index_cmds[1].has_key?('key2'))
|
945
|
+
end
|
946
|
+
|
947
|
+
def test_remove_multi_keys
|
948
|
+
driver.configure("remove_keys key1, key2\n")
|
949
|
+
stub_elastic
|
950
|
+
driver.run(default_tag: 'test') do
|
951
|
+
driver.feed(sample_record.merge('key1' => 'v1', 'key2' => 'v2'))
|
952
|
+
end
|
953
|
+
assert(!index_cmds[1].has_key?('key1'))
|
954
|
+
assert(!index_cmds[1].has_key?('key2'))
|
955
|
+
end
|
956
|
+
|
957
|
+
def test_request_error
|
958
|
+
stub_elastic_unavailable
|
959
|
+
assert_raise(Fluent::Plugin::ElasticsearchOutput::RecoverableRequestFailure) {
|
960
|
+
driver.run(default_tag: 'test', shutdown: false) do
|
961
|
+
driver.feed(sample_record)
|
962
|
+
end
|
963
|
+
}
|
964
|
+
end
|
965
|
+
|
966
|
+
def test_request_forever
|
967
|
+
omit("retry_forever test is unstable.") if ENV["CI"]
|
968
|
+
|
969
|
+
stub_elastic
|
970
|
+
driver.configure(Fluent::Config::Element.new(
|
971
|
+
'ROOT', '', {
|
972
|
+
'@type' => 'elasticsearch',
|
973
|
+
}, [
|
974
|
+
Fluent::Config::Element.new('buffer', '', {
|
975
|
+
'retry_forever' => true
|
976
|
+
}, [])
|
977
|
+
]
|
978
|
+
))
|
979
|
+
stub_elastic_timeout
|
980
|
+
assert_raise(Timeout::Error) {
|
981
|
+
driver.run(default_tag: 'test', timeout: 10, force_flush_retry: true) do
|
982
|
+
driver.feed(sample_record)
|
983
|
+
end
|
984
|
+
}
|
985
|
+
end
|
986
|
+
|
987
|
+
def test_tag_parts_index_error_event
|
988
|
+
stub_elastic
|
989
|
+
driver.configure("logstash_prefix ${tag_parts[1]}\n")
|
990
|
+
flexmock(driver.instance.router).should_receive(:emit_error_event)
|
991
|
+
.with('test', Fluent::EventTime, Hash, TypeError).once
|
992
|
+
driver.run(default_tag: 'test') do
|
993
|
+
driver.feed(sample_record)
|
994
|
+
end
|
995
|
+
end
|
996
|
+
|
997
|
+
def test_connection_failed
|
998
|
+
connection_resets = 0
|
999
|
+
|
1000
|
+
stub_request(:post, "http://localhost:9200/_bulk").with do |req|
|
1001
|
+
connection_resets += 1
|
1002
|
+
raise Faraday::ConnectionFailed, "Test message"
|
1003
|
+
end
|
1004
|
+
|
1005
|
+
assert_raise(Fluent::Plugin::ElasticsearchOutput::RecoverableRequestFailure) {
|
1006
|
+
driver.run(default_tag: 'test', shutdown: false) do
|
1007
|
+
driver.feed(sample_record)
|
1008
|
+
end
|
1009
|
+
}
|
1010
|
+
assert_equal(1, connection_resets)
|
1011
|
+
end
|
1012
|
+
|
1013
|
+
def test_reconnect_on_error_enabled
|
1014
|
+
connection_resets = 0
|
1015
|
+
|
1016
|
+
stub_request(:post, "http://localhost:9200/_bulk").with do |req|
|
1017
|
+
connection_resets += 1
|
1018
|
+
raise ZeroDivisionError, "any not host_unreachable_exceptions exception"
|
1019
|
+
end
|
1020
|
+
|
1021
|
+
driver.configure("reconnect_on_error true\n")
|
1022
|
+
|
1023
|
+
assert_raise(Fluent::Plugin::ElasticsearchOutput::RecoverableRequestFailure) {
|
1024
|
+
driver.run(default_tag: 'test', shutdown: false) do
|
1025
|
+
driver.feed(sample_record)
|
1026
|
+
end
|
1027
|
+
}
|
1028
|
+
|
1029
|
+
assert_raise(Timeout::Error) {
|
1030
|
+
driver.run(default_tag: 'test', shutdown: false) do
|
1031
|
+
driver.feed(sample_record)
|
1032
|
+
end
|
1033
|
+
}
|
1034
|
+
# FIXME: Consider keywords arguments in #run and how to test this later.
|
1035
|
+
# Because v0.14 test driver does not have 1 to 1 correspondence between #run and #flush in tests.
|
1036
|
+
assert_equal(1, connection_resets)
|
1037
|
+
end
|
1038
|
+
|
1039
|
+
def test_reconnect_on_error_disabled
|
1040
|
+
connection_resets = 0
|
1041
|
+
|
1042
|
+
stub_request(:post, "http://localhost:9200/_bulk").with do |req|
|
1043
|
+
connection_resets += 1
|
1044
|
+
raise ZeroDivisionError, "any not host_unreachable_exceptions exception"
|
1045
|
+
end
|
1046
|
+
|
1047
|
+
driver.configure("reconnect_on_error false\n")
|
1048
|
+
|
1049
|
+
assert_raise(Fluent::Plugin::ElasticsearchOutput::RecoverableRequestFailure) {
|
1050
|
+
driver.run(default_tag: 'test', shutdown: false) do
|
1051
|
+
driver.feed(sample_record)
|
1052
|
+
end
|
1053
|
+
}
|
1054
|
+
|
1055
|
+
assert_raise(Timeout::Error) {
|
1056
|
+
driver.run(default_tag: 'test', shutdown: false) do
|
1057
|
+
driver.feed(sample_record)
|
1058
|
+
end
|
1059
|
+
}
|
1060
|
+
assert_equal(1, connection_resets)
|
1061
|
+
end
|
1062
|
+
|
1063
|
+
def test_update_should_not_write_if_theres_no_id
|
1064
|
+
driver.configure("write_operation update\n")
|
1065
|
+
stub_elastic
|
1066
|
+
driver.run(default_tag: 'test') do
|
1067
|
+
driver.feed(sample_record)
|
1068
|
+
end
|
1069
|
+
assert_nil(index_cmds)
|
1070
|
+
end
|
1071
|
+
|
1072
|
+
def test_upsert_should_not_write_if_theres_no_id
|
1073
|
+
driver.configure("write_operation upsert\n")
|
1074
|
+
stub_elastic
|
1075
|
+
driver.run(default_tag: 'test') do
|
1076
|
+
driver.feed(sample_record)
|
1077
|
+
end
|
1078
|
+
assert_nil(index_cmds)
|
1079
|
+
end
|
1080
|
+
|
1081
|
+
def test_create_should_not_write_if_theres_no_id
|
1082
|
+
driver.configure("write_operation create\n")
|
1083
|
+
stub_elastic
|
1084
|
+
driver.run(default_tag: 'test') do
|
1085
|
+
driver.feed(sample_record)
|
1086
|
+
end
|
1087
|
+
assert_nil(index_cmds)
|
1088
|
+
end
|
1089
|
+
|
1090
|
+
def test_update_should_write_update_op_and_doc_as_upsert_is_false
|
1091
|
+
driver.configure("write_operation update
|
1092
|
+
id_key request_id")
|
1093
|
+
stub_elastic
|
1094
|
+
driver.run(default_tag: 'test') do
|
1095
|
+
driver.feed(sample_record)
|
1096
|
+
end
|
1097
|
+
assert(index_cmds[0].has_key?("update"))
|
1098
|
+
assert(!index_cmds[1]["doc_as_upsert"])
|
1099
|
+
end
|
1100
|
+
|
1101
|
+
def test_upsert_should_write_update_op_and_doc_as_upsert_is_true
|
1102
|
+
driver.configure("write_operation upsert
|
1103
|
+
id_key request_id")
|
1104
|
+
stub_elastic
|
1105
|
+
driver.run(default_tag: 'test') do
|
1106
|
+
driver.feed(sample_record)
|
1107
|
+
end
|
1108
|
+
assert(index_cmds[0].has_key?("update"))
|
1109
|
+
assert(index_cmds[1]["doc_as_upsert"])
|
1110
|
+
end
|
1111
|
+
|
1112
|
+
def test_create_should_write_create_op
|
1113
|
+
driver.configure("write_operation create
|
1114
|
+
id_key request_id")
|
1115
|
+
stub_elastic
|
1116
|
+
driver.run(default_tag: 'test') do
|
1117
|
+
driver.feed(sample_record)
|
1118
|
+
end
|
1119
|
+
assert(index_cmds[0].has_key?("create"))
|
1120
|
+
end
|
1121
|
+
|
1122
|
+
def test_include_index_in_url
|
1123
|
+
stub_elastic('http://localhost:9200/logstash-2018.01.01/_bulk')
|
1124
|
+
|
1125
|
+
driver.configure("index_name logstash-2018.01.01
|
1126
|
+
include_index_in_url true")
|
1127
|
+
driver.run(default_tag: 'test') do
|
1128
|
+
driver.feed(sample_record)
|
1129
|
+
end
|
1130
|
+
|
1131
|
+
assert_equal(2, index_cmds.length)
|
1132
|
+
assert_equal(nil, index_cmds.first['index']['_index'])
|
1133
|
+
end
|
1134
|
+
end
|