fluentd 1.7.4 → 1.8.0.rc1

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.

Potentially problematic release.


This version of fluentd might be problematic. Click here for more details.

Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +26 -0
  3. data/example/out_forward_sd.conf +17 -0
  4. data/example/sd.yaml +8 -0
  5. data/lib/fluent/command/cat.rb +1 -2
  6. data/lib/fluent/compat/call_super_mixin.rb +9 -0
  7. data/lib/fluent/compat/exec_util.rb +1 -1
  8. data/lib/fluent/counter/base_socket.rb +2 -4
  9. data/lib/fluent/engine.rb +1 -8
  10. data/lib/fluent/event.rb +5 -7
  11. data/lib/fluent/msgpack_factory.rb +19 -2
  12. data/lib/fluent/plugin.rb +10 -1
  13. data/lib/fluent/plugin/buf_file.rb +9 -1
  14. data/lib/fluent/plugin/buf_file_single.rb +6 -0
  15. data/lib/fluent/plugin/buffer/file_chunk.rb +2 -3
  16. data/lib/fluent/plugin/buffer/file_single_chunk.rb +1 -2
  17. data/lib/fluent/plugin/formatter_csv.rb +22 -0
  18. data/lib/fluent/plugin/in_forward.rb +1 -1
  19. data/lib/fluent/plugin/in_tail.rb +6 -0
  20. data/lib/fluent/plugin/in_unix.rb +1 -1
  21. data/lib/fluent/plugin/out_forward.rb +77 -28
  22. data/lib/fluent/plugin/out_forward/ack_handler.rb +1 -1
  23. data/lib/fluent/plugin/out_forward/load_balancer.rb +5 -2
  24. data/lib/fluent/plugin/out_stream.rb +1 -1
  25. data/lib/fluent/plugin/parser.rb +1 -0
  26. data/lib/fluent/plugin/sd_file.rb +155 -0
  27. data/lib/fluent/plugin/sd_static.rb +58 -0
  28. data/lib/fluent/plugin/service_discovery.rb +80 -0
  29. data/lib/fluent/plugin_helper.rb +1 -0
  30. data/lib/fluent/plugin_helper/record_accessor.rb +10 -19
  31. data/lib/fluent/plugin_helper/service_discovery.rb +80 -0
  32. data/lib/fluent/plugin_helper/service_discovery/manager.rb +132 -0
  33. data/lib/fluent/plugin_helper/service_discovery/round_robin_balancer.rb +43 -0
  34. data/lib/fluent/plugin_id.rb +7 -0
  35. data/lib/fluent/supervisor.rb +9 -8
  36. data/lib/fluent/system_config.rb +0 -2
  37. data/lib/fluent/version.rb +1 -1
  38. data/test/config/test_system_config.rb +0 -1
  39. data/test/plugin/data/sd_file/config +11 -0
  40. data/test/plugin/data/sd_file/config.json +17 -0
  41. data/test/plugin/data/sd_file/config.yaml +11 -0
  42. data/test/plugin/data/sd_file/config.yml +11 -0
  43. data/test/plugin/data/sd_file/invalid_config.yml +7 -0
  44. data/test/plugin/out_forward/test_handshake_protocol.rb +2 -2
  45. data/test/plugin/out_forward/test_socket_cache.rb +2 -2
  46. data/test/plugin/test_formatter_csv.rb +9 -0
  47. data/test/plugin/test_in_forward.rb +9 -9
  48. data/test/plugin/test_in_unix.rb +5 -5
  49. data/test/plugin/test_out_forward.rb +45 -1
  50. data/test/plugin/test_out_stream.rb +3 -3
  51. data/test/plugin/test_sd_file.rb +211 -0
  52. data/test/plugin_helper/service_discovery/test_manager.rb +93 -0
  53. data/test/plugin_helper/service_discovery/test_round_robin_balancer.rb +21 -0
  54. data/test/plugin_helper/test_service_discovery.rb +72 -0
  55. data/test/test_event.rb +15 -15
  56. metadata +29 -3
@@ -23,6 +23,7 @@ module Fluent
23
23
  def initialize
24
24
  super
25
25
  @_plugin_root_dir = nil
26
+ @id = nil
26
27
  end
27
28
 
28
29
  def configure(conf)
