fluentd 0.12.0.pre.1 → 0.12.0.pre.2

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 (81) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/.travis.yml +1 -0
  4. data/ChangeLog +21 -0
  5. data/README.md +10 -2
  6. data/Rakefile +4 -13
  7. data/example/v1_literal_example.conf +36 -0
  8. data/fluentd.gemspec +4 -1
  9. data/lib/fluent/buffer.rb +73 -46
  10. data/lib/fluent/command/fluentd.rb +7 -2
  11. data/lib/fluent/config/basic_parser.rb +5 -0
  12. data/lib/fluent/config/element.rb +2 -5
  13. data/lib/fluent/config/literal_parser.rb +26 -7
  14. data/lib/fluent/config/section.rb +2 -0
  15. data/lib/fluent/config/v1_parser.rb +9 -2
  16. data/lib/fluent/formatter.rb +2 -1
  17. data/lib/fluent/mixin.rb +22 -7
  18. data/lib/fluent/output.rb +17 -8
  19. data/lib/fluent/parser.rb +14 -3
  20. data/lib/fluent/plugin/buf_file.rb +30 -15
  21. data/lib/fluent/plugin/filter_grep.rb +69 -0
  22. data/lib/fluent/plugin/filter_record_transformer.rb +183 -0
  23. data/lib/fluent/plugin/in_exec.rb +6 -0
  24. data/lib/fluent/plugin/in_forward.rb +34 -4
  25. data/lib/fluent/plugin/in_http.rb +1 -1
  26. data/lib/fluent/plugin/out_exec.rb +1 -1
  27. data/lib/fluent/plugin/out_exec_filter.rb +8 -1
  28. data/lib/fluent/plugin/out_forward.rb +82 -4
  29. data/lib/fluent/supervisor.rb +1 -1
  30. data/lib/fluent/timezone.rb +131 -0
  31. data/lib/fluent/version.rb +1 -1
  32. data/test/config/assertions.rb +42 -0
  33. data/test/config/test_config_parser.rb +385 -0
  34. data/test/config/test_configurable.rb +530 -0
  35. data/test/config/test_configure_proxy.rb +99 -0
  36. data/test/config/test_dsl.rb +237 -0
  37. data/test/config/test_literal_parser.rb +293 -0
  38. data/test/config/test_section.rb +112 -0
  39. data/test/config/test_system_config.rb +49 -0
  40. data/test/helper.rb +25 -0
  41. data/test/plugin/test_buf_file.rb +604 -0
  42. data/test/plugin/test_buf_memory.rb +204 -0
  43. data/test/plugin/test_filter_grep.rb +124 -0
  44. data/test/plugin/test_filter_record_transformer.rb +251 -0
  45. data/test/plugin/test_in_exec.rb +1 -0
  46. data/test/plugin/test_in_forward.rb +205 -2
  47. data/test/plugin/test_in_gc_stat.rb +1 -0
  48. data/test/plugin/test_in_http.rb +58 -2
  49. data/test/plugin/test_in_object_space.rb +1 -0
  50. data/test/plugin/test_in_status.rb +1 -0
  51. data/test/plugin/test_in_stream.rb +1 -1
  52. data/test/plugin/test_in_syslog.rb +1 -1
  53. data/test/plugin/test_in_tail.rb +1 -0
  54. data/test/plugin/test_in_tcp.rb +1 -1
  55. data/test/plugin/test_in_udp.rb +1 -1
  56. data/test/plugin/test_out_copy.rb +1 -0
  57. data/test/plugin/test_out_exec.rb +1 -0
  58. data/test/plugin/test_out_exec_filter.rb +1 -0
  59. data/test/plugin/test_out_file.rb +36 -0
  60. data/test/plugin/test_out_forward.rb +279 -8
  61. data/test/plugin/test_out_roundrobin.rb +1 -0
  62. data/test/plugin/test_out_stdout.rb +1 -0
  63. data/test/plugin/test_out_stream.rb +1 -1
  64. data/test/test_buffer.rb +530 -0
  65. data/test/test_config.rb +1 -1
  66. data/test/test_configdsl.rb +1 -1
  67. data/test/test_formatter.rb +223 -0
  68. data/test/test_match.rb +1 -2
  69. data/test/test_mixin.rb +74 -2
  70. data/test/test_parser.rb +7 -1
  71. metadata +88 -35
  72. data/lib/fluent/plugin/buf_zfile.rb +0 -75
  73. data/spec/config/config_parser_spec.rb +0 -314
  74. data/spec/config/configurable_spec.rb +0 -524
  75. data/spec/config/configure_proxy_spec.rb +0 -96
  76. data/spec/config/dsl_spec.rb +0 -239
  77. data/spec/config/helper.rb +0 -49
  78. data/spec/config/literal_parser_spec.rb +0 -222
  79. data/spec/config/section_spec.rb +0 -97
  80. data/spec/config/system_config_spec.rb +0 -49
  81. data/spec/spec_helper.rb +0 -60
