fluent-plugin-exec_cron 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: cbbcf3f7345626fd259b551bebfca72f62a994cd
4
+ data.tar.gz: 24ca495172005d6079578070c02ad81a371023ad
5
+ SHA512:
6
+ metadata.gz: f4f551d1ef67f94df3df94f9b1423c1157cd1c9e4e2c57c4b8d1f1ab1e4e2715442075e6158076426eca32688aab17b6132f4166d2d079eae166e10a46982a3b
7
+ data.tar.gz: 98b8abdcf12ef59e76b02b2b9c01b609eaeee4016cf55a89e6a10172d9d2c925fd2f96b1c069f54243c45f9227a044f72b0da2289c629f419114aa28a579a6ad
@@ -0,0 +1,3 @@
1
+ -
2
+ ChangeLog.md
3
+ LICENSE.txt
@@ -0,0 +1,9 @@
1
+ Gemfile.lock
2
+ doc/
3
+ pkg/
4
+ **/*.gem
5
+ .yardoc/
6
+ .bundle/
7
+ vendor/bundle/
8
+ .tags
9
+ tmp/
@@ -0,0 +1,15 @@
1
+ language: ruby
2
+
3
+ rvm:
4
+ - 1.9.3
5
+ - 2.0.0
6
+ - 2.1
7
+
8
+ os:
9
+ - linux
10
+ - osx
11
+
12
+ gemfile:
13
+ - Gemfile
14
+
15
+ script: 'bundle exec rake test'
@@ -0,0 +1 @@
1
+ --markup markdown --title "fluent-plugin-exec_cron Documentation" --protected
data/Gemfile ADDED
@@ -0,0 +1,7 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem 'kramdown'
7
+ end
@@ -0,0 +1,79 @@
1
+ # fluent-plugin-exec_cron [![Build Status](https://secure.travis-ci.org/toyama0919/fluent-plugin-exec_cron.png?branch=master)](http://travis-ci.org/toyama0919/fluent-plugin-exec_cron)
2
+
3
+ executes external programs with cron syntax.
4
+
5
+ ## Examples
6
+
7
+ ### minutely
8
+ ```
9
+ <source>
10
+ type exec_cron
11
+ tag exec_cron.example
12
+ command echo '{"a":"a"}'
13
+ format json
14
+ cron * * * * *
15
+ graceful_shutdown false
16
+ </source>
17
+
18
+ <match exec_cron.example>
19
+ type stdout
20
+ </match>
21
+ ```
22
+
23
+ #### output
24
+ ```
25
+ 2015-05-27 13:07:00 +0900 exec_cron.example: {"a":"a"}
26
+ 2015-05-27 13:08:00 +0900 exec_cron.example: {"a":"a"}
27
+ 2015-05-27 13:09:00 +0900 exec_cron.example: {"a":"a"}
28
+ 2015-05-27 13:10:00 +0900 exec_cron.example: {"a":"a"}
29
+ 2015-05-27 13:11:00 +0900 exec_cron.example: {"a":"a"}
30
+ 2015-05-27 13:12:00 +0900 exec_cron.example: {"a":"a"}
31
+ ```
32
+
33
+ ### hourly
34
+ ```
35
+ <source>
36
+ type exec_cron
37
+ tag exec_cron.example
38
+ command echo '{"a":"a"}'
39
+ format json
40
+ cron 0 * * * *
41
+ graceful_shutdown true
42
+ </source>
43
+
44
+ <match exec_cron.example>
45
+ type stdout
46
+ </match>
47
+ ```
48
+
49
+ #### output
50
+ ```
51
+ 2015-05-27 12:00:00 +0900 exec_cron.example: {"a":"a"}
52
+ 2015-05-27 13:00:00 +0900 exec_cron.example: {"a":"a"}
53
+ ```
54
+
55
+
56
+ ## Installation
57
+ ```
58
+ sudo td-agent-gem install fluent-plugin-exec_cron
59
+ ```
60
+
61
+ ## Contributing
62
+
63
+ 1. Fork it
64
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
65
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
66
+ 4. Push to the branch (`git push origin my-new-feature`)
67
+ 5. Create new [Pull Request](../../pull/new/master)
68
+
69
+ ## Information
70
+
71
+ * [Homepage](https://github.com/toyama0919/fluent-plugin-exec_cron)
72
+ * [Issues](https://github.com/toyama0919/fluent-plugin-exec_cron/issues)
73
+ * [Documentation](http://rubydoc.info/gems/fluent-plugin-exec_cron/frames)
74
+ * [Email](mailto:toyama0919@gmail.com)
75
+
76
+ ## Copyright
77
+
78
+ Copyright (c) 2015 Hiroshi Toyama
79
+
@@ -0,0 +1,11 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new(:test) do |test|
5
+ test.libs << 'lib' << 'test'
6
+ test.pattern = 'test/**/test_*.rb'
7
+ test.verbose = true
8
+ end
9
+
10
+ task :default => :test
11
+
@@ -0,0 +1,18 @@
1
+ <source>
2
+ type forward
3
+ port 24224
4
+ </source>
5
+
6
+ <source>
7
+ type exec_cron
8
+ tag exec_cron.example
9
+ command echo '{"a":"a"}'
10
+ format json
11
+ cron * * * * *
12
+ graceful_shutdown false
13
+ </source>
14
+
15
+ <match exec_cron.exsample>
16
+ type stdout
17
+ </match>
18
+
@@ -0,0 +1,26 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.name = "fluent-plugin-exec_cron"
5
+ gem.version = "0.0.2"
6
+ gem.summary = %q{executes external programs with cron syntax.}
7
+ gem.description = %q{executes external programs with cron syntax.}
8
+ gem.license = "MIT"
9
+ gem.authors = ["Hiroshi Toyama"]
10
+ gem.email = "toyama0919@gmail.com"
11
+ gem.homepage = "https://github.com/toyama0919/fluent-plugin-exec_cron"
12
+
13
+ gem.files = `git ls-files`.split($/)
14
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
15
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
16
+ gem.require_paths = ['lib']
17
+
18
+ gem.add_runtime_dependency "parse-cron"
19
+ gem.add_development_dependency 'bundler', '~> 1.7.2'
20
+ gem.add_development_dependency 'fluentd'
21
+ gem.add_development_dependency 'pry', '~> 0.10.1'
22
+ gem.add_development_dependency 'rake', '~> 10.3.2'
23
+ gem.add_development_dependency 'rubocop', '~> 0.24.1'
24
+ gem.add_development_dependency 'rubygems-tasks', '~> 0.2'
25
+ gem.add_development_dependency 'yard', '~> 0.8'
26
+ end
@@ -0,0 +1,136 @@
1
+ module Fluent
2
+ class ExecCronInput < Input
3
+ Plugin.register_input('exec_cron', self)
4
+
5
+ def initialize
6
+ super
7
+ require 'fluent/plugin/exec_util'
8
+ require 'fluent/timezone'
9
+ require 'parse-cron'
10
+ require 'erb'
11
+ end
12
+
13
+ SUPPORTED_FORMAT = {
14
+ 'tsv' => :tsv,
15
+ 'json' => :json,
16
+ 'msgpack' => :msgpack,
17
+ }
18
+
19
+ unless method_defined?(:router)
20
+ define_method("router") { Fluent::Engine }
21
+ end
22
+
23
+ config_param :command, :string
24
+ config_param :format, :default => :tsv do |val|
25
+ f = SUPPORTED_FORMAT[val]
26
+ raise ConfigError, "Unsupported format '#{val}'" unless f
27
+ f
28
+ end
29
+ config_param :keys, :default => [] do |val|
30
+ val.split(',')
31
+ end
32
+ config_param :tag, :string, :default => nil
33
+ config_param :tag_key, :string, :default => nil
34
+ config_param :time_key, :string, :default => nil
35
+ config_param :time_format, :string, :default => nil
36
+ config_param :run_interval, :time, :default => nil
37
+ config_param :graceful_shutdown, :bool, :default => false
38
+ config_param :cron, :string
39
+
40
+ def configure(conf)
41
+ super
42
+
43
+ if localtime = conf['localtime']
44
+ @localtime = true
45
+ elsif utc = conf['utc']
46
+ @localtime = false
47
+ end
48
+
49
+ if conf['timezone']
50
+ @timezone = conf['timezone']
51
+ Fluent::Timezone.validate!(@timezone)
52
+ end
53
+
54
+ if !@tag && !@tag_key
55
+ raise ConfigError, "'tag' or 'tag_key' option is required on exec input"
56
+ end
57
+
58
+ if @time_key
59
+ if @time_format
60
+ f = @time_format
61
+ @time_parse_proc = Proc.new {|str| Time.strptime(str, f).to_i }
62
+ else
63
+ @time_parse_proc = Proc.new {|str| str.to_i }
64
+ end
65
+ end
66
+
67
+ case @format
68
+ when :tsv
69
+ if @keys.empty?
70
+ raise ConfigError, "keys option is required on exec input for tsv format"
71
+ end
72
+ @parser = ExecUtil::TSVParser.new(@keys, method(:on_message))
73
+ when :json
74
+ @parser = ExecUtil::JSONParser.new(method(:on_message))
75
+ when :msgpack
76
+ @parser = ExecUtil::MessagePackParser.new(method(:on_message))
77
+ end
78
+
79
+ begin
80
+ @cron_parser = CronParser.new(@cron)
81
+ rescue => e
82
+ raise ConfigError, "invalid cron expression. [#{@cron}]"
83
+ end
84
+ @command = ERB.new(@command.gsub(/\$\{([^}]+)\}/, '<%= \1 %>'))
85
+ end
86
+
87
+ def start
88
+ @finished = false
89
+ @thread = Thread.new(&method(:run_periodic))
90
+ end
91
+
92
+ def shutdown
93
+ @finished = true
94
+ if @graceful_shutdown
95
+ @thread.join
96
+ else
97
+ Thread.kill(@thread)
98
+ end
99
+ end
100
+
101
+ def run_periodic
102
+ until @finished
103
+ begin
104
+ secs = @cron_parser.next(Time.now) - Time.now
105
+ sleep secs
106
+ io = IO.popen(@command.result(binding), "r")
107
+ @parser.call(io)
108
+ Process.waitpid(io.pid)
109
+ rescue
110
+ log.error "exec failed to run or shutdown child process", :error => $!.to_s, :error_class => $!.class.to_s
111
+ log.warn_backtrace $!.backtrace
112
+ end
113
+ end
114
+ end
115
+
116
+ private
117
+
118
+ def on_message(record)
119
+ if val = record.delete(@tag_key)
120
+ tag = val
121
+ else
122
+ tag = @tag
123
+ end
124
+
125
+ if val = record.delete(@time_key)
126
+ time = @time_parse_proc.call(val)
127
+ else
128
+ time = Engine.now
129
+ end
130
+
131
+ router.emit(tag, time, record)
132
+ rescue => e
133
+ log.error "exec failed to emit", :error => e.to_s, :error_class => e.class.to_s, :tag => tag, :record => Yajl.dump(record)
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,18 @@
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
+ require 'fluent/test'
15
+ require 'fluent/plugin/in_exec_cron'
16
+
17
+ class Test::Unit::TestCase
18
+ end
@@ -0,0 +1,75 @@
1
+ require 'helper'
2
+
3
+ class ExecCronInputTest < Test::Unit::TestCase
4
+ def setup
5
+ Fluent::Test.setup
6
+ end
7
+
8
+ def create_driver(conf)
9
+ Fluent::Test::InputTestDriver.new(Fluent::ExecCronInput).configure(conf)
10
+ end
11
+
12
+ def test_configure_full
13
+ d = create_driver %q{
14
+ type exec_cron
15
+ tag exec_cron.example
16
+ command echo '{"a":"a"}'
17
+ format json
18
+ cron * * * * *
19
+ graceful_shutdown false
20
+ }
21
+
22
+ assert_equal 'exec_cron.example', d.instance.tag
23
+ end
24
+
25
+ def test_configure_error_when_config_is_empty
26
+ assert_raise(Fluent::ConfigError) do
27
+ create_driver ''
28
+ end
29
+ end
30
+
31
+ def test_configure_error_cron_syntax
32
+ assert_raise(Fluent::ConfigError) do
33
+ create_driver %q{
34
+ tag exec_cron.example
35
+ command echo '{"a":"a"}'
36
+ format json
37
+ cron hogehoge
38
+ graceful_shutdown false
39
+ }
40
+ end
41
+ end
42
+
43
+ def test_configure_placeholder
44
+ d = create_driver %q{
45
+ type exec_cron
46
+ tag exec_cron.example
47
+ command echo '{"a":"${(Date.new(2015, 1, 1) - 1).strftime('%Y/%m/%d')}"}'
48
+ format json
49
+ cron * * * * *
50
+ graceful_shutdown false
51
+ }
52
+ assert_equal %Q{echo '{"a":"2014/12/31"}'}, d.instance.command.result(binding)
53
+ end
54
+
55
+ def test_emit
56
+ d = create_driver %q{
57
+ tag exec_cron.example
58
+ command echo '{"a":"a", "time":"2011-01-02 13:14:15"}'
59
+ format json
60
+ time_key time
61
+ time_format %Y-%m-%d %H:%M:%S
62
+ cron * * * * *
63
+ graceful_shutdown false
64
+ }
65
+
66
+ d.run do
67
+ sleep 60
68
+ end
69
+
70
+ emits = d.emits
71
+ assert_equal true, emits.length > 0
72
+ assert_equal ["exec_cron.example", Time.parse("2011-01-02 13:14:15").to_i, {"a"=>"a"}], emits[0]
73
+ end
74
+
75
+ end
metadata ADDED
@@ -0,0 +1,170 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fluent-plugin-exec_cron
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Hiroshi Toyama
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-06-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: parse-cron
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
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: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 1.7.2
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 1.7.2
41
+ - !ruby/object:Gem::Dependency
42
+ name: fluentd
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.10.1
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.10.1
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 10.3.2
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 10.3.2
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubocop
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: 0.24.1
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: 0.24.1
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubygems-tasks
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '0.2'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '0.2'
111
+ - !ruby/object:Gem::Dependency
112
+ name: yard
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '0.8'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '0.8'
125
+ description: executes external programs with cron syntax.
126
+ email: toyama0919@gmail.com
127
+ executables: []
128
+ extensions: []
129
+ extra_rdoc_files: []
130
+ files:
131
+ - ".document"
132
+ - ".gitignore"
133
+ - ".travis.yml"
134
+ - ".yardopts"
135
+ - Gemfile
136
+ - README.md
137
+ - Rakefile
138
+ - exsample/exsample.conf
139
+ - fluent-plugin-exec_cron.gemspec
140
+ - lib/fluent/plugin/in_exec_cron.rb
141
+ - test/helper.rb
142
+ - test/plugin/test_in_exec_cron.rb
143
+ homepage: https://github.com/toyama0919/fluent-plugin-exec_cron
144
+ licenses:
145
+ - MIT
146
+ metadata: {}
147
+ post_install_message:
148
+ rdoc_options: []
149
+ require_paths:
150
+ - lib
151
+ required_ruby_version: !ruby/object:Gem::Requirement
152
+ requirements:
153
+ - - ">="
154
+ - !ruby/object:Gem::Version
155
+ version: '0'
156
+ required_rubygems_version: !ruby/object:Gem::Requirement
157
+ requirements:
158
+ - - ">="
159
+ - !ruby/object:Gem::Version
160
+ version: '0'
161
+ requirements: []
162
+ rubyforge_project:
163
+ rubygems_version: 2.4.2
164
+ signing_key:
165
+ specification_version: 4
166
+ summary: executes external programs with cron syntax.
167
+ test_files:
168
+ - test/helper.rb
169
+ - test/plugin/test_in_exec_cron.rb
170
+ has_rdoc: