logger_pipe 0.3.0 → 0.3.1
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.
- 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: /
|