fluentd 1.12.4 → 1.13.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of fluentd might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.github/workflows/windows-test.yaml +13 -2
- data/CHANGELOG.md +42 -0
- data/CONTRIBUTING.md +2 -2
- data/MAINTAINERS.md +1 -1
- data/README.md +1 -1
- data/example/counter.conf +1 -1
- data/lib/fluent/command/cat.rb +19 -3
- data/lib/fluent/command/fluentd.rb +1 -2
- data/lib/fluent/log.rb +1 -0
- data/lib/fluent/plugin/file_wrapper.rb +13 -4
- data/lib/fluent/plugin/in_http.rb +10 -0
- data/lib/fluent/plugin/in_tail.rb +119 -39
- data/lib/fluent/plugin/out_forward.rb +13 -30
- data/lib/fluent/plugin_helper/service_discovery.rb +39 -1
- data/lib/fluent/plugin_helper/service_discovery/manager.rb +11 -5
- data/lib/fluent/supervisor.rb +15 -0
- data/lib/fluent/system_config.rb +14 -0
- data/lib/fluent/version.rb +1 -1
- data/test/command/test_cat.rb +96 -0
- data/test/config/test_system_config.rb +46 -0
- data/test/plugin/in_tail/test_io_handler.rb +4 -4
- data/test/plugin/test_file_wrapper.rb +11 -1
- data/test/plugin/test_in_http.rb +15 -0
- data/test/plugin/test_in_tail.rb +223 -1
- data/test/plugin/test_out_forward.rb +11 -6
- data/test/plugin_helper/test_service_discovery.rb +74 -14
- data/test/test_config.rb +2 -1
- data/test/test_supervisor.rb +35 -0
- metadata +4 -2
@@ -58,6 +58,15 @@ class FileWrapperTest < Test::Unit::TestCase
|
|
58
58
|
assert_equal("#<Fluent::Win32Error: code: 32, The process cannot access the file because it is being used by another process. - C:\file.txt>",
|
59
59
|
Fluent::Win32Error.new(ERROR_SHARING_VIOLATION, "C:\file.txt").inspect)
|
60
60
|
end
|
61
|
+
|
62
|
+
data('0' => [false, 0],
|
63
|
+
'9999' => [false, 9999],
|
64
|
+
'10000' => [true, 10000],
|
65
|
+
'10001' => [true, 10001])
|
66
|
+
test 'wsaerr?' do |data|
|
67
|
+
expected, code = data
|
68
|
+
assert_equal(expected, Fluent::Win32Error.new(code).wsaerr?)
|
69
|
+
end
|
61
70
|
end
|
62
71
|
|
63
72
|
sub_test_case 'WindowsFile exceptions' do
|
@@ -92,7 +101,8 @@ class FileWrapperTest < Test::Unit::TestCase
|
|
92
101
|
path = "#{TMP_DIR}/test_windows_file.txt"
|
93
102
|
file1 = file2 = nil
|
94
103
|
file1 = File.open(path, "wb")
|
95
|
-
|
104
|
+
win32err = Fluent::Win32Error.new(ERROR_SHARING_VIOLATION, path)
|
105
|
+
assert_raise(Errno::EACCES.new(win32err.message)) do
|
96
106
|
file2 = Fluent::WindowsFile.new(path, 'r', FILE_SHARE_READ)
|
97
107
|
ensure
|
98
108
|
file2.close if file2
|
data/test/plugin/test_in_http.rb
CHANGED
@@ -770,6 +770,15 @@ class HttpInputTest < Test::Unit::TestCase
|
|
770
770
|
end
|
771
771
|
end
|
772
772
|
|
773
|
+
def test_get_request
|
774
|
+
d = create_driver(CONFIG)
|
775
|
+
|
776
|
+
d.run do
|
777
|
+
res = get("/cors.test", {}, {})
|
778
|
+
assert_equal "200", res.code
|
779
|
+
end
|
780
|
+
end
|
781
|
+
|
773
782
|
def test_cors_preflight
|
774
783
|
d = create_driver(CONFIG + 'cors_allow_origins ["*"]')
|
775
784
|
|
@@ -985,6 +994,12 @@ class HttpInputTest < Test::Unit::TestCase
|
|
985
994
|
assert_equal $test_in_http_connection_object_ids[0], $test_in_http_connection_object_ids[1]
|
986
995
|
end
|
987
996
|
|
997
|
+
def get(path, params, header = {})
|
998
|
+
http = Net::HTTP.new("127.0.0.1", PORT)
|
999
|
+
req = Net::HTTP::Get.new(path, header)
|
1000
|
+
http.request(req)
|
1001
|
+
end
|
1002
|
+
|
988
1003
|
def options(path, params, header = {})
|
989
1004
|
http = Net::HTTP.new("127.0.0.1", PORT)
|
990
1005
|
req = Net::HTTP::Options.new(path, header)
|
data/test/plugin/test_in_tail.rb
CHANGED
@@ -156,6 +156,7 @@ class TailInputTest < Test::Unit::TestCase
|
|
156
156
|
assert_equal 2, d.instance.rotate_wait
|
157
157
|
assert_equal "#{TMP_DIR}/tail.pos", d.instance.pos_file
|
158
158
|
assert_equal 1000, d.instance.read_lines_limit
|
159
|
+
assert_equal -1, d.instance.read_bytes_limit_per_second
|
159
160
|
assert_equal false, d.instance.ignore_repeated_permission_error
|
160
161
|
assert_nothing_raised do
|
161
162
|
d.instance.have_read_capability?
|
@@ -195,6 +196,22 @@ class TailInputTest < Test::Unit::TestCase
|
|
195
196
|
end
|
196
197
|
end
|
197
198
|
|
199
|
+
sub_test_case "log throttling per file" do
|
200
|
+
test "w/o watcher timer is invalid" do
|
201
|
+
conf = CONFIG_ENABLE_WATCH_TIMER + config_element("ROOT", "", {"read_bytes_limit_per_second" => "8k"})
|
202
|
+
assert_raise(Fluent::ConfigError) do
|
203
|
+
create_driver(conf)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
test "valid" do
|
208
|
+
conf = config_element("ROOT", "", {"read_bytes_limit_per_second" => "8k"})
|
209
|
+
assert_raise(Fluent::ConfigError) do
|
210
|
+
create_driver(conf)
|
211
|
+
end
|
212
|
+
end
|
213
|
+
end
|
214
|
+
|
198
215
|
test "both enable_watch_timer and enable_stat_watcher are false" do
|
199
216
|
assert_raise(Fluent::ConfigError) do
|
200
217
|
create_driver(CONFIG_ENABLE_WATCH_TIMER + CONFIG_DISABLE_STAT_WATCHER + PARSE_SINGLE_LINE_CONFIG)
|
@@ -323,6 +340,138 @@ class TailInputTest < Test::Unit::TestCase
|
|
323
340
|
assert num_events <= d.emit_count
|
324
341
|
end
|
325
342
|
|
343
|
+
sub_test_case "log throttling per file" do
|
344
|
+
teardown do
|
345
|
+
cleanup_file("#{TMP_DIR}/tail.txt")
|
346
|
+
end
|
347
|
+
|
348
|
+
sub_test_case "reads_bytes_per_second w/o throttled" do
|
349
|
+
data("flat 8192 bytes, 2 events" => [:flat, 100, 8192, 2, false],
|
350
|
+
"flat 8192 bytes, 2 events already read limit reached" => [:flat, 100, 8192, 2, true],
|
351
|
+
"flat 8192 bytes, 2 events w/o stat watcher" => [:flat_without_stat, 100, 8192, 2, false],
|
352
|
+
"flat #{8192*10} bytes, 20 events" => [:flat, 100, (8192 * 10), 20],
|
353
|
+
"flat #{8192*10} bytes, 20 events w/o stat watcher" => [:flat_without_stat, 100, (8192 * 10), 20],
|
354
|
+
"parse #{8192*4} bytes, 8 events" => [:parse, 100, (8192 * 4), 8],
|
355
|
+
"parse #{8192*4} bytes, 8 events w/o stat watcher" => [:parse_without_stat, 100, (8192 * 4), 8],
|
356
|
+
"parse #{8192*10} bytes, 20 events" => [:parse, 100, (8192 * 10), 20],
|
357
|
+
"parse #{8192*10} bytes, 20 events w/o stat watcher" => [:parse_without_stat, 100, (8192 * 10), 20],
|
358
|
+
"flat 8k bytes with unit, 2 events" => [:flat, 100, "8k", 2],
|
359
|
+
"flat 8k bytes with unit, 2 events w/o stat watcher" => [:flat_without_stat, 100, "8k", 2],
|
360
|
+
"flat #{8*10}k bytes with unit, 20 events" => [:flat, 100, "#{8*10}k", 20],
|
361
|
+
"flat #{8*10}k bytes with unit, 20 events w/o stat watcher" => [:flat_without_stat, 100, "#{8*10}k", 20],
|
362
|
+
"parse #{8*4}k bytes with unit, 8 events" => [:parse, 100, "#{8*4}k", 8],
|
363
|
+
"parse #{8*4}k bytes with unit, 8 events w/o stat watcher" => [:parse_without_stat, 100, "#{8*4}k", 8],
|
364
|
+
"parse #{8*10}k bytes with unit, 20 events" => [:parse, 100, "#{8*10}k", 20],
|
365
|
+
"parse #{8*10}k bytes with unit, 20 events w/o stat watcher" => [:parse_without_stat, 100, "#{8*10}k", 20])
|
366
|
+
def test_emit_with_read_bytes_limit_per_second(data)
|
367
|
+
config_style, limit, limit_bytes, num_events = data
|
368
|
+
case config_style
|
369
|
+
when :flat
|
370
|
+
config = CONFIG_READ_FROM_HEAD + SINGLE_LINE_CONFIG + config_element("", "", { "read_lines_limit" => limit, "read_bytes_limit_per_second" => limit_bytes })
|
371
|
+
when :parse
|
372
|
+
config = CONFIG_READ_FROM_HEAD + config_element("", "", { "read_lines_limit" => limit, "read_bytes_limit_per_second" => limit_bytes }) + PARSE_SINGLE_LINE_CONFIG
|
373
|
+
when :flat_without_stat
|
374
|
+
config = CONFIG_READ_FROM_HEAD + SINGLE_LINE_CONFIG + CONFIG_DISABLE_STAT_WATCHER + config_element("", "", { "read_lines_limit" => limit, "read_bytes_limit_per_second" => limit_bytes })
|
375
|
+
when :parse_without_stat
|
376
|
+
config = CONFIG_READ_FROM_HEAD + CONFIG_DISABLE_STAT_WATCHER + config_element("", "", { "read_lines_limit" => limit, "read_bytes_limit_per_second" => limit_bytes }) + PARSE_SINGLE_LINE_CONFIG
|
377
|
+
end
|
378
|
+
|
379
|
+
msg = 'test' * 2000 # in_tail reads 8192 bytes at once.
|
380
|
+
start_time = Fluent::Clock.now
|
381
|
+
|
382
|
+
d = create_driver(config)
|
383
|
+
d.run(expect_emits: 2) do
|
384
|
+
File.open("#{TMP_DIR}/tail.txt", "ab") {|f|
|
385
|
+
100.times do
|
386
|
+
f.puts msg
|
387
|
+
end
|
388
|
+
}
|
389
|
+
end
|
390
|
+
|
391
|
+
assert_true(Fluent::Clock.now - start_time > 1)
|
392
|
+
assert_equal(num_events.times.map { {"message" => msg} },
|
393
|
+
d.events.collect { |event| event[2] })
|
394
|
+
end
|
395
|
+
|
396
|
+
def test_read_bytes_limit_precede_read_lines_limit
|
397
|
+
config = CONFIG_READ_FROM_HEAD +
|
398
|
+
SINGLE_LINE_CONFIG +
|
399
|
+
config_element("", "", {
|
400
|
+
"read_lines_limit" => 1000,
|
401
|
+
"read_bytes_limit_per_second" => 8192
|
402
|
+
})
|
403
|
+
msg = 'abc'
|
404
|
+
start_time = Fluent::Clock.now
|
405
|
+
d = create_driver(config)
|
406
|
+
d.run(expect_emits: 2) do
|
407
|
+
File.open("#{TMP_DIR}/tail.txt", "ab") {|f|
|
408
|
+
8000.times do
|
409
|
+
f.puts msg
|
410
|
+
end
|
411
|
+
}
|
412
|
+
end
|
413
|
+
|
414
|
+
assert_true(Fluent::Clock.now - start_time > 1)
|
415
|
+
assert_equal(4096.times.map { {"message" => msg} },
|
416
|
+
d.events.collect { |event| event[2] })
|
417
|
+
end
|
418
|
+
end
|
419
|
+
|
420
|
+
sub_test_case "reads_bytes_per_second w/ throttled already" do
|
421
|
+
data("flat 8192 bytes, 2 events" => [:flat, 100, 8192, 2],
|
422
|
+
"flat #{8192*10} bytes, 20 events" => [:flat, 100, (8192 * 10), 20],
|
423
|
+
"parse #{8192*4} bytes, 8 events" => [:parse, 100, (8192 * 4), 8],
|
424
|
+
"parse #{8192*10} bytes, 20 events" => [:parse, 100, (8192 * 10), 20],
|
425
|
+
"flat 8k bytes with unit, 2 events" => [:flat, 100, "8k", 2],
|
426
|
+
"flat #{8*10}k bytes with unit, 20 events" => [:flat, 100, "#{8*10}k", 20],
|
427
|
+
"parse #{8*4}k bytes with unit, 8 events" => [:parse, 100, "#{8*4}k", 8],
|
428
|
+
"parse #{8*10}k bytes with unit, 20 events" => [:parse, 100, "#{8*10}k", 20])
|
429
|
+
def test_emit_with_read_bytes_limit_per_second(data)
|
430
|
+
config_style, limit, limit_bytes, num_events = data
|
431
|
+
case config_style
|
432
|
+
when :flat
|
433
|
+
config = CONFIG_READ_FROM_HEAD + SINGLE_LINE_CONFIG + config_element("", "", { "read_lines_limit" => limit, "read_bytes_limit_per_second" => limit_bytes })
|
434
|
+
when :parse
|
435
|
+
config = CONFIG_READ_FROM_HEAD + config_element("", "", { "read_lines_limit" => limit, "read_bytes_limit_per_second" => limit_bytes }) + PARSE_SINGLE_LINE_CONFIG
|
436
|
+
end
|
437
|
+
d = create_driver(config)
|
438
|
+
msg = 'test' * 2000 # in_tail reads 8192 bytes at once.
|
439
|
+
|
440
|
+
mock.proxy(d.instance).io_handler(anything, anything) do |io_handler|
|
441
|
+
require 'fluent/config/types'
|
442
|
+
limit_bytes_value = Fluent::Config.size_value(limit_bytes)
|
443
|
+
io_handler.instance_variable_set(:@number_bytes_read, limit_bytes_value)
|
444
|
+
if Fluent.linux?
|
445
|
+
mock.proxy(io_handler).handle_notify.at_least(5)
|
446
|
+
else
|
447
|
+
mock.proxy(io_handler).handle_notify.twice
|
448
|
+
end
|
449
|
+
io_handler
|
450
|
+
end
|
451
|
+
|
452
|
+
File.open("#{TMP_DIR}/tail.txt", "ab") do |f|
|
453
|
+
100.times do
|
454
|
+
f.puts msg
|
455
|
+
end
|
456
|
+
end
|
457
|
+
|
458
|
+
# We should not do shutdown here due to hard timeout.
|
459
|
+
d.run do
|
460
|
+
start_time = Fluent::Clock.now
|
461
|
+
while Fluent::Clock.now - start_time < 0.8 do
|
462
|
+
File.open("#{TMP_DIR}/tail.txt", "ab") do |f|
|
463
|
+
f.puts msg
|
464
|
+
f.flush
|
465
|
+
end
|
466
|
+
sleep 0.05
|
467
|
+
end
|
468
|
+
end
|
469
|
+
|
470
|
+
assert_equal([], d.events)
|
471
|
+
end
|
472
|
+
end
|
473
|
+
end
|
474
|
+
|
326
475
|
data(flat: CONFIG_READ_FROM_HEAD + SINGLE_LINE_CONFIG,
|
327
476
|
parse: CONFIG_READ_FROM_HEAD + PARSE_SINGLE_LINE_CONFIG)
|
328
477
|
def test_emit_with_read_from_head(data)
|
@@ -1935,6 +2084,79 @@ class TailInputTest < Test::Unit::TestCase
|
|
1935
2084
|
d.run(shutdown: false) {}
|
1936
2085
|
end
|
1937
2086
|
d.instance_shutdown
|
1938
|
-
assert($log.out.logs.any?{|log| log.include?("stat() for #{path} failed with ENOENT. Drop tail watcher for now.\n") })
|
2087
|
+
assert($log.out.logs.any?{|log| log.include?("stat() for #{path} failed with Errno::ENOENT. Drop tail watcher for now.\n") })
|
2088
|
+
end
|
2089
|
+
|
2090
|
+
def test_EACCES_error_after_setup_watcher
|
2091
|
+
path = "#{TMP_DIR}/noaccess/tail.txt"
|
2092
|
+
begin
|
2093
|
+
FileUtils.mkdir_p("#{TMP_DIR}/noaccess")
|
2094
|
+
FileUtils.chmod(0755, "#{TMP_DIR}/noaccess")
|
2095
|
+
FileUtils.touch(path)
|
2096
|
+
config = config_element('', '', {
|
2097
|
+
'tag' => "tail",
|
2098
|
+
'path' => path,
|
2099
|
+
'format' => 'none',
|
2100
|
+
})
|
2101
|
+
d = create_driver(config, false)
|
2102
|
+
mock.proxy(d.instance).setup_watcher(anything, anything) do |tw|
|
2103
|
+
FileUtils.chmod(0000, "#{TMP_DIR}/noaccess")
|
2104
|
+
tw
|
2105
|
+
end
|
2106
|
+
assert_nothing_raised do
|
2107
|
+
d.run(shutdown: false) {}
|
2108
|
+
end
|
2109
|
+
d.instance_shutdown
|
2110
|
+
assert($log.out.logs.any?{|log| log.include?("stat() for #{path} failed with Errno::EACCES. Drop tail watcher for now.\n") })
|
2111
|
+
end
|
2112
|
+
ensure
|
2113
|
+
FileUtils.chmod(0755, "#{TMP_DIR}/noaccess")
|
2114
|
+
FileUtils.rm_rf("#{TMP_DIR}/noaccess")
|
2115
|
+
end unless Fluent.windows?
|
2116
|
+
|
2117
|
+
def test_EACCES
|
2118
|
+
path = "#{TMP_DIR}/tail.txt"
|
2119
|
+
FileUtils.touch(path)
|
2120
|
+
config = config_element('', '', {
|
2121
|
+
'format' => 'none',
|
2122
|
+
})
|
2123
|
+
d = create_driver(config)
|
2124
|
+
mock.proxy(Fluent::FileWrapper).stat(path) do |stat|
|
2125
|
+
raise Errno::EACCES
|
2126
|
+
end.at_least(1)
|
2127
|
+
assert_nothing_raised do
|
2128
|
+
d.run(shutdown: false) {}
|
2129
|
+
end
|
2130
|
+
d.instance_shutdown
|
2131
|
+
assert($log.out.logs.any?{|log| log.include?("expand_paths: stat() for #{path} failed with Errno::EACCES. Skip file.\n") })
|
2132
|
+
end
|
2133
|
+
|
2134
|
+
def test_shutdown_timeout
|
2135
|
+
path = "#{TMP_DIR}/tail.txt"
|
2136
|
+
File.open("#{TMP_DIR}/tail.txt", "wb") do |f|
|
2137
|
+
(1024 * 1024 * 5).times do
|
2138
|
+
f.puts "{\"test\":\"fizzbuzz\"}"
|
2139
|
+
end
|
2140
|
+
end
|
2141
|
+
|
2142
|
+
config =
|
2143
|
+
CONFIG_READ_FROM_HEAD +
|
2144
|
+
config_element('', '', {
|
2145
|
+
'format' => 'json',
|
2146
|
+
'skip_refresh_on_startup' => true,
|
2147
|
+
})
|
2148
|
+
d = create_driver(config)
|
2149
|
+
mock.proxy(d.instance).io_handler(anything, anything) do |io_handler|
|
2150
|
+
io_handler.shutdown_timeout = 0.5
|
2151
|
+
io_handler
|
2152
|
+
end
|
2153
|
+
|
2154
|
+
start_time = Fluent::Clock.now
|
2155
|
+
assert_nothing_raised do
|
2156
|
+
d.run(expect_emits: 1)
|
2157
|
+
end
|
2158
|
+
|
2159
|
+
elapsed = Fluent::Clock.now - start_time
|
2160
|
+
assert_true(elapsed > 0.5 && elapsed < 2.5)
|
1939
2161
|
end
|
1940
2162
|
end
|
@@ -277,11 +277,16 @@ EOL
|
|
277
277
|
</service_discovery>
|
278
278
|
])
|
279
279
|
|
280
|
-
|
281
|
-
assert_equal
|
282
|
-
|
283
|
-
|
284
|
-
|
280
|
+
|
281
|
+
assert_equal(
|
282
|
+
[
|
283
|
+
{ host: '127.0.0.1', port: 1234 },
|
284
|
+
{ host: '127.0.0.1', port: 1235 },
|
285
|
+
],
|
286
|
+
d.instance.discovery_manager.services.collect do |service|
|
287
|
+
{ host: service.host, port: service.port }
|
288
|
+
end
|
289
|
+
)
|
285
290
|
end
|
286
291
|
|
287
292
|
test 'pass username and password as empty string to HandshakeProtocol' do
|
@@ -1073,7 +1078,7 @@ EOL
|
|
1073
1078
|
test 'when out_forward has @id' do
|
1074
1079
|
# cancel https://github.com/fluent/fluentd/blob/077508ac817b7637307434d0c978d7cdc3d1c534/lib/fluent/plugin_id.rb#L43-L53
|
1075
1080
|
# it always return true in test
|
1076
|
-
mock.proxy(Fluent::Plugin).new_sd(
|
1081
|
+
mock.proxy(Fluent::Plugin).new_sd('static', parent: anything) { |v|
|
1077
1082
|
stub(v).plugin_id_for_test? { false }
|
1078
1083
|
}.once
|
1079
1084
|
|
@@ -17,6 +17,24 @@ class ServiceDiscoveryHelper < Test::Unit::TestCase
|
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
+
class DummyPlugin < Fluent::Plugin::TestBase
|
21
|
+
helpers :service_discovery
|
22
|
+
|
23
|
+
def configure(conf)
|
24
|
+
super
|
25
|
+
service_discovery_configure(:service_discovery_helper_test, static_default_service_directive: 'node')
|
26
|
+
end
|
27
|
+
|
28
|
+
def select_service(&block)
|
29
|
+
service_discovery_select_service(&block)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Make these mehtod public
|
33
|
+
def discovery_manager
|
34
|
+
super
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
20
38
|
setup do
|
21
39
|
@sd_file_dir = File.expand_path('../plugin/data/sd_file', __dir__)
|
22
40
|
|
@@ -33,7 +51,7 @@ class ServiceDiscoveryHelper < Test::Unit::TestCase
|
|
33
51
|
end
|
34
52
|
end
|
35
53
|
|
36
|
-
test '
|
54
|
+
test 'support calling #service_discovery_create_manager and #discovery_manager from plugin' do
|
37
55
|
d = @d = Dummy.new
|
38
56
|
|
39
57
|
d.service_discovery_create_manager(
|
@@ -55,13 +73,30 @@ class ServiceDiscoveryHelper < Test::Unit::TestCase
|
|
55
73
|
assert_equal 1234, services[0].port
|
56
74
|
end
|
57
75
|
|
58
|
-
test '
|
59
|
-
d = @d =
|
76
|
+
test 'start discovery manager' do
|
77
|
+
d = @d = DummyPlugin.new
|
60
78
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
79
|
+
services = [config_element('service', '', { 'host' => '127.0.0.1', 'port' => '1234' })]
|
80
|
+
d.configure(config_element('root', '', {}, [config_element('service_discovery', '', {'@type' => 'static'}, services)]))
|
81
|
+
|
82
|
+
assert_true !!d.discovery_manager
|
83
|
+
|
84
|
+
mock.proxy(d.discovery_manager).start.once
|
85
|
+
mock.proxy(d).timer_execute(:service_discovery_helper_test, anything).never
|
86
|
+
|
87
|
+
d.start
|
88
|
+
d.event_loop_wait_until_start
|
89
|
+
|
90
|
+
assert_equal 1, d.discovery_manager.services.size
|
91
|
+
d.select_service do |serv|
|
92
|
+
assert_equal "127.0.0.1", serv.host
|
93
|
+
assert_equal 1234, serv.port
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
test 'call timer_execute if dynamic configuration' do
|
98
|
+
d = @d = DummyPlugin.new
|
99
|
+
d.configure(config_element('root', '', {}, [config_element('service_discovery', '', { '@type' => 'file', 'path' => File.join(@sd_file_dir, 'config.yml' )})]))
|
65
100
|
|
66
101
|
assert_true !!d.discovery_manager
|
67
102
|
mock.proxy(d.discovery_manager).start.once
|
@@ -71,25 +106,22 @@ class ServiceDiscoveryHelper < Test::Unit::TestCase
|
|
71
106
|
end
|
72
107
|
|
73
108
|
test 'exits service discovery instances without any errors' do
|
74
|
-
d = @d =
|
109
|
+
d = @d = DummyPlugin.new
|
75
110
|
mockv = flexmock('dns_resolver', getaddress: '127.0.0.1')
|
76
111
|
.should_receive(:getresources)
|
77
112
|
.and_return([Resolv::DNS::Resource::IN::SRV.new(1, 10, 8081, 'service1.example.com')])
|
78
113
|
.mock
|
79
114
|
mock(Resolv::DNS).new { mockv }
|
80
115
|
|
81
|
-
d.
|
82
|
-
:service_discovery_helper_test2,
|
83
|
-
configurations: [{ type: :srv, conf: config_element('service_discovery', '', { 'service' => 'service1', 'hostname' => 'example.com' }) }],
|
84
|
-
)
|
116
|
+
d.configure(config_element('root', '', {}, [config_element('service_discovery', '', { '@type' => 'srv', 'service' => 'service1', 'hostname' => 'example.com' })]))
|
85
117
|
|
86
118
|
assert_true !!d.discovery_manager
|
87
119
|
mock.proxy(d.discovery_manager).start.once
|
88
|
-
mock(d).timer_execute(:
|
120
|
+
mock(d).timer_execute(:service_discovery_helper_test, anything).once
|
89
121
|
|
90
122
|
# To avoid claring `@logs` during `terminate` step
|
91
123
|
# https://github.com/fluent/fluentd/blob/bc78d889f93dad8c2a4e0ad1ca802546185dacba/lib/fluent/test/log.rb#L33
|
92
|
-
mock(d.log).reset.
|
124
|
+
mock(d.log).reset.times(3)
|
93
125
|
|
94
126
|
d.start
|
95
127
|
d.event_loop_wait_until_start
|
@@ -102,4 +134,32 @@ class ServiceDiscoveryHelper < Test::Unit::TestCase
|
|
102
134
|
|
103
135
|
assert_false(d.log.out.logs.any? { |e| e.match?(/thread doesn't exit correctly/) })
|
104
136
|
end
|
137
|
+
|
138
|
+
test 'static service discovery will be configured automatically when default service directive is specified' do
|
139
|
+
d = @d = DummyPlugin.new
|
140
|
+
|
141
|
+
nodes = [
|
142
|
+
config_element('node', '', { 'host' => '192.168.0.1', 'port' => '24224' }),
|
143
|
+
config_element('node', '', { 'host' => '192.168.0.2', 'port' => '24224' })
|
144
|
+
]
|
145
|
+
d.configure(config_element('root', '', {}, nodes))
|
146
|
+
|
147
|
+
assert_true !!d.discovery_manager
|
148
|
+
|
149
|
+
mock.proxy(d.discovery_manager).start.once
|
150
|
+
mock.proxy(d).timer_execute(:service_discovery_helper_test, anything).never
|
151
|
+
|
152
|
+
d.start
|
153
|
+
d.event_loop_wait_until_start
|
154
|
+
|
155
|
+
assert_equal 2, d.discovery_manager.services.size
|
156
|
+
d.select_service do |serv|
|
157
|
+
assert_equal "192.168.0.1", serv.host
|
158
|
+
assert_equal 24224, serv.port
|
159
|
+
end
|
160
|
+
d.select_service do |serv|
|
161
|
+
assert_equal "192.168.0.2", serv.host
|
162
|
+
assert_equal 24224, serv.port
|
163
|
+
end
|
164
|
+
end
|
105
165
|
end
|