fluentd 1.14.6-x64-mingw32 → 1.15.2-x64-mingw32

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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/linux-test.yaml +1 -1
  3. data/.github/workflows/windows-test.yaml +4 -1
  4. data/CHANGELOG.md +85 -1
  5. data/fluentd.gemspec +1 -3
  6. data/lib/fluent/command/ctl.rb +4 -1
  7. data/lib/fluent/command/fluentd.rb +11 -6
  8. data/lib/fluent/config/literal_parser.rb +2 -2
  9. data/lib/fluent/config/yaml_parser/fluent_value.rb +47 -0
  10. data/lib/fluent/config/yaml_parser/loader.rb +91 -0
  11. data/lib/fluent/config/yaml_parser/parser.rb +166 -0
  12. data/lib/fluent/config/yaml_parser/section_builder.rb +107 -0
  13. data/lib/fluent/config/yaml_parser.rb +56 -0
  14. data/lib/fluent/config.rb +14 -1
  15. data/lib/fluent/error.rb +3 -0
  16. data/lib/fluent/plugin/base.rb +19 -0
  17. data/lib/fluent/plugin/file_wrapper.rb +57 -113
  18. data/lib/fluent/plugin/in_tail/group_watch.rb +204 -0
  19. data/lib/fluent/plugin/in_tail/position_file.rb +1 -15
  20. data/lib/fluent/plugin/in_tail.rb +68 -48
  21. data/lib/fluent/plugin/out_file.rb +11 -1
  22. data/lib/fluent/plugin/out_forward/socket_cache.rb +2 -0
  23. data/lib/fluent/plugin/output.rb +2 -1
  24. data/lib/fluent/plugin/parser_syslog.rb +1 -1
  25. data/lib/fluent/plugin_helper/child_process.rb +3 -0
  26. data/lib/fluent/plugin_helper/server.rb +3 -1
  27. data/lib/fluent/plugin_helper/service_discovery.rb +2 -2
  28. data/lib/fluent/supervisor.rb +125 -31
  29. data/lib/fluent/system_config.rb +4 -2
  30. data/lib/fluent/version.rb +1 -1
  31. data/lib/fluent/win32api.rb +38 -0
  32. data/lib/fluent/winsvc.rb +5 -8
  33. data/test/command/test_ctl.rb +0 -1
  34. data/test/command/test_fluentd.rb +33 -0
  35. data/test/config/test_system_config.rb +5 -1
  36. data/test/config/test_types.rb +1 -1
  37. data/test/plugin/in_tail/test_io_handler.rb +14 -4
  38. data/test/plugin/in_tail/test_position_file.rb +0 -63
  39. data/test/plugin/out_forward/test_socket_cache.rb +26 -1
  40. data/test/plugin/test_base.rb +34 -0
  41. data/test/plugin/test_file_wrapper.rb +0 -73
  42. data/test/plugin/test_in_object_space.rb +9 -3
  43. data/test/plugin/test_in_syslog.rb +1 -1
  44. data/test/plugin/test_in_tail.rb +629 -353
  45. data/test/plugin/test_out_forward.rb +30 -20
  46. data/test/plugin/test_parser_syslog.rb +1 -1
  47. data/test/plugin_helper/test_cert_option.rb +1 -1
  48. data/test/plugin_helper/test_child_process.rb +16 -4
  49. data/test/test_config.rb +135 -4
  50. data/test/test_supervisor.rb +155 -0
  51. metadata +12 -39
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0437b57bc07c96e97f0fd6f12bcb1e8fdfa2bda366c887aaad5ad99679221988
4
- data.tar.gz: 679a45104420e99c66525884c7a274972a1875abc008d097b786080c9e01833f
3
+ metadata.gz: 43c812153e86b62ca62799c3c043ffd5516546338154cbeb9179a9ba73eca63d
4
+ data.tar.gz: bc7da3f9b2bc71818d69dad63d5692365d09c75bab57b880c1900c2e7c47c404
5
5
  SHA512:
6
- metadata.gz: 8cc3ff86580a0779fcdc27588ca715b1d6b4c2c1c68600066b76ae52882486e4aef2f46160402d0fc56e5ad7831a490dbcad0a0e3376af7627ed6472c83e16c5
7
- data.tar.gz: cdeacccd982235e7baf9e47fd6407d9855bad5face3775ac9c87220b26eb5998d550b1d8cb2f8b425005fb34e239645d118f2cb5afda06103a41be71da934fed
6
+ metadata.gz: eef98928a89a7a77788e1a9843feb1b0d0cb351b0900653f60de2daf350df6550b48a3ea26db0b1b9efa72d6a678539329451a8aa7e2613103819f50a0d9996a
7
+ data.tar.gz: 01e93aacc411435f5aa36e6d428508b587bde5ed690e4ba7c35acd3ea08118acbaab376cdc5f8384a73f173227b7b48cb100e76a9c43c3f637a1d55a1bd1aa20
@@ -13,7 +13,7 @@ jobs:
13
13
  strategy:
14
14
  fail-fast: false
15
15
  matrix:
16
- ruby-version: ['3.1', '3.0', '2.7', '2.6']
16
+ ruby-version: ['3.1', '3.0', '2.7']
17
17
  os: [ubuntu-latest]
18
18
  experimental: [false]
19
19
  include:
@@ -13,11 +13,14 @@ jobs:
13
13
  strategy:
14
14
  fail-fast: false
15
15
  matrix:
16
- ruby-version: ['2.7', '2.6']
16
+ ruby-version: ['3.1', '2.7']
17
17
  os:
18
18
  - windows-latest
19
19
  experimental: [false]
20
20
  include:
21
+ - ruby-version: head
22
+ os: windows-latest
23
+ experimental: true
21
24
  - ruby-version: '3.0.3'
22
25
  os: windows-latest
23
26
  experimental: false
data/CHANGELOG.md CHANGED
@@ -1,3 +1,87 @@
1
+ # v1.15
2
+
3
+ ## Release v1.15.2 - 2022/08/22
4
+
5
+ ### Enhancement
6
+
7
+ * Add a new system configuration `enable_jit`
8
+ https://github.com/fluent/fluentd/pull/3857
9
+
10
+ ### Bug Fix
11
+
12
+ * out_file: Fix append mode with `--daemon` flag
13
+ https://github.com/fluent/fluentd/pull/3864
14
+ * child_process: Plug file descriptor leak
15
+ https://github.com/fluent/fluentd/pull/3844
16
+
17
+ ### Misc
18
+
19
+ * Drop win32-api gem to support Ruby 3.2
20
+ https://github.com/fluent/fluentd/pull/3849
21
+ https://github.com/fluent/fluentd/pull/3866
22
+
23
+ ## Release v1.15.1 - 2022/07/27
24
+
25
+ ### Bug Fix
26
+
27
+ * Add support for concurrent append in out_file
28
+ https://github.com/fluent/fluentd/pull/3808
29
+
30
+ ### Misc
31
+
32
+ * in_tail: Show more information on skipping update_watcher
33
+ https://github.com/fluent/fluentd/pull/3829
34
+
35
+ ## Release v1.15.0 - 2022/06/29
36
+
37
+ ### Enhancement
38
+
39
+ * in_tail: Add log throttling in files based on group rules
40
+ https://github.com/fluent/fluentd/pull/3535
41
+ https://github.com/fluent/fluentd/pull/3771
42
+ * Add `dump` command to fluent-ctl
43
+ https://github.com/fluent/fluentd/pull/3680
44
+ * Handle YAML configuration format on configuration file
45
+ https://github.com/fluent/fluentd/pull/3712
46
+ * Add `restart_worker_interval` parameter in `<system>` directive to set
47
+ interval to restart workers that has stopped for some reason.
48
+ https://github.com/fluent/fluentd/pull/3768
49
+
50
+ ### Bug fixes
51
+
52
+ * out_forward: Fix to update timeout of cached sockets
53
+ https://github.com/fluent/fluentd/pull/3711
54
+ * in_tail: Fix a possible crash on file rotation when `follow_inodes true`
55
+ https://github.com/fluent/fluentd/pull/3754
56
+ * output: Fix a possible crash of flush thread
57
+ https://github.com/fluent/fluentd/pull/3755
58
+ * in_tail: Fix crash bugs on Ruby 3.1 on Windows
59
+ https://github.com/fluent/fluentd/pull/3766
60
+ * in_tail: Fix a bug that in_tail cannot open non-ascii path on Windows
61
+ https://github.com/fluent/fluentd/pull/3774
62
+ * Fix a bug that fluentd doesn't release its own log file even after rotated by
63
+ external tools
64
+ https://github.com/fluent/fluentd/pull/3782
65
+
66
+ ### Misc
67
+
68
+ * in_tail: Simplify TargetInfo related code
69
+ https://github.com/fluent/fluentd/pull/3489
70
+ * Fix a wrong issue number in CHANGELOG
71
+ https://github.com/fluent/fluentd/pull/3700
72
+ * server helper: Add comments to linger_timeout behavior about Windows
73
+ https://github.com/fluent/fluentd/pull/3701
74
+ * service_discovery: Fix typo
75
+ https://github.com/fluent/fluentd/pull/3724
76
+ * test: Fix unstable tests and warnings
77
+ https://github.com/fluent/fluentd/pull/3745
78
+ https://github.com/fluent/fluentd/pull/3753
79
+ https://github.com/fluent/fluentd/pull/3767
80
+ https://github.com/fluent/fluentd/pull/3783
81
+ https://github.com/fluent/fluentd/pull/3784
82
+ https://github.com/fluent/fluentd/pull/3785
83
+ https://github.com/fluent/fluentd/pull/3787
84
+
1
85
  # v1.14
