fluentd 0.14.4 → 0.14.5

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.

Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/ChangeLog +18 -0
  3. data/example/in_forward.conf +3 -0
  4. data/example/in_forward_client.conf +37 -0
  5. data/example/in_forward_shared_key.conf +15 -0
  6. data/example/in_forward_users.conf +24 -0
  7. data/example/out_forward.conf +13 -13
  8. data/example/out_forward_client.conf +109 -0
  9. data/example/out_forward_shared_key.conf +36 -0
  10. data/example/out_forward_users.conf +65 -0
  11. data/example/{out_buffered_null.conf → out_null.conf} +10 -6
  12. data/example/secondary_file.conf +41 -0
  13. data/lib/fluent/agent.rb +3 -1
  14. data/lib/fluent/plugin/buffer.rb +5 -1
  15. data/lib/fluent/plugin/in_forward.rb +300 -50
  16. data/lib/fluent/plugin/in_tail.rb +41 -85
  17. data/lib/fluent/plugin/multi_output.rb +4 -0
  18. data/lib/fluent/plugin/out_forward.rb +326 -209
  19. data/lib/fluent/plugin/out_null.rb +37 -0
  20. data/lib/fluent/plugin/out_secondary_file.rb +128 -0
  21. data/lib/fluent/plugin/out_stdout.rb +38 -2
  22. data/lib/fluent/plugin/output.rb +13 -5
  23. data/lib/fluent/root_agent.rb +1 -1
  24. data/lib/fluent/test/startup_shutdown.rb +33 -0
  25. data/lib/fluent/version.rb +1 -1
  26. data/test/plugin/test_in_forward.rb +906 -441
  27. data/test/plugin/test_in_monitor_agent.rb +4 -0
  28. data/test/plugin/test_in_tail.rb +681 -663
  29. data/test/plugin/test_out_forward.rb +150 -208
  30. data/test/plugin/test_out_null.rb +85 -9
  31. data/test/plugin/test_out_secondary_file.rb +432 -0
  32. data/test/plugin/test_out_stdout.rb +143 -45
  33. data/test/test_root_agent.rb +42 -0
  34. metadata +14 -9
  35. data/lib/fluent/plugin/out_buffered_null.rb +0 -59
  36. data/lib/fluent/plugin/out_buffered_stdout.rb +0 -70
  37. data/test/plugin/test_out_buffered_null.rb +0 -79
  38. data/test/plugin/test_out_buffered_stdout.rb +0 -122
@@ -1,14 +1,17 @@
1
1
  require_relative '../helper'
2
2
  require 'fluent/test'
3
+ require 'fluent/test/startup_shutdown'
3
4
  require 'fluent/plugin/out_forward'
4
5
 
5
6
  class ForwardOutputTest < Test::Unit::TestCase
7
+ extend Fluent::Test::StartupShutdown
8
+
6
9
  def setup
7
10
  Fluent::Test.setup
8
11
  end
9
12
 
10
13
  TARGET_HOST = '127.0.0.1'
11
- TARGET_PORT = 13999
14
+ TARGET_PORT = unused_port
12
15
  CONFIG = %[
13
16
  send_timeout 51
14
17
  heartbeat_type udp
@@ -25,7 +28,7 @@ class ForwardOutputTest < Test::Unit::TestCase
25
28
  ]
26
29
 
27
30
  def create_driver(conf=CONFIG)
28
- Fluent::Test::BufferedOutputTestDriver.new(Fluent::ForwardOutput) {
31
+ d = Fluent::Test::BufferedOutputTestDriver.new(Fluent::ForwardOutput) {
29
32
  attr_reader :responses, :exceptions
30
33
 
31
34
  def initialize
@@ -34,18 +37,32 @@ class ForwardOutputTest < Test::Unit::TestCase
34
37
  @exceptions = []
35
38
  end
36
39
 
37
- def send_data(node, tag, chunk)
38
- # Original #send_data returns nil when it does not wait for responses or when on response timeout.
39
- @responses << super(node, tag, chunk)
40
- rescue => e
41
- @exceptions << e
42
- raise e
40
+ def configure(conf)
41
+ super
42
+ m = Module.new do
43
+ def send_data(tag, chunk)
44
+ @sender.responses << super
45
+ rescue => e
46
+ @sender.exceptions << e
47
+ raise e
48
+ end
49
+ end
50
+ @nodes.each do |node|
51
+ node.singleton_class.prepend(m)
52
+ end
43
53
  end
44
54
  }.configure(conf)
55
+ router = Object.new
56
+ def router.method_missing(name, *args, **kw_args, &block)
57
+ Engine.root_agent.event_router.__send__(name, *args, **kw_args, &block)
58
+ end
59
+ d.instance.router = router
60
+ d
45
61
  end
46
62
 
47
63
  def test_configure
48
64
  d = create_driver(%[
65
+ self_hostname localhost
49
66
  <server>
50
67
  name test
51
68
  host #{TARGET_HOST}
@@ -59,7 +76,7 @@ class ForwardOutputTest < Test::Unit::TestCase
59
76
  node = nodes.first
60
77
  assert_equal "test", node.name
61
78
  assert_equal '127.0.0.1', node.host
62
- assert_equal 13999, node.port
79
+ assert_equal TARGET_PORT, node.port
63
80
  end
64
81
 
65
82
  def test_configure_udp_heartbeat
@@ -79,11 +96,9 @@ class ForwardOutputTest < Test::Unit::TestCase
79
96
 
80
97
  d = create_driver(CONFIG + "\nheartbeat_type tcp\ndns_round_robin true")
81
98
  assert_equal true, d.instance.dns_round_robin
82
- assert_equal true, d.instance.nodes.first.conf.dns_round_robin
83
99
 
84
100
  d = create_driver(CONFIG + "\nheartbeat_type none\ndns_round_robin true")
85
101
  assert_equal true, d.instance.dns_round_robin
86
- assert_equal true, d.instance.nodes.first.conf.dns_round_robin
87
102
  end
88
103
 
89
104
  def test_configure_no_server
@@ -118,70 +133,6 @@ class ForwardOutputTest < Test::Unit::TestCase
118
133
  assert_equal 2, d.instance.ack_response_timeout
119
134
  end
120
135
 
121
- def test_sending_contains_with_ack
122
- target_input_driver = create_target_input_driver(true)
123
-
124
- d = create_driver(CONFIG + %[
125
- ack_response_timeout 1s
126
- ])
127
-
128
- time = Time.parse("2011-01-02 13:14:15 UTC").to_i
129
-
130
- records = [
131
- {"a" => 1},
132
- {"a" => 2}
133
- ]
134
- d.register_run_post_condition do
135
- d.instance.responses.length == 1
136
- end
137
-
138
- target_input_driver.run do
139
- d.run do
140
- records.each do |record|
141
- d.emit record, time
142
- end
143
- end
144
- end
145
-
146
- emits = target_input_driver.emits
147
- assert_equal ['test', time, records[0]], emits[0]
148
- assert_equal ['test', time, records[1]], emits[1]
149
-
150
- assert_equal target_input_driver.instance.received_options[0]['size'], 2
151
- end
152
-
153
- def test_sending_contains_without_ack
154
- target_input_driver = create_target_input_driver(true)
155
-
156
- d = create_driver(CONFIG + %[
157
- ack_response_timeout 1s
158
- ])
159
-
160
- time = Time.parse("2011-01-02 13:14:15 UTC").to_i
161
-
162
- records = [
163
- {"a" => 1},
164
- {"a" => 2}
165
- ]
166
- d.register_run_post_condition do
167
- d.instance.responses.length == 1
168
- end
169
-
170
- target_input_driver.run do
171
- d.run do
172
- records.each do |record|
173
- d.emit record, time
174
- end
175
- end
176
- end
177
-
178
- emits = target_input_driver.emits
179
- assert_equal ['test', time, records[0]], emits[0]
180
- assert_equal ['test', time, records[1]], emits[1]
181
-
182
- assert_equal target_input_driver.instance.received_options[0]['size'], 2
183
- end
184
-
185
136
  def test_send_with_time_as_integer
186
137
  target_input_driver = create_target_input_driver
187
138
 
@@ -252,7 +203,7 @@ class ForwardOutputTest < Test::Unit::TestCase
252
203
  end
253
204
 
254
205
  def test_send_to_a_node_supporting_responses
255
- target_input_driver = create_target_input_driver(true)
206
+ target_input_driver = create_target_input_driver(response_stub: true)
256
207
 
257
208
  d = create_driver(CONFIG + %[flush_interval 1s])
258
209
 
@@ -314,7 +265,7 @@ class ForwardOutputTest < Test::Unit::TestCase
314
265
  end
315
266
 
316
267
  def test_require_a_node_supporting_responses_to_respond_with_ack
317
- target_input_driver = create_target_input_driver(true)
268
+ target_input_driver = create_target_input_driver
318
269
 
319
270
  d = create_driver(CONFIG + %[
320
271
  flush_interval 1s
@@ -350,8 +301,7 @@ class ForwardOutputTest < Test::Unit::TestCase
350
301
  end
351
302
 
352
303
  def test_require_a_node_not_supporting_responses_to_respond_with_ack
353
- # in_forward, that doesn't support ack feature, and keep connection alive
354
- target_input_driver = create_target_input_driver
304
+ target_input_driver = create_target_input_driver(response_stub: ->(_option) { nil }, disconnect: true)
355
305
 
356
306
  d = create_driver(CONFIG + %[
357
307
  flush_interval 1s
@@ -394,7 +344,7 @@ class ForwardOutputTest < Test::Unit::TestCase
394
344
  # bdf1f4f104c00a791aa94dc20087fe2011e1fd83
395
345
  def test_require_a_node_not_supporting_responses_2_to_respond_with_ack
396
346
  # in_forward, that doesn't support ack feature, and disconnect immediately
397
- target_input_driver = create_target_input_driver(false, true)
347
+ target_input_driver = create_target_input_driver(response_stub: ->(_option) { nil }, disconnect: true)
398
348
 
399
349
  d = create_driver(CONFIG + %[
400
350
  flush_interval 1s
@@ -413,7 +363,7 @@ class ForwardOutputTest < Test::Unit::TestCase
413
363
  end
414
364
  d.run_timeout = 2
415
365
 
416
- assert_raise Fluent::ForwardOutputConnectionClosedError do
366
+ assert_raise Fluent::ForwardOutputACKTimeoutError do
417
367
  target_input_driver.run do
418
368
  d.run do
419
369
  records.each do |record|
@@ -434,85 +384,136 @@ class ForwardOutputTest < Test::Unit::TestCase
434
384
  assert_equal false, node.available # node is regarded as unavailable when unexpected EOF
435
385
  end
436
386
 
437
- def create_target_input_driver(do_respond=false, disconnect=false, conf=TARGET_CONFIG)
438
- require 'fluent/plugin/in_forward'
387
+ def test_authentication_with_shared_key
388
+ input_conf = TARGET_CONFIG + %[
389
+ <security>
390
+ self_hostname in.localhost
391
+ shared_key fluentd-sharedkey
392
+ <client>
393
+ host 127.0.0.1
394
+ </client>
395
+ </security>
396
+ ]
397
+ target_input_driver = create_target_input_driver(conf: input_conf)
398
+
399
+ output_conf = %[
400
+ send_timeout 51
401
+ <security>
402
+ self_hostname localhost
403
+ shared_key fluentd-sharedkey
404
+ </security>
405
+ <server>
406
+ name test
407
+ host #{TARGET_HOST}
408
+ port #{TARGET_PORT}
409
+ shared_key fluentd-sharedkey
410
+ </server>
411
+ ]
412
+ d = create_driver(output_conf)
439
413
 
440
- # TODO: Support actual TCP heartbeat test
441
- DummyEngineDriver.new(Fluent::ForwardInput) {
442
- handler_class = Class.new(Fluent::ForwardInput::Handler) { |klass|
443
- attr_reader :chunk_counter # for checking if received data is successfully deserialized
444
- attr_reader :received_options
445
-
446
- def initialize(sock, log, on_message)
447
- @sock = sock
448
- @log = log
449
- @chunk_counter = 0
450
- @received_options = []
451
- @on_message = ->(msg, chunk_size, source) {
452
- option = on_message.call(msg, chunk_size, source)
453
- @received_options << option
454
- option
455
- }
456
- @source = nil
457
- @peeraddr = nil
414
+ time = Time.parse("2011-01-02 13:14:15 UTC").to_i
415
+ records = [
416
+ {"a" => 1},
417
+ {"a" => 2}
418
+ ]
419
+
420
+ target_input_driver.run do
421
+ sleep 0.1 until target_input_driver.instance.instance_eval{ @thread } && target_input_driver.instance.instance_eval{ @thread }.status
422
+
423
+ d.run do
424
+ records.each do |record|
425
+ d.emit(record, time)
458
426
  end
459
427
 
460
- if do_respond
461
- def write(data)
462
- @sock.write data
463
- rescue
464
- @sock.close_write
465
- @sock.close
466
- end
467
- else
468
- def write(data)
469
- # do nothing
470
- end
428
+ # run_post_condition of Fluent::Test::*Driver are buggy:
429
+ t = Time.now
430
+ while Time.now < t + 15 && target_input_driver.emits.size < 2
431
+ sleep 0.1
471
432
  end
433
+ end
434
+ end
472
435
 
473
- def close
474
- unless @sock.closed?
475
- @sock.close_write
476
- @sock.close
477
- end
436
+ emits = target_input_driver.emits
437
+ assert{ emits != [] }
438
+ assert_equal(['test', time, records[0]], emits[0])
439
+ assert_equal(['test', time, records[1]], emits[1])
440
+ end
441
+
442
+ def test_authentication_with_user_auth
443
+ input_conf = TARGET_CONFIG + %[
444
+ <security>
445
+ self_hostname in.localhost
446
+ shared_key fluentd-sharedkey
447
+ user_auth true
448
+ <user>
449
+ username fluentd
450
+ password fluentd
451
+ </user>
452
+ <client>
453
+ host 127.0.0.1
454
+ </client>
455
+ </security>
456
+ ]
457
+ target_input_driver = create_target_input_driver(conf: input_conf)
458
+
459
+ output_conf = %[
460
+ send_timeout 51
461
+ <security>
462
+ self_hostname localhost
463
+ shared_key fluentd-sharedkey
464
+ </security>
465
+ <server>
466
+ name test
467
+ host #{TARGET_HOST}
468
+ port #{TARGET_PORT}
469
+ shared_key fluentd-sharedkey
470
+ username fluentd
471
+ password fluentd
472
+ </server>
473
+ ]
474
+ d = create_driver(output_conf)
475
+
476
+ time = Time.parse("2011-01-02 13:14:15 UTC").to_i
477
+ records = [
478
+ {"a" => 1},
479
+ {"a" => 2}
480
+ ]
481
+
482
+ target_input_driver.run do
483
+ sleep 0.1 until target_input_driver.instance.instance_eval{ @thread } && target_input_driver.instance.instance_eval{ @thread }.status
484
+
485
+ d.run do
486
+ records.each do |record|
487
+ d.emit(record, time)
478
488
  end
479
- }
480
-
481
- define_method(:_start) do
482
- @thread = Thread.new do
483
- Socket.tcp_server_loop(@bind, @port) do |sock, client_addrinfo|
484
- begin
485
- handler = handler_class.new(sock, @log, method(:on_message))
486
- loop do
487
- raw_data = sock.recv(1024)
488
- handler.on_read(raw_data)
489
- # chunk_counter is reset to zero only after all the data have been received and successfully deserialized.
490
- break if handler.chunk_counter == 0
491
- break if sock.closed?
492
- end
493
- if disconnect
494
- handler.close
495
- sock = nil
496
- end
497
- sleep # wait for connection to be closed by client
498
- ensure
499
- if sock && !sock.closed?
500
- sock.close_write
501
- sock.close
502
- end
503
- @received_options = handler.received_options
504
- end
505
- end
489
+
490
+ # run_post_condition of Fluent::Test::*Driver are buggy:
491
+ t = Time.now
492
+ while Time.now < t + 15 && target_input_driver.emits.size < 2
493
+ sleep 0.1
506
494
  end
507
495
  end
496
+ end
508
497
 
509
- attr_reader :received_options
498
+ emits = target_input_driver.emits
499
+ assert{ emits != [] }
500
+ assert_equal(['test', time, records[0]], emits[0])
501
+ assert_equal(['test', time, records[1]], emits[1])
502
+ end
503
+
504
+ def create_target_input_driver(response_stub: nil, disconnect: false, conf: TARGET_CONFIG)
505
+ require 'fluent/plugin/in_forward'
510
506
 
511
- def _shutdown
512
- @thread.kill
513
- @thread.join
507
+ # TODO: Support actual TCP heartbeat test
508
+ Fluent::Test::InputTestDriver.new(Fluent::ForwardInput) {
509
+ if response_stub.nil?
510
+ # do nothing because in_forward responds for ack option in default
511
+ else
512
+ define_method(:response) do |options|
513
+ return response_stub.(options)
514
+ end
514
515
  end
515
- }.configure(conf).inject_router()
516
+ }.configure(conf)
516
517
  end
517
518
 
518
519
  def test_heartbeat_type_none
@@ -528,63 +529,4 @@ class ForwardOutputTest < Test::Unit::TestCase
528
529
  node.tick
529
530
  assert_equal node.available, true
530
531
  end
531
-
532
- # To suppress calling `ForwardInput#start` in `DummyEngineDriver`,
533
- # `DummyEnigneDriver` should avoid calling CallSuperMixin.prepend at `Fluent::Compat::Input#initialize`.
534
- module SuppressCallSuperMixin
535
- def start
536
- _start
537
- end
538
-
539
- def before_shutdown
540
- # nothing
541
- end
542
-
543
- def shutdown
544
- _shutdown
545
- end
546
- end
547
-
548
- class DummyEngineDriver < Fluent::Test::TestDriver
549
- def initialize(klass, &block)
550
- super(klass, &block)
551
- @instance.class.prepend(SuppressCallSuperMixin)
552
- @engine = DummyEngineClass.new
553
- end
554
-
555
- def inject_router
556
- @instance.router = @engine
557
- self
558
- end
559
-
560
- def run(&block)
561
- super(&block)
562
- end
563
-
564
- def emits
565
- all = []
566
- @engine.emit_streams.each {|tag,events|
567
- events.each {|time,record|
568
- all << [tag, time, record]
569
- }
570
- }
571
- all
572
- end
573
-
574
- class DummyEngineClass
575
- attr_reader :emit_streams
576
-
577
- def initialize
578
- @emit_streams ||= []
579
- end
580
-
581
- def clear!
582
- @emit_streams = []
583
- end
584
-
585
- def emit_stream(tag, es)
586
- @emit_streams << [tag, es.to_a]
587
- end
588
- end
589
- end
590
532
  end