@@ -1,75 +0,0 @@
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
- class ZFileBufferChunk < FileBufferChunk
19
- def initialize(path)
20
- super(path)
21
- @z = Zlib::Deflate.new
22
- end
23
-
24
- def <<(data)
25
- zdata = @z.deflate(data, Z_NO_FLUSH)
26
- unless zdata.empty?
27
- super(zdata)
28
- end
29
- end
30
-
31
- def close_write
32
- zdata = @z.flush
33
- unless zdata.empty?
34
- @file.write(zdata)
35
- @size += zdata.bytesize
36
- end
37
- super
38
- end
39
-
40
- def close
41
- @z.close
42
- super
43
- end
44
-
45
- def purge
46
- @z.close
47
- super
48
- end
49
-
50
- #def open(&block)
51
- #end
52
- end
53
-
54
- class ZFileBuffer < FileBuffer
55
- #Plugin.register_buffer('zfile', self)
56
-
57
- def initialize
58
- require 'zlib'
59
- super
60
- end
61
-
62
- def resume_queue
63
- queue = resume_queue_paths.map {|path|
64
- ZFileBufferChunk.new(path)
65
- }
66
- top = new_chunk
67
- return queue, top
68
- end
69
-
70
- def new_chunk
71
- path = new_chunk_path
72
- ZFileBufferChunk.new(path)
73
- end
74
- end
75
- end
@@ -1,314 +0,0 @@
1
- require "json"
2
- require "config/helper"
3
- require "fluent/config/error"
4
- require "fluent/config/basic_parser"
5
- require "fluent/config/literal_parser"
6
- require "fluent/config/v1_parser"
7
-
8
- describe Fluent::Config::V1Parser do
9
- include_context 'config_helper'
10
-
11
- def read_config(path)
12
- path = File.expand_path(path)
13
- data = File.read(path)
14
- Fluent::Config::V1Parser.parse(data, File.basename(path), File.dirname(path))
15
- end
16
-
17
- def parse_text(text)
18
- basepath = File.expand_path(File.dirname(__FILE__) + '/../../')
19
- Fluent::Config::V1Parser.parse(text, '(test)', basepath, nil)
20
- end
21
-
22
- def root(*elements)
23
- if elements.first.is_a?(Fluent::Config::Element)
24
- attrs = {}
25
- else
26
- attrs = elements.shift || {}
27
- end
28
- Fluent::Config::Element.new('ROOT', '', attrs, elements)
29
- end
30
-
31
- def e(name, arg='', attrs={}, elements=[])
32
- Fluent::Config::Element.new(name, arg, attrs, elements)
33
- end
34
-
35
- describe 'attribute parsing' do
36
- it "parses attributes" do
37
- expect(%[
38
- k1 v1
39
- k2 v2
40
- ]).to be_parsed_as(e('ROOT', '', {"k1"=>"v1", "k2"=>"v2"}))
41
- end
42
-
43
- it "allows attribute without value" do
44
- expect(%[
45
- k1
46
- k2 v2
47
- ]).to be_parsed_as(e('ROOT', '', {"k1"=>"", "k2"=>"v2"}))
48
- end
49
-
50
- it "parses attribute key always string" do
51
- expect("1 1").to be_parsed_as(e('ROOT', '', {"1" => "1"}))
52
- end
53
-
54
- [
55
- "_.%$!,",
56
- "/=~-~@\`:?",
57
- "()*{}.[]",
58
- ].each do |v|
59
- it "parses a value with symbol #{v.inspect}" do
60
- expect("k #{v}").to be_parsed_as(e('ROOT', '', {"k" => v}))
61
- end
62
- end
63
-
64
- it "ignores spacing around value" do
65
- expect(" k1 a ").to be_parsed_as(e('ROOT', '', {"k1" => "a"}))
66
- end
67
-
68
- it "allows spaces in value" do
69
- expect("k1 a b c").to be_parsed_as(e('ROOT', '', {"k1" => "a b c"}))
70
- end
71
-
72
- it "ignores comments after value" do
73
- expect(" k1 a#comment").to be_parsed_as(e('ROOT', '', {"k1" => "a"}))
74
- end
75
-
76
- it "allows # in value if quoted" do
77
- expect(' k1 "a#comment"').to be_parsed_as(e('ROOT', '', {"k1" => "a#comment"}))
78
- end
79
-
80
- it "rejects characters after quoted string" do
81
- expect(' k1 "a" 1').to be_parse_error
82
- end
83
-
84
- it "rejects @ prefix in parameter name" do
85
- expect(' @k v').to be_parse_error
86
- end
87
- end
88
-
89
- describe 'element parsing' do
90
- it do
91
- expect("").to be_parsed_as(root)
92
- end
93
-
94
- it "accepts empty element" do
95
- expect(%[
96
- <test>
97
- </test>
98
- ]).to be_parsed_as(
99
- root(
100
- e("test")
101
- )
102
- )
103
- end
104
-
105
- it "accepts argument and attributes" do
106
- expect(%[
107
- <test var>
108
- key val
109
- </test>
110
- ]).to be_parsed_as(root(
111
- e("test", 'var', {'key'=>"val"})
112
- ))
113
- end
114
-
115
- it "accepts nested elements" do
116
- expect(%[
117
- <test var>
118
- key 1
119
- <nested1>
120
- </nested1>
121
- <nested2>
122
- </nested2>
123
- </test>
124
- ]).to be_parsed_as(root(
125
- e("test", 'var', {'key'=>'1'}, [
126
- e('nested1'),
127
- e('nested2')
128
- ])
129
- ))
130
- end
131
-
132
- it "accepts multiline json values" do
133
- expect(%[
134
- <test var>
135
- key ["a",
136
- "b", "c",
137
- "d"]
138
- </test>
139
- ]).to be_parsed_as(root(
140
- e("test", 'var', {'key'=>"[\"a\",\"b\",\"c\",\"d\"]"})
141
- ))
142
- end
143
-
144
- [
145
- "**",
146
- "*.*",
147
- "1",
148
- "_.%$!",
149
- "/",
150
- "()*{}.[]",
151
- ].each do |arg|
152
- it "parses element argument #{arg.inspect}" do
153
- expect(%[
154
- <test #{arg}>
155
- </test>
156
- ]).to be_parsed_as(root(
157
- e("test", arg)
158
- ))
159
- end
160
- end
161
-
162
- it "parses empty element argument to nil" do
163
- expect(%[
164
- <test >
165
- </test>
166
- ]).to be_parsed_as(root(
167
- e("test", '')
168
- ))
169
- end
170
-
171
- it "ignores spacing around element argument" do
172
- expect(%[
173
- <test a >
174
- </test>
175
- ]).to be_parsed_as(root(
176
- e("test", "a")
177
- ))
178
- end
179
-
180
- it "considers comments in element argument" do
181
- expect(%[
182
- <test #a>
183
- </test>
184
- ]).to be_parse_error
185
- end
186
-
187
- it "requires line_end after begin tag" do
188
- expect(%[
189
- <test></test>
190
- ]).to be_parse_error
191
- end
192
-
193
- it "requires line_end after end tag" do
194
- expect(%[
195
- <test>
196
- </test><test>
197
- </test>
198
- ]).to be_parse_error
199
- end
200
- end
201
-
202
- # port from test_config.rb
203
- describe '@include parsing' do
204
- TMP_DIR = File.dirname(__FILE__) + "/tmp/v1_config#{ENV['TEST_ENV_NUMBER']}"
205
-
206
- def write_config(path, data)
207
- FileUtils.mkdir_p(File.dirname(path))
208
- File.open(path, "w") { |f| f.write data }
209
- end
210
-
211
- def prepare_config
212
- write_config "#{TMP_DIR}/config_test_1.conf", %[
213
- k1 root_config
214
- include dir/config_test_2.conf #
215
- @include #{TMP_DIR}/config_test_4.conf
216
- include file://#{TMP_DIR}/config_test_5.conf
217
- @include config.d/*.conf
218
- ]
219
- write_config "#{TMP_DIR}/dir/config_test_2.conf", %[
220
- k2 relative_path_include
221
- @include ../config_test_3.conf
222
- ]
223
- write_config "#{TMP_DIR}/config_test_3.conf", %[
224
- k3 relative_include_in_included_file
225
- ]
226
- write_config "#{TMP_DIR}/config_test_4.conf", %[
227
- k4 absolute_path_include
228
- ]
229
- write_config "#{TMP_DIR}/config_test_5.conf", %[
230
- k5 uri_include
231
- ]
232
- write_config "#{TMP_DIR}/config.d/config_test_6.conf", %[
233
- k6 wildcard_include_1
234
- <elem1 name>
235
- include normal_parameter
236
- </elem1>
237
- ]
238
- write_config "#{TMP_DIR}/config.d/config_test_7.conf", %[
239
- k7 wildcard_include_2
240
- ]
241
- write_config "#{TMP_DIR}/config.d/config_test_8.conf", %[
242
- <elem2 name>
243
- @include ../dir/config_test_9.conf
244
- </elem2>
245
- ]
246
- write_config "#{TMP_DIR}/dir/config_test_9.conf", %[
247
- k9 embeded
248
- <elem3 name>
249
- nested nested_value
250
- include hoge
251
- </elem3>
252
- ]
253
- write_config "#{TMP_DIR}/config.d/00_config_test_8.conf", %[
254
- k8 wildcard_include_3
255
- <elem4 name>
256
- include normal_parameter
257
- </elem4>
258
- ]
259
- end
260
-
261
- it 'parses @include / include correctly' do
262
- prepare_config
263
- c = read_config("#{TMP_DIR}/config_test_1.conf")
264
- expect(c['k1']).to eq('root_config')
265
- expect(c['k2']).to eq('relative_path_include')
266
- expect(c['k3']).to eq('relative_include_in_included_file')
267
- expect(c['k4']).to eq('absolute_path_include')
268
- expect(c['k5']).to eq('uri_include')
269
- expect(c['k6']).to eq('wildcard_include_1')
270
- expect(c['k7']).to eq('wildcard_include_2')
271
- expect(c['k8']).to eq('wildcard_include_3')
272
- expect(c.keys).to eq([
273
- 'k1',
274
- 'k2',
275
- 'k3',
276
- 'k4',
277
- 'k5',
278
- 'k8', # Because of the file name this comes first.
279
- 'k6',
280
- 'k7',
281
- ])
282
-
283
- elem1 = c.elements.find { |e| e.name == 'elem1' }
284
- expect(elem1).to be
285
- expect(elem1.arg).to eq('name')
286
- expect(elem1['include']).to eq('normal_parameter')
287
-
288
- elem2 = c.elements.find { |e| e.name == 'elem2' }
289
- expect(elem2).to be
290
- expect(elem2.arg).to eq('name')
291
- expect(elem2['k9']).to eq('embeded')
292
- expect(elem2.has_key?('include')).to be(false)
293
-
294
- elem3 = elem2.elements.find { |e| e.name == 'elem3' }
295
- expect(elem3).to be
296
- expect(elem3['nested']).to eq('nested_value')
297
- expect(elem3['include']).to eq('hoge')
298
- end
299
-
300
- # TODO: Add uri based include spec
301
- end
302
-
303
- describe 'unescape parameter' do
304
- it 'parses dumpped configuration' do
305
- original = %q!a\\\\\n\r\f\b\\'\\"z!
306
- expected = %!a\\\n\r\f\b'"z!
307
-
308
- conf = parse_text(%[k1 #{original}])
309
- expect(conf['k1']).to eq(expected) # escape check
310
- conf2 = parse_text(conf.to_s) # use dumpped configuration to check unescape
311
- expect(conf2.elements.first['k1']).to eq(expected)
312
- end
313
- end
314
- end
@@ -1,524 +0,0 @@
1
- require 'fluent/configurable'
2
- require 'fluent/config/element'
3
- require 'fluent/config/section'
4
-
5
- module ConfigurableSpec
6
- class Base1
7
- include Fluent::Configurable
8
-
9
- config_param :node, :string, :default => "node"
10
- config_param :flag1, :bool, :default => false
11
- config_param :flag2, :bool, :default => true
12
-
13
- config_param :name1, :string
14
- config_param :name2, :string
15
- config_param :name3, :string, :default => "base1"
16
- config_param :name4, :string, :default => "base1"
17
-
18
- def get_all
19
- [@node, @flag1, @flag2, @name1, @name2, @name3, @name4]
20
- end
21
- end
22
-
23
- class Base2 < Base1
24
- config_set_default :name2, "base2"
25
- config_set_default :name4, "base2"
26
- config_param :name5, :string
27
- config_param :name6, :string, :default => "base2"
28
-
29
- def get_all
30
- ary = super
31
- ary + [@name5, @name6]
32
- end
33
- end
34
-
35
- class Base3 < Base2
36
- config_section :node do
37
- config_param :name, :string, :default => "node"
38
- config_param :type, :string
39
- end
40
- config_section :branch, required: true, multi: true do
41
- config_argument :name, :string
42
- config_param :size, :integer, default: 10
43
- config_section :leaf, required: false, multi: true do
44
- config_param :weight, :integer
45
- config_section :worm, param_name: 'worms', multi: true do
46
- config_param :type, :string, default: 'ladybird'
47
- end
48
- end
49
- end
50
-
51
- def get_all
52
- ary = super
53
- ary + [@branch]
54
- end
55
- end
56
-
57
- class Base4 < Base2
58
- config_section :node, param_name: :nodes do
59
- config_argument :num, :integer
60
- config_param :name, :string, :default => "node"
61
- config_param :type, :string, :default => "b4"
62
- end
63
- config_section :description1, required: false, multi: false do
64
- config_argument :note, :string, default: "desc1"
65
- config_param :text, :string
66
- end
67
- config_section :description2, required: true, multi: false do
68
- config_argument :note, :string, default: "desc2"
69
- config_param :text, :string
70
- end
71
- config_section :description3, required: true, multi: true do
72
- config_argument :note, default: "desc3" do |val|
73
- "desc3: #{val}"
74
- end
75
- config_param :text, :string
76
- end
77
-
78
- def get_all
79
- ary = super
80
- ary + [@nodes, @description1, @description2, @description3]
81
- end
82
- end
83
-
84
- class Example0
85
- include Fluent::Configurable
86
-
87
- config_param :stringvalue, :string
88
- config_param :boolvalue, :bool
89
- config_param :integervalue, :integer
90
- config_param :sizevalue, :size
91
- config_param :timevalue, :time
92
- config_param :floatvalue, :float
93
- config_param :hashvalue, :hash
94
- config_param :arrayvalue, :array
95
- end
96
-
97
- class Example1
98
- include Fluent::Configurable
99
-
100
- config_param :name, :string, alias: :fullname
101
- config_param :bool, :bool, alias: :flag
102
- config_section :detail, required: true, multi: false, alias: "information" do
103
- config_param :address, :string
104
- end
105
-
106
- def get_all
107
- [@name, @detail]
108
- end
109
- end
110
- end
111
-
112
- describe Fluent::Configurable do
113
- context 'class defined without config_section' do
114
- describe '#initialize' do
115
- it 'create instance methods and default values by config_param and config_set_default' do
116
- obj1 = ConfigurableSpec::Base1.new
117
- expect(obj1.node).to eql("node")
118
- expect(obj1.flag1).to eq(false)
119
- expect(obj1.flag2).to eq(true)
120
- expect(obj1.name1).to be_nil
121
- expect(obj1.name2).to be_nil
122
- expect(obj1.name3).to eql("base1")
123
- expect(obj1.name4).to eql("base1")
124
- end
125
-
126
- it 'create instance methods and default values overwritten by sub class definition' do
127
- obj2 = ConfigurableSpec::Base2.new
128
- expect(obj2.node).to eql("node")
129
- expect(obj2.flag1).to eq(false)
130
- expect(obj2.flag2).to eq(true)
131
- expect(obj2.name1).to be_nil
132
- expect(obj2.name2).to eql("base2")
133
- expect(obj2.name3).to eql("base1")
134
- expect(obj2.name4).to eql("base2")
135
- expect(obj2.name5).to be_nil
136
- expect(obj2.name6).to eql("base2")
137
- end
138
- end
139
-
140
- describe '#configure' do
141
- it 'returns configurable object itself' do
142
- b2 = ConfigurableSpec::Base2.new
143
- expect(b2.configure({"name1" => "t1", "name5" => "t5"})).to be_a(ConfigurableSpec::Base2)
144
- end
145
-
146
- it 'raise errors without any specifications for param without defaults' do
147
- b2 = ConfigurableSpec::Base2.new
148
- expect{ b2.configure({}) }.to raise_error(Fluent::ConfigError)
149
- expect{ b2.configure({"name1" => "t1"}) }.to raise_error(Fluent::ConfigError)
150
- expect{ b2.configure({"name5" => "t5"}) }.to raise_error(Fluent::ConfigError)
151
- expect{ b2.configure({"name1" => "t1", "name5" => "t5"}) }.not_to raise_error()
152
-
153
- expect(b2.get_all).to eql(["node", false, true, "t1", "base2", "base1", "base2", "t5", "base2"])
154
- end
155
-
156
- it 'can configure bool values' do
157
- b2a = ConfigurableSpec::Base2.new
158
- expect{ b2a.configure({"flag1" => "true", "flag2" => "yes", "name1" => "t1", "name5" => "t5"}) }.not_to raise_error()
159
- expect(b2a.flag1).to eq(true)
160
- expect(b2a.flag2).to eq(true)
161
-
162
- b2b = ConfigurableSpec::Base2.new
163
- expect{ b2b.configure({"flag1" => false, "flag2" => "no", "name1" => "t1", "name5" => "t5"}) }.not_to raise_error()
164
- expect(b2b.flag1).to eq(false)
165
- expect(b2b.flag2).to eq(false)
166
- end
167
-
168
- it 'overwrites values of defaults' do
169
- b2 = ConfigurableSpec::Base2.new
170
- b2.configure({"name1" => "t1", "name2" => "t2", "name3" => "t3", "name4" => "t4", "name5" => "t5"})
171
- expect(b2.name1).to eql("t1")
172
- expect(b2.name2).to eql("t2")
173
- expect(b2.name3).to eql("t3")
174
- expect(b2.name4).to eql("t4")
175
- expect(b2.name5).to eql("t5")
176
- expect(b2.name6).to eql("base2")
177
-
178
- expect(b2.get_all).to eql(["node", false, true, "t1", "t2", "t3", "t4", "t5", "base2"])
179
- end
180
- end
181
- end
182
-
183
- context 'class defined with config_section' do
184
- describe '#initialize' do
185
- it 'create instance methods and default values as nil for params from config_section specified as non-multi' do
186
- b4 = ConfigurableSpec::Base4.new
187
- expect(b4.description1).to be_nil
188
- expect(b4.description2).to be_nil
189
- end
190
-
191
- it 'create instance methods and default values as [] for params from config_section specified as multi' do
192
- b4 = ConfigurableSpec::Base4.new
193
- expect(b4.description3).to eql([])
194
- end
195
-
196
- it 'overwrite base class definition by config_section of sub class definition' do
197
- b3 = ConfigurableSpec::Base3.new
198
- expect(b3.node).to eql([])
199
- end
200
-
201
- it 'create instance methods and default values by param_name' do
202
- b4 = ConfigurableSpec::Base4.new
203
- expect(b4.nodes).to eql([])
204
- expect(b4.node).to eql("node")
205
- end
206
-
207
- it 'create non-required and multi without any specifications' do
208
- b3 = ConfigurableSpec::Base3.new
209
- expect(b3.class.merged_configure_proxy.sections[:node].required?).to be false
210
- expect(b3.class.merged_configure_proxy.sections[:node].multi?).to be true
211
- end
212
- end
213
-
214
- describe '#configure' do
215
- def e(name, arg = '', attrs = {}, elements = [])
216
- attrs_str_keys = {}
217
- attrs.each{|key, value| attrs_str_keys[key.to_s] = value }
218
- Fluent::Config::Element.new(name, arg, attrs_str_keys, elements)
219
- end
220
-
221
- BASE_ATTRS = {
222
- "name1" => "1", "name2" => "2", "name3" => "3",
223
- "name4" => "4", "name5" => "5", "name6" => "6",
224
- }
225
- it 'checks required subsections' do
226
- b3 = ConfigurableSpec::Base3.new
227
- # branch sections required
228
- expect{ b3.configure(e('ROOT', '', BASE_ATTRS, [])) }.to raise_error(Fluent::ConfigError)
229
-
230
- # branch argument required
231
- msg = "'<branch ARG>' section requires argument, in section branch"
232
- expect{ b3.configure(e('ROOT', '', BASE_ATTRS, [e('branch', '')])) }.to raise_error(Fluent::ConfigError, msg)
233
-
234
- # leaf is not required
235
- expect{ b3.configure(e('ROOT', '', BASE_ATTRS, [e('branch', 'branch_name')])) }.not_to raise_error()
236
-
237
- # leaf weight required
238
- msg = "'weight' parameter is required, in section branch > leaf"
239
- branch1 = e('branch', 'branch_name', {size: 1}, [e('leaf', '10', {weight: 1})])
240
- expect{ b3.configure(e('ROOT', '', BASE_ATTRS, [branch1])) }.not_to raise_error()
241
- branch2 = e('branch', 'branch_name', {size: 1}, [e('leaf', '20')])
242
- expect{ b3.configure(e('ROOT', '', BASE_ATTRS, [branch1, branch2])) }.to raise_error(Fluent::ConfigError, msg)
243
- branch3 = e('branch', 'branch_name', {size: 1}, [e('leaf', '10', {weight: 3}), e('leaf', '20')])
244
- expect{ b3.configure(e('ROOT', '', BASE_ATTRS, [branch3])) }.to raise_error(Fluent::ConfigError, msg)
245
-
246
- ### worm not required
247
-
248
- b4 = ConfigurableSpec::Base4.new
249
-
250
- d1 = e('description1', '', {text:"d1"})
251
- d2 = e('description2', '', {text:"d2"})
252
- d3 = e('description3', '', {text:"d3"})
253
- expect{ b4.configure(e('ROOT', '', BASE_ATTRS, [d1.dup, d2.dup, d3.dup])) }.not_to raise_error()
254
-
255
- # description1 cannot be specified 2 or more
256
- msg = "'<description1>' section cannot be written twice or more"
257
- expect{ b4.configure(e('ROOT', '', BASE_ATTRS, [d1.dup, d2.dup, d1.dup, d3.dup])) }.to raise_error(Fluent::ConfigError, msg)
258
-
259
- # description2 cannot be specified 2 or more
260
- msg = "'<description2>' section cannot be written twice or more"
261
- expect{ b4.configure(e('ROOT', '', BASE_ATTRS, [d1.dup, d2.dup, d3.dup, d2.dup])) }.to raise_error(Fluent::ConfigError, msg)
262
-
263
- # description3 can be specified 2 or more
264
- expect{ b4.configure(e('ROOT', '', BASE_ATTRS, [d1.dup, d2.dup, d3.dup, d3.dup])) }.not_to raise_error()
265
- end
266
-
267
- it 'constructs confuguration object tree for Base3' do
268
- conf = e(
269
- 'ROOT',
270
- '',
271
- BASE_ATTRS,
272
- [
273
- e('node', '', {type:"1"}), e('node', '', {name:"node2",type:"2"}),
274
- e('branch', 'b1.*', {}, []),
275
- e('branch',
276
- 'b2.*',
277
- {size: 5},
278
- [
279
- e('leaf', 'THIS IS IGNORED', {weight: 55}, []),
280
- e('leaf', 'THIS IS IGNORED', {weight: 50}, [ e('worm', '', {}) ]),
281
- e('leaf', 'THIS IS IGNORED', {weight: 50}, [ e('worm', '', {type:"w1"}), e('worm', '', {type:"w2"}) ]),
282
- ]
283
- ),
284
- e('branch',
285
- 'b3.*',
286
- {size: "503"},
287
- [
288
- e('leaf', 'THIS IS IGNORED', {weight: 55}, []),
289
- ]
290
- )
291
- ],
292
- )
293
- b3 = ConfigurableSpec::Base3.new.configure(conf)
294
-
295
- expect(b3.node).not_to eql("node") # overwritten
296
-
297
- expect(b3.name1).to eql("1")
298
- expect(b3.name2).to eql("2")
299
- expect(b3.name3).to eql("3")
300
- expect(b3.name4).to eql("4")
301
- expect(b3.name5).to eql("5")
302
- expect(b3.name6).to eql("6")
303
-
304
- expect(b3.node).to be_a(Array)
305
- expect(b3.node.size).to eql(2)
306
-
307
- expect(b3.node[0].name).to eql("node")
308
- expect(b3.node[0].type).to eql("1")
309
- expect(b3.node[0][:type]).to eq(b3.node[0].type)
310
- expect(b3.node[1].name).to eql("node2")
311
- expect(b3.node[1].type).to eql("2")
312
- expect(b3.node[1][:type]).to eq(b3.node[1].type)
313
-
314
- expect(b3.branch).to be_a(Array)
315
- expect(b3.branch.size).to eql(3)
316
-
317
- expect(b3.branch[0].name).to eql('b1.*')
318
- expect(b3.branch[0].size).to eql(10)
319
- expect(b3.branch[0].leaf).to eql([])
320
-
321
- expect(b3.branch[1].name).to eql('b2.*')
322
- expect(b3.branch[1].size).to eql(5)
323
- expect(b3.branch[1].leaf.size).to eql(3)
324
- expect(b3.branch[1][:leaf]).to eq(b3.branch[1].leaf)
325
-
326
- expect(b3.branch[1].leaf[0].weight).to eql(55)
327
- expect(b3.branch[1].leaf[0].worms.size).to eql(0)
328
-
329
- expect(b3.branch[1].leaf[1].weight).to eql(50)
330
- expect(b3.branch[1].leaf[1].worms.size).to eql(1)
331
- expect(b3.branch[1].leaf[1].worms[0].type).to eql("ladybird")
332
-
333
- expect(b3.branch[1].leaf[2].weight).to eql(50)
334
- expect(b3.branch[1].leaf[2].worms.size).to eql(2)
335
- expect(b3.branch[1].leaf[2].worms[0].type).to eql("w1")
336
- expect(b3.branch[1].leaf[2].worms[1].type).to eql("w2")
337
-
338
- expect(b3.branch[2].name).to eql('b3.*')
339
- expect(b3.branch[2].size).to eql(503)
340
- expect(b3.branch[2].leaf.size).to eql(1)
341
- expect(b3.branch[2].leaf[0].weight).to eql(55)
342
- end
343
-
344
- it 'constructs confuguration object tree for Base4' do
345
- conf = e(
346
- 'ROOT',
347
- '',
348
- BASE_ATTRS,
349
- [
350
- e('node', '1', {type:"1"}), e('node', '2', {name:"node2"}),
351
- e('description3', '', {text:"dddd3-1"}),
352
- e('description2', 'd-2', {text:"dddd2"}),
353
- e('description1', '', {text:"dddd1"}),
354
- e('description3', 'd-3', {text:"dddd3-2"}),
355
- e('description3', 'd-3a', {text:"dddd3-3"}),
356
- e('node', '4', {type:"four"}),
357
- ],
358
- )
359
- b4 = ConfigurableSpec::Base4.new.configure(conf)
360
-
361
- expect(b4.node).to eql("node")
362
-
363
- expect(b4.name1).to eql("1")
364
- expect(b4.name2).to eql("2")
365
- expect(b4.name3).to eql("3")
366
- expect(b4.name4).to eql("4")
367
- expect(b4.name5).to eql("5")
368
- expect(b4.name6).to eql("6")
369
-
370
- expect(b4.nodes).to be_a(Array)
371
- expect(b4.nodes.size).to eql(3)
372
- expect(b4.nodes[0].num).to eql(1)
373
- expect(b4.nodes[0].name).to eql("node")
374
- expect(b4.nodes[0].type).to eql("1")
375
- expect(b4.nodes[1].num).to eql(2)
376
- expect(b4.nodes[1].name).to eql("node2")
377
- expect(b4.nodes[1].type).to eql("b4")
378
- expect(b4.nodes[2].num).to eql(4)
379
- expect(b4.nodes[2].name).to eql("node")
380
- expect(b4.nodes[2].type).to eql("four")
381
-
382
- # e('description3', '', {text:"dddd3-1"}),
383
- # e('description3', 'd-3', {text:"dddd3-2"}),
384
- # e('description3', 'd-3a', {text:"dddd3-3"}),
385
-
386
- expect(b4.description1).to be_a(Fluent::Config::Section)
387
- expect(b4.description1.note).to eql("desc1")
388
- expect(b4.description1.text).to eql("dddd1")
389
-
390
- expect(b4.description2).to be_a(Fluent::Config::Section)
391
- expect(b4.description2.note).to eql("d-2")
392
- expect(b4.description2.text).to eql("dddd2")
393
-
394
- expect(b4.description3).to be_a(Array)
395
- expect(b4.description3.size).to eql(3)
396
- expect(b4.description3[0].note).to eql('desc3')
397
- expect(b4.description3[0].text).to eql('dddd3-1')
398
- expect(b4.description3[1].note).to eql('desc3: d-3')
399
- expect(b4.description3[1].text).to eql('dddd3-2')
400
- expect(b4.description3[2].note).to eql('desc3: d-3a')
401
- expect(b4.description3[2].text).to eql('dddd3-3')
402
- end
403
-
404
- it 'checks missing of specifications' do
405
- conf0 = e('ROOT', '', {}, [])
406
- ex01 = ConfigurableSpec::Example0.new
407
- expect { ex01.configure(conf0) }.to raise_error(Fluent::ConfigError)
408
-
409
- complete = {
410
- "stringvalue" => "s1", "boolvalue" => "yes", "integervalue" => "10",
411
- "sizevalue" => "10m", "timevalue" => "100s", "floatvalue" => "1.001",
412
- "hashvalue" => '{"foo":1, "bar":2}',
413
- "arrayvalue" => '[1,"ichi"]',
414
- }
415
-
416
- checker = lambda {|conf| ConfigurableSpec::Example0.new.configure(conf) }
417
-
418
- expect { checker.call(complete) }.not_to raise_error()
419
- expect { checker.call(complete.reject{|k,v| k == "stringvalue" }) }.to raise_error(Fluent::ConfigError)
420
- expect { checker.call(complete.reject{|k,v| k == "boolvalue" }) }.to raise_error(Fluent::ConfigError)
421
- expect { checker.call(complete.reject{|k,v| k == "integervalue"}) }.to raise_error(Fluent::ConfigError)
422
- expect { checker.call(complete.reject{|k,v| k == "sizevalue" }) }.to raise_error(Fluent::ConfigError)
423
- expect { checker.call(complete.reject{|k,v| k == "timevalue" }) }.to raise_error(Fluent::ConfigError)
424
- expect { checker.call(complete.reject{|k,v| k == "floatvalue" }) }.to raise_error(Fluent::ConfigError)
425
- expect { checker.call(complete.reject{|k,v| k == "hashvalue" }) }.to raise_error(Fluent::ConfigError)
426
- expect { checker.call(complete.reject{|k,v| k == "arrayvalue" }) }.to raise_error(Fluent::ConfigError)
427
- end
428
-
429
- it 'accepts configuration values as string representation' do
430
- conf = {
431
- "stringvalue" => "s1", "boolvalue" => "yes", "integervalue" => "10",
432
- "sizevalue" => "10m", "timevalue" => "10m", "floatvalue" => "1.001",
433
- "hashvalue" => '{"foo":1, "bar":2}',
434
- "arrayvalue" => '[1,"ichi"]',
435
- }
436
- ex = ConfigurableSpec::Example0.new.configure(conf)
437
- expect(ex.stringvalue).to eq("s1")
438
- expect(ex.boolvalue).to equal(true)
439
- expect(ex.integervalue).to eq(10)
440
- expect(ex.sizevalue).to eq(10 * 1024 * 1024)
441
- expect(ex.timevalue).to eq(10 * 60)
442
- expect(ex.floatvalue).to eq(1.001)
443
- expect(ex.hashvalue).to eq({"foo" => 1, "bar" => 2})
444
- expect(ex.arrayvalue).to eq([1, "ichi"])
445
- end
446
-
447
- it 'accepts configuration values as ruby value representation (especially for DSL)' do
448
- conf = {
449
- "stringvalue" => "s1", "boolvalue" => true, "integervalue" => 10,
450
- "sizevalue" => 10 * 1024 * 1024, "timevalue" => 10 * 60, "floatvalue" => 1.001,
451
- "hashvalue" => {"foo" => 1, "bar" => 2},
452
- "arrayvalue" => [1,"ichi"],
453
- }
454
- ex = ConfigurableSpec::Example0.new.configure(conf)
455
- expect(ex.stringvalue).to eq("s1")
456
- expect(ex.boolvalue).to equal(true)
457
- expect(ex.integervalue).to eq(10)
458
- expect(ex.sizevalue).to eq(10 * 1024 * 1024)
459
- expect(ex.timevalue).to eq(10 * 60)
460
- expect(ex.floatvalue).to eq(1.001)
461
- expect(ex.hashvalue).to eq({"foo" => 1, "bar" => 2})
462
- expect(ex.arrayvalue).to eq([1, "ichi"])
463
- end
464
-
465
- it 'gets both of true(yes) and false(no) for bool value parameter' do
466
- conf = {
467
- "stringvalue" => "s1", "integervalue" => 10,
468
- "sizevalue" => 10 * 1024 * 1024, "timevalue" => 10 * 60, "floatvalue" => 1.001,
469
- "hashvalue" => {"foo" => 1, "bar" => 2},
470
- "arrayvalue" => [1,"ichi"],
471
- }
472
- ex0 = ConfigurableSpec::Example0.new.configure(conf.merge({"boolvalue" => "true"}))
473
- expect(ex0.boolvalue).to equal(true)
474
-
475
- ex1 = ConfigurableSpec::Example0.new.configure(conf.merge({"boolvalue" => "yes"}))
476
- expect(ex1.boolvalue).to equal(true)
477
-
478
- ex2 = ConfigurableSpec::Example0.new.configure(conf.merge({"boolvalue" => true}))
479
- expect(ex2.boolvalue).to equal(true)
480
-
481
- ex3 = ConfigurableSpec::Example0.new.configure(conf.merge({"boolvalue" => "false"}))
482
- expect(ex3.boolvalue).to equal(false)
483
-
484
- ex4 = ConfigurableSpec::Example0.new.configure(conf.merge({"boolvalue" => "no"}))
485
- expect(ex4.boolvalue).to equal(false)
486
-
487
- ex5 = ConfigurableSpec::Example0.new.configure(conf.merge({"boolvalue" => false}))
488
- expect(ex5.boolvalue).to equal(false)
489
- end
490
- end
491
- end
492
-
493
- context 'class defined with config_param/config_section having :alias' do
494
- describe '#initialize' do
495
- it 'does not create methods for alias' do
496
- ex1 = ConfigurableSpec::Example1.new
497
- expect { ex1.name }.not_to raise_error()
498
- expect { ex1.fullname }.to raise_error(NoMethodError)
499
- expect { ex1.bool }.not_to raise_error()
500
- expect { ex1.flag }.to raise_error(NoMethodError)
501
- expect { ex1.detail }.not_to raise_error()
502
- expect { ex1.information}.to raise_error(NoMethodError)
503
- end
504
- end
505
-
506
- describe '#configure' do
507
- def e(name, arg = '', attrs = {}, elements = [])
508
- attrs_str_keys = {}
509
- attrs.each{|key, value| attrs_str_keys[key.to_s] = value }
510
- Fluent::Config::Element.new(name, arg, attrs_str_keys, elements)
511
- end
512
-
513
- it 'provides accessible data for alias attribute keys' do
514
- ex1 = ConfigurableSpec::Example1.new
515
- ex1.configure(e('ROOT', '', {"fullname" => "foo bar", "bool" => false}, [e('information', '', {"address" => "Mountain View 0"})]))
516
- expect(ex1.name).to eql("foo bar")
517
- expect(ex1.bool).not_to be_nil
518
- expect(ex1.bool).to be_falsy
519
- expect(ex1.detail).not_to be_nil
520
- expect(ex1.detail.address).to eql("Mountain View 0")
521
- end
522
- end
523
- end
524
- end