2
86
 
3
87
  ## Release v1.14.6 - 2022/03/31
@@ -443,7 +527,7 @@ We recommend to upgrade Fluentd to v1.14.2 or use patched version of
443
527
  ### New feature
444
528
 
445
529
  * in_tail: Add `follow_inode` to support log rotation with wild card
446
- https://github.com/fluent/fluentd/pull/2992
530
+ https://github.com/fluent/fluentd/pull/3182
447
531
  * in_tail: Handle linux capability
448
532
  https://github.com/fluent/fluentd/pull/3155
449
533
  https://github.com/fluent/fluentd/pull/3162
data/fluentd.gemspec CHANGED
@@ -22,7 +22,7 @@ Gem::Specification.new do |gem|
22
22
  gem.add_runtime_dependency("msgpack", [">= 1.3.1", "< 2.0.0"])
23
23
  gem.add_runtime_dependency("yajl-ruby", ["~> 1.0"])
24
24
  gem.add_runtime_dependency("cool.io", [">= 1.4.5", "< 2.0.0"])
25
- gem.add_runtime_dependency("serverengine", [">= 2.2.5", "< 3.0.0"])
25
+ gem.add_runtime_dependency("serverengine", [">= 2.3.0", "< 3.0.0"])
26
26
  gem.add_runtime_dependency("http_parser.rb", [">= 0.5.1", "< 0.9.0"])
27
27
  gem.add_runtime_dependency("sigdump", ["~> 0.2.2"])
28
28
  gem.add_runtime_dependency("tzinfo", [">= 1.0", "< 3.0"])
@@ -34,11 +34,9 @@ Gem::Specification.new do |gem|
34
34
  fake_platform = ENV['GEM_BUILD_FAKE_PLATFORM'].to_s
35
35
  gem.platform = fake_platform unless fake_platform.empty?
36
36
  if /mswin|mingw/ =~ fake_platform || (/mswin|mingw/ =~ RUBY_PLATFORM && fake_platform.empty?)
