fluent-mixin-config-placeholders 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in fluent-mixin-config-placeholders.gemspec
4
+ gemspec
@@ -0,0 +1,13 @@
1
+ Copyright (c) 2012- TAGOMORI Satoshi
2
+
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software
10
+ distributed under the License is distributed on an "AS IS" BASIS,
11
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ See the License for the specific language governing permissions and
13
+ limitations under the License.
@@ -0,0 +1,42 @@
1
+ # Fluent::Mixin::ConfigPlaceholders
2
+
3
+ Fluent::Mixin::ConfigPlaceHolders provide some placeholders to fluentd plugins that includes this mix-in. Placeholders below are expanded in 'super' of including plugin's #configure method.
4
+
5
+ Available placeholders are:
6
+
7
+ * hostname (${hostname} or \_\_HOSTNAME\_\_)
8
+ * you can specify hostname string explicitly on 'hostname' parameter
9
+ * random uuid (${uuid}, ${uuid:random}, \_\_UUID\_\_ or \_\_UUID\_RANDOM\_\_)
10
+ * hostname string based uuid (${uuid:hostname} or \_\_UUID\_HOSTNAME\_\_)
11
+ * timestamp based uuid (${uuid:timestamp} or \_\_UUID\_TIMESTAMP\_\_)
12
+
13
+ ## Usage
14
+
15
+ In plugin (both of input and output), just include mixin.
16
+
17
+ class FooInput < Fluent::Input
18
+ Fluent::Plugin.register_input('foo', self)
19
+
20
+ config_param :tag, :string
21
+
22
+ include Fluent::Mixin::ConfigPlaceholders
23
+
24
+ def configure(conf)
25
+ super # MUST call 'super' at first!
26
+
27
+ @tag #=> here, you can get string replaced '${hostname}' into actual hostname
28
+ end
29
+
30
+ # ...
31
+ end
32
+
33
+ You can use this feature for tags for each fluentd node, paths for remote storage services like /root/${hostname}/access_log or non-race-condition paths like /files/${uuid:random}.
34
+
35
+ ## AUTHORS
36
+
37
+ * TAGOMORI Satoshi <tagomoris@gmail.com>
38
+
39
+ ## LICENSE
40
+
41
+ * Copyright: Copyright (c) 2012- tagomoris
42
+ * License: Apache License, Version 2.0
@@ -0,0 +1,11 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+
4
+ require 'rake/testtask'
5
+ Rake::TestTask.new(:test) do |test|
6
+ test.libs << 'lib' << 'test'
7
+ test.pattern = 'test/**/test_*.rb'
8
+ test.verbose = true
9
+ end
10
+
11
+ task :default => :test
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ Gem::Specification.new do |gem|
3
+ gem.name = "fluent-mixin-config-placeholders"
4
+ gem.version = "0.1.0"
5
+ gem.authors = ["TAGOMORI Satoshi"]
6
+ gem.email = ["tagomoris@gmail.com"]
7
+ gem.description = %q{to add various placeholders for plugin configurations}
8
+ gem.summary = %q{Configuration syntax extension mixin for fluentd plugin}
9
+ gem.homepage = "https://github.com/tagomoris/fluent-mixin-config-placeholders"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.require_paths = ["lib"]
15
+
16
+ gem.add_development_dependency "fluentd"
17
+ gem.add_development_dependency "uuidtools"
18
+ gem.add_runtime_dependency "fluentd"
19
+ gem.add_runtime_dependency "uuidtools"
20
+ end
@@ -0,0 +1,74 @@
1
+ require 'fluent/config'
2
+ require 'uuidtools'
3
+
4
+ module Fluent
5
+ module Mixin
6
+ module ConfigPlaceholders
7
+ attr_accessor :hostname
8
+
9
+ # ${hostname}, __HOSTNAME__
10
+
11
+ # ${uuid} or ${uuid:random} , __UUID__ or __UUID_RANDOM__
12
+ # UUIDTools::UUID.random_create
13
+ # => #<UUID:0x19013a UUID:984265dc-4200-4f02-ae70-fe4f48964159>
14
+
15
+ # ${uuid:hostname} , __UUID_HOSTNAME__
16
+ # UUIDTools::UUID.sha1_create(UUIDTools::UUID_DNS_NAMESPACE, "www.widgets.com")
17
+ # => #<UUID:0x2a0116 UUID:21f7f8de-8051-5b89-8680-0195ef798b6a>
18
+
19
+ # ${uuid:timestamp} , __UUID_TIMESTAMP__
20
+ # UUIDTools::UUID.timestamp_create
21
+ # => #<UUID:0x2adfdc UUID:64a5189c-25b3-11da-a97b-00c04fd430c8>
22
+
23
+ def uuid_random
24
+ UUIDTools::UUID.random_create.to_s
25
+ end
26
+
27
+ def uuid_hostname(hostname)
28
+ UUIDTools::UUID.sha1_create(UUIDTools::UUID_DNS_NAMESPACE, hostname).to_s
29
+ end
30
+
31
+ def uuid_timestamp
32
+ UUIDTools::UUID.timestamp_create.to_s
33
+ end
34
+
35
+ def replace(map, value)
36
+ map.reduce(value){|r,p| r.gsub(p[0], p[1].call())}
37
+ end
38
+
39
+ def configure(conf)
40
+ # Element#has_key? inserts key name into 'used' list, so we should escape that method...
41
+ hostname = conf.keys.include?('hostname') ? conf['hostname'] : `hostname`.chomp
42
+
43
+ mapping = {
44
+ '${hostname}' => lambda{ hostname },
45
+ '__HOSTNAME__' => lambda{ hostname },
46
+ '${uuid}' => lambda{ uuid_random() },
47
+ '__UUID__' => lambda{ uuid_random() },
48
+ '${uuid:random}' => lambda{ uuid_random() },
49
+ '__UUID_RANDOM__' => lambda{ uuid_random() },
50
+ '${uuid:hostname}' => lambda { uuid_hostname(hostname) },
51
+ '__UUID_HOSTNAME__' => lambda { uuid_hostname(hostname) },
52
+ '${uuid:timestamp}' => lambda { uuid_timestamp() },
53
+ '__UUID_TIMESTAMP__' => lambda { uuid_timestamp() },
54
+ }
55
+
56
+ def check_element(map,c)
57
+ c.arg = replace(map, c.arg)
58
+ c.keys.each do |k|
59
+ v = c.fetch(k, nil)
60
+ if v and v.is_a? String
61
+ c[k] = replace(map, v)
62
+ end
63
+ end
64
+ c.elements.each{|e| check_element(map,e)}
65
+ end
66
+
67
+ check_element(mapping,conf)
68
+
69
+ super
70
+ end
71
+
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,30 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ begin
4
+ Bundler.setup(:default, :development)
5
+ rescue Bundler::BundlerError => e
6
+ $stderr.puts e.message
7
+ $stderr.puts "Run `bundle install` to install missing gems"
8
+ exit e.status_code
9
+ end
10
+ require 'test/unit'
11
+
12
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
13
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
14
+
15
+ require 'fluent/test'
16
+ unless ENV.has_key?('VERBOSE')
17
+ nulllogger = Object.new
18
+ nulllogger.instance_eval {|obj|
19
+ def method_missing(method, *args)
20
+ # pass
21
+ end
22
+ }
23
+ $log = nulllogger
24
+ end
25
+
26
+ require 'fluent/mixin/config_placeholders'
27
+ require_relative 'plugin'
28
+
29
+ class Test::Unit::TestCase
30
+ end
@@ -0,0 +1,159 @@
1
+ require 'helper'
2
+
3
+ class ConfigPlaceholdersTest < Test::Unit::TestCase
4
+ def create_plugin_instances(conf)
5
+ [
6
+ Fluent::ConfigPlaceholdersTest0Input, Fluent::ConfigPlaceholdersTest1Input, Fluent::ConfigPlaceholdersTest2Input
7
+ ].map{|klass| Fluent::Test::InputTestDriver.new(klass).configure(conf).instance }
8
+ end
9
+
10
+ def test_unused
11
+ conf = %[
12
+ tag HOGE
13
+ path POSPOSPOS
14
+ ]
15
+ p = Fluent::Test::InputTestDriver.new(Fluent::ConfigPlaceholdersTest2Input).configure(conf).instance
16
+ assert_equal ['tag','path'], p.conf.used
17
+
18
+ conf = %[
19
+ tag HOGE
20
+ path POSPOSPOS
21
+ ]
22
+ p = Fluent::Test::InputTestDriver.new(Fluent::ConfigPlaceholdersTestXInput).configure(conf).instance
23
+ assert_equal [], p.conf.used
24
+
25
+ conf = %[
26
+ tag HOGE
27
+ path POSPOSPOS ${hostname} MOGEMOGE
28
+ ]
29
+ p = Fluent::Test::InputTestDriver.new(Fluent::ConfigPlaceholdersTestXInput).configure(conf).instance
30
+ assert_equal [], p.conf.used
31
+ end
32
+
33
+ def test_hostname
34
+ conf = %[
35
+ hostname testing.local
36
+ tag out.${hostname}
37
+ path /path/to/file.__HOSTNAME__.txt
38
+ ]
39
+ p1, p2, p3 = create_plugin_instances(conf)
40
+
41
+ assert_equal 'out.${hostname}', p1.tag
42
+ assert_equal 'out.testing.local', p2.tag
43
+ assert_equal 'out.testing.local', p3.tag
44
+
45
+ assert_equal '/path/to/file.__HOSTNAME__.txt', p1.path
46
+ assert_equal '/path/to/file.testing.local.txt', p2.path
47
+ assert_equal '/PATH/TO/FILE.TESTING.LOCAL.TXT', p3.path
48
+ end
49
+
50
+ PATH_CHECK_REGEXP = Regexp.compile('^/path/to/file\.[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}.txt$')
51
+ PATH_CHECK_REGEXP2 = Regexp.compile('^/PATH/TO/FILE\.[0-9A-F]{8}-([0-9A-F]{4}-){3}[0-9A-F]{12}.TXT$')
52
+
53
+ def test_uuid_random
54
+ conf1 = %[
55
+ tag test.out
56
+ path /path/to/file.${uuid}.txt
57
+ ]
58
+ p1, p2, p3 = create_plugin_instances(conf1)
59
+ assert_match PATH_CHECK_REGEXP, p2.path
60
+ assert_match PATH_CHECK_REGEXP2, p3.path
61
+
62
+ conf2 = %[
63
+ tag test.out
64
+ path /path/to/file.${uuid:random}.txt
65
+ ]
66
+ p1, p2, p3 = create_plugin_instances(conf2)
67
+ assert_match PATH_CHECK_REGEXP, p2.path
68
+ assert_match PATH_CHECK_REGEXP2, p3.path
69
+
70
+ conf3 = %[
71
+ tag test.out
72
+ path /path/to/file.__UUID__.txt
73
+ ]
74
+ p1, p2, p3 = create_plugin_instances(conf3)
75
+ assert_match PATH_CHECK_REGEXP, p2.path
76
+ assert_match PATH_CHECK_REGEXP2, p3.path
77
+
78
+ conf4 = %[
79
+ tag test.out
80
+ path /path/to/file.__UUID__.txt
81
+ ]
82
+ p1, p2, p3 = create_plugin_instances(conf4)
83
+ assert_match PATH_CHECK_REGEXP, p2.path
84
+ assert_match PATH_CHECK_REGEXP2, p3.path
85
+ end
86
+
87
+ PATH_CHECK_H_REGEXP = Regexp.compile('^/path/to/file\.[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}.log$')
88
+ PATH_CHECK_H_REGEXP2 = Regexp.compile('^/PATH/TO/FILE\.[0-9A-F]{8}-([0-9A-F]{4}-){3}[0-9A-F]{12}.LOG$')
89
+
90
+ def test_uuid_hostname
91
+ conf1 = %[
92
+ tag test.out
93
+ path /path/to/file.${uuid:hostname}.log
94
+ ]
95
+ p1, p2, p3 = create_plugin_instances(conf1)
96
+ assert_match PATH_CHECK_H_REGEXP, p2.path
97
+ assert_equal '/path/to/file.87577bd5-6d8c-5dff-8988-0bc01cb8ed53.log', p2.path
98
+ assert_match PATH_CHECK_H_REGEXP2, p3.path
99
+ assert_equal '/PATH/TO/FILE.87577BD5-6D8C-5DFF-8988-0BC01CB8ED53.LOG', p3.path
100
+
101
+ conf2 = %[
102
+ tag test.out
103
+ path /path/to/file.__UUID_HOSTNAME__.log
104
+ ]
105
+ p1, p2, p3 = create_plugin_instances(conf2)
106
+ assert_match PATH_CHECK_H_REGEXP, p2.path
107
+ assert_equal '/path/to/file.87577bd5-6d8c-5dff-8988-0bc01cb8ed53.log', p2.path
108
+ assert_match PATH_CHECK_H_REGEXP2, p3.path
109
+ assert_equal '/PATH/TO/FILE.87577BD5-6D8C-5DFF-8988-0BC01CB8ED53.LOG', p3.path
110
+ end
111
+
112
+ PATH_CHECK_T_REGEXP = Regexp.compile('^/path/to/file\.[0-9a-f]{8}-([0-9a-f]{4}-){3}[0-9a-f]{12}.out$')
113
+ PATH_CHECK_T_REGEXP2 = Regexp.compile('^/PATH/TO/FILE\.[0-9A-F]{8}-([0-9A-F]{4}-){3}[0-9A-F]{12}.OUT$')
114
+
115
+ def test_uuid_hostname
116
+ conf1 = %[
117
+ tag test.out
118
+ path /path/to/file.${uuid:timestamp}.out
119
+ ]
120
+ p1, p2, p3 = create_plugin_instances(conf1)
121
+ assert_match PATH_CHECK_T_REGEXP, p2.path
122
+ assert_match PATH_CHECK_T_REGEXP2, p3.path
123
+
124
+ conf2 = %[
125
+ tag test.out
126
+ path /path/to/file.__UUID_HOSTNAME__.out
127
+ ]
128
+ p1, p2, p3 = create_plugin_instances(conf2)
129
+ assert_match PATH_CHECK_T_REGEXP, p2.path
130
+ assert_match PATH_CHECK_T_REGEXP2, p3.path
131
+ end
132
+
133
+ def test_nested
134
+ conf = %[
135
+ hostname test.host.local
136
+ tag test.out
137
+ path /path/to/file.log
138
+ <config ${hostname}>
139
+ var val1.${uuid:hostname}
140
+ <group>
141
+ field value.1.${uuid:hostname}
142
+ </group>
143
+ <group>
144
+ field value.2.__UUID_HOSTNAME__
145
+ </group>
146
+ </config>
147
+ ]
148
+ require 'uuidtools'
149
+ uuid = UUIDTools::UUID.sha1_create(UUIDTools::UUID_DNS_NAMESPACE, "test.host.local").to_s
150
+
151
+ p1, p2, p3 = create_plugin_instances(conf)
152
+ assert_equal "config", p3.conf.elements.first.name
153
+ assert_equal "test.host.local", p3.conf.elements.first.arg
154
+ assert_equal "val1." + uuid, p3.conf.elements.first['var']
155
+ assert_equal "group", p3.conf.elements.first.elements[0].name
156
+ assert_equal "value.1." + uuid, p3.conf.elements.first.elements[0]['field']
157
+ assert_equal "value.2." + uuid, p3.conf.elements.first.elements[1]['field']
158
+ end
159
+ end
@@ -0,0 +1,53 @@
1
+ class Fluent::ConfigPlaceholdersTestXInput < Fluent::Input
2
+ Fluent::Plugin.register_input('config_placeholder_test_x', self)
3
+
4
+ attr_accessor :conf
5
+ def configure(conf)
6
+ super
7
+
8
+ @conf = conf
9
+ end
10
+ end
11
+
12
+ class Fluent::ConfigPlaceholdersTest0Input < Fluent::Input
13
+ Fluent::Plugin.register_input('config_placeholder_test_0', self)
14
+
15
+ config_param :tag, :string
16
+ config_param :path, :string
17
+
18
+ attr_accessor :conf
19
+
20
+ def configure(conf)
21
+ super
22
+
23
+ @conf = conf
24
+ end
25
+ end
26
+
27
+ class Fluent::ConfigPlaceholdersTest1Input < Fluent::Input
28
+ Fluent::Plugin.register_input('config_placeholder_test_1', self)
29
+
30
+ config_param :tag, :string
31
+ config_param :path, :string
32
+
33
+ include Fluent::Mixin::ConfigPlaceholders
34
+ end
35
+
36
+ class Fluent::ConfigPlaceholdersTest2Input < Fluent::Input
37
+ Fluent::Plugin.register_input('config_placeholder_test_2', self)
38
+
39
+ config_param :tag, :string
40
+ config_param :path, :string
41
+
42
+ include Fluent::Mixin::ConfigPlaceholders
43
+
44
+ attr_accessor :conf
45
+
46
+ def configure(conf)
47
+ super
48
+
49
+ @path.upcase!
50
+
51
+ @conf = conf
52
+ end
53
+ end
metadata ADDED
@@ -0,0 +1,122 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-mixin-config-placeholders
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - TAGOMORI Satoshi
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-08-20 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: fluentd
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: uuidtools
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: fluentd
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: uuidtools
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ description: to add various placeholders for plugin configurations
79
+ email:
80
+ - tagomoris@gmail.com
81
+ executables: []
82
+ extensions: []
83
+ extra_rdoc_files: []
84
+ files:
85
+ - .gitignore
86
+ - Gemfile
87
+ - LICENSE.txt
88
+ - README.md
89
+ - Rakefile
90
+ - fluent-mixin-config-placeholders.gemspec
91
+ - lib/fluent/mixin/config_placeholders.rb
92
+ - test/helper.rb
93
+ - test/mixin/test_config_placeholders.rb
94
+ - test/plugin.rb
95
+ homepage: https://github.com/tagomoris/fluent-mixin-config-placeholders
96
+ licenses: []
97
+ post_install_message:
98
+ rdoc_options: []
99
+ require_paths:
100
+ - lib
101
+ required_ruby_version: !ruby/object:Gem::Requirement
102
+ none: false
103
+ requirements:
104
+ - - ! '>='
105
+ - !ruby/object:Gem::Version
106
+ version: '0'
107
+ required_rubygems_version: !ruby/object:Gem::Requirement
108
+ none: false
109
+ requirements:
110
+ - - ! '>='
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ requirements: []
114
+ rubyforge_project:
115
+ rubygems_version: 1.8.21
116
+ signing_key:
117
+ specification_version: 3
118
+ summary: Configuration syntax extension mixin for fluentd plugin
119
+ test_files:
120
+ - test/helper.rb
121
+ - test/mixin/test_config_placeholders.rb
122
+ - test/plugin.rb