@@ -76,5 +77,11 @@ module Fluent
76
77
  @_plugin_root_dir = dir.freeze
77
78
  dir
78
79
  end
80
+
81
+ def stop
82
+ @@configured_ids.delete(@id)
83
+
84
+ super
85
+ end
79
86
  end
80
87
  end
@@ -25,6 +25,7 @@ require 'fluent/log'
25
25
  require 'fluent/plugin'
26
26
  require 'fluent/rpc'
27
27
  require 'fluent/system_config'
28
+ require 'fluent/msgpack_factory'
28
29
  require 'serverengine'
29
30
 
30
31
  if Fluent.windows?
@@ -41,7 +42,6 @@ end
41
42
  module Fluent
42
43
  module ServerModule
43
44
  def before_run
44
- @start_time = Time.now
45
45
  @rpc_server = nil
46
46
  @counter = nil
47
47
 
@@ -457,7 +457,6 @@ module Fluent
457
457
  @plugin_dirs = opt[:plugin_dirs]
458
458
  @chgroup = opt[:chgroup]
459
459
  @chuser = opt[:chuser]
460
- @rpc_server = nil
461
460
  @process_name = nil
462
461
 
463
462
  @workers = opt[:workers]
@@ -554,6 +553,7 @@ module Fluent
554
553
  main_process do
555
554
  create_socket_manager if @standalone_worker
556
555
  change_privilege if @standalone_worker
556
+ MessagePackFactory.init
557
557
  init_engine
558
558
  run_configure
559
559
  run_engine
@@ -585,6 +585,7 @@ module Fluent
585
585
  begin
586
586
  Fluent::Engine.dry_run_mode = true
587
587
  change_privilege
588
+ MessagePackFactory.init
588
589
  init_engine
589
590
  run_configure
590
591
  rescue Fluent::ConfigError => e
@@ -772,15 +773,15 @@ module Fluent
772
773
  end
773
774
 
774
775
  def read_config
775
- @config_fname = File.basename(@config_path)
776
- @config_basedir = File.dirname(@config_path)
777
- @config_data = File.open(@config_path, "r:#{@conf_encoding}:utf-8") {|f| f.read }
776
+ config_fname = File.basename(@config_path)
777
+ config_basedir = File.dirname(@config_path)
778
+ config_data = File.open(@config_path, "r:#{@conf_encoding}:utf-8") {|f| f.read }
778
779
  if @inline_config == '-'
779
- @config_data << "\n" << STDIN.read
780
+ config_data << "\n" << STDIN.read
780
781
  elsif @inline_config
781
- @config_data << "\n" << @inline_config.gsub("\\n","\n")
782
+ config_data << "\n" << @inline_config.gsub("\\n","\n")
782
783
  end
783
- @conf = Fluent::Config.parse(@config_data, @config_fname, @config_basedir, @use_v1_config)
784
+ @conf = Fluent::Config.parse(config_data, config_fname, config_basedir, @use_v1_config)
784
785
  end
785
786
 
786
787
  def set_system_config
@@ -152,8 +152,6 @@ module Fluent
152
152
  case param
153
153
  when :log_level
154
154
  @log.level = @log_level = param_value
155
- when :emit_error_log_interval
156
- @suppress_interval = param_value
157
155
  else
158
156
  instance_variable_set("@#{param}", param_value)
159
157
  end
@@ -16,6 +16,6 @@
16
16
 
17
17
  module Fluent
18
18
 
19
- VERSION = '1.7.4'
19
+ VERSION = '1.8.0.rc1'
20
20
 
21
21
  end
@@ -74,7 +74,6 @@ module Fluent::Config
74
74
  'root_dir' => ['root_dir', File.join(TMP_DIR, 'root')],
75
75
  'log_level' => ['log_level', 'error'],
76
76
  'suppress_repeated_stacktrace' => ['suppress_repeated_stacktrace', true],
77
- 'emit_error_log_interval' => ['emit_error_log_interval', 60],
78
77
  'log_event_verbose' => ['log_event_verbose', true],
79
78
  'suppress_config_dump' => ['suppress_config_dump', true],
80
79
  'without_source' => ['without_source', true],