37
- gem.add_runtime_dependency("win32-api", [">= 1.10", "< 2.0.0"])
38
37
  gem.add_runtime_dependency("win32-service", ["~> 2.3.0"])
39
38
  gem.add_runtime_dependency("win32-ipc", ["~> 0.7.0"])
40
39
  gem.add_runtime_dependency("win32-event", ["~> 0.6.3"])
41
- gem.add_runtime_dependency("windows-pr", ["~> 1.2.6"])
42
40
  gem.add_runtime_dependency("certstore_c", ["~> 0.1.7"])
43
41
  end
44
42
 
@@ -36,6 +36,7 @@ module Fluent
36
36
  restart: "HUP",
37
37
  flush: "USR1",
38
38
  reload: "USR2",
39
+ dump: "CONT",
39
40
  }
40
41
  WINSVC_CONTROL_CODE_MAP = {
41
42
  shutdown: SERVICE_CONTROL_STOP,
@@ -44,6 +45,7 @@ module Fluent
44
45
  restart: 128,
45
46
  flush: 129,
46
47
  reload: SERVICE_CONTROL_PARAMCHANGE,
48
+ dump: 130,
47
49
  }
48
50
  else
49
51
  COMMAND_MAP = {
@@ -51,6 +53,7 @@ module Fluent
51
53
  restart: :HUP,
52
54
  flush: :USR1,
53
55
  reload: :USR2,
56
+ dump: :CONT,
54
57
  }
55
58
  end
56
59
 
@@ -146,7 +149,7 @@ module Fluent
146
149
  event = Win32::Event.open("#{prefix}#{suffix}")
147
150
  event.set
148
151
  event.close
149
- rescue Errno::ENOENT => e
152
+ rescue Errno::ENOENT
150
153
  puts "Error: Cannot find the fluentd process with the event name: \"#{prefix}\""
151
154
  end
152
155
  end
@@ -126,6 +126,16 @@ op.on('--without-source', "invoke a fluentd without input plugins", TrueClass) {
126
126
  opts[:without_source] = b
127
127
  }
128
128
 
129
+ op.on('--config-file-type VALU', 'guessing file type of fluentd configuration. yaml/yml or guess') { |s|
130
+ if (s == 'yaml') || (s == 'yml')
131
+ opts[:config_file_type] = s.to_sym
132
+ elsif (s == 'guess')
133
+ opts[:config_file_type] = s.to_sym
134
+ else
135
+ usage '--config-file-type accepts yaml/yml or guess'
136
+ end
137
+ }
138
+
129
139
  op.on('--use-v1-config', "Use v1 configuration format (default)", TrueClass) {|b|
130
140
  opts[:use_v1_config] = b
131
141
  }
@@ -179,9 +189,6 @@ op.on('--disable-shared-socket', "Don't open shared socket for multiple workers"
179
189
  }
180
190
 
181
191
  if Fluent.windows?
