awesome_spawn 1.0.0
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.
Potentially problematic release.
This version of awesome_spawn might be problematic. Click here for more details.
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/.yardopts +1 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +41 -0
- data/Rakefile +6 -0
- data/awesome_spawn.gemspec +34 -0
- data/lib/awesome_spawn.rb +174 -0
- data/lib/awesome_spawn/command_result.rb +16 -0
- data/lib/awesome_spawn/command_result_error.rb +11 -0
- data/lib/awesome_spawn/no_such_file_error.rb +11 -0
- data/lib/awesome_spawn/version.rb +3 -0
- data/spec/awesome_spawn_spec.rb +159 -0
- data/spec/command_result_spec.rb +13 -0
- data/spec/spec_helper.rb +26 -0
- metadata +176 -0
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/.yardopts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--markup markdown
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Red Hat, Inc.
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# AwesomeSpawn
|
2
|
+
|
3
|
+
[](http://badge.fury.io/rb/awesome_spawn)
|
4
|
+
[](https://travis-ci.org/ManageIQ/awesome_spawn)
|
5
|
+
[](https://codeclimate.com/github/ManageIQ/awesome_spawn)
|
6
|
+
[](https://coveralls.io/r/ManageIQ/awesome_spawn)
|
7
|
+
[](https://gemnasium.com/ManageIQ/awesome_spawn)
|
8
|
+
|
9
|
+
AwesomeSpawn is a module that provides some useful features over Ruby's Kernel.spawn.
|
10
|
+
|
11
|
+
Some additional features include...
|
12
|
+
|
13
|
+
- Parameter passing as a Hash or associative Array sanitizing them to prevent command line injection.
|
14
|
+
- Results returned as an object giving access to the output stream, error stream, and exit status.
|
15
|
+
- Optionally raising an exception when exit status is not 0.
|
16
|
+
|
17
|
+
## Usage
|
18
|
+
|
19
|
+
See the [YARD documentation](http://rubydoc.info/gems/awesome_spawn)
|
20
|
+
|
21
|
+
## Installation
|
22
|
+
|
23
|
+
Add this line to your application's Gemfile:
|
24
|
+
|
25
|
+
gem 'awesome_spawn'
|
26
|
+
|
27
|
+
And then execute:
|
28
|
+
|
29
|
+
$ bundle
|
30
|
+
|
31
|
+
Or install it yourself as:
|
32
|
+
|
33
|
+
$ gem install awesome_spawn
|
34
|
+
|
35
|
+
## Contributing
|
36
|
+
|
37
|
+
1. Fork it
|
38
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
39
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
40
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
41
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'awesome_spawn/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
authors = {
|
8
|
+
"Jason Frey" => "jfrey@redhat.com",
|
9
|
+
"Brandon Dunne" => "bdunne@redhat.com",
|
10
|
+
"Joe Rafaniello" => "jrafanie@redhat.com",
|
11
|
+
"Mo Morsi" => "mmorsi@redhat.com"
|
12
|
+
}
|
13
|
+
|
14
|
+
spec.name = "awesome_spawn"
|
15
|
+
spec.version = AwesomeSpawn::VERSION
|
16
|
+
spec.authors = authors.keys
|
17
|
+
spec.email = authors.values
|
18
|
+
spec.description = %q{AwesomeSpawn is a module that provides some useful features over Ruby's Kernel.spawn.}
|
19
|
+
spec.summary = spec.description
|
20
|
+
spec.homepage = "https://github.com/ManageIQ/awesome_spawn"
|
21
|
+
spec.license = "MIT"
|
22
|
+
|
23
|
+
spec.files = `git ls-files`.split($/)
|
24
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
25
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
26
|
+
spec.require_paths = ["lib"]
|
27
|
+
|
28
|
+
spec.add_development_dependency "bundler", "~> 1.3"
|
29
|
+
spec.add_development_dependency "rake"
|
30
|
+
spec.add_development_dependency "rspec"
|
31
|
+
spec.add_development_dependency "coveralls"
|
32
|
+
spec.add_development_dependency "yard"
|
33
|
+
spec.add_development_dependency "redcarpet"
|
34
|
+
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
require "awesome_spawn/version"
|
2
|
+
require "awesome_spawn/command_result"
|
3
|
+
require "awesome_spawn/command_result_error"
|
4
|
+
require "awesome_spawn/no_such_file_error"
|
5
|
+
|
6
|
+
require "shellwords"
|
7
|
+
|
8
|
+
module AwesomeSpawn
|
9
|
+
extend self
|
10
|
+
|
11
|
+
# Execute `command` synchronously via Kernel.spawn and gather the output
|
12
|
+
# stream, error stream, and exit status in a {CommandResult}.
|
13
|
+
#
|
14
|
+
# @example With normal output
|
15
|
+
# result = AwesomeSpawn.run('echo Hi')
|
16
|
+
# # => #<AwesomeSpawn::CommandResult:0x007f9d1d197320 @exit_status=0>
|
17
|
+
# result.output # => "Hi\n"
|
18
|
+
# result.error # => ""
|
19
|
+
# result.exit_status # => 0
|
20
|
+
#
|
21
|
+
# @example With error output as well
|
22
|
+
# result = AwesomeSpawn.run('echo Hi; echo "Hi2" 1>&2')
|
23
|
+
# # => <AwesomeSpawn::CommandResult:0x007ff64b98d930 @exit_status=0>
|
24
|
+
# result.output # => "Hi\n"
|
25
|
+
# result.error # => "Hi2\n"
|
26
|
+
# result.exit_status # => 0
|
27
|
+
#
|
28
|
+
# @example With exit status that is not 0
|
29
|
+
# result = AwesomeSpawn.run('false')
|
30
|
+
# #<AwesomeSpawn::CommandResult:0x007ff64b971410 @exit_status=1>
|
31
|
+
# result.exit_status # => 1
|
32
|
+
#
|
33
|
+
# @example With parameters sanitized
|
34
|
+
# result = AwesomeSpawn.run('echo', :params => {"--out" => "; rm /some/file"})
|
35
|
+
# # => #<AwesomeSpawn::CommandResult:0x007ff64baa6650 @exit_status=0>
|
36
|
+
# result.command_line
|
37
|
+
# # => "echo --out \\;\\ rm\\ /some/file"
|
38
|
+
#
|
39
|
+
# @param [String] command The command to run
|
40
|
+
# @param [Hash] options The options for running the command
|
41
|
+
# @option options [Hash,Array] :params The command line parameters. See
|
42
|
+
# {#build_command_line} for how to specify params. Alternate key
|
43
|
+
# `:parameters`.
|
44
|
+
# @option options [String] :chdir see the `:chdir` parameter for Kernel.spawn
|
45
|
+
#
|
46
|
+
# @raise [NoSuchFileError] if the `command` is not found
|
47
|
+
# @return [CommandResult] the output stream, error stream, and exit status
|
48
|
+
# @see http://ruby-doc.org/core/Kernel.html#method-i-spawn Kernel.spawn
|
49
|
+
def run(command, options = {})
|
50
|
+
params = options[:params] || options[:parameters]
|
51
|
+
|
52
|
+
launch_params = {}
|
53
|
+
launch_params[:chdir] = options[:chdir] if options[:chdir]
|
54
|
+
|
55
|
+
output = ""
|
56
|
+
error = ""
|
57
|
+
status = nil
|
58
|
+
command_line = build_command_line(command, params)
|
59
|
+
|
60
|
+
begin
|
61
|
+
output, error = launch(command_line, launch_params)
|
62
|
+
status = exitstatus
|
63
|
+
ensure
|
64
|
+
output ||= ""
|
65
|
+
error ||= ""
|
66
|
+
self.exitstatus = nil
|
67
|
+
end
|
68
|
+
rescue Errno::ENOENT => err
|
69
|
+
raise NoSuchFileError.new(err.message) if NoSuchFileError.detected?(err.message)
|
70
|
+
raise
|
71
|
+
else
|
72
|
+
CommandResult.new(command_line, output, error, status)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Same as {#run}, additionally raising a {CommandResultError} if the exit
|
76
|
+
# status is not 0.
|
77
|
+
#
|
78
|
+
# @example With exit status that is not 0
|
79
|
+
# error = AwesomeSpawn.run!('false') rescue $!
|
80
|
+
# # => #<AwesomeSpawn::CommandResultError: false exit code: 1>
|
81
|
+
# error.message # => false exit code: 1
|
82
|
+
# error.result # => #<AwesomeSpawn::CommandResult:0x007ff64ba08018 @exit_status=1>
|
83
|
+
#
|
84
|
+
# @raise [CommandResultError] if the exit status is not 0.
|
85
|
+
# @return (see #run)
|
86
|
+
def run!(command, options = {})
|
87
|
+
command_result = run(command, options)
|
88
|
+
|
89
|
+
if command_result.exit_status != 0
|
90
|
+
message = "#{command} exit code: #{command_result.exit_status}"
|
91
|
+
raise CommandResultError.new(message, command_result)
|
92
|
+
end
|
93
|
+
|
94
|
+
command_result
|
95
|
+
end
|
96
|
+
|
97
|
+
# Build the full command line.
|
98
|
+
#
|
99
|
+
# @param [String] command The command to run
|
100
|
+
# @param [Hash,Array] params Optional command line parameters. They can
|
101
|
+
# be passed as a Hash or associative Array. The values are sanitized to
|
102
|
+
# prevent command line injection.
|
103
|
+
#
|
104
|
+
# - `{"--key" => "value"}` generates `--key value`
|
105
|
+
# - `{"--key=" => "value"}` generates `--key=value`
|
106
|
+
# - `{"--key" => nil}` generates `--key`
|
107
|
+
# - `{"-f" => ["file1", "file2"]}` generates `-f file1 file2`
|
108
|
+
# - `{nil => ["file1", "file2"]}` generates `file1 file2`
|
109
|
+
#
|
110
|
+
# @return [String] The full command line
|
111
|
+
def build_command_line(command, params = nil)
|
112
|
+
return command.to_s if params.nil? || params.empty?
|
113
|
+
"#{command} #{assemble_params(sanitize(params))}"
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
def sanitize(params)
|
119
|
+
return [] if params.nil? || params.empty?
|
120
|
+
params.collect do |k, v|
|
121
|
+
v = case v
|
122
|
+
when Array; v.collect {|i| i.to_s.shellescape}
|
123
|
+
when NilClass; v
|
124
|
+
else v.to_s.shellescape
|
125
|
+
end
|
126
|
+
[k, v]
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
def assemble_params(sanitized_params)
|
131
|
+
sanitized_params.collect do |pair|
|
132
|
+
pair_joiner = pair.first.to_s.end_with?("=") ? "" : " "
|
133
|
+
pair.flatten.compact.join(pair_joiner)
|
134
|
+
end.join(" ")
|
135
|
+
end
|
136
|
+
|
137
|
+
# IO pipes have a maximum size of 64k before blocking,
|
138
|
+
# so we need to read and write synchronously.
|
139
|
+
# http://stackoverflow.com/questions/13829830/ruby-process-spawn-stdout-pipe-buffer-size-limit/13846146#13846146
|
140
|
+
THREAD_SYNC_KEY = "#{self.name}-exitstatus"
|
141
|
+
|
142
|
+
def launch(command, spawn_options = {})
|
143
|
+
out_r, out_w = IO.pipe
|
144
|
+
err_r, err_w = IO.pipe
|
145
|
+
pid = Kernel.spawn(command, {:err => err_w, :out => out_w}.merge(spawn_options))
|
146
|
+
wait_for_process(pid, out_w, err_w)
|
147
|
+
wait_for_pipes(out_r, err_r)
|
148
|
+
end
|
149
|
+
|
150
|
+
def wait_for_process(pid, out_w, err_w)
|
151
|
+
self.exitstatus = :not_done
|
152
|
+
Thread.new(Thread.current) do |parent_thread|
|
153
|
+
_, status = Process.wait2(pid)
|
154
|
+
out_w.close
|
155
|
+
err_w.close
|
156
|
+
parent_thread[THREAD_SYNC_KEY] = status.exitstatus
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
def wait_for_pipes(out_r, err_r)
|
161
|
+
out = out_r.read
|
162
|
+
err = err_r.read
|
163
|
+
sleep(0.1) while exitstatus == :not_done
|
164
|
+
return out, err
|
165
|
+
end
|
166
|
+
|
167
|
+
def exitstatus
|
168
|
+
Thread.current[THREAD_SYNC_KEY]
|
169
|
+
end
|
170
|
+
|
171
|
+
def exitstatus=(value)
|
172
|
+
Thread.current[THREAD_SYNC_KEY] = value
|
173
|
+
end
|
174
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module AwesomeSpawn
|
2
|
+
class CommandResult
|
3
|
+
attr_reader :command_line, :output, :error, :exit_status
|
4
|
+
|
5
|
+
def initialize(command_line, output, error, exit_status)
|
6
|
+
@command_line = command_line
|
7
|
+
@output = output
|
8
|
+
@error = error
|
9
|
+
@exit_status = exit_status
|
10
|
+
end
|
11
|
+
|
12
|
+
def inspect
|
13
|
+
"#{to_s.chop} @exit_status=#{@exit_status}>"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module AwesomeSpawn
|
2
|
+
class NoSuchFileError < Errno::ENOENT
|
3
|
+
def initialize(message)
|
4
|
+
super(message.split("No such file or directory -").last.split(" ").first)
|
5
|
+
end
|
6
|
+
|
7
|
+
def self.detected?(message)
|
8
|
+
message.start_with?("No such file or directory -")
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'pathname' # For Pathname specific specs
|
3
|
+
|
4
|
+
describe AwesomeSpawn do
|
5
|
+
subject { described_class }
|
6
|
+
|
7
|
+
let(:params) do
|
8
|
+
{
|
9
|
+
"--user" => "bob",
|
10
|
+
"--pass" => "P@$sw0^& |<>/-+*d%",
|
11
|
+
"--db" => nil,
|
12
|
+
"--desc=" => "Some Description",
|
13
|
+
nil => ["pkg1", "some pkg"]
|
14
|
+
}
|
15
|
+
end
|
16
|
+
|
17
|
+
let (:modified_params) do
|
18
|
+
params.to_a + [123, 456].collect {|pool| ["--pool", pool]}
|
19
|
+
end
|
20
|
+
|
21
|
+
shared_examples_for "run" do
|
22
|
+
context "parameters" do
|
23
|
+
before do
|
24
|
+
subject.stub(:exitstatus => 0)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "won't modify caller params" do
|
28
|
+
orig_params = params.dup
|
29
|
+
subject.stub(:launch)
|
30
|
+
subject.send(run_method, "true", :params => params)
|
31
|
+
expect(orig_params).to eq(params)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "supports spawn's chdir option" do
|
35
|
+
subject.should_receive(:launch).once.with("true", {:chdir => ".."})
|
36
|
+
subject.send(run_method, "true", :chdir => "..")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "with real execution" do
|
41
|
+
before do
|
42
|
+
# Re-enable actual spawning just for these specs.
|
43
|
+
Kernel.stub(:spawn).and_call_original
|
44
|
+
end
|
45
|
+
|
46
|
+
it "command ok exit ok" do
|
47
|
+
expect(subject.send(run_method, "true")).to be_kind_of AwesomeSpawn::CommandResult
|
48
|
+
end
|
49
|
+
|
50
|
+
it "command ok exit bad" do
|
51
|
+
if run_method == "run!"
|
52
|
+
error = nil
|
53
|
+
|
54
|
+
# raise_error with do/end block notation is broken in rspec-expectations 2.14.x
|
55
|
+
# and has been fixed in master but not yet released.
|
56
|
+
# See: https://github.com/rspec/rspec-expectations/commit/b0df827f4c12870aa4df2f20a817a8b01721a6af
|
57
|
+
expect { subject.send(run_method, "false") }.to raise_error {|e| error = e }
|
58
|
+
expect(error).to be_kind_of AwesomeSpawn::CommandResultError
|
59
|
+
expect(error.result).to be_kind_of AwesomeSpawn::CommandResult
|
60
|
+
else
|
61
|
+
expect { subject.send(run_method, "false") }.to_not raise_error
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
it "command bad" do
|
66
|
+
expect { subject.send(run_method, "XXXXX --user=bob") }.to raise_error(Errno::ENOENT, "No such file or directory - XXXXX")
|
67
|
+
end
|
68
|
+
|
69
|
+
context "#exit_status" do
|
70
|
+
it "command ok exit ok" do
|
71
|
+
expect(subject.send(run_method, "true").exit_status).to eq(0)
|
72
|
+
end
|
73
|
+
|
74
|
+
it "command ok exit bad" do
|
75
|
+
expect(subject.send(run_method, "false").exit_status).to eq(1) if run_method == "run"
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context "#output" do
|
80
|
+
it "command ok exit ok" do
|
81
|
+
expect(subject.send(run_method, "echo \"Hello World\"").output).to eq("Hello World\n")
|
82
|
+
end
|
83
|
+
|
84
|
+
it "command ok exit bad" do
|
85
|
+
expect(subject.send(run_method, "echo 'bad' && false").output).to eq("bad\n") if run_method == "run"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
context "#error" do
|
90
|
+
it "command ok exit ok" do
|
91
|
+
expect(subject.send(run_method, "echo \"Hello World\" >&2").error).to eq("Hello World\n")
|
92
|
+
end
|
93
|
+
|
94
|
+
it "command ok exit bad" do
|
95
|
+
expect(subject.send(run_method, "echo 'bad' >&2 && false").error).to eq("bad\n") if run_method == "run"
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
context ".run" do
|
102
|
+
include_examples "run" do
|
103
|
+
let(:run_method) {"run"}
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
context ".run!" do
|
108
|
+
include_examples "run" do
|
109
|
+
let(:run_method) {"run!"}
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context ".build_command_line" do
|
114
|
+
it "sanitizes crazy params" do
|
115
|
+
cl = subject.build_command_line("true", modified_params)
|
116
|
+
expect(cl).to eq "true --user bob --pass P@\\$sw0\\^\\&\\ \\|\\<\\>/-\\+\\*d\\% --db --desc=Some\\ Description pkg1 some\\ pkg --pool 123 --pool 456"
|
117
|
+
end
|
118
|
+
|
119
|
+
it "sanitizes Fixnum array param value" do
|
120
|
+
cl = subject.build_command_line("true", nil => [1])
|
121
|
+
expect(cl).to eq "true 1"
|
122
|
+
end
|
123
|
+
|
124
|
+
it "sanitizes Pathname param value" do
|
125
|
+
cl = subject.build_command_line("true", nil => [Pathname.new("/usr/bin/ruby")])
|
126
|
+
expect(cl).to eq "true /usr/bin/ruby"
|
127
|
+
end
|
128
|
+
|
129
|
+
it "sanitizes Pathname param key" do
|
130
|
+
cl = subject.build_command_line("true", Pathname.new("/usr/bin/ruby") => nil)
|
131
|
+
expect(cl).to eq "true /usr/bin/ruby"
|
132
|
+
end
|
133
|
+
|
134
|
+
it "with params as empty Hash" do
|
135
|
+
cl = subject.build_command_line("true", {})
|
136
|
+
expect(cl).to eq "true"
|
137
|
+
end
|
138
|
+
|
139
|
+
it "with params as nil" do
|
140
|
+
cl = subject.build_command_line("true", nil)
|
141
|
+
expect(cl).to eq "true"
|
142
|
+
end
|
143
|
+
|
144
|
+
it "without params" do
|
145
|
+
cl = subject.build_command_line("true")
|
146
|
+
expect(cl).to eq "true"
|
147
|
+
end
|
148
|
+
|
149
|
+
it "with Pathname command" do
|
150
|
+
cl = subject.build_command_line(Pathname.new("/usr/bin/ruby"))
|
151
|
+
expect(cl).to eq "/usr/bin/ruby"
|
152
|
+
end
|
153
|
+
|
154
|
+
it "with Pathname command and params" do
|
155
|
+
cl = subject.build_command_line(Pathname.new("/usr/bin/ruby"), "-v" => nil)
|
156
|
+
expect(cl).to eq "/usr/bin/ruby -v"
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe AwesomeSpawn::CommandResult do
|
4
|
+
context "#inspect" do
|
5
|
+
it "will not display sensitive information" do
|
6
|
+
str = described_class.new("aaa", "bbb", "ccc", 0).inspect
|
7
|
+
|
8
|
+
expect(str.include?("aaa")).to be_false
|
9
|
+
expect(str.include?("bbb")).to be_false
|
10
|
+
expect(str.include?("ccc")).to be_false
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
2
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
3
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
4
|
+
# loaded once.
|
5
|
+
#
|
6
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
7
|
+
RSpec.configure do |config|
|
8
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
9
|
+
config.run_all_when_everything_filtered = true
|
10
|
+
config.filter_run :focus
|
11
|
+
|
12
|
+
# Run specs in random order to surface order dependencies. If you find an
|
13
|
+
# order dependency and want to debug it, you can fix the order by providing
|
14
|
+
# the seed, which is printed after each run.
|
15
|
+
# --seed 1234
|
16
|
+
config.order = 'random'
|
17
|
+
|
18
|
+
config.before do
|
19
|
+
Kernel.stub(:spawn).and_raise("Spawning is not permitted in specs. Please change your spec to use expectations/stubs.")
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
require 'coveralls'
|
24
|
+
Coveralls.wear!
|
25
|
+
|
26
|
+
require 'awesome_spawn'
|
metadata
ADDED
@@ -0,0 +1,176 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: awesome_spawn
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jason Frey
|
9
|
+
- Brandon Dunne
|
10
|
+
- Joe Rafaniello
|
11
|
+
- Mo Morsi
|
12
|
+
autorequire:
|
13
|
+
bindir: bin
|
14
|
+
cert_chain: []
|
15
|
+
date: 2014-01-04 00:00:00.000000000 Z
|
16
|
+
dependencies:
|
17
|
+
- !ruby/object:Gem::Dependency
|
18
|
+
name: bundler
|
19
|
+
requirement: !ruby/object:Gem::Requirement
|
20
|
+
none: false
|
21
|
+
requirements:
|
22
|
+
- - ~>
|
23
|
+
- !ruby/object:Gem::Version
|
24
|
+
version: '1.3'
|
25
|
+
type: :development
|
26
|
+
prerelease: false
|
27
|
+
version_requirements: !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '1.3'
|
33
|
+
- !ruby/object:Gem::Dependency
|
34
|
+
name: rake
|
35
|
+
requirement: !ruby/object:Gem::Requirement
|
36
|
+
none: false
|
37
|
+
requirements:
|
38
|
+
- - ! '>='
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
type: :development
|
42
|
+
prerelease: false
|
43
|
+
version_requirements: !ruby/object:Gem::Requirement
|
44
|
+
none: false
|
45
|
+
requirements:
|
46
|
+
- - ! '>='
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: '0'
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
name: rspec
|
51
|
+
requirement: !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ! '>='
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
version: '0'
|
57
|
+
type: :development
|
58
|
+
prerelease: false
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
61
|
+
requirements:
|
62
|
+
- - ! '>='
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: '0'
|
65
|
+
- !ruby/object:Gem::Dependency
|
66
|
+
name: coveralls
|
67
|
+
requirement: !ruby/object:Gem::Requirement
|
68
|
+
none: false
|
69
|
+
requirements:
|
70
|
+
- - ! '>='
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
version: '0'
|
73
|
+
type: :development
|
74
|
+
prerelease: false
|
75
|
+
version_requirements: !ruby/object:Gem::Requirement
|
76
|
+
none: false
|
77
|
+
requirements:
|
78
|
+
- - ! '>='
|
79
|
+
- !ruby/object:Gem::Version
|
80
|
+
version: '0'
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: yard
|
83
|
+
requirement: !ruby/object:Gem::Requirement
|
84
|
+
none: false
|
85
|
+
requirements:
|
86
|
+
- - ! '>='
|
87
|
+
- !ruby/object:Gem::Version
|
88
|
+
version: '0'
|
89
|
+
type: :development
|
90
|
+
prerelease: false
|
91
|
+
version_requirements: !ruby/object:Gem::Requirement
|
92
|
+
none: false
|
93
|
+
requirements:
|
94
|
+
- - ! '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: redcarpet
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
none: false
|
101
|
+
requirements:
|
102
|
+
- - ! '>='
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
version: '0'
|
105
|
+
type: :development
|
106
|
+
prerelease: false
|
107
|
+
version_requirements: !ruby/object:Gem::Requirement
|
108
|
+
none: false
|
109
|
+
requirements:
|
110
|
+
- - ! '>='
|
111
|
+
- !ruby/object:Gem::Version
|
112
|
+
version: '0'
|
113
|
+
description: AwesomeSpawn is a module that provides some useful features over Ruby's
|
114
|
+
Kernel.spawn.
|
115
|
+
email:
|
116
|
+
- jfrey@redhat.com
|
117
|
+
- bdunne@redhat.com
|
118
|
+
- jrafanie@redhat.com
|
119
|
+
- mmorsi@redhat.com
|
120
|
+
executables: []
|
121
|
+
extensions: []
|
122
|
+
extra_rdoc_files: []
|
123
|
+
files:
|
124
|
+
- .gitignore
|
125
|
+
- .rspec
|
126
|
+
- .travis.yml
|
127
|
+
- .yardopts
|
128
|
+
- Gemfile
|
129
|
+
- LICENSE.txt
|
130
|
+
- README.md
|
131
|
+
- Rakefile
|
132
|
+
- awesome_spawn.gemspec
|
133
|
+
- lib/awesome_spawn.rb
|
134
|
+
- lib/awesome_spawn/command_result.rb
|
135
|
+
- lib/awesome_spawn/command_result_error.rb
|
136
|
+
- lib/awesome_spawn/no_such_file_error.rb
|
137
|
+
- lib/awesome_spawn/version.rb
|
138
|
+
- spec/awesome_spawn_spec.rb
|
139
|
+
- spec/command_result_spec.rb
|
140
|
+
- spec/spec_helper.rb
|
141
|
+
homepage: https://github.com/ManageIQ/awesome_spawn
|
142
|
+
licenses:
|
143
|
+
- MIT
|
144
|
+
post_install_message:
|
145
|
+
rdoc_options: []
|
146
|
+
require_paths:
|
147
|
+
- lib
|
148
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
149
|
+
none: false
|
150
|
+
requirements:
|
151
|
+
- - ! '>='
|
152
|
+
- !ruby/object:Gem::Version
|
153
|
+
version: '0'
|
154
|
+
segments:
|
155
|
+
- 0
|
156
|
+
hash: -1223152174146401530
|
157
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
158
|
+
none: false
|
159
|
+
requirements:
|
160
|
+
- - ! '>='
|
161
|
+
- !ruby/object:Gem::Version
|
162
|
+
version: '0'
|
163
|
+
segments:
|
164
|
+
- 0
|
165
|
+
hash: -1223152174146401530
|
166
|
+
requirements: []
|
167
|
+
rubyforge_project:
|
168
|
+
rubygems_version: 1.8.23
|
169
|
+
signing_key:
|
170
|
+
specification_version: 3
|
171
|
+
summary: AwesomeSpawn is a module that provides some useful features over Ruby's Kernel.spawn.
|
172
|
+
test_files:
|
173
|
+
- spec/awesome_spawn_spec.rb
|
174
|
+
- spec/command_result_spec.rb
|
175
|
+
- spec/spec_helper.rb
|
176
|
+
has_rdoc:
|