fluent-plugin-exec_cron 0.0.2

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,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: