fluentd 1.10.1 → 1.11.1

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 (62) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +112 -1
  3. data/CONTRIBUTING.md +1 -1
  4. data/lib/fluent/command/debug.rb +1 -0
  5. data/lib/fluent/command/fluentd.rb +12 -1
  6. data/lib/fluent/config.rb +1 -0
  7. data/lib/fluent/log.rb +45 -6
  8. data/lib/fluent/match.rb +1 -1
  9. data/lib/fluent/plugin/in_dummy.rb +2 -2
  10. data/lib/fluent/plugin/in_forward.rb +2 -2
  11. data/lib/fluent/plugin/in_gc_stat.rb +16 -0
  12. data/lib/fluent/plugin/in_http.rb +146 -75
  13. data/lib/fluent/plugin/in_monitor_agent.rb +1 -1
  14. data/lib/fluent/plugin/in_syslog.rb +4 -4
  15. data/lib/fluent/plugin/in_tail.rb +4 -4
  16. data/lib/fluent/plugin/in_unix.rb +77 -77
  17. data/lib/fluent/plugin/out_copy.rb +1 -1
  18. data/lib/fluent/plugin/out_file.rb +1 -1
  19. data/lib/fluent/plugin/out_forward.rb +23 -18
  20. data/lib/fluent/plugin/out_forward/load_balancer.rb +1 -1
  21. data/lib/fluent/plugin/out_http.rb +15 -2
  22. data/lib/fluent/plugin/parser_multiline.rb +1 -1
  23. data/lib/fluent/plugin/parser_syslog.rb +215 -54
  24. data/lib/fluent/plugin_helper/child_process.rb +3 -2
  25. data/lib/fluent/plugin_helper/record_accessor.rb +14 -0
  26. data/lib/fluent/plugin_helper/service_discovery.rb +7 -0
  27. data/lib/fluent/plugin_helper/service_discovery/manager.rb +8 -0
  28. data/lib/fluent/plugin_helper/socket.rb +20 -2
  29. data/lib/fluent/plugin_helper/socket_option.rb +2 -2
  30. data/lib/fluent/supervisor.rb +21 -9
  31. data/lib/fluent/system_config.rb +2 -1
  32. data/lib/fluent/test/filter_test.rb +2 -2
  33. data/lib/fluent/test/output_test.rb +3 -3
  34. data/lib/fluent/version.rb +1 -1
  35. data/test/command/test_fluentd.rb +57 -10
  36. data/test/config/test_system_config.rb +2 -0
  37. data/test/plugin/out_forward/test_load_balancer.rb +46 -0
  38. data/test/plugin/test_in_gc_stat.rb +24 -1
  39. data/test/plugin/test_in_http.rb +57 -0
  40. data/test/plugin/test_in_syslog.rb +1 -1
  41. data/test/plugin/test_in_tail.rb +20 -16
  42. data/test/plugin/test_in_unix.rb +128 -73
  43. data/test/plugin/test_out_forward.rb +11 -2
  44. data/test/plugin/test_out_http.rb +38 -0
  45. data/test/plugin/test_out_null.rb +1 -1
  46. data/test/plugin/test_output_as_buffered_retries.rb +12 -4
  47. data/test/plugin/test_parser_syslog.rb +66 -29
  48. data/test/plugin_helper/data/cert/cert_chains/ca-cert-key.pem +27 -0
  49. data/test/plugin_helper/data/cert/cert_chains/ca-cert.pem +20 -0
  50. data/test/plugin_helper/data/cert/cert_chains/cert-key.pem +27 -0
  51. data/test/plugin_helper/data/cert/cert_chains/cert.pem +40 -0
  52. data/test/plugin_helper/data/cert/generate_cert.rb +38 -0
  53. data/test/plugin_helper/http_server/test_app.rb +1 -1
  54. data/test/plugin_helper/http_server/test_route.rb +1 -1
  55. data/test/plugin_helper/test_child_process.rb +15 -0
  56. data/test/plugin_helper/test_http_server_helper.rb +2 -2
  57. data/test/plugin_helper/test_record_accessor.rb +41 -0
  58. data/test/plugin_helper/test_server.rb +1 -1
  59. data/test/plugin_helper/test_service_discovery.rb +37 -4
  60. data/test/plugin_helper/test_socket.rb +131 -0
  61. data/test/test_log.rb +44 -0
  62. metadata +12 -2
