flueconf 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 9effe81389c67ea7f4b51c8683f99402fcc20cf5bc43a18f5200ea43a712b363
4
+ data.tar.gz: 697df4d11e65ecf85ec54427e5326e9231b6e75b320d2be589bd9ac3327bd872
5
+ SHA512:
6
+ metadata.gz: eb218202d17afbd5afb401ab713e83cfe4ad748f6429af6d34089426cdc95cfc17c2bfc13e0080aa3de81bfe6a6dafd46cf8cc946d705142335c8ee89508de51
7
+ data.tar.gz: 212ef5b7c85e2fd53c4ddb8401c2623d353644d74fa19f4e9103b058ee09460ebf533d1baae430b94300ed091a46489f0a3dc40b6d365e2d92336cc7a87a842a
@@ -0,0 +1,10 @@
1
+ module Flueconf
2
+ def build(*args, &block)
3
+ Flueconf::Builder.new(*args, &block)
4
+ end
5
+ module_function :build
6
+ end
7
+
8
+ require 'flueconf/builder'
9
+ require 'flueconf/serializer'
10
+ require 'flueconf/version'
@@ -0,0 +1,94 @@
1
+ require 'json'
2
+
3
+ class Flueconf::Builder
4
+ def initialize(options = {}, &block)
5
+ @attributes = {}
6
+ @current = @attributes
7
+ @context = nil
8
+
9
+ build(&block) if block_given?
10
+ end
11
+
12
+ def build(&block)
13
+ return unless block_given?
14
+
15
+ @context = eval('self', block.binding)
16
+
17
+ instance_eval(&block)
18
+
19
+ self
20
+ end
21
+
22
+ def label(*args, &block)
23
+ method = block_given? ? :label : :@label
24
+ add(method, *args, &block)
25
+ end
26
+
27
+ %i(type id).each do |method|
28
+ define_method method do |*args, &block|
29
+ add(:"@#{method}", *args, &block)
30
+ end
31
+ end
32
+
33
+ %i(source match filter system).each do |method|
34
+ define_method method do |*args, &block|
35
+ add(method, *args, &block)
36
+ end
37
+ end
38
+
39
+ def method_missing(method, *args, &block)
40
+ if @context and @context.respond_to?(method)
41
+ @context.send(method, *args, &block)
42
+ else
43
+ add(method, *args, &block)
44
+ end
45
+ end
46
+
47
+ def add(*args, &block)
48
+ if block_given?
49
+ obj = {}
50
+ k = args.first.to_sym
51
+
52
+ @current[k] = [] unless @current[k].is_a? Array
53
+ @current[k] << obj
54
+
55
+ c = obj
56
+ args[1..-1].each do |k|
57
+ obj = {}
58
+ c[k.to_sym] = obj
59
+ c = obj
60
+ end
61
+
62
+ previous = @current
63
+ @current = obj
64
+ instance_eval(&block)
65
+ @current = previous
66
+ elsif args.length >= 1
67
+ method = args.shift.to_sym
68
+
69
+ value = case args.length
70
+ when 0
71
+ nil
72
+ when 1
73
+ args.first
74
+ else
75
+ args
76
+ end
77
+ value = case value
78
+ when Hash
79
+ value.map { |k, v| v.nil? ? nil : "#{k}:#{v}" }.compact.join(',')
80
+ when Array
81
+ value.compact.join(',')
82
+ else
83
+ value
84
+ end
85
+ @current[method] = value
86
+ else
87
+ raise ArgumentError, "One key and at least one of values are required: #{args.join(',')}"
88
+ end
89
+ end
90
+
91
+ def to_fluent(*args)
92
+ Flueconf::Serializer.serialize(@attributes, *args)
93
+ end
94
+ end
@@ -0,0 +1,44 @@
1
+ require 'json'
2
+
3
+ class Flueconf::Serializer
4
+ class << self
5
+ def serialize(obj, options = {})
6
+ indent = options[:indent]
7
+ indent = 2 unless indent.is_a? Integer and indent >= 0
8
+
9
+ dump(obj, [], indent, 0)
10
+ end
11
+
12
+ private
13
+
14
+ def dump(obj, keys = [], indent = 0, depth = 0)
15
+ prefix = ' ' * indent * depth
16
+ key = keys.empty? ? nil : keys.join(' ')
17
+
18
+ case obj
19
+ when Array
20
+ obj.map do |v|
21
+ send(__method__, v, [key], indent, depth)
22
+ end.compact.join("\n")
23
+ when Hash
24
+ compacted = keys.empty? || (!obj.empty? && obj.values.all? { |v| v.is_a? Hash })
25
+
26
+ str = obj.map do |k, v|
27
+ k = k.to_s.strip
28
+
29
+ send(__method__, v, (compacted ? (keys + [k]) : [k]), indent, (compacted ? depth : depth + 1))
30
+ end.compact.join("\n")
31
+
32
+ compacted ? str : "#{prefix}<#{key}>\n" + (str.empty? ? '' : "#{str}\n") + "#{prefix}</#{keys.first}>"
33
+ when Numeric, TrueClass, FalseClass
34
+ (key ? "#{prefix}#{key} " : '') + obj.inspect
35
+ when NilClass
36
+ key ? "#{prefix}#{key}" : nil
37
+ when Regexp
38
+ (key ? "#{prefix}#{key} " : '') + obj.to_s
39
+ else
40
+ (key ? "#{prefix}#{key} " : '') + (/["#]/.match?(obj) ? obj.to_s.to_json : obj.to_s)
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,8 @@
1
+ module Flueconf
2
+ VERSION = '0.0.1'.freeze
3
+
4
+ def version
5
+ VERSION
6
+ end
7
+ module_function :version
8
+ end
@@ -0,0 +1,340 @@
1
+ describe Flueconf do
2
+ it 'can handle primitive types' do
3
+ fluent = Flueconf.build do
4
+ it_is_integer 1
5
+ it_is_negtive_integer -1
6
+ it_is_float 1.23
7
+ it_is_negtive_float -1.23
8
+ it_is_string 'foo'
9
+ it_is_special_string '#{Socket.gethostname}'
10
+ it_is_null nil
11
+ it_is_true true
12
+ it_is_false false
13
+ it_is_regexp /^.*$/
14
+ it_is_array [1, -2, 3.3, -4.4, 'bar', nil, true, false]
15
+ it_is_empty_array []
16
+ it_is_hash({ foo: 123, bar: 'aaa', null: nil })
17
+ it_is_empty_hash({})
18
+ end.to_fluent
19
+
20
+ expect(fluent).to eq <<~'EOF'.chomp
21
+ it_is_integer 1
22
+ it_is_negtive_integer -1
23
+ it_is_float 1.23
24
+ it_is_negtive_float -1.23
25
+ it_is_string foo
26
+ it_is_special_string "#{Socket.gethostname}"
27
+ it_is_null
28
+ it_is_true true
29
+ it_is_false false
30
+ it_is_regexp (?-mix:^.*$)
31
+ it_is_array 1,-2,3.3,-4.4,bar,true,false
32
+ it_is_empty_array
33
+ it_is_hash foo:123,bar:aaa
34
+ it_is_empty_hash
35
+ EOF
36
+ end
37
+
38
+ it 'can handle array object' do
39
+ fluent = Flueconf.build do
40
+ it_is_array_object do
41
+ foo 'bar'
42
+ end
43
+ end.to_fluent
44
+
45
+ expect(fluent).to eq <<~'EOF'.chomp
46
+ <it_is_array_object>
47
+ foo bar
48
+ </it_is_array_object>
49
+ EOF
50
+ end
51
+
52
+ it 'can handle empty array object' do
53
+ fluent = Flueconf.build do
54
+ it_is_array_object do
55
+ end
56
+ end.to_fluent
57
+
58
+ expect(fluent).to eq <<~'EOF'.chomp
59
+ <it_is_array_object>
60
+ </it_is_array_object>
61
+ EOF
62
+ end
63
+
64
+ it 'can handle object' do
65
+ fluent = Flueconf.build do
66
+ it_is_object 'obj' do
67
+ foo 'bar'
68
+ end
69
+ end.to_fluent
70
+
71
+ expect(fluent).to eq <<~'EOF'.chomp
72
+ <it_is_object obj>
73
+ foo bar
74
+ </it_is_object>
75
+ EOF
76
+ end
77
+
78
+ it 'can handle empty object' do
79
+ fluent = Flueconf.build do
80
+ it_is_object 'obj' do
81
+ end
82
+ end.to_fluent
83
+
84
+ expect(fluent).to eq <<~'EOF'.chomp
85
+ <it_is_object obj>
86
+ </it_is_object>
87
+ EOF
88
+ end
89
+
90
+ it 'can handle object with multiple keys' do
91
+ fluent = Flueconf.build do
92
+ it_is_object 'o', 'b', 'j' do
93
+ foo 'bar'
94
+ end
95
+ end.to_fluent
96
+
97
+ expect(fluent).to eq <<~'EOF'.chomp
98
+ <it_is_object o b j>
99
+ foo bar
100
+ </it_is_object>
101
+ EOF
102
+ end
103
+
104
+ it 'can handle nested data types' do
105
+ fluent = Flueconf.build do
106
+ foo 'bar'
107
+ obj 'nested', 'obj' do
108
+ obj 'obj', 'in', 'obj' do
109
+ float 3.14
110
+ arr do
111
+ int 123
112
+ end
113
+ arr do
114
+ bool true
115
+ arr_in_arr do
116
+ bool false
117
+ end
118
+ end
119
+ end
120
+ end
121
+ end.to_fluent
122
+
123
+ expect(fluent).to eq <<~'EOF'.chomp
124
+ foo bar
125
+ <obj nested obj>
126
+ <obj obj in obj>
127
+ float 3.14
128
+ <arr>
129
+ int 123
130
+ </arr>
131
+ <arr>
132
+ bool true
133
+ <arr_in_arr>
134
+ bool false
135
+ </arr_in_arr>
136
+ </arr>
137
+ </obj>
138
+ </obj>
139
+ EOF
140
+ end
141
+
142
+ it 'can handle multiple builds' do
143
+ builder = Flueconf.build do
144
+ obj do
145
+ first 1
146
+ end
147
+ end
148
+
149
+ fluent = builder.build do
150
+ second 2
151
+ end.to_fluent
152
+
153
+ expect(fluent).to eq <<~'EOF'.chomp
154
+ <obj>
155
+ first 1
156
+ </obj>
157
+ second 2
158
+ EOF
159
+ end
160
+
161
+ it 'can serialize with different indent' do
162
+ fluent = Flueconf.build do
163
+ foo 'bar'
164
+ obj 'nested', 'obj' do
165
+ obj 'obj', 'in', 'obj' do
166
+ float 3.14
167
+ arr do
168
+ int 123
169
+ end
170
+ arr do
171
+ bool true
172
+ end
173
+ end
174
+ end
175
+ end.to_fluent(indent: 4)
176
+
177
+ expect(fluent).to eq <<~'EOF'.chomp
178
+ foo bar
179
+ <obj nested obj>
180
+ <obj obj in obj>
181
+ float 3.14
182
+ <arr>
183
+ int 123
184
+ </arr>
185
+ <arr>
186
+ bool true
187
+ </arr>
188
+ </obj>
189
+ </obj>
190
+ EOF
191
+ end
192
+
193
+ it 'can handle method in different context' do
194
+ def bar
195
+ 'barbar'
196
+ end
197
+
198
+ fluent = Flueconf.build do
199
+ foo bar
200
+ end.to_fluent
201
+
202
+ expect(fluent).to eq <<~'EOF'.chomp
203
+ foo barbar
204
+ EOF
205
+ end
206
+
207
+ it 'can handle predefined types' do
208
+ fluent = Flueconf.build do
209
+ system do
210
+ dir_permission '0755'
211
+ end
212
+ source do
213
+ type 'forward'
214
+ id 'in_forward'
215
+ label '@outside'
216
+ port 24224
217
+ end
218
+ source do
219
+ type 'tail'
220
+ id 'in_tail_httpd_access'
221
+ path '/var/log/httpd-access.log'
222
+ pos_file '/var/log/td-agent/httpd-access.log.pos'
223
+ tag 'apache.access'
224
+ parse do
225
+ type 'apache2'
226
+ end
227
+ end
228
+ filter 'fluent.**' do
229
+ type 'record_transformer'
230
+ record do
231
+ level '${tag_parts[1]}'
232
+ end
233
+ end
234
+ filter '**' do
235
+ type 'record_transformer'
236
+ record do
237
+ hostname '#{Socket.gethostname}'
238
+ end
239
+ end
240
+ match 'fluent.**' do
241
+ type 'rewrite_tag_filter'
242
+ rule do
243
+ key 'message'
244
+ pattern /.*/
245
+ tag 'fluent'
246
+ end
247
+ end
248
+ match '**' do
249
+ type 'forward'
250
+ server do
251
+ host '192.0.2.1'
252
+ weight 100
253
+ end
254
+ server do
255
+ host '192.0.2.2'
256
+ weight 50
257
+ end
258
+ end
259
+ label '@outside' do
260
+ match '**' do
261
+ type 'forward'
262
+ server do
263
+ host '192.0.2.1'
264
+ weight 100
265
+ end
266
+ server do
267
+ host '192.0.2.2'
268
+ weight 50
269
+ end
270
+ end
271
+ end
272
+ end.to_fluent
273
+
274
+ expect(fluent).to eq <<~'EOF'.chomp
275
+ <system>
276
+ dir_permission 0755
277
+ </system>
278
+ <source>
279
+ @type forward
280
+ @id in_forward
281
+ @label @outside
282
+ port 24224
283
+ </source>
284
+ <source>
285
+ @type tail
286
+ @id in_tail_httpd_access
287
+ path /var/log/httpd-access.log
288
+ pos_file /var/log/td-agent/httpd-access.log.pos
289
+ tag apache.access
290
+ <parse>
291
+ @type apache2
292
+ </parse>
293
+ </source>
294
+ <filter fluent.**>
295
+ @type record_transformer
296
+ <record>
297
+ level ${tag_parts[1]}
298
+ </record>
299
+ </filter>
300
+ <filter **>
301
+ @type record_transformer
302
+ <record>
303
+ hostname "#{Socket.gethostname}"
304
+ </record>
305
+ </filter>
306
+ <match fluent.**>
307
+ @type rewrite_tag_filter
308
+ <rule>
309
+ key message
310
+ pattern (?-mix:.*)
311
+ tag fluent
312
+ </rule>
313
+ </match>
314
+ <match **>
315
+ @type forward
316
+ <server>
317
+ host 192.0.2.1
318
+ weight 100
319
+ </server>
320
+ <server>
321
+ host 192.0.2.2
322
+ weight 50
323
+ </server>
324
+ </match>
325
+ <label @outside>
326
+ <match **>
327
+ @type forward
328
+ <server>
329
+ host 192.0.2.1
330
+ weight 100
331
+ </server>
332
+ <server>
333
+ host 192.0.2.2
334
+ weight 50
335
+ </server>
336
+ </match>
337
+ </label>
338
+ EOF
339
+ end
340
+ end
@@ -0,0 +1 @@
1
+ require 'flueconf'
metadata ADDED
@@ -0,0 +1,94 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: flueconf
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Rianol Jou
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-08-17 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '12.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '12.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '3.8'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '3.8'
55
+ description: " Config fluentd in ruby. And featuring all programming features (variables,
56
+ iterators, functions, regexp, etc) in ruby.\n"
57
+ email:
58
+ - rianol.jou@gmail.com
59
+ executables: []
60
+ extensions: []
61
+ extra_rdoc_files: []
62
+ files:
63
+ - lib/flueconf.rb
64
+ - lib/flueconf/builder.rb
65
+ - lib/flueconf/serializer.rb
66
+ - lib/flueconf/version.rb
67
+ - spec/flueconf_spec.rb
68
+ - spec/spec_helper.rb
69
+ homepage: https://github.com/RiANOl/flueconf
70
+ licenses:
71
+ - MIT
72
+ metadata: {}
73
+ post_install_message:
74
+ rdoc_options: []
75
+ require_paths:
76
+ - lib
77
+ required_ruby_version: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '2.4'
82
+ required_rubygems_version: !ruby/object:Gem::Requirement
83
+ requirements:
84
+ - - ">="
85
+ - !ruby/object:Gem::Version
86
+ version: '0'
87
+ requirements: []
88
+ rubygems_version: 3.0.3
89
+ signing_key:
90
+ specification_version: 4
91
+ summary: Config fluentd in ruby.
92
+ test_files:
93
+ - spec/flueconf_spec.rb
94
+ - spec/spec_helper.rb