@@ -0,0 +1,11 @@
1
+ - 'host': 127.0.0.1
2
+ 'port': 24224
3
+ 'weight': 1
4
+ 'name': test1
5
+ 'standby': false
6
+ 'username': user1
7
+ 'password': pass1
8
+ 'shared_key': key1
9
+ - 'host': 127.0.0.1
10
+ 'port': 24225
11
+ 'weight': 1
@@ -0,0 +1,17 @@
1
+ [
2
+ {
3
+ "host": "127.0.0.1",
4
+ "port": 24224,
5
+ "weight": 1,
6
+ "name": "test1",
7
+ "standby": false,
8
+ "username": "user1",
9
+ "password": "pass1",
10
+ "shared_key": "key1"
11
+ },
12
+ {
13
+ "host": "127.0.0.1",
14
+ "port": 24225,
15
+ "weight": 1
16
+ }
17
+ ]
@@ -0,0 +1,11 @@
1
+ - 'host': 127.0.0.1
2
+ 'port': 24224
3
+ 'weight': 1
4
+ 'name': test1
5
+ 'standby': false
6
+ 'username': user1
7
+ 'password': pass1
8
+ 'shared_key': key1
9
+ - 'host': 127.0.0.1
10
+ 'port': 24225
11
+ 'weight': 1
@@ -0,0 +1,11 @@
1
+ - 'host': 127.0.0.1
2
+ 'port': 24224
3
+ 'weight': 1
4
+ 'name': test1
5
+ 'standby': false
6
+ 'username': user1
7
+ 'password': pass1
8
+ 'shared_key': key1
9
+ - 'host': 127.0.0.1
10
+ 'port': 24225
11
+ 'weight': 1
@@ -0,0 +1,7 @@
1
+ - 'host': 127.0.0.1
2
+ 'weight': 1
3
+ 'name': test1
4
+ 'standby': false
5
+ 'username': user1
6
+ 'password': pass1
7
+ 'shared_key': key1
@@ -16,7 +16,7 @@ class HandshakeProtocolTest < Test::Unit::TestCase
16
16
  handshake.invoke(sock, ri, ['HELO', {}])
17
17
 
18
18
  assert_equal(ri.state, :pingpong)
19
- Fluent::Engine.msgpack_factory.unpacker.feed_each(sock.string) do |ping|
19
+ Fluent::MessagePackFactory.msgpack_unpacker.feed_each(sock.string) do |ping|
20
20
  assert_equal(ping.size, 6)
21
21
  assert_equal(ping[0], 'PING')
22
22
  assert_equal(ping[1], hostname)
@@ -38,7 +38,7 @@ class HandshakeProtocolTest < Test::Unit::TestCase
38
38
  handshake.invoke(sock, ri, ['HELO', { 'auth' => 'auth' }])
39
39
 
40
40
  assert_equal(ri.state, :pingpong)
41
- Fluent::Engine.msgpack_factory.unpacker.feed_each(sock.string) do |ping|
41
+ Fluent::MessagePackFactory.msgpack_unpacker.feed_each(sock.string) do |ping|
42
42
  assert_equal(ping.size, 6)
43
43
  assert_equal(ping[0], 'PING')
44
44
  assert_equal(ping[1], hostname)
@@ -23,7 +23,7 @@ class SocketCacheTest < Test::Unit::TestCase
23
23
 
24
24
  test 'when given key exists but used by other' do
25
25
  c = Fluent::Plugin::ForwardOutput::SocketCache.new(10, $log)
26
- assert_equal(@sock, c.checkout_or('key') { @sock })
26
+ assert_equal('sock', c.checkout_or('key') { 'sock' })
27
27
 
28
28
  new_sock = 'new sock'
29
29
  sock = mock!.open { new_sock }.subject
@@ -32,7 +32,7 @@ class SocketCacheTest < Test::Unit::TestCase
32
32
 
33
33
  test "when given key's value was expired" do
34
34
  c = Fluent::Plugin::ForwardOutput::SocketCache.new(0, $log)
35
- assert_equal(@sock, c.checkout_or('key') { @sock })
35
+ assert_equal('sock', c.checkout_or('key') { 'sock' })
36
36
 
37
37
  new_sock = 'new sock'
38
38
  sock = mock!.open { new_sock }.subject
