pdi 1.0.1 → 2.0.0.pre.alpha
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/README.md +1 -0
- data/lib/pdi.rb +2 -0
- data/lib/pdi/executor.rb +33 -11
- data/lib/pdi/executor/result.rb +1 -1
- data/lib/pdi/executor/status.rb +2 -3
- data/lib/pdi/spoon.rb +3 -2
- data/lib/pdi/version.rb +1 -1
- data/spec/mocks/spoon/sleep.sh +10 -0
- data/spec/pdi/executor_spec.rb +52 -0
- data/spec/pdi/spoon_spec.rb +17 -4
- metadata +8 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3adae07a9c634b7075a87a47c810c0d4e3c90137ee85a08e01e09038baf990e1
|
4
|
+
data.tar.gz: 9f7ecf0e06ace02def29a7e710ea87d5ed5e2af82282a1dba935fa3628116533
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5104d4d97f12a70e7f2d492dee6f8f870c388fea8091bc26d60fd87efb826331479a5efa851de7cbeb278d48aad9368d12cbad7bbb675b9cd9a20baee50f087e
|
7
|
+
data.tar.gz: 3ff6caa7e64806a1f03f918b7a6692e25c7493aa6280c0f9edabc99dd937e8890d76f3e8e0f060584964b993791c990621dc3cd8c908f91b5e81a25ac3e9f5ff
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
# 2.0.0 (May 7th, 2020)
|
2
|
+
|
3
|
+
Breaking Changes:
|
4
|
+
|
5
|
+
* Standard error and output have been combined into one stream (out). Early feedback indicated that reading both at the same time was preferable.
|
6
|
+
|
7
|
+
Enhancements:
|
8
|
+
|
9
|
+
* Added optional `timeout_in_seconds` argument to Pdi::Spoon#initialize.
|
10
|
+
|
1
11
|
# 1.0.1 (February 19th, 2020)
|
2
12
|
|
3
13
|
Fixes:
|
data/README.md
CHANGED
@@ -50,6 +50,7 @@ Notes:
|
|
50
50
|
|
51
51
|
* You can also override the names of the scripts using the `kitchen` and `pan` constructor keyword arguments. The defaults are `kitchen.sh` and `pan.sh`, respectively.
|
52
52
|
* For other command line arguments that are not supported first-class in the Options objects below you can utilize the `args` argument when instantiating a `Spoon` instance.
|
53
|
+
* Another optional argument is `timeout_in_seconds`. If set it will ensure the sub-process runs within a given window. If it times out the sub-process will be terminated and a Timeout::Error will be raised.
|
53
54
|
|
54
55
|
### Executing a Job/Transformation
|
55
56
|
|
data/lib/pdi.rb
CHANGED
data/lib/pdi/executor.rb
CHANGED
@@ -13,20 +13,42 @@ module Pdi
|
|
13
13
|
# This class is the library's "metal" layer, the one which actually makes the system call and
|
14
14
|
# interacts with the operating system (through Ruby's standard library.)
|
15
15
|
class Executor
|
16
|
+
attr_reader :timeout_in_seconds
|
17
|
+
|
18
|
+
def initialize(timeout_in_seconds: nil)
|
19
|
+
@timeout_in_seconds = timeout_in_seconds
|
20
|
+
|
21
|
+
freeze
|
22
|
+
end
|
23
|
+
|
16
24
|
def run(args)
|
17
25
|
args = Array(args).map(&:to_s)
|
18
26
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
27
|
+
IO.popen(args, err: %i[child out]) do |io|
|
28
|
+
begin
|
29
|
+
io_read =
|
30
|
+
if timeout_in_seconds
|
31
|
+
Timeout.timeout(timeout_in_seconds) { io.read }
|
32
|
+
else
|
33
|
+
io.read
|
34
|
+
end
|
35
|
+
|
36
|
+
io.close
|
37
|
+
status = $CHILD_STATUS
|
38
|
+
|
39
|
+
Result.new(
|
40
|
+
args: args,
|
41
|
+
status: {
|
42
|
+
code: status.exitstatus,
|
43
|
+
out: io_read,
|
44
|
+
pid: status.pid
|
45
|
+
}
|
46
|
+
)
|
47
|
+
rescue Timeout::Error => e
|
48
|
+
Process.kill(9, io.pid)
|
49
|
+
raise e
|
50
|
+
end
|
51
|
+
end
|
30
52
|
end
|
31
53
|
end
|
32
54
|
end
|
data/lib/pdi/executor/result.rb
CHANGED
data/lib/pdi/executor/status.rb
CHANGED
@@ -13,12 +13,11 @@ module Pdi
|
|
13
13
|
class Status
|
14
14
|
acts_as_hashable
|
15
15
|
|
16
|
-
attr_reader :code, :out, :
|
16
|
+
attr_reader :code, :out, :pid
|
17
17
|
|
18
|
-
def initialize(code:, out: '',
|
18
|
+
def initialize(code:, out: '', pid:)
|
19
19
|
@code = code
|
20
20
|
@out = out
|
21
|
-
@err = err
|
22
21
|
@pid = pid
|
23
22
|
|
24
23
|
freeze
|
data/lib/pdi/spoon.rb
CHANGED
@@ -30,7 +30,8 @@ module Pdi
|
|
30
30
|
args: [],
|
31
31
|
dir:,
|
32
32
|
kitchen: DEFAULT_KITCHEN,
|
33
|
-
pan: DEFAULT_PAN
|
33
|
+
pan: DEFAULT_PAN,
|
34
|
+
timeout_in_seconds: nil
|
34
35
|
)
|
35
36
|
assert_required(:dir, dir)
|
36
37
|
assert_required(:kitchen, kitchen)
|
@@ -40,7 +41,7 @@ module Pdi
|
|
40
41
|
@dir = File.expand_path(dir.to_s)
|
41
42
|
@kitchen = kitchen.to_s
|
42
43
|
@pan = pan.to_s
|
43
|
-
@executor = Executor.new
|
44
|
+
@executor = Executor.new(timeout_in_seconds: timeout_in_seconds)
|
44
45
|
@parser = Parser.new
|
45
46
|
|
46
47
|
freeze
|
data/lib/pdi/version.rb
CHANGED
@@ -0,0 +1,52 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
#
|
4
|
+
# Copyright (c) 2018-present, Blue Marble Payroll, LLC
|
5
|
+
#
|
6
|
+
# This source code is licensed under the MIT license found in the
|
7
|
+
# LICENSE file in the root directory of this source tree.
|
8
|
+
#
|
9
|
+
|
10
|
+
require 'spec_helper'
|
11
|
+
|
12
|
+
describe Pdi::Executor do
|
13
|
+
let(:script) { File.join('spec', 'mocks', 'spoon', 'sleep.sh') }
|
14
|
+
let(:one_second) { 1 }
|
15
|
+
let(:return_code) { 33 }
|
16
|
+
|
17
|
+
describe '#run' do
|
18
|
+
context 'with a timeout' do
|
19
|
+
# do not make these too high, bugs could cause the entire script to still be executed without
|
20
|
+
# killing it so these high values could draw out results.
|
21
|
+
let(:thirty_seconds) { 30 }
|
22
|
+
|
23
|
+
subject { described_class.new(timeout_in_seconds: one_second) }
|
24
|
+
|
25
|
+
# This will run a script that will take 30 seconds to process, but by limiting the
|
26
|
+
# timeout using the #run argument, it should raise an error after one second.
|
27
|
+
it 'times out and kills process after 5 seconds' do
|
28
|
+
args = [script, thirty_seconds]
|
29
|
+
|
30
|
+
expect { subject.run(args) }.to raise_error(Timeout::Error)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'without a timeout' do
|
35
|
+
it 'returns right exit status as code' do
|
36
|
+
args = [script, one_second, return_code]
|
37
|
+
|
38
|
+
result = subject.run(args)
|
39
|
+
|
40
|
+
expect(result.code).to eq(return_code)
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'returns right standard output and error as out' do
|
44
|
+
args = [script, one_second, return_code]
|
45
|
+
|
46
|
+
result = subject.run(args)
|
47
|
+
|
48
|
+
expect(result.out).to eq("std_out\nerr_out\nafter_sleep\n")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
data/spec/pdi/spoon_spec.rb
CHANGED
@@ -14,6 +14,21 @@ describe Pdi::Spoon do
|
|
14
14
|
let(:mocks_dir) { %w[spec mocks spoon] }
|
15
15
|
let(:dir) { File.join(*mocks_dir) }
|
16
16
|
|
17
|
+
describe '#initialize' do
|
18
|
+
it 'sets executor' do
|
19
|
+
timeout_in_seconds = 987
|
20
|
+
|
21
|
+
subject = described_class.new(dir: dir, timeout_in_seconds: timeout_in_seconds)
|
22
|
+
|
23
|
+
# Private/internal testing is not recommended, but I really wanted to ensure
|
24
|
+
# this class is properly configuring the Executor instance, that way I can rely
|
25
|
+
# mainly on the Executor unit tests instead of integration tests at this level.
|
26
|
+
executor = subject.send('executor')
|
27
|
+
|
28
|
+
expect(executor.timeout_in_seconds).to eq(timeout_in_seconds)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
17
32
|
describe '#run' do
|
18
33
|
context 'transformations' do
|
19
34
|
let(:options) do
|
@@ -43,8 +58,7 @@ describe Pdi::Spoon do
|
|
43
58
|
|
44
59
|
result = subject.run(options)
|
45
60
|
|
46
|
-
expect(result.out).to eq("output to stdout\n")
|
47
|
-
expect(result.err).to eq("output to sterr\n")
|
61
|
+
expect(result.out).to eq("output to stdout\noutput to sterr\n")
|
48
62
|
expect(result.code).to eq(0)
|
49
63
|
end
|
50
64
|
end
|
@@ -97,8 +111,7 @@ describe Pdi::Spoon do
|
|
97
111
|
|
98
112
|
result = subject.run(options)
|
99
113
|
|
100
|
-
expect(result.out).to eq("output to stdout\n")
|
101
|
-
expect(result.err).to eq("output to sterr\n")
|
114
|
+
expect(result.out).to eq("output to stdout\noutput to sterr\n")
|
102
115
|
expect(result.code).to eq(0)
|
103
116
|
end
|
104
117
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pdi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0.pre.alpha
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Matthew Ruggio
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-05-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: acts_as_hashable
|
@@ -160,7 +160,9 @@ files:
|
|
160
160
|
- lib/pdi/version.rb
|
161
161
|
- pdi.gemspec
|
162
162
|
- spec/mocks/spoon/return_code.sh
|
163
|
+
- spec/mocks/spoon/sleep.sh
|
163
164
|
- spec/mocks/spoon/version.sh
|
165
|
+
- spec/pdi/executor_spec.rb
|
164
166
|
- spec/pdi/spoon/kitchen_error_spec.rb
|
165
167
|
- spec/pdi/spoon/options/arg_spec.rb
|
166
168
|
- spec/pdi/spoon/options/param_spec.rb
|
@@ -183,9 +185,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
183
185
|
version: 2.3.8
|
184
186
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
185
187
|
requirements:
|
186
|
-
- - "
|
188
|
+
- - ">"
|
187
189
|
- !ruby/object:Gem::Version
|
188
|
-
version:
|
190
|
+
version: 1.3.1
|
189
191
|
requirements: []
|
190
192
|
rubygems_version: 3.0.3
|
191
193
|
signing_key:
|
@@ -193,7 +195,9 @@ specification_version: 4
|
|
193
195
|
summary: Ruby wrapper for invoking Pentaho Data Integration
|
194
196
|
test_files:
|
195
197
|
- spec/mocks/spoon/return_code.sh
|
198
|
+
- spec/mocks/spoon/sleep.sh
|
196
199
|
- spec/mocks/spoon/version.sh
|
200
|
+
- spec/pdi/executor_spec.rb
|
197
201
|
- spec/pdi/spoon/kitchen_error_spec.rb
|
198
202
|
- spec/pdi/spoon/options/arg_spec.rb
|
199
203
|
- spec/pdi/spoon/options/param_spec.rb
|