@@ -0,0 +1,20 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDPTCCAiWgAwIBAgILAJJ76Kpa6DYtsncwDQYJKoZIhvcNAQELBQAwUzELMAkG
3
+ A1UEBhMCVVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MR8w
4
+ HQYDVQQDDBZjYS50ZXN0aW5nLmZsdWVudGQub3JnMCAXDTcwMDEwMTAwMDAwMFoY
5
+ DzIxMTgxMDI3MDgwNjU3WjBTMQswCQYDVQQGEwJVUzELMAkGA1UECAwCQ0ExFjAU
6
+ BgNVBAcMDU1vdW50YWluIFZpZXcxHzAdBgNVBAMMFmNhLnRlc3RpbmcuZmx1ZW50
7
+ ZC5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDbWKfypGoGt9iV
8
+ EevU3p4ard3gKcp76VO3SwZtpvXrvSzT6HWUa2NafLqAtKe3k8FjfoJSgUHwy1Fy
9
+ JUbbNSEH50Bl7gyy3l3Mk7pw41P+X9RJsJWtD/HybdjN4k2Pz18Jnv/umjwKkR+f
10
+ XoEwB3pMxdlnw74MKC/dKWITLGmL0IuDY8rABXiXCS1sZ6dhp1YsVaO/lr5ASUUY
11
+ f+27mNQOGCCiKyhAbJkKWzZWZuvpEf66LLyOzeDHL7liBu7CStC2Nt/DF7nISx3p
12
+ GDM7yguqWjALAKufgI1pcXBplr++pxbNjguqIRYt+YWkVxJl2haOvVYewlL88zcD
13
+ Il5rycCdAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB
14
+ AGPhEAc+vb9PHyet9t5gKJTZF7S4x207hKZ0zLqCQCLM7VjrTVBh/TUFT+saiPsv
15
+ 4k2TYSZKInYXh6tkSzdGlRyzk166hF1eOTOae/92Da5PEQMT0AC+SDRDHXrNTyD8
16
+ ZxP2xOl0j+FNeKQDdNL+PCU56PYehY40dYZ/EjRyu4VjKaSCMHcVx7eMTyxU3wtB
17
+ HbOa8UJdUXEjn4h7icz4aca22aqLedXNaDr6YX+mo25t1jsTO7cEMfr4Ce7GvxdA
18
+ msey/b5jnsKcpL7/2uYz5+owD39JZQBRQt+1YAzIU+BNiz8yzdXJO4aQpGWTflIB
19
+ jO31o7x4loEvaBTQbX3iP2g=
20
+ -----END CERTIFICATE-----
@@ -0,0 +1,27 @@
1
+ -----BEGIN RSA PRIVATE KEY-----
2
+ MIIEogIBAAKCAQEAzQtGZgClcBIDKC0U1sQpznVV9HzAZANDVazrDGA8Euf8Kx4X
3
+ dnVoE+HzwAviL4VLDPzNBLyoZ2wf3wg6D+1UAhA0DqPRCihhfJqBX0WgewakSl5a
4
+ wrc1XIXtiMxcWE/5+XtodjO71gECBgmd/l0UtdFY7mMt/gArH8PQf29ABGiB1zzn
5
+ d0MNgA0r2OlXICe4kDzTHqDBv7nFgQFro2vkI/QJD5fABbb62HRWgUfQ13DUShSG
6
+ H5FPkMxTkCs5GShyjYCC5IhI+AKx5RWvb4kuMRsxWC7JHc/XKPdbeLkNWRCFzTnO
7
+ OR09Qdp45tBbXtX0IjInxsnNOBzW0zTSg0xUtwIDAQABAoIBAG4N5zNIlYOZp2gh
8
+ ClZb47SU9hXL/9euiK2rql1yKcxcB9V8yUsjqUFCvfoOZtDq0mWeKsyoFhusxU6I
9
+ s+FomPaii85vzvuMwQaIR3hDfueJoRTpn/1zKIkIuX37cnVUN+/YdTE8g01SLSvg
10
+ bZThkQQl4X3SbhUvMfZSu84qgEncdtJ08zx81CB1Fpn0HIjpmpRM1F9jjDwtkVUw
11
+ 1gVQm9g7fwbgRfqSUyKkEqKvCVYnLQx3X5inuAEps4zIzAXF8RtxFymyHfExzZqr
12
+ Pj5uYjTbf/wkaU9nWQzXeCbRTz3ZrjvFnisFt1HI2uijd1DjJ7CB7Ls752RWekXS
13
+ Yc9FFwECgYEA/gZ3Hx4dIb6NW6UmPKjiQex/tVqwCRaxGtpA7qensf187N2nn4FD
14
+ jdQJ69XmoDRKr2X+e7tsgKpETGufdDQ8MNBHz2krfqXVSlsEIOjeLfRRqhh+8Bcr
15
+ flri0sumVbk0X9bnXzyCc4AGcRhtT9U69HCMTlly2z0pjIlVvmFXARECgYEAzqNV
16
+ FSHHbEU+5zToJK0jyTaE/F+u9n5YKDcRN9RrKrEYcoUzKbIYJrUulbRGfsqAxY5L
17
+ KtIDRI9NmPDBYqBwqSFnm9LcLn8CgQH/rRSFJv1Iw+sPHd/Nrk1KWjpO0OYRgfiB
18
+ oxcgGSzHp0OZP+e7Trtq1TKW6VyadEsPZ7oKeUcCgYB9TiMkrm4gXybLtkOOWKCD
19
+ dG3qv7lmQlNKs66kCv+lxS0CirRM8i6on5flRbZmAGV28BEAaAu1zEe0isI1SC8I
20
+ xTUnEvHpn1P/QbZfpX8zm/lMtpinRkamJZ8N7Hc4ggtb2152lBqlbtm+oBYL81sJ
21
+ iRss6uLFUv5T3Mr3Bn0sgQKBgGr4xQf+h6V2J307t12dQCRfE/MueX3jpDGVaFV1
22
+ otDkAxrt97GDH9uR+f7H56KlpIohAqq1M7nfUbV2FTbAhfIYd/GD9DYhzCMK7Ngm
23
+ AlRP1MaPvjCh9nFgU7hn7PtZzwBwrHPIefZuZyEg7onVpfK5NTIPUW6XYOIJJX12
24
+ IwvrAoGAGwg2Cq6Vs/KkiCDxoy42HVZLS/DS/iHfUTAXtekF88qwT1zHFqF1ImvO
25
+ +FEUx8IbxY1oifSQc3Jw9HYnmYqmFW1PThNG3CwyaOGgtlEFcvhHsNjLRGJSQbN2
26
+ cUYBe2hHXii7OL8T8kIvLlCAKGA8IIfPGhsu3uUtrvMBo5c0WmQ=
27
+ -----END RSA PRIVATE KEY-----
@@ -0,0 +1,40 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIDQjCCAiqgAwIBAgILANkmymLgb5e04tcwDQYJKoZIhvcNAQELBQAwVDELMAkG
3
+ A1UEBhMCVVMxCzAJBgNVBAgMAkNBMRYwFAYDVQQHDA1Nb3VudGFpbiBWaWV3MSAw
4
+ HgYDVQQDDBdjYTIudGVzdGluZy5mbHVlbnRkLm9yZzAgFw03MDAxMDEwMDAwMDBa
5
+ GA8yMTE4MTAyNzA4MDY1N1owVzELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAkNBMRYw
6
+ FAYDVQQHDA1Nb3VudGFpbiBWaWV3MSMwIQYDVQQDDBpzZXJ2ZXIudGVzdGluZy5m
7
+ bHVlbnRkLm9yZzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM0LRmYA
8
+ pXASAygtFNbEKc51VfR8wGQDQ1Ws6wxgPBLn/CseF3Z1aBPh88AL4i+FSwz8zQS8
9
+ qGdsH98IOg/tVAIQNA6j0QooYXyagV9FoHsGpEpeWsK3NVyF7YjMXFhP+fl7aHYz
10
+ u9YBAgYJnf5dFLXRWO5jLf4AKx/D0H9vQARogdc853dDDYANK9jpVyAnuJA80x6g
11
+ wb+5xYEBa6Nr5CP0CQ+XwAW2+th0VoFH0Ndw1EoUhh+RT5DMU5ArORkoco2AguSI
12
+ SPgCseUVr2+JLjEbMVguyR3P1yj3W3i5DVkQhc05zjkdPUHaeObQW17V9CIyJ8bJ
13
+ zTgc1tM00oNMVLcCAwEAAaMQMA4wDAYDVR0TBAUwAwEBADANBgkqhkiG9w0BAQsF
14
+ AAOCAQEAMzoxZJqhu8zyKI20Hz5SAqva+jcHbZbR9AXlt4LWQEttsXy4S52XLZBB
15
+ 4Es/Fah4lyou9R1xdUfF6iGBV6HgDMIuh+QYfqA/jJ4HXNMKLtDXakS8xYp2A0Wn
16
+ g0EnjGx44DNweBkKGB9asldgwOM7MYMoQvS3Nkyu3oFqpfLpuWpWB/3Vw3PMGEdx
17
+ r/c8Ev5XoVtl2+dXszsEp2jwUOFo8+DZzFdBZdA2F7RmcP+zxbAHIw/jHf/ptDGg
18
+ NtzHmLhxiLblGlJHw/4a0HhXa453jzLsD1+hQpqBRUNbXBp1qpjqEr5SF1iVNGpZ
19
+ peWFawp53MkIBXRls66ViJsl//fPBg==
20
+ -----END CERTIFICATE-----
21
+ -----BEGIN CERTIFICATE-----
22
+ MIIDPTCCAiWgAwIBAgIKRbRr9ZfmrY72TjANBgkqhkiG9w0BAQsFADBTMQswCQYD
23
+ VQQGEwJVUzELMAkGA1UECAwCQ0ExFjAUBgNVBAcMDU1vdW50YWluIFZpZXcxHzAd
24
+ BgNVBAMMFmNhLnRlc3RpbmcuZmx1ZW50ZC5vcmcwIBcNNzAwMTAxMDAwMDAwWhgP
25
+ MjExODEwMjcwODA2NTdaMFQxCzAJBgNVBAYTAlVTMQswCQYDVQQIDAJDQTEWMBQG
26
+ A1UEBwwNTW91bnRhaW4gVmlldzEgMB4GA1UEAwwXY2EyLnRlc3RpbmcuZmx1ZW50
27
+ ZC5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQC6gnGxD4RQuAA1
28
+ fQNMl9mctiIvcJ0Dz5f3JtCJlKKqBDKJ17py7tjFZ2MZ5vytIl1DUU2oxHew8F/u
29
+ U8s+8ljmL3seiXx2kMCOxCvSW3JYUQrzbTHKszna7Ffy94SzpRDh/4/2RGatnSqi
30
+ n4fRpalrchhH6Ds6v486o7YcwEKPR2dlD+Ltd/V3lMAOAmoRoe2aQlLudOUQjHJU
31
+ YWGim8XS2dNAEy4WR5DvjYEA+CwKEX7f9p0Dihs8FKBjB2TvBwUkdfILLEnwA1rs
32
+ r0coUt3kwYt9TYNYv6/SZYvFtaYjM3BmLVHI3mtEchaA+Tij4V4gRZ573Ai1+Fb8
33
+ rxn+oTsVAgMBAAGjEDAOMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEB
34
+ AHID7VD2PS7svmCXRg4qe7MkhA0veIadZRE6WZgJo3Z64p9jUWu/Y3ZrlZuDg0qI
35
+ yV65UgWrgUOiGN6RZmI5A850DH3ryjvQElPHWjRavm0GtrOxFhHYpX8N7DRFW7t0
36
+ 7mld7YvbKRj0BrovU3avPC1P9w8FpegMKh48HsoRCO3NhHvYwtAf2B767UuAaqnI
37
+ DW9rMPRTZv+Pv+G+kJN+updOs6HiHFxeS8Bwb8GlADcwWNGMqyJJyKmaefYVzDKt
38
+ xfBiKiwev6Hm8RVTk1H3rKVZox/ZkDiZfZhmBJqO4mdDR4LLFIRIPqjUPxENsKFJ
39
+ MyrDcwH+0Aq9ZSiRaVyfCkQ=
40
+ -----END CERTIFICATE-----
@@ -7,6 +7,7 @@ end
7
7
 
8
8
  WITHOUT_CA_DIR = './without_ca'.freeze
9
9
  WITH_CA_DIR = './with_ca'.freeze
10
+ WITH_CERT_CHAIN_DIR = './cert_chains'.freeze
10
11
 
11
12
  CA_OPTION = {
12
13
  private_key_length: 2048,
@@ -83,5 +84,42 @@ def create_with_ca
83
84
  create_server_pair_signed_by_ca(ca_cert_pass_path, ca_key_pass_path, 'orange', cert_pass_path, cert_key_pass_path, 'apple')
84
85
  end
85
86
 
87
+ def create_cert_pair_chained_with_root_ca(ca_cert_path, ca_key_path, ca_key_passphrase, cert_path, private_key_path, passphrase)
88
+ root_cert, root_key, _ = CertUtil.cert_option_generate_ca_pair_self_signed(CA_OPTION)
89
+ write_cert_and_key(ca_cert_path, root_cert, ca_key_path, root_key, ca_key_passphrase)
90
+
91
+ intermediate_ca_options = CA_OPTION.dup
92
+ intermediate_ca_options[:common_name] = 'ca2.testing.fluentd.org'
93
+ chain_cert, chain_key = CertUtil.cert_option_generate_pair(intermediate_ca_options, root_cert.subject)
94
+ chain_cert.add_extension(OpenSSL::X509::Extension.new('basicConstraints', OpenSSL::ASN1.Sequence([OpenSSL::ASN1::Boolean(true)])))
95
+ chain_cert.sign(root_key, 'sha256')
96
+
97
+ cert, server_key, _ = CertUtil.cert_option_generate_pair(SERVER_OPTION, chain_cert.subject)
98
+ cert.add_extension OpenSSL::X509::Extension.new('basicConstraints', OpenSSL::ASN1.Sequence([OpenSSL::ASN1::Boolean(false)]))
99
+ cert.sign(chain_key, 'sha256')
100
+
101
+ # write chained cert
102
+ File.open(cert_path, 'w') do |f|
103
+ f.write(cert.to_pem)
104
+ f.write(chain_cert.to_pem)
105
+ end
106
+
107
+ key_str = passphrase ? server_key.export(OpenSSL::Cipher.new("AES-256-CBC"), passphrase) : server_key.export
108
+ File.open(private_key_path, "w") { |f| f.write(key_str) }
109
+ File.chmod(0600, cert_path, private_key_path)
110
+ end
111
+
112
+ def create_cert_chain
113
+ FileUtils.mkdir_p(WITH_CERT_CHAIN_DIR)
114
+ ca_cert_path = File.join(WITH_CERT_CHAIN_DIR, 'ca-cert.pem')
115
+ ca_key_path = File.join(WITH_CERT_CHAIN_DIR, 'ca-cert-key.pem')
116
+
117
+ cert_path = File.join(WITH_CERT_CHAIN_DIR, 'cert.pem')
118
+ private_key_path = File.join(WITH_CERT_CHAIN_DIR, 'cert-key.pem')
119
+
120
+ create_server_pair_chained_with_root_ca(ca_cert_path, ca_key_path, nil, cert_path, private_key_path, nil)
121
+ end
122
+
86
123
  create_without_ca
87
124
  create_with_ca
125
+ create_cert_chain
@@ -9,7 +9,7 @@ rescue LoadError => _
9
9
  end
10
10
 
11
11
  unless skip
12
- class HtttpHelperAppTest < Test::Unit::TestCase
12
+ class HttpHelperAppTest < Test::Unit::TestCase
13
13
  NULL_LOGGER = Logger.new(nil)
14
14
 
15
15
  class DummyRounter
@@ -9,7 +9,7 @@ rescue LoadError => _
9
9
  end
10
10
 
11
11
  unless skip
12
- class HtttpHelperRouterTest < Test::Unit::TestCase
12
+ class HttpHelperRouterTest < Test::Unit::TestCase
13
13
  sub_test_case '#mount' do
14
14
  test 'mount with method and path' do
15
15
  router = Fluent::PluginHelper::HttpServer::Router.new
@@ -818,5 +818,20 @@ class ChildProcessTest < Test::Unit::TestCase
818
818
  end
819
819
  assert File.exist?(@temp_path)
820
820
  end
821
+
822
+ test 'execute child process writing data to stdout which is unread' do
823
+ callback_called = false
824
+ exit_status = nil
825
+ prog = "echo writing to stdout"
826
+ callback = ->(status){ exit_status = status; callback_called = true }
827
+ Timeout.timeout(TEST_DEADLOCK_TIMEOUT) do
828
+ @d.child_process_execute(:out_exec_process, prog, stderr: :connect, immediate: true, parallel: true, mode: [], wait_timeout: 1, on_exit_callback: callback)
829
+ sleep TEST_WAIT_INTERVAL_FOR_BLOCK_RUNNING until callback_called
830
+ end
831
+ assert callback_called
832
+ assert exit_status
833
+ assert exit_status.success?
834
+ assert_equal 0, exit_status.exitstatus
835
+ end
821
836
  end
822
837
  end
@@ -8,7 +8,7 @@ require 'uri'
8
8
  require 'openssl'
9
9
  require 'async'
10
10
 
11
- class HtttpHelperTest < Test::Unit::TestCase
11
+ class HttpHelperTest < Test::Unit::TestCase
12
12
  PORT = unused_port
13
13
  NULL_LOGGER = Logger.new(nil)
14
14
  CERT_DIR = File.expand_path(File.dirname(__FILE__) + '/data/cert/without_ca')
@@ -110,7 +110,7 @@ class HtttpHelperTest < Test::Unit::TestCase
110
110
  end
111
111
 
112
112
  context.cert_store = cert_store
113
- if !hostname && context.respond_to?(:verify_hostname=)
113
+ if !hostname
114
114
  context.verify_hostname = false # In test code, using hostname to be connected is very difficult
115
115
  end
116
116
 
@@ -194,4 +194,45 @@ class RecordAccessorHelperTest < Test::Unit::TestCase
194
194
  end
195
195
  end
196
196
  end
197
+
198
+ sub_test_case 'Fluent::PluginHelper::RecordAccessor::Accessor#set' do
199
+ setup do
200
+ @d = Dummy.new
201
+ end
202
+
203
+ data('normal' => 'key1',
204
+ 'space' => 'ke y2',
205
+ 'dot key' => 'this.is.key3')
206
+ test 'set top key' do |param|
207
+ r = {'key1' => 'v1', 'ke y2' => 'v2', 'this.is.key3' => 'v3'}
208
+ accessor = @d.record_accessor_create(param)
209
+ accessor.set(r, "test")
210
+ assert_equal "test", r[param]
211
+ end
212
+
213
+ test "set top key using bracket style" do
214
+ r = {'key1' => 'v1', 'ke y2' => 'v2', 'this.is.key3' => 'v3'}
215
+ accessor = @d.record_accessor_create('$["this.is.key3"]')
216
+ accessor.set(r, "test")
217
+ assert_equal "test", r["this.is.key3"]
218
+ end
219
+
220
+ data('bracket' => "$['key1'][0]['ke y2']",
221
+ 'bracket w/ double quotes' => '$["key1"][0]["ke y2"]')
222
+ test "set nested keys ['key1', 0, 'ke y2']" do |param|
223
+ r = {'key1' => [{'ke y2' => "value"}]}
224
+ accessor = @d.record_accessor_create(param)
225
+ accessor.set(r, "nested_message")
226
+ assert_equal "nested_message", r['key1'][0]['ke y2']
227
+ end
228
+
229
+ test "don't raise an error when unexpected record is coming" do
230
+ r = {'key1' => [{'key3' => "value"}]}
231
+ accessor = @d.record_accessor_create("$['key1']['key2']['key3']")
232
+ assert_nothing_raised do
233
+ accessor.set(r, "unknown field")
234
+ end
235
+ assert_equal({'key1' => [{'key3' => "value"}]}, r)
236
+ end
237
+ end
197
238
  end
@@ -860,7 +860,7 @@ class ServerPluginHelperTest < Test::Unit::TestCase
860
860
  end
861
861
  context.verify_mode = OpenSSL::SSL::VERIFY_PEER
862
862
  context.cert_store = cert_store
863
- if !hostname && context.respond_to?(:verify_hostname=)
863
+ if !hostname
864
864
  context.verify_hostname = false # In test code, using hostname to be connected is very difficult
865
865
  end
866
866
  else
@@ -4,9 +4,6 @@ require 'fluent/plugin_helper/service_discovery'
4
4
  require 'fluent/plugin/output'
5
5
 
6
6
  class ServiceDiscoveryHelper < Test::Unit::TestCase
7
- PORT = unused_port
8
- NULL_LOGGER = Logger.new(nil)
9
-
10
7
  class Dummy < Fluent::Plugin::TestBase
11
8
  helpers :service_discovery
12
9
 
@@ -30,6 +27,7 @@ class ServiceDiscoveryHelper < Test::Unit::TestCase
30
27
  if @d
31
28
  @d.stop unless @d.stopped?
32
29
  @d.shutdown unless @d.shutdown?
30
+ @d.after_shutdown unless @d.after_shutdown?
33
31
  @d.close unless @d.closed?
34
32
  @d.terminate unless @d.terminated?
35
33
  end
@@ -40,7 +38,7 @@ class ServiceDiscoveryHelper < Test::Unit::TestCase
40
38
 
41
39
  d.service_discovery_create_manager(
42
40
  :service_discovery_helper_test,
43
- configurations: [{ type: :static, conf: config_element('root', '', {}, [config_element('service', '', { 'host' => '127.0.0.1', 'port' => '1234' })]) }],
41
+ configurations: [{ type: :static, conf: config_element('root', '', {}, [config_element('service', '', { 'host' => '127.0.0.1', 'port' => '1234' })]) }],
44
42
  )
45
43
 
46
44
  assert_true !!d.discovery_manager
@@ -49,6 +47,7 @@ class ServiceDiscoveryHelper < Test::Unit::TestCase
49
47
  mock.proxy(d).timer_execute(:service_discovery_helper_test, anything).never
50
48
 
51
49
  d.start
50
+ d.event_loop_wait_until_start
52
51
 
53
52
  services = d.discovery_manager.services
54
53
  assert_equal 1, services.size
@@ -68,5 +67,39 @@ class ServiceDiscoveryHelper < Test::Unit::TestCase
68
67
  mock.proxy(d.discovery_manager).start.once
69
68
  mock(d).timer_execute(:service_discovery_helper_test, anything).once
70
69
  d.start
70
+ d.event_loop_wait_until_start
71
+ end
72
+
73
+ test 'exits service discovery instances without any errors' do
74
+ d = @d = Dummy.new
75
+ mockv = flexmock('dns_resolver', getaddress: '127.0.0.1')
76
+ .should_receive(:getresources)
77
+ .and_return([Resolv::DNS::Resource::IN::SRV.new(1, 10, 8081, 'service1.example.com')])
78
+ .mock
79
+ mock(Resolv::DNS).new { mockv }
80
+
81
+ d.service_discovery_create_manager(
82
+ :service_discovery_helper_test2,
83
+ configurations: [{ type: :srv, conf: config_element('service_discovery', '', { 'service' => 'service1', 'hostname' => 'example.com' }) }],
84
+ )
85
+
86
+ assert_true !!d.discovery_manager
87
+ mock.proxy(d.discovery_manager).start.once
88
+ mock(d).timer_execute(:service_discovery_helper_test2, anything).once
89
+
90
+ # To avoid claring `@logs` during `terminate` step
91
+ # https://github.com/fluent/fluentd/blob/bc78d889f93dad8c2a4e0ad1ca802546185dacba/lib/fluent/test/log.rb#L33
92
+ mock(d.log).reset.twice
93
+
94
+ d.start
95
+ d.event_loop_wait_until_start
96
+
97
+ d.stop unless d.stopped?
98
+ d.shutdown unless d.shutdown?
99
+ d.after_shutdown unless d.after_shutdown?
100
+ d.close unless d.closed?
101
+ d.terminate unless d.terminated?
102
+
103
+ assert_false(d.log.out.logs.any? { |e| e.match?(/thread doesn't exit correctly/) })
71
104
  end
72
105
  end
@@ -0,0 +1,131 @@
1
+ require_relative '../helper'
2
+ require 'fluent/plugin_helper/socket'
3
+ require 'fluent/plugin/base'
4
+
5
+ require 'socket'
6
+ require 'openssl'
7
+
8
+ class SocketHelperTest < Test::Unit::TestCase
9
+ PORT = unused_port
10
+ CERT_DIR = File.expand_path(File.dirname(__FILE__) + '/data/cert/without_ca')
11
+ CA_CERT_DIR = File.expand_path(File.dirname(__FILE__) + '/data/cert/with_ca')
12
+ CERT_CHAINS_DIR = File.expand_path(File.dirname(__FILE__) + '/data/cert/cert_chains')
13
+
14
+ class SocketHelperTestPlugin < Fluent::Plugin::TestBase
15
+ helpers :socket
16
+ end
17
+
18
+ class EchoTLSServer
19
+ def initialize(host = '127.0.0.1', port = PORT, cert_path: nil, private_key_path: nil, ca_path: nil)
20
+ server = TCPServer.open(host, port)
21
+ ctx = OpenSSL::SSL::SSLContext.new
22
+ ctx.cert = OpenSSL::X509::Certificate.new(File.open(cert_path)) if cert_path
23
+
24
+ cert_store = OpenSSL::X509::Store.new
25
+ cert_store.set_default_paths
26
+ cert_store.add_file(ca_path) if ca_path
27
+ ctx.cert_store = cert_store
28
+
29
+ ctx.key = OpenSSL::PKey::RSA.new(File.open(private_key_path)) if private_key_path
30
+ ctx.verify_mode = OpenSSL::SSL::VERIFY_PEER
31
+ ctx.verify_hostname = false
32
+
33
+ @server = OpenSSL::SSL::SSLServer.new(server, ctx)
34
+ @thread = nil
35
+ @r, @w = IO.pipe
36
+ end
37
+
38
+ def start
39
+ do_start
40
+
41
+ if block_given?
42
+ begin
43
+ yield
44
+ @thread.join(5)
45
+ ensure
46
+ stop
47
+ end
48
+ end
49
+ end
50
+
51
+ def stop
52
+ unless @w.closed?
53
+ @w.write('stop')
54
+ end
55
+
56
+ [@server, @w, @r].each do |s|
57
+ next if s.closed?
58
+ s.close
59
+ end
60
+
61
+ @thread.join(5)
62
+ end
63
+
64
+ private
65
+
66
+ def do_start
67
+ @thread = Thread.new(@server) do |s|
68
+ socks, _, _ = IO.select([s.accept, @r], nil, nil)
69
+
70
+ if socks.include?(@r)
71
+ break
72
+ end
73
+
74
+ sock = socks.first
75
+ buf = +''
76
+ loop do
77
+ b = sock.read_nonblock(1024, nil, exception: false)
78
+ if b == :wait_readable || b.nil?
79
+ break
80
+ end
81
+ buf << b
82
+ end
83
+
84
+ sock.write(buf)
85
+ sock.close
86
+ end
87
+ end
88
+ end
89
+
90
+ test 'with self-signed cert/key pair' do
91
+ cert_path = File.join(CERT_DIR, 'cert.pem')
92
+ private_key_path = File.join(CERT_DIR, 'cert-key.pem')
93
+
94
+ EchoTLSServer.new(cert_path: cert_path, private_key_path: private_key_path).start do
95
+ client = SocketHelperTestPlugin.new.socket_create_tls('127.0.0.1', PORT, verify_fqdn: false, cert_paths: [cert_path])
96
+ client.write('hello')
97
+ assert_equal 'hello', client.readpartial(100)
98
+ client.close
99
+ end
100
+ end
101
+
102
+ test 'with cert/key signed by self-signed CA' do
103
+ cert_path = File.join(CA_CERT_DIR, 'cert.pem')
104
+ private_key_path = File.join(CA_CERT_DIR, 'cert-key.pem')
105
+
106
+ ca_cert_path = File.join(CA_CERT_DIR, 'ca-cert.pem')
107
+
108
+ EchoTLSServer.new(cert_path: cert_path, private_key_path: private_key_path).start do
109
+ client = SocketHelperTestPlugin.new.socket_create_tls('127.0.0.1', PORT, verify_fqdn: false, cert_paths: [ca_cert_path])
110
+ client.write('hello')
111
+ assert_equal 'hello', client.readpartial(100)
112
+ client.close
113
+ end
114
+ end
115
+
116
+ test 'with cert/key signed by self-signed CA in server and client cert chain' do
117
+ cert_path = File.join(CERT_DIR, 'cert.pem')
118
+ private_key_path = File.join(CERT_DIR, 'cert-key.pem')
119
+
120
+ client_ca_cert_path = File.join(CERT_CHAINS_DIR, 'ca-cert.pem')
121
+ client_cert_path = File.join(CERT_CHAINS_DIR, 'cert.pem')
122
+ client_private_key_path = File.join(CERT_CHAINS_DIR, 'cert-key.pem')
123
+
124
+ EchoTLSServer.new(cert_path: cert_path, private_key_path: private_key_path, ca_path: client_ca_cert_path).start do
125
+ client = SocketHelperTestPlugin.new.socket_create_tls('127.0.0.1', PORT, verify_fqdn: false, cert_path: client_cert_path, private_key_path: client_private_key_path, cert_paths: [cert_path])
126
+ client.write('hello')
127
+ assert_equal 'hello', client.readpartial(100)
128
+ client.close
129
+ end
130
+ end
131
+ end