@@ -54,6 +54,15 @@ class CsvFormatterTest < ::Test::Unit::TestCase
54
54
  assert_equal("\"awesome\",\"awesome2\"\n", formatted)
55
55
  end
56
56
 
57
+ def test_format_with_nested_fields
58
+ d = create_driver("fields" => "message,$.nest.key")
59
+ formatted = d.instance.format(tag, @time, {
60
+ 'message' => 'awesome',
61
+ 'nest' => {'key' => 'awesome2'}
62
+ })
63
+ assert_equal("\"awesome\",\"awesome2\"\n", formatted)
64
+ end
65
+
57
66
  def test_format_without_newline
58
67
  d = create_driver("fields" => "message,message2", "add_newline" => false)
59
68
  formatted = d.instance.format(tag, @time, {
@@ -538,7 +538,7 @@ class ForwardInputTest < Test::Unit::TestCase
538
538
  chunk = ["tag1", entries, { 'compressed' => 'gzip' }].to_msgpack
539
539
 
540
540
  d.run do
541
- Fluent::Engine.msgpack_factory.unpacker.feed_each(chunk) do |obj|
541
+ Fluent::MessagePackFactory.msgpack_unpacker.feed_each(chunk) do |obj|
542
542
  option = d.instance.send(:on_message, obj, chunk.size, DUMMY_SOCK)
543
543
  assert_equal 'gzip', option['compressed']
544
544
  end
@@ -568,7 +568,7 @@ class ForwardInputTest < Test::Unit::TestCase
568
568
  mock(Fluent::CompressedMessagePackEventStream).new(entries, nil, 0)
569
569
 
570
570
  d.run do
571
- Fluent::Engine.msgpack_factory.unpacker.feed_each(chunk) do |obj|
571
+ Fluent::MessagePackFactory.msgpack_unpacker.feed_each(chunk) do |obj|
572
572
  option = d.instance.send(:on_message, obj, chunk.size, DUMMY_SOCK)
573
573
  assert_equal 'gzip', option['compressed']
574
574
  end
@@ -592,7 +592,7 @@ class ForwardInputTest < Test::Unit::TestCase
592
592
  assert chunk.size < (32 * 1024 * 1024)
593
593
 
594
594
  d.run(shutdown: false) do
595
- Fluent::Engine.msgpack_factory.unpacker.feed_each(chunk) do |obj|
595
+ Fluent::MessagePackFactory.msgpack_unpacker.feed_each(chunk) do |obj|
596
596
  d.instance.send(:on_message, obj, chunk.size, DUMMY_SOCK)
597
597
  end
598
598
  end
@@ -624,7 +624,7 @@ class ForwardInputTest < Test::Unit::TestCase
624
624
  chunk = [ "test.tag", (0...16).map{|i| [time + i, {"data" => str}] } ].to_msgpack
625
625
 
626
626
  d.run(shutdown: false) do
627
- Fluent::Engine.msgpack_factory.unpacker.feed_each(chunk) do |obj|
627
+ Fluent::MessagePackFactory.msgpack_unpacker.feed_each(chunk) do |obj|
628
628
  d.instance.send(:on_message, obj, chunk.size, DUMMY_SOCK)
629
629
  end
630
630
  end
@@ -654,7 +654,7 @@ class ForwardInputTest < Test::Unit::TestCase
654
654
 
655
655
  # d.run => send_data
656
656
  d.run(shutdown: false) do
657
- Fluent::Engine.msgpack_factory.unpacker.feed_each(chunk) do |obj|
657
+ Fluent::MessagePackFactory.msgpack_unpacker.feed_each(chunk) do |obj|
658
658
  d.instance.send(:on_message, obj, chunk.size, DUMMY_SOCK)
659
659
  end
660
660
  end
@@ -1004,11 +1004,11 @@ class ForwardInputTest < Test::Unit::TestCase
1004
1004
  end
1005
1005
 
1006
1006
  def packer(*args)
1007
- Fluent::Engine.msgpack_factory.packer(*args)
1007
+ Fluent::MessagePackFactory.msgpack_packer(*args)
1008
1008
  end
1009
1009
 
1010
1010
  def unpacker
1011
- Fluent::Engine.msgpack_factory.unpacker
1011
+ Fluent::MessagePackFactory.msgpack_unpacker
1012
1012
  end
1013
1013
 
1014
1014
  # res
@@ -1158,9 +1158,9 @@ class ForwardInputTest < Test::Unit::TestCase
1158
1158
  execute_test_with_source_hostname_key(*keys) { |events|
1159
1159
  entries = ''
1160
1160
  events.each { |tag, time, record|
1161
- Fluent::Engine.msgpack_factory.packer(entries).write([time, record]).flush
1161
+ Fluent::MessagePackFactory.msgpack_packer(entries).write([time, record]).flush
1162
1162
  }
1163
- send_data Fluent::Engine.msgpack_factory.packer.write(["tag1", entries]).to_s
1163
+ send_data Fluent::MessagePackFactory.msgpack_packer.write(["tag1", entries]).to_s
1164
1164
  }
1165
1165
  end
1166
1166
  end
@@ -18,7 +18,7 @@ module StreamInputTest
18
18
 
19
19
  d.run do
20
20
  d.expected_emits.each {|tag,_time,record|
21
- send_data Fluent::Engine.msgpack_factory.packer.write([tag, 0, record]).to_s
21
+ send_data Fluent::MessagePackFactory.msgpack_packer.write([tag, 0, record]).to_s
22
22
  }
23
23
  end
24
24
  end
@@ -33,7 +33,7 @@ module StreamInputTest
33
33
 
34
34
  d.run do
35
35
  d.expected_emits.each {|tag,_time,record|
36
- send_data Fluent::Engine.msgpack_factory.packer.write([tag, _time, record]).to_s
36
+ send_data Fluent::MessagePackFactory.msgpack_packer.write([tag, _time, record]).to_s
37
37
  }
38
38
  end
39
39
  end
@@ -51,7 +51,7 @@ module StreamInputTest
51
51
  d.expected_emits.each {|tag,_time,record|
52
52
  entries << [_time, record]
53
53
  }
54
- send_data Fluent::Engine.msgpack_factory.packer.write(["tag1", entries]).to_s
54
+ send_data Fluent::MessagePackFactory.msgpack_packer.write(["tag1", entries]).to_s
55
55
  end
56
56
  end
57
57
 
@@ -66,9 +66,9 @@ module StreamInputTest
66
66
  d.run do
67
67
  entries = ''
68
68
  d.expected_emits.each {|tag,_time,record|
69
- Fluent::Engine.msgpack_factory.packer(entries).write([_time, record]).flush
69
+ Fluent::MessagePackFactory.msgpack_packer(entries).write([_time, record]).flush
70
70
  }
71
- send_data Fluent::Engine.msgpack_factory.packer.write(["tag1", entries]).to_s
71
+ send_data Fluent::MessagePackFactory.msgpack_packer.write(["tag1", entries]).to_s
72
72
  end
73
73
  end
74
74
 
@@ -39,7 +39,7 @@ class ForwardOutputTest < Test::Unit::TestCase
39
39
 
40
40
  def create_driver(conf=CONFIG)
41
41
  Fluent::Test::Driver::Output.new(Fluent::Plugin::ForwardOutput) {
42
- attr_reader :sent_chunk_ids, :ack_handler
42
+ attr_reader :sent_chunk_ids, :ack_handler, :discovery_manager
43
43
 
44
44
  def initialize
45
45
  super
@@ -260,6 +260,30 @@ EOL
260
260
  end
261
261
  end
262
262
 
263
+ test 'server is an abbreviation of static type of service_discovery' do
264
+ @d = d = create_driver(%[
265
+ <server>
266
+ host 127.0.0.1
267
+ port 1234
268
+ </server>
269
+
270
+ <service_discovery>
271
+ @type static
272
+
273
+ <service>
274
+ host 127.0.0.1
275
+ port 1235
276
+ </service>
277
+ </service_discovery>
278
+ ])
279
+
280
+ assert_equal 2, d.instance.discovery_manager.services.size
281
+ assert_equal '127.0.0.1', d.instance.discovery_manager.services[0].host
282
+ assert_equal 1234, d.instance.discovery_manager.services[0].port
283
+ assert_equal '127.0.0.1', d.instance.discovery_manager.services[1].host
284
+ assert_equal 1235, d.instance.discovery_manager.services[1].port
285
+ end
286
+
263
287
  test 'compress_default_value' do
264
288
  @d = d = create_driver
265
289
  assert_equal :text, d.instance.compress
@@ -945,6 +969,26 @@ EOL
945
969
  end
946
970
  end
947
971
 
972
+ test 'when out_forward has @id' do
973
+ # cancel https://github.com/fluent/fluentd/blob/077508ac817b7637307434d0c978d7cdc3d1c534/lib/fluent/plugin_id.rb#L43-L53
974
+ # it always return true in test
975
+ mock.proxy(Fluent::Plugin).new_sd(:static, anything) { |v|
976
+ stub(v).plugin_id_for_test? { false }
977
+ }.once
978
+
979
+ output = Fluent::Test::Driver::Output.new(Fluent::Plugin::ForwardOutput) {
980
+ def plugin_id_for_test?
981
+ false
982
+ end
983
+ }
984
+
985
+ assert_nothing_raised do
986
+ output.configure(CONFIG + %[
987
+ @id unique_out_forward
988
+ ])
989
+ end
990
+ end
991
+
948
992
  sub_test_case 'verify_connection_at_startup' do
949
993
  test 'nodes are not available' do
950
994
  @d = d = create_driver(CONFIG + %[
@@ -31,10 +31,10 @@ module StreamOutputTest
31
31
  d.emit({"a"=>2}, time)
32
32
 
33
33
  expect = ["test",
34
- Fluent::Engine.msgpack_factory.packer.write([time,{"a"=>1}]).to_s +
35
- Fluent::Engine.msgpack_factory.packer.write([time,{"a"=>2}]).to_s
34
+ Fluent::MessagePackFactory.msgpack_packer.write([time,{"a"=>1}]).to_s +
35
+ Fluent::MessagePackFactory.msgpack_packer.write([time,{"a"=>2}]).to_s
36
36
  ]
37
- expect = Fluent::Engine.msgpack_factory.packer.write(expect).to_s
37
+ expect = Fluent::MessagePackFactory.msgpack_packer.write(expect).to_s
38
38
 
39
39
  result = d.run
40
40
  assert_equal(expect, result)
@@ -0,0 +1,211 @@
1
+ require_relative '../helper'
2
+ require 'fluent/plugin/sd_file'
3
+ require 'fileutils'
4
+ require 'json'
5
+
6
+ class FileServiceDiscoveryTest < ::Test::Unit::TestCase
7
+ setup do
8
+ @dir = File.expand_path('data/sd_file', __dir__)
9
+ FileUtils.mkdir_p(File.join(@dir, 'tmp'))
10
+ end
11
+
12
+ teardown do
13
+ FileUtils.rm_r(File.join(@dir, 'tmp'))
14
+ end
15
+
16
+ sub_test_case 'configure' do
17
+ test 'load yml' do
18
+ sdf = Fluent::Plugin::FileServiceDiscovery.new
19
+ sdf.configure(config_element('service_discovery', '', { 'path' => File.join(@dir, 'config.yml') }))
20
+ assert_equal Fluent::Plugin::ServiceDiscovery::Service.new(:file, '127.0.0.1', 24224, 'test1', 1, false, 'user1', 'pass1', 'key1'), sdf.services[0]
21
+ assert_equal Fluent::Plugin::ServiceDiscovery::Service.new(:file, '127.0.0.1', 24225, nil, 1), sdf.services[1]
22
+ end
23
+
24
+ test 'load yaml' do
25
+ sdf = Fluent::Plugin::FileServiceDiscovery.new
26
+ sdf.configure(config_element('service_discovery', '', { 'path' => File.join(@dir, 'config.yaml') }))
27
+ assert_equal Fluent::Plugin::ServiceDiscovery::Service.new(:file, '127.0.0.1', 24224, 'test1', 1, false, 'user1', 'pass1', 'key1'), sdf.services[0]
28
+ assert_equal Fluent::Plugin::ServiceDiscovery::Service.new(:file, '127.0.0.1', 24225, nil, 1), sdf.services[1]
29
+ end
30
+
31
+ test 'load json' do
32
+ sdf = Fluent::Plugin::FileServiceDiscovery.new
33
+ sdf.configure(config_element('service_discovery', '', { 'path' => File.join(@dir, 'config.json') }))
34
+ assert_equal Fluent::Plugin::ServiceDiscovery::Service.new(:file, '127.0.0.1', 24224, 'test1', 1, false, 'user1', 'pass1', 'key1'), sdf.services[0]
35
+ assert_equal Fluent::Plugin::ServiceDiscovery::Service.new(:file, '127.0.0.1', 24225, nil, 1), sdf.services[1]
36
+ end
37
+
38
+ test 'regard as yaml if ext is not givened' do
39
+ sdf = Fluent::Plugin::FileServiceDiscovery.new
40
+ sdf.configure(config_element('service_discovery', '', { 'path' => File.join(@dir, 'config') }))
41
+ assert_equal Fluent::Plugin::ServiceDiscovery::Service.new(:file, '127.0.0.1', 24224, 'test1', 1, false, 'user1', 'pass1', 'key1'), sdf.services[0]
42
+ assert_equal Fluent::Plugin::ServiceDiscovery::Service.new(:file, '127.0.0.1', 24225, nil, 1), sdf.services[1]
43
+ end
44
+
45
+ test 'raise an error if config has error' do
46
+ sdf = Fluent::Plugin::FileServiceDiscovery.new
47
+ e = assert_raise Fluent::ConfigError do
48
+ sdf.configure(config_element('service_discovery', '', { 'path' => File.join(@dir, 'invalid_config.yaml') }))
49
+ end
50
+ assert_match(/path=/, e.message)
51
+ end
52
+
53
+ test 'raise an error if config file does not exist' do
54
+ sdf = Fluent::Plugin::FileServiceDiscovery.new
55
+ e = assert_raise Fluent::ConfigError do
56
+ sdf.configure(config_element('service_discovery', '', { 'path' => File.join(@dir, 'invalid_not_found.json') }))
57
+ end
58
+ assert_match(/not found/, e.message)
59
+ end
60
+ end
61
+
62
+ sub_test_case '#start' do
63
+ module TestStatEventHelperWrapper
64
+ # easy to control statsevent
65
+ def event_loop_attach(watcher)
66
+ unless watcher.is_a?(Fluent::Plugin::FileServiceDiscovery::StatWatcher)
67
+ super
68
+ return
69
+ end
70
+
71
+ @test_stat_event_helper_wrapper_watchers ||= []
72
+ @test_stat_event_helper_wrapper_watchers << watcher
73
+
74
+ @test_stat_event_helper_wrapper_context = Fiber.new do
75
+ loop do
76
+ @test_stat_event_helper_wrapper_watchers.each do |w|
77
+ w.on_change('old', 'new')
78
+ end
79
+
80
+ if Fiber.yield == :finish
81
+ break
82
+ end
83
+ end
84
+ end
85
+ resume
86
+ end
87
+
88
+ def resume
89
+ @test_stat_event_helper_wrapper_context.resume(:resume)
90
+ end
91
+
92
+ def shutdown
93
+ super
94
+
95
+ if @test_stat_event_helper_wrapper_context
96
+ @test_stat_event_helper_wrapper_context.resume(:finish)
97
+ end
98
+ end
99
+ end
100
+
101
+ def create_tmp_config(path, body)
102
+ File.write(File.join(@dir, 'tmp', path), body)
103
+ end
104
+
105
+ setup do
106
+ sdf = Fluent::Plugin::FileServiceDiscovery.new
107
+ @sd_file = sdf
108
+ end
109
+
110
+ teardown do
111
+ if @sd_file
112
+ @sd_file.stop unless @sd_file.stopped?
113
+ @sd_file.before_shutdown unless @sd_file.before_shutdown?
114
+ @sd_file.shutdown unless @sd_file.shutdown?
115
+ @sd_file.after_shutdown unless @sd_file.after_shutdown?
116
+ @sd_file.close unless @sd_file.closed?
117
+ @sd_file.terminate unless @sd_file.terminated?
118
+ end
119
+ end
120
+
121
+ test 'Skip if file is not updated' do
122
+ @sd_file.extend(TestStatEventHelperWrapper)
123
+
124
+ create_tmp_config('config.json', JSON.generate([{ port: 1233, host: '127.0.0.1' }]))
125
+ @sd_file.configure(config_element('service_discovery', '', { 'path' => File.join(@dir, 'config.yml') }))
126
+ queue = []
127
+ mock.proxy(@sd_file).refresh_file(queue).twice
128
+
129
+ @sd_file.start(queue)
130
+ assert_empty queue
131
+
132
+ @sd_file.resume
133
+ assert_empty queue
134
+ end
135
+
136
+ test 'Skip if file is invalid contents' do
137
+ @sd_file.extend(TestStatEventHelperWrapper)
138
+
139
+ create_tmp_config('config.json', JSON.generate([{ port: 1233, host: '127.0.0.1' }]))
140
+ @sd_file.configure(config_element('service_discovery', '', { 'path' => File.join(@dir, 'config.yml') }))
141
+
142
+ queue = []
143
+ @sd_file.start(queue)
144
+
145
+ mock.proxy(@sd_file).refresh_file(queue).once
146
+ create_tmp_config('test.json', 'invalid contents')
147
+ @sd_file.resume
148
+
149
+ assert_empty queue
150
+ end
151
+
152
+ test 'if service is updated, service_in and service_out event happen' do
153
+ @sd_file.extend(TestStatEventHelperWrapper)
154
+
155
+ create_tmp_config('test.json', JSON.generate([{ port: 1233, host: '127.0.0.1' }]))
156
+ @sd_file.configure(config_element('service_discovery', '', { 'path' => File.join(@dir, 'tmp/test.json') }))
157
+
158
+ queue = []
159
+ @sd_file.start(queue)
160
+ create_tmp_config('test.json', JSON.generate([{ port: 1234, host: '127.0.0.1' }]))
161
+ @sd_file.resume
162
+
163
+ assert_equal 2, queue.size
164
+ join = queue.shift
165
+ drain = queue.shift
166
+ assert_equal Fluent::Plugin::ServiceDiscovery::SERVICE_IN, join.type
167
+ assert_equal 1234, join.service.port
168
+ assert_equal '127.0.0.1', join.service.host
169
+
170
+ assert_equal Fluent::Plugin::ServiceDiscovery::SERVICE_OUT, drain.type
171
+ assert_equal 1233, drain.service.port
172
+ assert_equal '127.0.0.1', drain.service.host
173
+ end
174
+
175
+ test 'if service is deleted, service_out event happens' do
176
+ @sd_file.extend(TestStatEventHelperWrapper)
177
+
178
+ create_tmp_config('test.json', JSON.generate([{ port: 1233, host: '127.0.0.1' }, { port: 1234, host: '127.0.0.2' }]))
179
+ @sd_file.configure(config_element('service_discovery', '', { 'path' => File.join(@dir, 'tmp/test.json') }))
180
+
181
+ queue = []
182
+ @sd_file.start(queue)
183
+ create_tmp_config('test.json', JSON.generate([{ port: 1233, host: '127.0.0.1' }]))
184
+ @sd_file.resume
185
+
186
+ assert_equal 1, queue.size
187
+ drain = queue.shift
188
+ assert_equal Fluent::Plugin::ServiceDiscovery::SERVICE_OUT, drain.type
189
+ assert_equal 1234, drain.service.port
190
+ assert_equal '127.0.0.2', drain.service.host
191
+ end
192
+
193
+ test 'if new service is added, service_in event happens' do
194
+ @sd_file.extend(TestStatEventHelperWrapper)
195
+
196
+ create_tmp_config('test.json', JSON.generate([{ port: 1233, host: '127.0.0.1' }]))
197
+ @sd_file.configure(config_element('service_discovery', '', { 'path' => File.join(@dir, 'tmp/test.json') }))
198
+
199
+ queue = []
200
+ @sd_file.start(queue)
201
+ create_tmp_config('test.json', JSON.generate([{ port: 1233, host: '127.0.0.1' }, { port: 1234, host: '127.0.0.2' }]))
202
+ @sd_file.resume
203
+
204
+ assert_equal 1, queue.size
205
+ join = queue.shift
206
+ assert_equal Fluent::Plugin::ServiceDiscovery::SERVICE_IN, join.type
207
+ assert_equal 1234, join.service.port
208
+ assert_equal '127.0.0.2', join.service.host
209
+ end
210
+ end
211
+ end