182
- require 'windows/library'
183
- include Windows::Library
184
-
185
192
  opts.merge!(
186
193
  :winsvc_name => 'fluentdwinsvc',
187
194
  :winsvc_display_name => 'Fluentd Windows Service',
@@ -282,9 +289,7 @@ if winsvcinstmode = opts[:regwinsvc]
282
289
  case winsvcinstmode
283
290
  when 'i'
284
291
  binary_path = File.join(File.dirname(__FILE__), "..")
285
- ruby_path = "\0" * 256
286
- GetModuleFileName.call(0,ruby_path,256)
287
- ruby_path = ruby_path.rstrip.gsub(/\\/, '/')
292
+ ruby_path = ServerEngine.ruby_bin_path
288
293
  start_type = Service::DEMAND_START
289
294
  if opts[:regwinsvcautostart]
290
295
  start_type = Service::AUTO_START
@@ -191,9 +191,9 @@ worker_id = ENV['SERVERENGINE_WORKER_ID'] || ''
191
191
  EOM
192
192
  begin
193
193
  @eval_context.instance_eval(code)
194
- rescue SetNil => e
194
+ rescue SetNil
195
195
  nil
196
- rescue SetDefault => e
196
+ rescue SetDefault
197
197
  :default
198
198
  end
199
199
  end
@@ -0,0 +1,47 @@
1
+ #
2
+ # Fluentd
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ module Fluent
18
+ module Config
19
+ module YamlParser
20
+ module FluentValue
21
+ JsonValue = Struct.new(:val) do
22
+ def to_s
23
+ val.to_json
24
+ end
25
+
26
+ def to_element
27
+ to_s
28
+ end
29
+ end
30
+
31
+ StringValue = Struct.new(:val, :context) do
32
+ def to_s
33
+ context.instance_eval("\"#{val}\"")
34
+ rescue Fluent::SetNil => _
35
+ ''
36
+ rescue Fluent::SetDefault => _
37
+ ':default'
38
+ end
39
+
40
+ def to_element
41
+ to_s
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,91 @@
1
+ #
2
+ # Fluentd
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ require 'psych'
18
+ require 'json'
19
+ require 'fluent/config/error'
20
+ require 'fluent/config/yaml_parser/fluent_value'
21
+
22
+ # Based on https://github.com/eagletmt/hako/blob/34cdde06fe8f3aeafd794be830180c3cedfbb4dc/lib/hako/yaml_loader.rb
23
+
24
+ module Fluent
25
+ module Config
26
+ module YamlParser
27
+ class Loader
28
+ INCLUDE_TAG = 'tag:include'.freeze
29
+ FLUENT_JSON_TAG = 'tag:fluent/json'.freeze
30
+ FLUENT_STR_TAG = 'tag:fluent/s'.freeze
31
+ SHOVEL = '<<'.freeze
32
+
33
+ def initialize(context = Kernel.binding)
34
+ @context = context
35
+ @current_path = nil
36
+ end
37
+
38
+ # @param [String] path
39
+ # @return [Hash]
40
+ def load(path)
41
+ class_loader = Psych::ClassLoader.new
42
+ scanner = Psych::ScalarScanner.new(class_loader)
43
+
44
+ visitor = Visitor.new(scanner, class_loader)
45
+
46
+ visitor._register_domain(INCLUDE_TAG) do |_, val|
47
+ load(path.parent.join(val))
48
+ end
49
+
50
+ visitor._register_domain(FLUENT_JSON_TAG) do |_, val|
51
+ Fluent::Config::YamlParser::FluentValue::JsonValue.new(val)
52
+ end
53
+
54
+ visitor._register_domain(FLUENT_STR_TAG) do |_, val|
55
+ Fluent::Config::YamlParser::FluentValue::StringValue.new(val, @context)
56
+ end
57
+
58
+ path.open do |f|
59
+ visitor.accept(Psych.parse(f))
60
+ end
61
+ end
62
+
63
+ class Visitor < Psych::Visitors::ToRuby
64
+ def initialize(scanner, class_loader)
65
+ super(scanner, class_loader)
66
+ end
67
+
68
+ def _register_domain(name, &block)
69
+ @domain_types.merge!({ name => [name, block] })
70
+ end
71
+
72
+ def revive_hash(hash, o)
73
+ super(hash, o).tap do |r|
74
+ if r[SHOVEL].is_a?(Hash)
75
+ h2 = {}
76
+ r.each do |k, v|
77
+ if k == SHOVEL
78
+ h2.merge!(v)
79
+ else
80
+ h2[k] = v
81
+ end
82
+ end
83
+ r.replace(h2)
84
+ end
85
+ end
86
+ end
87
+ end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,166 @@
1
+ #
2
+ # Fluentd
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ require 'fluent/config/yaml_parser/section_builder'
18
+
19
+ module Fluent
20
+ module Config
21
+ module YamlParser
22
+ class Parser
23
+ def initialize(config, indent: 2)
24
+ @base_indent = indent
25
+ @config = config
26
+ end
27
+
28
+ def build
29
+ s = @config['system'] && system_config_build(@config['system'])
30
+ c = @config['config'] && config_build(@config['config'], root: true)
31
+ RootBuilder.new(s, c)
32
+ end
33
+
34
+ private
35
+
36
+ def system_config_build(config)
37
+ section_build('system', config)
38
+ end
39
+
40
+ def config_build(config, indent: 0, root: false)
41
+ sb = SectionBodyBuilder.new(indent, root: root)
42
+ config.each do |c|
43
+ if (lc = c.delete('label'))
44
+ sb.add_section(label_build(lc, indent: indent))
45
+ end
46
+
47
+ if (sc = c.delete('source'))
48
+ sb.add_section(source_build(sc, indent: indent))
49
+ end
50
+
51
+ if (fc = c.delete('filter'))
52
+ sb.add_section(filter_build(fc, indent: indent))
53
+ end
54
+
55
+ if (mc = c.delete('match'))
56
+ sb.add_section(match_build(mc, indent: indent))
57
+ end
58
+
59
+ if (wc = c.delete('worker'))
60
+ sb.add_section(worker_build(wc, indent: indent))
61
+ end
62
+
63
+ included_sections_build(c, sb, indent: indent)
64
+ end
65
+
66
+ sb
67
+ end
68
+
69
+ def label_build(config, indent: 0)
70
+ config = config.dup
71
+ name = config.delete('$name')
72
+ c = config.delete('config')
73
+ SectionBuilder.new('label', config_build(c, indent: indent + @base_indent), indent, name)
74
+ end
75
+
76
+ def worker_build(config, indent: 0)
77
+ config = config.dup
78
+ num = config.delete('$arg')
79
+ c = config.delete('config')
80
+ SectionBuilder.new('worker', config_build(c, indent: indent + @base_indent), indent, num)
81
+ end
82
+
83
+ def source_build(config, indent: 0)
84
+ section_build('source', config, indent: indent)
85
+ end
86
+
87
+ def filter_build(config, indent: 0)
88
+ config = config.dup
89
+ tag = config.delete('$tag')
90
+ if tag.is_a?(Array)
91
+ section_build('filter', config, indent: indent, arg: tag&.join(','))
92
+ else
93
+ section_build('filter', config, indent: indent, arg: tag)
94
+ end
95
+ end
96
+
97
+ def match_build(config, indent: 0)
98
+ config = config.dup
99
+ tag = config.delete('$tag')
100
+ if tag.is_a?(Array)
101
+ section_build('match', config, indent: indent, arg: tag&.join(','))
102
+ else
103
+ section_build('match', config, indent: indent, arg: tag)
104
+ end
105
+ end
106
+
107
+ def included_sections_build(config, section_builder, indent: 0)
108
+ config.each_entry do |e|
109
+ k = e.keys.first
110
+ cc = e.delete(k)
111
+ case k
112
+ when 'label'
113
+ section_builder.add_section(label_build(cc, indent: indent))
114
+ when 'worker'
115
+ section_builder.add_section(worker_build(cc, indent: indent))
116
+ when 'source'
117
+ section_builder.add_section(source_build(cc, indent: indent))
118
+ when 'filter'
119
+ section_builder.add_section(filter_build(cc, indent: indent))
120
+ when 'match'
121
+ section_builder.add_section(match_build(cc, indent: indent))
122
+ end
123
+ end
124
+ end
125
+
126
+ def section_build(name, config, indent: 0, arg: nil)
127
+ sb = SectionBodyBuilder.new(indent + @base_indent)
128
+
129
+ if (v = config.delete('$type'))
130
+ sb.add_line('@type', v)
131
+ end
132
+
133
+ if (v = config.delete('$label'))
134
+ sb.add_line('@label', v)
135
+ end
136
+
137
+ if (v = config.delete('$id'))
138
+ sb.add_line('@id', v)
139
+ end
140
+
141
+ config.each do |key, val|
142
+ if val.is_a?(Array)
143
+ val.each do |v|
144
+ sb.add_section(section_build(key, v, indent: indent + @base_indent))
145
+ end
146
+ elsif val.is_a?(Hash)
147
+ harg = val.delete('$arg')
148
+ if harg.is_a?(Array)
149
+ # To prevent to generate invalid configuration for arg.
150
+ # "arg" should be String object and concatenated by ","
151
+ # when two or more objects are specified there.
152
+ sb.add_section(section_build(key, val, indent: indent + @base_indent, arg: harg&.join(',')))
153
+ else
154
+ sb.add_section(section_build(key, val, indent: indent + @base_indent, arg: harg))
155
+ end
156
+ else
157
+ sb.add_line(key, val)
158
+ end
159
+ end
160
+
161
+ SectionBuilder.new(name, sb, indent, arg)
162
+ end
163
+ end
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,107 @@
1
+ #
2
+ # Fluentd
3
+ #
4
+ # Licensed under the Apache License, Version 2.0 (the "License");
5
+ # you may not use this file except in compliance with the License.
6
+ # You may obtain a copy of the License at
7
+ #
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+ #
10
+ # Unless required by applicable law or agreed to in writing, software
11
+ # distributed under the License is distributed on an "AS IS" BASIS,
12
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
+ # See the License for the specific language governing permissions and
14
+ # limitations under the License.
15
+ #
16
+
17
+ module Fluent
18
+ module Config
19
+ module YamlParser
20
+ SectionBuilder = Struct.new(:name, :body, :indent_size, :arg) do
21
+ def to_s
22
+ indent = ' ' * indent_size
23
+
24
+ if arg && !arg.to_s.empty?
25
+ "#{indent}<#{name} #{arg}>\n#{body}\n#{indent}</#{name}>"
26
+ else
27
+ "#{indent}<#{name}>\n#{body}\n#{indent}</#{name}>"
28
+ end
29
+ end
30
+
31
+ def to_element
32
+ elem = body.to_element
33
+ elem.name = name
34
+ elem.arg = arg.to_s if arg
35
+ elem.v1_config = true
36
+ elem
37
+ end
38
+ end
39
+
40
+ class RootBuilder
41
+ def initialize(system, conf)
42
+ @system = system
43
+ @conf = conf
44
+ end
45
+
46
+ attr_reader :system, :conf
47
+
48
+ def to_element
49
+ Fluent::Config::Element.new('ROOT', '', {}, [@system, @conf].compact.map(&:to_element).flatten)
50
+ end
51
+
52
+ def to_s
53
+ s = StringIO.new(+'')
54
+ s.puts(@system.to_s) if @system
55
+ s.puts(@conf.to_s) if @conf
56
+
57
+ s.string
58
+ end
59
+ end
60
+
61
+ class SectionBodyBuilder
62
+ Row = Struct.new(:key, :value, :indent) do
63
+ def to_s
64
+ "#{indent}#{key} #{value}"
65
+ end
66
+ end
67
+
68
+ def initialize(indent, root: false)
69
+ @indent = ' ' * indent
70
+ @bodies = []
71
+ @root = root
72
+ end
73
+
74
+ def add_line(k, v)
75
+ @bodies << Row.new(k, v, @indent)
76
+ end
77
+
78
+ def add_section(section)
79
+ @bodies << section
80
+ end
81
+
82
+ def to_element
83
+ if @root
84
+ return @bodies.map(&:to_element)
85
+ end
86
+
87
+ not_section, section = @bodies.partition { |e| e.is_a?(Row) }
88
+ r = {}
89
+ not_section.each do |e|
90
+ v = e.value
91
+ r[e.key] = v.respond_to?(:to_element) ? v.to_element : v
92
+ end
93
+
94
+ if @root
95
+ section.map(&:to_element)
96
+ else
97
+ Fluent::Config::Element.new('', '', r, section.map(&:to_element))
98
+ end
99
+ end
100
+
101
+ def to_s
102
+ @bodies.map(&:to_s).join("\n")
103
+ end
104
+ end
105
+ end
106
+ end
107
+ end