logger_pipe 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rspec +1 -1
- data/README.md +1 -1
- data/lib/logger_pipe.rb +10 -0
- data/lib/logger_pipe/runner.rb +48 -20
- data/lib/logger_pipe/version.rb +1 -1
- data/spec/logger_pipe_spec.rb +59 -3
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: d79758d6c65671d213b290ca4e08150454226cfd
|
4
|
+
data.tar.gz: 94d6e1e1dce45bb19b42ba023516435fc15fa7c5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5adaebe24771bb24c89a2513826a51e6b62426bf25d593e74c12250895c7c544a9899b1d0bef46e5ac2436be42a7e9a5d573151210a1302ed69bf611b6cdc7ba
|
7
|
+
data.tar.gz: df6264bee36af034611c03a4af30cc1af87b8ea956d99103ebcd8e36575d24263a65e8b38c786155b3056ea9c6957e01ad8eda66b7c8b67a39a787a9ac0e8438
|
data/.rspec
CHANGED
@@ -1,2 +1,2 @@
|
|
1
|
-
--format
|
1
|
+
--format Fuubar
|
2
2
|
--color
|
data/README.md
CHANGED
data/lib/logger_pipe.rb
CHANGED
@@ -3,7 +3,17 @@ require "logger_pipe/version"
|
|
3
3
|
module LoggerPipe
|
4
4
|
autoload :Runner, "logger_pipe/runner"
|
5
5
|
|
6
|
+
SOURCES = [:none, :stdout, :stderr, :both].freeze
|
7
|
+
|
6
8
|
class << self
|
9
|
+
# run
|
10
|
+
# @param [Logger] logger
|
11
|
+
# @param [String] cmd Command to run on shell
|
12
|
+
# @param [Hash] options
|
13
|
+
# @option options [Integer] :timeout Seconds, default is nil.
|
14
|
+
# @option options [true|false] :dry_run If true given, command is not run actually
|
15
|
+
# @option options [Symbol] :returns Which output is used as return, one of :none, :stdout, :stderr, :both
|
16
|
+
# @option options [Symbol] :logging Which output is written to logger, one of :none, :stdout, :stderr, :both
|
7
17
|
def run(logger, cmd, options = {})
|
8
18
|
Runner.new(logger, cmd, options).execute
|
9
19
|
end
|
data/lib/logger_pipe/runner.rb
CHANGED
@@ -16,11 +16,14 @@ module LoggerPipe
|
|
16
16
|
|
17
17
|
class Runner
|
18
18
|
attr_accessor :logger, :cmd, :timeout
|
19
|
+
attr_accessor :returns, :logging
|
19
20
|
|
20
21
|
def initialize(logger, cmd, options = {})
|
21
22
|
@logger, @cmd = logger, cmd
|
22
23
|
@timeout = options[:timeout]
|
23
24
|
@dry_run = options[:dry_run]
|
25
|
+
@returns = options[:returns] || :stdout # :none, :stdout, :stderr, :both
|
26
|
+
@logging = options[:logging] || :both # :none, :stdout, :stderr, :both
|
24
27
|
end
|
25
28
|
|
26
29
|
def execute
|
@@ -28,35 +31,33 @@ module LoggerPipe
|
|
28
31
|
logger.info("dry run: #{cmd}")
|
29
32
|
return nil
|
30
33
|
end
|
31
|
-
logger.info("executing: #{cmd}")
|
32
34
|
@buf = []
|
33
35
|
# systemをタイムアウトさせることはできないので、popenの戻り値を使っています。
|
34
36
|
# see http://docs.ruby-lang.org/ja/2.0.0/class/Timeout.html
|
35
37
|
@com, @pid = nil, nil
|
36
|
-
|
37
|
-
|
38
|
+
setup do |actual_cmd, log_enable|
|
39
|
+
logger.info("executing: #{actual_cmd}")
|
38
40
|
|
41
|
+
timeout do
|
39
42
|
# popenにブロックを渡さないと$?がnilになってしまうので敢えてブロックで処理しています。
|
40
|
-
@com = IO.popen(
|
43
|
+
@com = IO.popen(actual_cmd) do |com|
|
41
44
|
@com = com
|
42
45
|
@pid = com.pid
|
43
46
|
while line = com.gets
|
44
47
|
@buf << line
|
45
|
-
logger.debug(line.chomp)
|
48
|
+
logger.debug(line.chomp) if log_enable
|
46
49
|
end
|
47
50
|
end
|
48
51
|
if $?.exitstatus == 0
|
49
|
-
|
50
|
-
|
51
|
-
return @buf.join
|
52
|
+
logger.info("\e[32mSUCCESS: %s\e[0m" % [actual_cmd])
|
53
|
+
return (returns == :none) ? nil : @buf.join
|
52
54
|
else
|
53
|
-
|
54
|
-
msg = "\e[31mFAILURE: %s\e[0m" % [cmd]
|
55
|
+
msg = "\e[31mFAILURE: %s\e[0m" % [actual_cmd]
|
55
56
|
logger.error(msg)
|
56
57
|
raise Failure.new(msg, @buf)
|
57
58
|
end
|
58
|
-
|
59
59
|
end
|
60
|
+
|
60
61
|
end
|
61
62
|
end
|
62
63
|
|
@@ -88,19 +89,46 @@ module LoggerPipe
|
|
88
89
|
end
|
89
90
|
end
|
90
91
|
|
91
|
-
def
|
92
|
-
|
93
|
-
|
94
|
-
|
92
|
+
def setup
|
93
|
+
raise ArgumentError, "Invalid option :returns #{returns.inspect}" unless SOURCES.include?(returns)
|
94
|
+
raise ArgumentError, "Invalid option :logging #{logging.inspect}" unless SOURCES.include?(logging)
|
95
|
+
if (returns == :both) && ([:stdout, :stderr].include?(logging))
|
96
|
+
raise ArgumentError, "Can' set logging: #{logging.inspect} with returns: #{returns.inspect}"
|
97
|
+
elsif (returns == :none) || (logging == :none) || (returns == logging)
|
98
|
+
actual_cmd =
|
99
|
+
case logging
|
100
|
+
when :none then
|
101
|
+
case returns
|
102
|
+
when :none then "#{cmd} 1>/dev/null 2>/dev/null"
|
103
|
+
when :stdout then "#{cmd} 2>/dev/null"
|
104
|
+
when :stderr then "#{cmd} 2>&1 1>/dev/null"
|
105
|
+
when :both then "#{cmd} 2>&1"
|
106
|
+
end
|
107
|
+
when :stdout then "#{cmd} 2>/dev/null"
|
108
|
+
when :stderr then "#{cmd} 2>&1 1>/dev/null"
|
109
|
+
when :both then "#{cmd} 2>&1"
|
110
|
+
end
|
111
|
+
return block_given? ? yield(actual_cmd, logging != :none) : nil
|
112
|
+
else
|
113
|
+
Tempfile.open("logger_pipe.stderr.log") do |f|
|
114
|
+
f.close
|
115
|
+
actual_cmd =
|
116
|
+
case returns
|
117
|
+
when :stdout then "#{cmd} 2>#{f.path}"
|
118
|
+
when :stderr then "#{cmd} 2>&1 1>#{f.path}"
|
119
|
+
end
|
120
|
+
begin
|
121
|
+
return block_given? ? yield(actual_cmd, logging == :both) : nil
|
122
|
+
ensure
|
123
|
+
logging_subfile(f)
|
124
|
+
end
|
125
|
+
end
|
95
126
|
end
|
96
127
|
end
|
97
128
|
|
98
|
-
def
|
129
|
+
def logging_subfile(f)
|
99
130
|
f.open
|
100
|
-
|
101
|
-
if !c.nil? && !c.empty?
|
102
|
-
logger.info("--- begin stderr ---\n#{c}\n--- end stderr ---")
|
103
|
-
end
|
131
|
+
logger.info("--- begin stderr ---\n%s\n--- end stderr ---" % f.read)
|
104
132
|
end
|
105
133
|
end
|
106
134
|
|
data/lib/logger_pipe/version.rb
CHANGED
data/spec/logger_pipe_spec.rb
CHANGED
@@ -30,7 +30,7 @@ describe LoggerPipe do
|
|
30
30
|
it "logging output" do
|
31
31
|
LoggerPipe.run(logger, cmd)
|
32
32
|
msg = buffer.string
|
33
|
-
expect(msg.lines.length).to
|
33
|
+
expect(msg.lines.length).to be >= 4
|
34
34
|
expect(msg.lines[0]).to match /executing: #{Regexp.escape(cmd)}/
|
35
35
|
expect(msg.lines[1]).to match /Foo: /
|
36
36
|
expect(msg.lines[2]).to match /Bar: /
|
@@ -38,7 +38,7 @@ describe LoggerPipe do
|
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
|
-
context "stderr" do
|
41
|
+
context "stderr" do # default options are {return: :stdout, logging: :both}
|
42
42
|
let(:cmd){ File.expand_path("../stderr_test.sh", __FILE__) }
|
43
43
|
it "returns STDOUT on success" do
|
44
44
|
res = LoggerPipe.run(logger, "#{cmd} 0")
|
@@ -56,6 +56,62 @@ describe LoggerPipe do
|
|
56
56
|
end
|
57
57
|
end
|
58
58
|
|
59
|
+
context ":returns and :logging" do
|
60
|
+
{
|
61
|
+
# [:returns, :logging] => [return of LoggerPipe.run, logging expectations]
|
62
|
+
[:none , :none ] => [nil , {foo: false, bar: false, baz: false}], # OK
|
63
|
+
[:none , :stdout] => [nil , {foo: true , bar: false, baz: true }], # OK
|
64
|
+
[:none , :stderr] => [nil , {foo: false, bar: true , baz: false}], # OK
|
65
|
+
[:none , :both ] => [nil , {foo: true , bar: true , baz: true }], # OK
|
66
|
+
[:stdout, :none ] => ["foo\nbaz\n" , {foo: false, bar: false, baz: false}], # OK
|
67
|
+
[:stdout, :stdout] => ["foo\nbaz\n" , {foo: true , bar: false, baz: true }], # BINGO
|
68
|
+
[:stdout, :stderr] => ["foo\nbaz\n" , {foo: false, bar: true , baz: false}], # NOT REALTIME
|
69
|
+
[:stdout, :both ] => ["foo\nbaz\n" , {foo: true , bar: true , baz: true }], # NOT REALTIME # DEFAULT
|
70
|
+
[:stderr, :none ] => ["bar\n" , {foo: false, bar: false, baz: false}], # OK
|
71
|
+
[:stderr, :stdout] => ["bar\n" , {foo: true , bar: false, baz: true }], # NOT REALTIME
|
72
|
+
[:stderr, :stderr] => ["bar\n" , {foo: false, bar: true , baz: false}], # BINGO
|
73
|
+
[:stderr, :both ] => ["bar\n" , {foo: true , bar: true , baz: true }], # NOT REALTIME
|
74
|
+
[:both , :none ] => ["foo\nbar\nbaz\n", {foo: false, bar: false, baz: false}], # OK
|
75
|
+
[:wrong , :none ] => :invalid,
|
76
|
+
[:none , :wrong ] => :invalid,
|
77
|
+
[:both , :stdout] => :invalid,
|
78
|
+
[:both , :stderr] => :invalid,
|
79
|
+
[:both , :both ] => ["foo\nbar\nbaz\n", {foo: true , bar: true , baz: true }], # BINGO
|
80
|
+
}.each do |options_values, expected|
|
81
|
+
options = {
|
82
|
+
returns: options_values.first,
|
83
|
+
logging: options_values.last,
|
84
|
+
}
|
85
|
+
context options do
|
86
|
+
let(:cmd){ File.expand_path("../stderr_test.sh", __FILE__) }
|
87
|
+
if expected == :invalid
|
88
|
+
it "raise invalid argument error" do
|
89
|
+
expect{ LoggerPipe.run(logger, "#{cmd} 0", options) }.to raise_error(ArgumentError)
|
90
|
+
end
|
91
|
+
else
|
92
|
+
it "returns STDOUT on success" do
|
93
|
+
res = LoggerPipe.run(logger, "#{cmd} 0", options)
|
94
|
+
expect(res).to eq expected.first
|
95
|
+
expected.last.each do |key, value|
|
96
|
+
m = value ? :to : :to_not
|
97
|
+
expect(buffer.string).send(m, match(/#{key}\n/))
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
it "buffer include stderr content on error" do
|
102
|
+
expect{
|
103
|
+
LoggerPipe.run(logger, "#{cmd} 1")
|
104
|
+
}.to raise_error(LoggerPipe::Failure)
|
105
|
+
# puts buffer.string
|
106
|
+
expect(buffer.string).to match /bar\n/
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
|
59
115
|
context "dry_run: true" do
|
60
116
|
let(:cmd){ "date +'Foo: %Y-%m-%dT%H:%M:%S'; sleep 1; date +'Bar: %Y-%m-%dT%H:%M:%S'" }
|
61
117
|
it "returns nil" do
|
@@ -81,7 +137,7 @@ describe LoggerPipe do
|
|
81
137
|
it "failure" do
|
82
138
|
LoggerPipe.run(logger, cmd) rescue nil
|
83
139
|
msg = buffer.string
|
84
|
-
expect(msg.lines.length).to
|
140
|
+
expect(msg.lines.length).to be >= 3
|
85
141
|
expect(msg.lines[0]).to match /executing: #{Regexp.escape(cmd)}/
|
86
142
|
expect(msg.lines[1]).to match /Foo: /
|
87
143
|
expect(msg.lines[2]).to match /FAILURE: date \+'Foo: /
|